-rw-r--r-- | .gitignore | 33 | ||||
-rw-r--r-- | COPYING | 2 | ||||
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | NEWS.xml | 6 | ||||
-rwxr-xr-x | autogen.sh | 2 | ||||
-rw-r--r-- | autoregen.sh | 2 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | include/opkele/expat.h | 3 | ||||
-rw-r--r-- | lib/basic_rp.cc | 3 | ||||
-rw-r--r-- | lib/discovery.cc | 31 | ||||
-rw-r--r-- | lib/expat.cc | 9 | ||||
-rw-r--r-- | test/RP.cc | 1 |
12 files changed, 71 insertions, 28 deletions
@@ -1,21 +1,16 @@ | |||
1 | configure | 1 | /configure |
2 | Makefile.in | 2 | Makefile.in |
3 | Doxyfile | 3 | /Doxyfile |
4 | config.log | 4 | /config.log |
5 | depcomp | 5 | /config.h |
6 | config.guess | 6 | /INSTALL |
7 | config.h | 7 | /NEWS |
8 | config.sub | ||
9 | ltmain.sh | ||
10 | INSTALL | ||
11 | NEWS | ||
12 | Makefile | 8 | Makefile |
13 | config.status | 9 | /config.status |
14 | stamp-h1 | 10 | /stamp-h1 |
15 | config.h.in | 11 | /config.h.in |
16 | libtool | 12 | /autom4te.cache |
17 | autom4te.cache | 13 | /libopkele.pc |
18 | libopkele.pc | 14 | /aclocal.m4 |
19 | missing | 15 | /aclocal.d |
20 | aclocal.m4 | 16 | /aux.d |
21 | install-sh | ||
@@ -1,19 +1,19 @@ | |||
1 | Copyright (c) 2005-2008 Klever Group (http://www.klever.net/) | 1 | Copyright (c) 2005-2009 Klever Group (http://www.klever.net/) |
2 | 2 | ||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of |
4 | this software and associated documentation files (the "Software"), to deal in | 4 | this software and associated documentation files (the "Software"), to deal in |
5 | the Software without restriction, including without limitation the rights to | 5 | the Software without restriction, including without limitation the rights to |
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
7 | of the Software, and to permit persons to whom the Software is furnished to do | 7 | of the Software, and to permit persons to whom the Software is furnished to do |
8 | so, subject to the following conditions: | 8 | so, subject to the following conditions: |
9 | 9 | ||
10 | The above copyright notice and this permission notice shall be included in all | 10 | The above copyright notice and this permission notice shall be included in all |
11 | copies or substantial portions of the Software. | 11 | copies or substantial portions of the Software. |
12 | 12 | ||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
19 | SOFTWARE. | 19 | SOFTWARE. |
diff --git a/Makefile.am b/Makefile.am index 3227bdb..7726dad 100644 --- a/Makefile.am +++ b/Makefile.am | |||
@@ -1,28 +1,29 @@ | |||
1 | |||
2 | SUBDIRS=include lib test | 1 | SUBDIRS=include lib test |
3 | EXTRA_DIST= NEWS NEWS.xml NEWS.xsl | 2 | EXTRA_DIST= NEWS NEWS.xml NEWS.xsl |
4 | 3 | ||
4 | ACLOCAL_AMFLAGS=-I aclocal.d | ||
5 | |||
5 | pkgconfigdir=${libdir}/pkgconfig | 6 | pkgconfigdir=${libdir}/pkgconfig |
6 | pkgconfig_DATA=libopkele.pc | 7 | pkgconfig_DATA=libopkele.pc |
7 | 8 | ||
8 | all-local: NEWS | 9 | all-local: NEWS |
9 | if HAVE_DOXYGEN | 10 | if HAVE_DOXYGEN |
10 | clean-local: | 11 | clean-local: |
11 | rm -rf doxydox | 12 | rm -rf doxydox |
12 | endif | 13 | endif |
13 | 14 | ||
14 | NEWS: NEWS.xsl NEWS.xml | 15 | NEWS: NEWS.xsl NEWS.xml |
15 | ${XSLTPROC} -o $@ NEWS.xsl NEWS.xml | 16 | ${XSLTPROC} -o $@ NEWS.xsl NEWS.xml |
16 | 17 | ||
17 | if HAVE_DOXYGEN | 18 | if HAVE_DOXYGEN |
18 | dox: Doxyfile | 19 | dox: Doxyfile |
19 | ${DOXYGEN} | 20 | ${DOXYGEN} |
20 | endif | 21 | endif |
21 | 22 | ||
22 | ISSUEFILES = $$(find ${top_srcdir} -type f '(' \ | 23 | ISSUEFILES = $$(find ${top_srcdir} -type f '(' \ |
23 | -name '*.cc' -or -name '*.h' \ | 24 | -name '*.cc' -or -name '*.h' \ |
24 | ')' ) \ | 25 | ')' ) \ |
25 | ${top_srcdir}/configure.ac | 26 | ${top_srcdir}/configure.ac |
26 | issues: todo fixme xxx | 27 | issues: todo fixme xxx |
27 | todo fixme xxx: | 28 | todo fixme xxx: |
28 | @grep --color=auto -in '$@:' ${ISSUEFILES} || true | 29 | @grep --color=auto -in '$@:' ${ISSUEFILES} || true |
@@ -1,65 +1,71 @@ | |||
1 | <?xml version="1.0" encoding="us-ascii"?> | 1 | <?xml version="1.0" encoding="us-ascii"?> |
2 | <news> | 2 | <news> |
3 | <version version="2.0.2" date="April 11th, 2009"> | ||
4 | <ni>Handling of unknown encodings during discovery</ni> | ||
5 | <ni>Discovery robustness improvements</ni> | ||
6 | <ni>Workaround for OPs (e.g. livejournal.com) breaking specs</ni> | ||
7 | <ni>Build fixes and improvements</ni> | ||
8 | </version> | ||
3 | <version version="2.0.1" date="November 22nd, 2008"> | 9 | <version version="2.0.1" date="November 22nd, 2008"> |
4 | <ni>Compile-time fixes and improvements</ni> | 10 | <ni>Compile-time fixes and improvements</ni> |
5 | <ni>Portability improvements for FreeBSD</ni> | 11 | <ni>Portability improvements for FreeBSD</ni> |
6 | <ni>Really suppress debugging message from htmltidy when --disable-debug is in | 12 | <ni>Really suppress debugging message from htmltidy when --disable-debug is in |
7 | effect</ni> | 13 | effect</ni> |
8 | <ni>minor bugfixes</ni> | 14 | <ni>minor bugfixes</ni> |
9 | <ni>thread-safety improvements</ni> | 15 | <ni>thread-safety improvements</ni> |
10 | </version> | 16 | </version> |
11 | <version version="2.0" date="June 26th, 2008"> | 17 | <version version="2.0" date="June 26th, 2008"> |
12 | <ni>OpenID 2.0 support</ni> | 18 | <ni>OpenID 2.0 support</ni> |
13 | <ni>Major rewrite of the whole thing</ni> | 19 | <ni>Major rewrite of the whole thing</ni> |
14 | <ni>Support for XRDS (YADIS and XRI/inames) discovery</ni> | 20 | <ni>Support for XRDS (YADIS and XRI/inames) discovery</ni> |
15 | <ni>Sheerly improved html-based discovery (only code using new, 2.0-enabled | 21 | <ni>Sheerly improved html-based discovery (only code using new, 2.0-enabled |
16 | classes benefits from it)</ni> | 22 | classes benefits from it)</ni> |
17 | <ni>Deprecation of the old api</ni> | 23 | <ni>Deprecation of the old api</ni> |
18 | <ni>Added sample RP and OP implementations</ni> | 24 | <ni>Added sample RP and OP implementations</ni> |
19 | <ni>Require expat xml stream parser library</ni> | 25 | <ni>Require expat xml stream parser library</ni> |
20 | <ni>Require htmltidy library</ni> | 26 | <ni>Require htmltidy library</ni> |
21 | <ni>Require tr1/memory (shared_ptr) support - either modern gcc or boost | 27 | <ni>Require tr1/memory (shared_ptr) support - either modern gcc or boost |
22 | library</ni> | 28 | library</ni> |
23 | </version> | 29 | </version> |
24 | <version version="0.3.2" date="November 22nd, 2007"> | 30 | <version version="0.3.2" date="November 22nd, 2007"> |
25 | <ni>code cleanup for stricter compiler</ni> | 31 | <ni>code cleanup for stricter compiler</ni> |
26 | </version> | 32 | </version> |
27 | <version version="0.3.1" date="November 20th, 2007"> | 33 | <version version="0.3.1" date="November 20th, 2007"> |
28 | <ni>more robustness improvements in links discovery</ni> | 34 | <ni>more robustness improvements in links discovery</ni> |
29 | <ni>removed dependency on pcre c++ bindings, because there are few of them and | 35 | <ni>removed dependency on pcre c++ bindings, because there are few of them and |
30 | not everyone likes all of them</ni> | 36 | not everyone likes all of them</ni> |
31 | <ni>minor build improvements</ni> | 37 | <ni>minor build improvements</ni> |
32 | </version> | 38 | </version> |
33 | <version version="0.3" date="August 9th, 2007"> | 39 | <version version="0.3" date="August 9th, 2007"> |
34 | <ni>fixed canonicalization procedure to be specs-compliant. Note, that the old | 40 | <ni>fixed canonicalization procedure to be specs-compliant. Note, that the old |
35 | consumer_t::canonicalize is now called consumer_t::normalize and the | 41 | consumer_t::canonicalize is now called consumer_t::normalize and the |
36 | canonicalize memeber is now virtual to allow caching layer, not static</ni> | 42 | canonicalize memeber is now virtual to allow caching layer, not static</ni> |
37 | <ni>robustness improvement in handling associations expiry</ni> | 43 | <ni>robustness improvement in handling associations expiry</ni> |
38 | <ni>minor documentation updates</ni> | 44 | <ni>minor documentation updates</ni> |
39 | </version> | 45 | </version> |
40 | <version version="0.2.1" date="June 24th, 2007"> | 46 | <version version="0.2.1" date="June 24th, 2007"> |
41 | <ni>open id server invalid signature bugfix</ni> | 47 | <ni>open id server invalid signature bugfix</ni> |
42 | </version> | 48 | </version> |
43 | <version version="0.2" date="June 19th, 2007"> | 49 | <version version="0.2" date="June 19th, 2007"> |
44 | <ni>A few robustness improvements and optimizations</ni> | 50 | <ni>A few robustness improvements and optimizations</ni> |
45 | <ni>More liberal key/values messages parsing</ni> | 51 | <ni>More liberal key/values messages parsing</ni> |
46 | <ni>Changed unusable --with-pcre++ configure option to --with-pcrepp</ni> | 52 | <ni>Changed unusable --with-pcre++ configure option to --with-pcrepp</ni> |
47 | </version> | 53 | </version> |
48 | <version version="0.1.1" date="January 16th, 2007"> | 54 | <version version="0.1.1" date="January 16th, 2007"> |
49 | <ni>Fixed a bug in curl errors handling</ni> | 55 | <ni>Fixed a bug in curl errors handling</ni> |
50 | <ni>added --disable-ssl-verify-host and --disable-ssl-verify-peer options to | 56 | <ni>added --disable-ssl-verify-host and --disable-ssl-verify-peer options to |
51 | configure to alter default implementation of consumer's retrieve_links | 57 | configure to alter default implementation of consumer's retrieve_links |
52 | behaviour</ni> | 58 | behaviour</ni> |
53 | <ni>Build fix that eliminates the need to pass --disable-konforka in the | 59 | <ni>Build fix that eliminates the need to pass --disable-konforka in the |
54 | absence of it.</ni> | 60 | absence of it.</ni> |
55 | </version> | 61 | </version> |
56 | <version version="0.1" date="January 12th, 2007"> | 62 | <version version="0.1" date="January 12th, 2007"> |
57 | <ni>OpenID simple registration extension implementation</ni> | 63 | <ni>OpenID simple registration extension implementation</ni> |
58 | <ni>OpenID extensions framework</ni> | 64 | <ni>OpenID extensions framework</ni> |
59 | <ni>Canonicalization bugfix</ni> | 65 | <ni>Canonicalization bugfix</ni> |
60 | <ni>Slightly improved interoperability with buggy implementations</ni> | 66 | <ni>Slightly improved interoperability with buggy implementations</ni> |
61 | </version> | 67 | </version> |
62 | <version version="0.0" date="July 25th, 2005"> | 68 | <version version="0.0" date="July 25th, 2005"> |
63 | <ni>Initial release</ni> | 69 | <ni>Initial release</ni> |
64 | </version> | 70 | </version> |
65 | </news> | 71 | </news> |
@@ -1,11 +1,11 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | tool_libtoolize="$(type -P glibtoolize || type -P libtoolize)" | 2 | tool_libtoolize="$(type -P glibtoolize || type -P libtoolize)" |
3 | if test -z "$tool_libtoolize" ; then | 3 | if test -z "$tool_libtoolize" ; then |
4 | echo "Failed to find libtoolize." ; exit 1; | 4 | echo "Failed to find libtoolize." ; exit 1; |
5 | fi | 5 | fi |
6 | "$tool_libtoolize" -f \ | 6 | "$tool_libtoolize" -f \ |
7 | && aclocal \ | 7 | && aclocal -I aclocal.d \ |
8 | && autoheader \ | 8 | && autoheader \ |
9 | && automake -a \ | 9 | && automake -a \ |
10 | && autoconf \ | 10 | && autoconf \ |
11 | && ./configure "$@" | 11 | && ./configure "$@" |
diff --git a/autoregen.sh b/autoregen.sh new file mode 100644 index 0000000..ce75a08 --- a/dev/null +++ b/autoregen.sh | |||
@@ -0,0 +1,2 @@ | |||
1 | #!/bin/bash | ||
2 | eval sh autogen.sh $(./config.status --version | grep '^ with options "'|sed -e 's/^[^"]\+"//' -e 's/"$//') "$@" | ||
diff --git a/configure.ac b/configure.ac index a7b56ff..2ded490 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -1,195 +1,197 @@ | |||
1 | AC_INIT([libopkele], [2.0.1], [libopkele-bugs@klever.net]) | 1 | AC_INIT([libopkele], [2.0.2], [libopkele-bugs@klever.net]) |
2 | AC_CONFIG_SRCDIR([include/opkele/opkele-config.h]) | 2 | AC_CONFIG_SRCDIR([include/opkele/opkele-config.h]) |
3 | AC_CONFIG_HEADERS([config.h include/opkele/acconfig.h]) | 3 | AC_CONFIG_HEADERS([config.h include/opkele/acconfig.h]) |
4 | AC_CONFIG_MACRO_DIR([aclocal.d]) | ||
5 | AC_CONFIG_AUX_DIR([aux.d]) | ||
4 | AM_INIT_AUTOMAKE([dist-bzip2]) | 6 | AM_INIT_AUTOMAKE([dist-bzip2]) |
5 | 7 | ||
6 | AC_PROG_INSTALL | 8 | AC_PROG_INSTALL |
7 | AC_PROG_CXX | 9 | AC_PROG_CXX |
8 | AC_PROG_CC | 10 | AC_PROG_CC |
9 | AC_PROG_LIBTOOL | 11 | AC_PROG_LIBTOOL |
10 | PKG_PROG_PKG_CONFIG | 12 | PKG_PROG_PKG_CONFIG |
11 | 13 | ||
12 | AC_HEADER_STDC | 14 | AC_HEADER_STDC |
13 | AC_CHECK_FUNCS([timegm]) | 15 | AC_CHECK_FUNCS([timegm]) |
14 | 16 | ||
15 | AC_PATH_PROG([XSLTPROC],[xsltproc],[true]) | 17 | AC_PATH_PROG([XSLTPROC],[xsltproc],[true]) |
16 | 18 | ||
17 | AC_MSG_CHECKING([for source tree version]) | 19 | AC_MSG_CHECKING([for source tree version]) |
18 | if headrev=$(cd $srcdir && git rev-parse --verify HEAD 2>/dev/null) ; then | 20 | if headrev=$(cd $srcdir && git rev-parse --verify HEAD 2>/dev/null) ; then |
19 | PACKAGE_SRC_VERSION="$(cd $srcdir && git describe --tags $headrev)" | 21 | PACKAGE_SRC_VERSION="$(cd $srcdir && git describe --tags $headrev)" |
20 | test "$PACKAGE_SRC_VERSION" = "$PACKAGE_VERSION" \ | 22 | test "$PACKAGE_SRC_VERSION" = "$PACKAGE_VERSION" \ |
21 | -o "${PACKAGE_SRC_VERSION#${PACKAGE_VERSION}-}" != "$PACKAGE_SRC_VERSION" || PACKAGE_SRC_VERSION="${PACKAGE_VERSION}:${PACKAGE_SRC_VERSION}" | 23 | -o "${PACKAGE_SRC_VERSION#${PACKAGE_VERSION}-}" != "$PACKAGE_SRC_VERSION" || PACKAGE_SRC_VERSION="${PACKAGE_VERSION}:${PACKAGE_SRC_VERSION}" |
22 | ( cd $srcdir && git diff-index $headrev | read dirt ) && PACKAGE_SRC_VERSION="${PACKAGE_SRC_VERSION}-dirty" | 24 | ( cd $srcdir && git diff-index $headrev | read dirt ) && PACKAGE_SRC_VERSION="${PACKAGE_SRC_VERSION}-dirty" |
23 | else | 25 | else |
24 | PACKAGE_SRC_VERSION="$PACKAGE_VERSION" | 26 | PACKAGE_SRC_VERSION="$PACKAGE_VERSION" |
25 | fi | 27 | fi |
26 | AC_MSG_RESULT([$PACKAGE_SRC_VERSION]) | 28 | AC_MSG_RESULT([$PACKAGE_SRC_VERSION]) |
27 | AC_SUBST([PACKAGE_SRC_VERSION]) | 29 | AC_SUBST([PACKAGE_SRC_VERSION]) |
28 | AC_DEFINE_UNQUOTED([PACKAGE_SRC_VERSION],["$PACKAGE_SRC_VERSION"],[more or less precise source tree version]) | 30 | AC_DEFINE_UNQUOTED([PACKAGE_SRC_VERSION],["$PACKAGE_SRC_VERSION"],[more or less precise source tree version]) |
29 | 31 | ||
30 | tr1_mem_std="false" | 32 | tr1_mem_std="false" |
31 | tr1_mem_boost="false" | 33 | tr1_mem_boost="false" |
32 | AC_CHECK_SHAREDPTR(std::tr1,tr1/memory,[ tr1_mem_std=true ]) | 34 | AC_CHECK_SHAREDPTR(std::tr1,tr1/memory,[ tr1_mem_std=true ]) |
33 | AC_CHECK_SHAREDPTR(boost,boost/shared_ptr.hpp,[ tr1_mem_boost=true ]) | 35 | AC_CHECK_SHAREDPTR(boost,boost/shared_ptr.hpp,[ tr1_mem_boost=true ]) |
34 | tr1_mem="" | 36 | tr1_mem="" |
35 | AC_ARG_WITH([tr1-memory], | 37 | AC_ARG_WITH([tr1-memory], |
36 | AC_HELP_STRING([--with-tr1-memory=<boost|std>],[select tr1/memory (shared_ptr<>) implementation to use]), | 38 | AC_HELP_STRING([--with-tr1-memory=<boost|std>],[select tr1/memory (shared_ptr<>) implementation to use]), |
37 | [ tr1_mem="$withval" ] | 39 | [ tr1_mem="$withval" ] |
38 | ) | 40 | ) |
39 | AC_MSG_CHECKING([for tr1/memory implementation to use]) | 41 | AC_MSG_CHECKING([for tr1/memory implementation to use]) |
40 | test -z "$tr1_mem" && $tr1_mem_std && tr1_mem=std | 42 | test -z "$tr1_mem" && $tr1_mem_std && tr1_mem=std |
41 | test -z "$tr1_mem" && $tr1_mem_boost && tr1_mem=boost | 43 | test -z "$tr1_mem" && $tr1_mem_boost && tr1_mem=boost |
42 | if test -z "$tr1_mem" ; then | 44 | if test -z "$tr1_mem" ; then |
43 | AC_MSG_RESULT([none found]) | 45 | AC_MSG_RESULT([none found]) |
44 | else | 46 | else |
45 | AC_MSG_RESULT([$tr1_mem]) | 47 | AC_MSG_RESULT([$tr1_mem]) |
46 | fi | 48 | fi |
47 | case "$tr1_mem" in | 49 | case "$tr1_mem" in |
48 | std) | 50 | std) |
49 | $tr1_mem_std || AC_MSG_ERROR([std implementation requested, but not found]) | 51 | $tr1_mem_std || AC_MSG_ERROR([std implementation requested, but not found]) |
50 | OPKELE_TR1_MEM_NS=std::tr1 | 52 | OPKELE_TR1_MEM_NS=std::tr1 |
51 | OPKELE_TR1_MEM_HEADER=tr1/memory | 53 | OPKELE_TR1_MEM_HEADER=tr1/memory |
52 | ;; | 54 | ;; |
53 | boost) | 55 | boost) |
54 | $tr1_mem_boost || AC_MSG_ERROR([boost implementation requested, but not found]) | 56 | $tr1_mem_boost || AC_MSG_ERROR([boost implementation requested, but not found]) |
55 | OPKELE_TR1_MEM_NS=boost | 57 | OPKELE_TR1_MEM_NS=boost |
56 | OPKELE_TR1_MEM_HEADER=boost/shared_ptr.hpp | 58 | OPKELE_TR1_MEM_HEADER=boost/shared_ptr.hpp |
57 | ;; | 59 | ;; |
58 | *) | 60 | *) |
59 | AC_MSG_ERROR([no shared_ptr<> implementation found]) | 61 | AC_MSG_ERROR([no shared_ptr<> implementation found]) |
60 | ;; | 62 | ;; |
61 | esac | 63 | esac |
62 | AC_SUBST([OPKELE_TR1_MEM_NS]) | 64 | AC_SUBST([OPKELE_TR1_MEM_NS]) |
63 | AC_SUBST([OPKELE_TR1_MEM_HEADER]) | 65 | AC_SUBST([OPKELE_TR1_MEM_HEADER]) |
64 | 66 | ||
65 | AC_MSG_CHECKING([for deprecated attribute support]) | 67 | AC_MSG_CHECKING([for deprecated attribute support]) |
66 | AC_COMPILE_IFELSE([ | 68 | AC_COMPILE_IFELSE([ |
67 | int __attribute__((deprecated)) deprecated_function(); | 69 | int __attribute__((deprecated)) deprecated_function(); |
68 | ],[ | 70 | ],[ |
69 | AC_MSG_RESULT([yes]) | 71 | AC_MSG_RESULT([yes]) |
70 | AC_DEFINE([OPKELE_DEPRECATE],[__attribute__((deprecated))],[deprecated function attribute]) | 72 | AC_DEFINE([OPKELE_DEPRECATE],[__attribute__((deprecated))],[deprecated function attribute]) |
71 | ],[ | 73 | ],[ |
72 | AC_MSG_RESULT([no]) | 74 | AC_MSG_RESULT([no]) |
73 | AC_DEFINE([OPKELE_DEPRECATE],,[deprecated function attribute]) | 75 | AC_DEFINE([OPKELE_DEPRECATE],,[deprecated function attribute]) |
74 | ] | 76 | ] |
75 | ) | 77 | ) |
76 | 78 | ||
77 | AC_LANG_PUSH([C++]) | 79 | AC_LANG_PUSH([C++]) |
78 | AC_MSG_CHECKING([for abi::__cxa_demangle]) | 80 | AC_MSG_CHECKING([for abi::__cxa_demangle]) |
79 | AC_COMPILE_IFELSE([ | 81 | AC_COMPILE_IFELSE([ |
80 | #include <typeinfo> | 82 | #include <typeinfo> |
81 | using namespace std; | 83 | using namespace std; |
82 | #include <cxxabi.h> | 84 | #include <cxxabi.h> |
83 | int main(int c,char **v) { | 85 | int main(int c,char **v) { |
84 | int dstat; | 86 | int dstat; |
85 | char *demangled = abi::__cxa_demangle(typeid(dstat).name(),0,0,&dstat); | 87 | char *demangled = abi::__cxa_demangle(typeid(dstat).name(),0,0,&dstat); |
86 | return 0; | 88 | return 0; |
87 | } | 89 | } |
88 | ],[ | 90 | ],[ |
89 | AC_MSG_RESULT([yes]) | 91 | AC_MSG_RESULT([yes]) |
90 | AC_DEFINE([HAVE_DEMANGLE],,[defined if abi::__cxa_demangle is available]) | 92 | AC_DEFINE([HAVE_DEMANGLE],,[defined if abi::__cxa_demangle is available]) |
91 | ],[ | 93 | ],[ |
92 | AC_MSG_RESULT([no]) | 94 | AC_MSG_RESULT([no]) |
93 | ] | 95 | ] |
94 | ) | 96 | ) |
95 | AC_LANG_POP([C++]) | 97 | AC_LANG_POP([C++]) |
96 | 98 | ||
97 | 99 | ||
98 | 100 | ||
99 | 101 | ||
100 | PKG_CHECK_MODULES([OPENSSL],[openssl],,[ | 102 | PKG_CHECK_MODULES([OPENSSL],[openssl],,[ |
101 | AC_MSG_ERROR([no openssl library found. get one from http://www.openssl.org/]) | 103 | AC_MSG_ERROR([no openssl library found. get one from http://www.openssl.org/]) |
102 | ]) | 104 | ]) |
103 | 105 | ||
104 | WANT_KONFORKA="yes" | 106 | WANT_KONFORKA="yes" |
105 | AC_ARG_ENABLE([konforka], | 107 | AC_ARG_ENABLE([konforka], |
106 | AC_HELP_STRING([--disable-konforka],[do not use konforka library (default: use if found)]), | 108 | AC_HELP_STRING([--disable-konforka],[do not use konforka library (default: use if found)]), |
107 | [ | 109 | [ |
108 | test "${enableval}" = "no" && WANT_KONFORKA="no" | 110 | test "${enableval}" = "no" && WANT_KONFORKA="no" |
109 | ] | 111 | ] |
110 | ) | 112 | ) |
111 | if test "${WANT_KONFORKA}" = "yes" ; then | 113 | if test "${WANT_KONFORKA}" = "yes" ; then |
112 | PKG_CHECK_MODULES([KONFORKA],[konforka],[ | 114 | PKG_CHECK_MODULES([KONFORKA],[konforka],[ |
113 | AC_SUBST([KONFORKA_CFLAGS]) | 115 | AC_SUBST([KONFORKA_CFLAGS]) |
114 | AC_SUBST([KONFORKA_LIBS]) | 116 | AC_SUBST([KONFORKA_LIBS]) |
115 | AC_DEFINE([HAVE_KONFORKA],,[defined in presence of konforka library]) | 117 | AC_DEFINE([HAVE_KONFORKA],,[defined in presence of konforka library]) |
116 | AC_DEFINE([OPKELE_HAVE_KONFORKA],,[defined in presence of konforka library]) | 118 | AC_DEFINE([OPKELE_HAVE_KONFORKA],,[defined in presence of konforka library]) |
117 | AC_SUBST([KONFORKA_KONFORKA],[konforka]) | 119 | AC_SUBST([KONFORKA_KONFORKA],[konforka]) |
118 | ],[true]) | 120 | ],[true]) |
119 | fi | 121 | fi |
120 | 122 | ||
121 | WANT_DOXYGEN="yes" | 123 | WANT_DOXYGEN="yes" |
122 | AC_ARG_ENABLE([doxygen], | 124 | AC_ARG_ENABLE([doxygen], |
123 | AC_HELP_STRING([--disable-doxygen],[do not generate documentation]), | 125 | AC_HELP_STRING([--disable-doxygen],[do not generate documentation]), |
124 | [ | 126 | [ |
125 | test "${enableval}" = "no" && WANT_DOXYGEN="no" | 127 | test "${enableval}" = "no" && WANT_DOXYGEN="no" |
126 | ] | 128 | ] |
127 | ) | 129 | ) |
128 | if test "${WANT_DOXYGEN}" = "yes" ; then | 130 | if test "${WANT_DOXYGEN}" = "yes" ; then |
129 | AC_WITH_DOXYGEN | 131 | AC_WITH_DOXYGEN |
130 | AC_WITH_DOT | 132 | AC_WITH_DOT |
131 | else | 133 | else |
132 | AM_CONDITIONAL([HAVE_DOXYGEN],[false]) | 134 | AM_CONDITIONAL([HAVE_DOXYGEN],[false]) |
133 | AM_CONDITIONAL([HAVE_DOT],[false]) | 135 | AM_CONDITIONAL([HAVE_DOT],[false]) |
134 | fi | 136 | fi |
135 | 137 | ||
136 | LIBCURL_CHECK_CONFIG(,,,[ | 138 | LIBCURL_CHECK_CONFIG(,,,[ |
137 | AC_MSG_ERROR([no required libcurl library. get one from http://curl.haxx.se/]) | 139 | AC_MSG_ERROR([no required libcurl library. get one from http://curl.haxx.se/]) |
138 | ]) | 140 | ]) |
139 | 141 | ||
140 | AC_CHECK_HEADER([expat.h],[ | 142 | AC_CHECK_HEADER([expat.h],[ |
141 | AC_CHECK_LIB([expat],[XML_ParserCreate],[ | 143 | AC_CHECK_LIB([expat],[XML_ParserCreate],[ |
142 | EXPAT_LIBS=-lexpat | 144 | EXPAT_LIBS=-lexpat |
143 | EXPAT_CFLAGS= | 145 | EXPAT_CFLAGS= |
144 | AC_SUBST([EXPAT_LIBS]) | 146 | AC_SUBST([EXPAT_LIBS]) |
145 | AC_SUBST([EXPAT_CFLAGS]) | 147 | AC_SUBST([EXPAT_CFLAGS]) |
146 | ],[ | 148 | ],[ |
147 | AC_MSG_ERROR([no required expat library. get one from http://expat.sourceforge.net/]) | 149 | AC_MSG_ERROR([no required expat library. get one from http://expat.sourceforge.net/]) |
148 | ]) | 150 | ]) |
149 | ],[ | 151 | ],[ |
150 | AC_MSG_ERROR([no required expat library. get one from http://expat.sourceforge.net/]) | 152 | AC_MSG_ERROR([no required expat library. get one from http://expat.sourceforge.net/]) |
151 | ]) | 153 | ]) |
152 | 154 | ||
153 | AC_CHECK_HEADERS([tidy.h tidy/tidy.h],[ | 155 | AC_CHECK_HEADERS([tidy.h tidy/tidy.h],[ |
154 | AC_CHECK_LIB([tidy],[tidyParseBuffer],[ | 156 | AC_CHECK_LIB([tidy],[tidyParseBuffer],[ |
155 | TIDY_LIBS=-ltidy | 157 | TIDY_LIBS=-ltidy |
156 | TIDY_CFLAGS= | 158 | TIDY_CFLAGS= |
157 | AC_SUBST([TIDY_LIBS]) | 159 | AC_SUBST([TIDY_LIBS]) |
158 | AC_SUBST([TIDY_CFLAGS]) | 160 | AC_SUBST([TIDY_CFLAGS]) |
159 | ],[ | 161 | ],[ |
160 | AC_MSG_ERROR([no required htmltidy library found. get one from http://tidy.sourceforge.net/]) | 162 | AC_MSG_ERROR([no required htmltidy library found. get one from http://tidy.sourceforge.net/]) |
161 | ]) | 163 | ]) |
162 | ],[ | 164 | ],[ |
163 | test "$ac_header" = "tidy/tidy.h" \ | 165 | test "$ac_header" = "tidy/tidy.h" \ |
164 | && AC_MSG_ERROR([no required htmltidy library found. get one from http://tidy.sourceforge.net/]) | 166 | && AC_MSG_ERROR([no required htmltidy library found. get one from http://tidy.sourceforge.net/]) |
165 | ]) | 167 | ]) |
166 | 168 | ||
167 | if test -n "$PCRE_LIBS" -a -n "$PCRE_CFLAGS" ; then | 169 | if test -n "$PCRE_LIBS" -a -n "$PCRE_CFLAGS" ; then |
168 | AC_SUBST([PCRE_CFLAGS]) | 170 | AC_SUBST([PCRE_CFLAGS]) |
169 | AC_SUBST([PCRE_LIBS]) | 171 | AC_SUBST([PCRE_LIBS]) |
170 | : | 172 | : |
171 | else | 173 | else |
172 | PKG_CHECK_MODULES([PCRE],[libpcre],,[ | 174 | PKG_CHECK_MODULES([PCRE],[libpcre],,[ |
173 | AC_MSG_ERROR([no libpcre found, go get it at http://www.pcre.org/]) | 175 | AC_MSG_ERROR([no libpcre found, go get it at http://www.pcre.org/]) |
174 | ]) | 176 | ]) |
175 | fi | 177 | fi |
176 | 178 | ||
177 | PKG_CHECK_MODULES([SQLITE3],[sqlite3],[have_sqlite3=true],[have_sqlite3=false]) | 179 | PKG_CHECK_MODULES([SQLITE3],[sqlite3],[have_sqlite3=true],[have_sqlite3=false]) |
178 | AM_CONDITIONAL([HAVE_SQLITE3],[$have_sqlite3]) | 180 | AM_CONDITIONAL([HAVE_SQLITE3],[$have_sqlite3]) |
179 | PKG_CHECK_MODULES([KINGATE],[kingate-plaincgi],[have_kingate=true],[have_kingate=false]) | 181 | PKG_CHECK_MODULES([KINGATE],[kingate-plaincgi],[have_kingate=true],[have_kingate=false]) |
180 | AM_CONDITIONAL([HAVE_KINGATE],[$have_kingate]) | 182 | AM_CONDITIONAL([HAVE_KINGATE],[$have_kingate]) |
181 | PKG_CHECK_MODULES([UUID],[uuid],[have_uuid=true],[have_uuid=false]) | 183 | PKG_CHECK_MODULES([UUID],[uuid],[have_uuid=true],[have_uuid=false]) |
182 | AM_CONDITIONAL([HAVE_UUID],[$have_uuid]) | 184 | AM_CONDITIONAL([HAVE_UUID],[$have_uuid]) |
183 | if $have_uuid ; then | 185 | if $have_uuid ; then |
184 | AC_DEFINE([HAVE_LIBUUID],,[defined in presence of libuuid]) | 186 | AC_DEFINE([HAVE_LIBUUID],,[defined in presence of libuuid]) |
185 | AC_SUBST([UUID_UUID],[uuid]) | 187 | AC_SUBST([UUID_UUID],[uuid]) |
186 | fi | 188 | fi |
187 | 189 | ||
188 | curl_ssl_verify_host="true" | 190 | curl_ssl_verify_host="true" |
189 | AC_ARG_ENABLE([ssl-verify-host], | 191 | AC_ARG_ENABLE([ssl-verify-host], |
190 | AC_HELP_STRING([--disable-ssl-verify-host],[disable cURL cert/host relationships verification]), | 192 | AC_HELP_STRING([--disable-ssl-verify-host],[disable cURL cert/host relationships verification]), |
191 | [ test "${enableval}" = "no" && curl_ssl_verify_host="false" ] | 193 | [ test "${enableval}" = "no" && curl_ssl_verify_host="false" ] |
192 | ) | 194 | ) |
193 | ${curl_ssl_verify_host} || AC_DEFINE([DISABLE_CURL_SSL_VERIFYHOST],,[defined if cURL is not to verify cert/host]) | 195 | ${curl_ssl_verify_host} || AC_DEFINE([DISABLE_CURL_SSL_VERIFYHOST],,[defined if cURL is not to verify cert/host]) |
194 | 196 | ||
195 | curl_ssl_verify_peer="true" | 197 | curl_ssl_verify_peer="true" |
diff --git a/include/opkele/expat.h b/include/opkele/expat.h index 3ab1630..21be003 100644 --- a/include/opkele/expat.h +++ b/include/opkele/expat.h | |||
@@ -1,91 +1,94 @@ | |||
1 | #ifndef __OPKELE_EXPAT_H | 1 | #ifndef __OPKELE_EXPAT_H |
2 | #define __OPKELE_EXPAT_H | 2 | #define __OPKELE_EXPAT_H |
3 | 3 | ||
4 | #include <cassert> | 4 | #include <cassert> |
5 | #include <expat.h> | 5 | #include <expat.h> |
6 | 6 | ||
7 | namespace opkele { | 7 | namespace opkele { |
8 | 8 | ||
9 | namespace util { | 9 | namespace util { |
10 | 10 | ||
11 | class expat_t { | 11 | class expat_t { |
12 | public: | 12 | public: |
13 | XML_Parser _x; | 13 | XML_Parser _x; |
14 | 14 | ||
15 | expat_t() : _x(0) { } | 15 | expat_t() : _x(0) { } |
16 | expat_t(XML_Parser x) : _x(x) { } | 16 | expat_t(XML_Parser x) : _x(x) { } |
17 | virtual ~expat_t() throw(); | 17 | virtual ~expat_t() throw(); |
18 | 18 | ||
19 | expat_t& operator=(XML_Parser x); | 19 | expat_t& operator=(XML_Parser x); |
20 | 20 | ||
21 | operator const XML_Parser(void) const { return _x; } | 21 | operator const XML_Parser(void) const { return _x; } |
22 | operator XML_Parser(void) { return _x; } | 22 | operator XML_Parser(void) { return _x; } |
23 | 23 | ||
24 | inline bool parse(const char *s,int len,bool final=false) { | 24 | inline bool parse(const char *s,int len,bool final=false) { |
25 | assert(_x); | 25 | assert(_x); |
26 | return XML_Parse(_x,s,len,final); | 26 | return XML_Parse(_x,s,len,final); |
27 | } | 27 | } |
28 | 28 | ||
29 | virtual int unknown_encoding(const XML_Char * /* n */,XML_Encoding * /* i */) { return XML_STATUS_ERROR; } | ||
30 | void set_unknown_encoding_handler(); | ||
31 | |||
29 | virtual void start_element(const XML_Char * /* n */,const XML_Char ** /* a */) { } | 32 | virtual void start_element(const XML_Char * /* n */,const XML_Char ** /* a */) { } |
30 | virtual void end_element(const XML_Char * /* n */) { } | 33 | virtual void end_element(const XML_Char * /* n */) { } |
31 | void set_element_handler(); | 34 | void set_element_handler(); |
32 | 35 | ||
33 | virtual void character_data(const XML_Char * /* s */,int /* l */) { } | 36 | virtual void character_data(const XML_Char * /* s */,int /* l */) { } |
34 | void set_character_data_handler(); | 37 | void set_character_data_handler(); |
35 | 38 | ||
36 | virtual void processing_instruction(const XML_Char * /* t */,const XML_Char * /* d */) { } | 39 | virtual void processing_instruction(const XML_Char * /* t */,const XML_Char * /* d */) { } |
37 | void set_processing_instruction_handler(); | 40 | void set_processing_instruction_handler(); |
38 | 41 | ||
39 | virtual void comment(const XML_Char * /* d */) { } | 42 | virtual void comment(const XML_Char * /* d */) { } |
40 | void set_comment_handler(); | 43 | void set_comment_handler(); |
41 | 44 | ||
42 | virtual void start_cdata_section() { } | 45 | virtual void start_cdata_section() { } |
43 | virtual void end_cdata_section() { } | 46 | virtual void end_cdata_section() { } |
44 | void set_cdata_section_handler(); | 47 | void set_cdata_section_handler(); |
45 | 48 | ||
46 | virtual void default_handler(const XML_Char * /* s */,int /* l */) { } | 49 | virtual void default_handler(const XML_Char * /* s */,int /* l */) { } |
47 | void set_default_handler(); | 50 | void set_default_handler(); |
48 | void set_default_handler_expand(); | 51 | void set_default_handler_expand(); |
49 | 52 | ||
50 | virtual void start_namespace_decl(const XML_Char * /* p */,const XML_Char * /* u */) { } | 53 | virtual void start_namespace_decl(const XML_Char * /* p */,const XML_Char * /* u */) { } |
51 | virtual void end_namespace_decl(const XML_Char * /* p */) { } | 54 | virtual void end_namespace_decl(const XML_Char * /* p */) { } |
52 | void set_namespace_decl_handler(); | 55 | void set_namespace_decl_handler(); |
53 | 56 | ||
54 | inline enum XML_Error get_error_code() { | 57 | inline enum XML_Error get_error_code() { |
55 | assert(_x); return XML_GetErrorCode(_x); } | 58 | assert(_x); return XML_GetErrorCode(_x); } |
56 | static inline const XML_LChar *error_string(XML_Error c) { | 59 | static inline const XML_LChar *error_string(XML_Error c) { |
57 | return XML_ErrorString(c); } | 60 | return XML_ErrorString(c); } |
58 | 61 | ||
59 | inline long get_current_byte_index() { | 62 | inline long get_current_byte_index() { |
60 | assert(_x); return XML_GetCurrentByteIndex(_x); } | 63 | assert(_x); return XML_GetCurrentByteIndex(_x); } |
61 | inline int get_current_line_number() { | 64 | inline int get_current_line_number() { |
62 | assert(_x); return XML_GetCurrentLineNumber(_x); } | 65 | assert(_x); return XML_GetCurrentLineNumber(_x); } |
63 | inline int get_current_column_number() { | 66 | inline int get_current_column_number() { |
64 | assert(_x); return XML_GetCurrentColumnNumber(_x); } | 67 | assert(_x); return XML_GetCurrentColumnNumber(_x); } |
65 | 68 | ||
66 | inline void set_user_data() { | 69 | inline void set_user_data() { |
67 | assert(_x); XML_SetUserData(_x,this); } | 70 | assert(_x); XML_SetUserData(_x,this); } |
68 | 71 | ||
69 | inline bool set_base(const XML_Char *b) { | 72 | inline bool set_base(const XML_Char *b) { |
70 | assert(_x); return XML_SetBase(_x,b); } | 73 | assert(_x); return XML_SetBase(_x,b); } |
71 | inline const XML_Char *get_base() { | 74 | inline const XML_Char *get_base() { |
72 | assert(_x); return XML_GetBase(_x); } | 75 | assert(_x); return XML_GetBase(_x); } |
73 | 76 | ||
74 | inline int get_specified_attribute_count() { | 77 | inline int get_specified_attribute_count() { |
75 | assert(_x); return XML_GetSpecifiedAttributeCount(_x); } | 78 | assert(_x); return XML_GetSpecifiedAttributeCount(_x); } |
76 | 79 | ||
77 | inline bool set_param_entity_parsing(enum XML_ParamEntityParsing c) { | 80 | inline bool set_param_entity_parsing(enum XML_ParamEntityParsing c) { |
78 | assert(_x); return XML_SetParamEntityParsing(_x,c); } | 81 | assert(_x); return XML_SetParamEntityParsing(_x,c); } |
79 | 82 | ||
80 | inline static XML_Parser parser_create(const XML_Char *e=0) { | 83 | inline static XML_Parser parser_create(const XML_Char *e=0) { |
81 | return XML_ParserCreate(e); } | 84 | return XML_ParserCreate(e); } |
82 | inline static XML_Parser parser_create_ns(const XML_Char *e=0,XML_Char s='\t') { | 85 | inline static XML_Parser parser_create_ns(const XML_Char *e=0,XML_Char s='\t') { |
83 | return XML_ParserCreateNS(e,s); } | 86 | return XML_ParserCreateNS(e,s); } |
84 | 87 | ||
85 | }; | 88 | }; |
86 | 89 | ||
87 | } | 90 | } |
88 | 91 | ||
89 | } | 92 | } |
90 | 93 | ||
91 | #endif /* __OPKELE_EXPAT_H */ | 94 | #endif /* __OPKELE_EXPAT_H */ |
diff --git a/lib/basic_rp.cc b/lib/basic_rp.cc index 3cad71c..9c7113b 100644 --- a/lib/basic_rp.cc +++ b/lib/basic_rp.cc | |||
@@ -29,298 +29,299 @@ namespace opkele { | |||
29 | throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related assertion"); | 29 | throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related assertion"); |
30 | assert(!claimed_id.empty()); | 30 | assert(!claimed_id.empty()); |
31 | return identity; | 31 | return identity; |
32 | } | 32 | } |
33 | 33 | ||
34 | static void dh_get_secret( | 34 | static void dh_get_secret( |
35 | secret_t& secret, const basic_openid_message& om, | 35 | secret_t& secret, const basic_openid_message& om, |
36 | const char *exp_assoc, const char *exp_sess, | 36 | const char *exp_assoc, const char *exp_sess, |
37 | util::dh_t& dh, | 37 | util::dh_t& dh, |
38 | size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*), | 38 | size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*), |
39 | size_t exp_s_len) try { | 39 | size_t exp_s_len) try { |
40 | if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess) | 40 | if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess) |
41 | throw bad_input(OPKELE_CP_ "Unexpected associate response"); | 41 | throw bad_input(OPKELE_CP_ "Unexpected associate response"); |
42 | util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public")); | 42 | util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public")); |
43 | vector<unsigned char> ck(DH_size(dh)+1); | 43 | vector<unsigned char> ck(DH_size(dh)+1); |
44 | unsigned char *ckptr = &(ck.front())+1; | 44 | unsigned char *ckptr = &(ck.front())+1; |
45 | int cklen = DH_compute_key(ckptr,s_pub,dh); | 45 | int cklen = DH_compute_key(ckptr,s_pub,dh); |
46 | if(cklen<0) | 46 | if(cklen<0) |
47 | throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); | 47 | throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); |
48 | if(cklen && (*ckptr)&0x80) { | 48 | if(cklen && (*ckptr)&0x80) { |
49 | (*(--ckptr))=0; ++cklen; } | 49 | (*(--ckptr))=0; ++cklen; } |
50 | assert(d_len<=SHA256_DIGEST_LENGTH); | 50 | assert(d_len<=SHA256_DIGEST_LENGTH); |
51 | unsigned char key_digest[SHA256_DIGEST_LENGTH]; | 51 | unsigned char key_digest[SHA256_DIGEST_LENGTH]; |
52 | secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key")); | 52 | secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key")); |
53 | if(secret.size()!=exp_s_len) | 53 | if(secret.size()!=exp_s_len) |
54 | throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type"); | 54 | throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type"); |
55 | }catch(opkele::failed_lookup& ofl) { | 55 | }catch(opkele::failed_lookup& ofl) { |
56 | throw bad_input(OPKELE_CP_ "Incoherent response from OP"); | 56 | throw bad_input(OPKELE_CP_ "Incoherent response from OP"); |
57 | } OPKELE_RETHROW | 57 | } OPKELE_RETHROW |
58 | 58 | ||
59 | static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) { | 59 | static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) { |
60 | util::curl_pick_t curl = util::curl_pick_t::easy_init(); | 60 | util::curl_pick_t curl = util::curl_pick_t::easy_init(); |
61 | if(!curl) | 61 | if(!curl) |
62 | throw exception_curl(OPKELE_CP_ "failed to initialize curl"); | 62 | throw exception_curl(OPKELE_CP_ "failed to initialize curl"); |
63 | string request = inm.query_string(); | 63 | string request = inm.query_string(); |
64 | CURLcode r; | 64 | CURLcode r; |
65 | (r=curl.misc_sets()) | 65 | (r=curl.misc_sets()) |
66 | || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str())) | 66 | || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str())) |
67 | || (r=curl.easy_setopt(CURLOPT_POST,1)) | 67 | || (r=curl.easy_setopt(CURLOPT_POST,1)) |
68 | || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) | 68 | || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) |
69 | || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) | 69 | || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) |
70 | || (r=curl.set_write()); | 70 | || (r=curl.set_write()); |
71 | if(r) | 71 | if(r) |
72 | throw exception_curl(OPKELE_CP_ "failed to set curly options",r); | 72 | throw exception_curl(OPKELE_CP_ "failed to set curly options",r); |
73 | if( (r=curl.easy_perform()) ) | 73 | if( (r=curl.easy_perform()) ) |
74 | throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); | 74 | throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); |
75 | oum.from_keyvalues(curl.response); | 75 | oum.from_keyvalues(curl.response); |
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | assoc_t basic_RP::associate(const string& OP) { | 79 | assoc_t basic_RP::associate(const string& OP) { |
80 | util::dh_t dh = DH_new(); | 80 | util::dh_t dh = DH_new(); |
81 | if(!dh) | 81 | if(!dh) |
82 | throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); | 82 | throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); |
83 | dh->p = util::dec_to_bignum(data::_default_p); | 83 | dh->p = util::dec_to_bignum(data::_default_p); |
84 | dh->g = util::dec_to_bignum(data::_default_g); | 84 | dh->g = util::dec_to_bignum(data::_default_g); |
85 | if(!DH_generate_key(dh)) | 85 | if(!DH_generate_key(dh)) |
86 | throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); | 86 | throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); |
87 | openid_message_t req; | 87 | openid_message_t req; |
88 | req.set_field("ns",OIURI_OPENID20); | 88 | req.set_field("ns",OIURI_OPENID20); |
89 | req.set_field("mode","associate"); | 89 | req.set_field("mode","associate"); |
90 | req.set_field("dh_modulus",util::bignum_to_base64(dh->p)); | 90 | req.set_field("dh_modulus",util::bignum_to_base64(dh->p)); |
91 | req.set_field("dh_gen",util::bignum_to_base64(dh->g)); | 91 | req.set_field("dh_gen",util::bignum_to_base64(dh->g)); |
92 | req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key)); | 92 | req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key)); |
93 | openid_message_t res; | 93 | openid_message_t res; |
94 | req.set_field("assoc_type","HMAC-SHA256"); | 94 | req.set_field("assoc_type","HMAC-SHA256"); |
95 | req.set_field("session_type","DH-SHA256"); | 95 | req.set_field("session_type","DH-SHA256"); |
96 | secret_t secret; | 96 | secret_t secret; |
97 | int expires_in; | 97 | int expires_in; |
98 | try { | 98 | try { |
99 | direct_request(res,req,OP); | 99 | direct_request(res,req,OP); |
100 | dh_get_secret( secret, res, | 100 | dh_get_secret( secret, res, |
101 | "HMAC-SHA256", "DH-SHA256", | 101 | "HMAC-SHA256", "DH-SHA256", |
102 | dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH ); | 102 | dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH ); |
103 | expires_in = util::string_to_long(res.get_field("expires_in")); | 103 | expires_in = util::string_to_long(res.get_field("expires_in")); |
104 | }catch(exception&) { | 104 | }catch(exception&) { |
105 | try { | 105 | try { |
106 | req.set_field("assoc_type","HMAC-SHA1"); | 106 | req.set_field("assoc_type","HMAC-SHA1"); |
107 | req.set_field("session_type","DH-SHA1"); | 107 | req.set_field("session_type","DH-SHA1"); |
108 | direct_request(res,req,OP); | 108 | direct_request(res,req,OP); |
109 | dh_get_secret( secret, res, | 109 | dh_get_secret( secret, res, |
110 | "HMAC-SHA1", "DH-SHA1", | 110 | "HMAC-SHA1", "DH-SHA1", |
111 | dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH ); | 111 | dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH ); |
112 | expires_in = util::string_to_long(res.get_field("expires_in")); | 112 | expires_in = util::string_to_long(res.get_field("expires_in")); |
113 | }catch(bad_input&) { | 113 | }catch(bad_input&) { |
114 | throw dumb_RP(OPKELE_CP_ "OP failed to supply an association"); | 114 | throw dumb_RP(OPKELE_CP_ "OP failed to supply an association"); |
115 | } | 115 | } |
116 | } | 116 | } |
117 | return store_assoc( | 117 | return store_assoc( |
118 | OP, res.get_field("assoc_handle"), | 118 | OP, res.get_field("assoc_handle"), |
119 | res.get_field("assoc_type"), secret, | 119 | res.get_field("assoc_type"), secret, |
120 | expires_in ); | 120 | expires_in ); |
121 | } | 121 | } |
122 | 122 | ||
123 | basic_openid_message& basic_RP::checkid_( | 123 | basic_openid_message& basic_RP::checkid_( |
124 | basic_openid_message& rv, | 124 | basic_openid_message& rv, |
125 | mode_t mode, | 125 | mode_t mode, |
126 | const string& return_to,const string& realm, | 126 | const string& return_to,const string& realm, |
127 | extension_t *ext) { | 127 | extension_t *ext) { |
128 | rv.reset_fields(); | 128 | rv.reset_fields(); |
129 | rv.set_field("ns",OIURI_OPENID20); | 129 | rv.set_field("ns",OIURI_OPENID20); |
130 | if(mode==mode_checkid_immediate) | 130 | if(mode==mode_checkid_immediate) |
131 | rv.set_field("mode","checkid_immediate"); | 131 | rv.set_field("mode","checkid_immediate"); |
132 | else if(mode==mode_checkid_setup) | 132 | else if(mode==mode_checkid_setup) |
133 | rv.set_field("mode","checkid_setup"); | 133 | rv.set_field("mode","checkid_setup"); |
134 | else | 134 | else |
135 | throw bad_input(OPKELE_CP_ "unknown checkid_* mode"); | 135 | throw bad_input(OPKELE_CP_ "unknown checkid_* mode"); |
136 | if(realm.empty() && return_to.empty()) | 136 | if(realm.empty() && return_to.empty()) |
137 | throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty"); | 137 | throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty"); |
138 | if(!realm.empty()) { | 138 | if(!realm.empty()) { |
139 | rv.set_field("realm",realm); | 139 | rv.set_field("realm",realm); |
140 | rv.set_field("trust_root",realm); | 140 | rv.set_field("trust_root",realm); |
141 | } | 141 | } |
142 | if(!return_to.empty()) | 142 | if(!return_to.empty()) |
143 | rv.set_field("return_to",return_to); | 143 | rv.set_field("return_to",return_to); |
144 | const openid_endpoint_t& ep = get_endpoint(); | 144 | const openid_endpoint_t& ep = get_endpoint(); |
145 | rv.set_field("claimed_id",ep.claimed_id); | 145 | rv.set_field("claimed_id",ep.claimed_id); |
146 | rv.set_field("identity",ep.local_id); | 146 | rv.set_field("identity",ep.local_id); |
147 | try { | 147 | try { |
148 | rv.set_field("assoc_handle",find_assoc(ep.uri)->handle()); | 148 | rv.set_field("assoc_handle",find_assoc(ep.uri)->handle()); |
149 | }catch(dumb_RP& drp) { | 149 | }catch(dumb_RP& drp) { |
150 | }catch(failed_lookup& fl) { | 150 | }catch(failed_lookup& fl) { |
151 | try { | 151 | try { |
152 | rv.set_field("assoc_handle",associate(ep.uri)->handle()); | 152 | rv.set_field("assoc_handle",associate(ep.uri)->handle()); |
153 | }catch(dumb_RP& drp) { } | 153 | }catch(dumb_RP& drp) { } |
154 | } OPKELE_RETHROW | 154 | } OPKELE_RETHROW |
155 | if(ext) ext->rp_checkid_hook(rv); | 155 | if(ext) ext->rp_checkid_hook(rv); |
156 | return rv; | 156 | return rv; |
157 | } | 157 | } |
158 | 158 | ||
159 | class signed_part_message_proxy : public basic_openid_message { | 159 | class signed_part_message_proxy : public basic_openid_message { |
160 | public: | 160 | public: |
161 | const basic_openid_message& x; | 161 | const basic_openid_message& x; |
162 | set<string> signeds; | 162 | set<string> signeds; |
163 | 163 | ||
164 | signed_part_message_proxy(const basic_openid_message& xx) : x(xx) { | 164 | signed_part_message_proxy(const basic_openid_message& xx) : x(xx) { |
165 | const string& slist = x.get_field("signed"); | 165 | const string& slist = x.get_field("signed"); |
166 | string::size_type p = 0; | 166 | string::size_type p = 0; |
167 | while(true) { | 167 | while(true) { |
168 | string::size_type co = slist.find(',',p); | 168 | string::size_type co = slist.find(',',p); |
169 | string f = (co==string::npos) | 169 | string f = (co==string::npos) |
170 | ?slist.substr(p):slist.substr(p,co-p); | 170 | ?slist.substr(p):slist.substr(p,co-p); |
171 | signeds.insert(f); | 171 | signeds.insert(f); |
172 | if(co==string::npos) break; | 172 | if(co==string::npos) break; |
173 | p = co+1; | 173 | p = co+1; |
174 | } | 174 | } |
175 | } | 175 | } |
176 | 176 | ||
177 | bool has_field(const string& n) const { | 177 | bool has_field(const string& n) const { |
178 | return signeds.find(n)!=signeds.end() && x.has_field(n); } | 178 | return signeds.find(n)!=signeds.end() && x.has_field(n); } |
179 | const string& get_field(const string& n) const { | 179 | const string& get_field(const string& n) const { |
180 | if(signeds.find(n)==signeds.end()) | 180 | if(signeds.find(n)==signeds.end()) |
181 | throw failed_lookup(OPKELE_CP_ "The field isn't known to be signed"); | 181 | throw failed_lookup(OPKELE_CP_ "The field isn't known to be signed"); |
182 | return x.get_field(n); } | 182 | return x.get_field(n); } |
183 | 183 | ||
184 | fields_iterator fields_begin() const { | 184 | fields_iterator fields_begin() const { |
185 | return signeds.begin(); } | 185 | return signeds.begin(); } |
186 | fields_iterator fields_end() const { | 186 | fields_iterator fields_end() const { |
187 | return signeds.end(); } | 187 | return signeds.end(); } |
188 | }; | 188 | }; |
189 | 189 | ||
190 | static void parse_query(const string& u,string::size_type q, | 190 | static void parse_query(const string& u,string::size_type q, |
191 | map<string,string>& p) { | 191 | map<string,string>& p) { |
192 | if(q==string::npos) | 192 | if(q==string::npos) |
193 | return; | 193 | return; |
194 | assert(u[q]=='?'); | 194 | assert(u[q]=='?'); |
195 | ++q; | 195 | ++q; |
196 | string::size_type l = u.size(); | 196 | string::size_type l = u.size(); |
197 | while(q<l) { | 197 | while(q<l) { |
198 | string::size_type eq = u.find('=',q); | 198 | string::size_type eq = u.find('=',q); |
199 | string::size_type am = u.find('&',q); | 199 | string::size_type am = u.find('&',q); |
200 | if(am==string::npos) { | 200 | if(am==string::npos) { |
201 | if(eq==string::npos) { | 201 | if(eq==string::npos) { |
202 | p[""] = u.substr(q); | 202 | p[""] = u.substr(q); |
203 | }else{ | 203 | }else{ |
204 | p[u.substr(q,eq-q)] = u.substr(eq+1); | 204 | p[u.substr(q,eq-q)] = u.substr(eq+1); |
205 | } | 205 | } |
206 | break; | 206 | break; |
207 | }else{ | 207 | }else{ |
208 | if(eq==string::npos || eq>am) { | 208 | if(eq==string::npos || eq>am) { |
209 | p[""] = u.substr(q,eq-q); | 209 | p[""] = u.substr(q,eq-q); |
210 | }else{ | 210 | }else{ |
211 | p[u.substr(q,eq-q)] = u.substr(eq+1,am-eq-1); | 211 | p[u.substr(q,eq-q)] = u.substr(eq+1,am-eq-1); |
212 | } | 212 | } |
213 | q = ++am; | 213 | q = ++am; |
214 | } | 214 | } |
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) { | 218 | void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) { |
219 | reset_vars(); | 219 | reset_vars(); |
220 | bool o2 = om.has_field("ns") | 220 | bool o2 = om.has_field("ns") |
221 | && om.get_field("ns")==OIURI_OPENID20; | 221 | && om.get_field("ns")==OIURI_OPENID20 |
222 | && om.has_field("op_endpoint") && !om.get_field("op_endpoint").empty(); | ||
222 | if( (!o2) && om.has_field("user_setup_url")) | 223 | if( (!o2) && om.has_field("user_setup_url")) |
223 | throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided", | 224 | throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided", |
224 | om.get_field("user_setup_url")); | 225 | om.get_field("user_setup_url")); |
225 | string m = om.get_field("mode"); | 226 | string m = om.get_field("mode"); |
226 | if(o2 && m=="setup_needed") | 227 | if(o2 && m=="setup_needed") |
227 | throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided"); | 228 | throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided"); |
228 | if(m=="cancel") | 229 | if(m=="cancel") |
229 | throw id_res_cancel(OPKELE_CP_ "authentication cancelled"); | 230 | throw id_res_cancel(OPKELE_CP_ "authentication cancelled"); |
230 | bool go_dumb=false; | 231 | bool go_dumb=false; |
231 | try { | 232 | try { |
232 | string OP = o2 | 233 | string OP = o2 |
233 | ?om.get_field("op_endpoint") | 234 | ?om.get_field("op_endpoint") |
234 | :get_endpoint().uri; | 235 | :get_endpoint().uri; |
235 | assoc_t assoc = retrieve_assoc( | 236 | assoc_t assoc = retrieve_assoc( |
236 | OP,om.get_field("assoc_handle")); | 237 | OP,om.get_field("assoc_handle")); |
237 | if(om.get_field("sig")!=util::base64_signature(assoc,om)) | 238 | if(om.get_field("sig")!=util::base64_signature(assoc,om)) |
238 | throw id_res_mismatch(OPKELE_CP_ "signature mismatch"); | 239 | throw id_res_mismatch(OPKELE_CP_ "signature mismatch"); |
239 | }catch(dumb_RP& drp) { | 240 | }catch(dumb_RP& drp) { |
240 | go_dumb=true; | 241 | go_dumb=true; |
241 | }catch(failed_lookup& e) { | 242 | }catch(failed_lookup& e) { |
242 | go_dumb=true; | 243 | go_dumb=true; |
243 | } OPKELE_RETHROW | 244 | } OPKELE_RETHROW |
244 | if(go_dumb) { | 245 | if(go_dumb) { |
245 | try { | 246 | try { |
246 | string OP = o2 | 247 | string OP = o2 |
247 | ?om.get_field("op_endpoint") | 248 | ?om.get_field("op_endpoint") |
248 | :get_endpoint().uri; | 249 | :get_endpoint().uri; |
249 | check_authentication(OP,om); | 250 | check_authentication(OP,om); |
250 | }catch(failed_check_authentication& fca) { | 251 | }catch(failed_check_authentication& fca) { |
251 | throw id_res_failed(OPKELE_CP_ "failed to check_authentication()"); | 252 | throw id_res_failed(OPKELE_CP_ "failed to check_authentication()"); |
252 | } OPKELE_RETHROW | 253 | } OPKELE_RETHROW |
253 | } | 254 | } |
254 | signed_part_message_proxy signeds(om); | 255 | signed_part_message_proxy signeds(om); |
255 | if(o2) { | 256 | if(o2) { |
256 | check_nonce(om.get_field("op_endpoint"), | 257 | check_nonce(om.get_field("op_endpoint"), |
257 | om.get_field("response_nonce")); | 258 | om.get_field("response_nonce")); |
258 | static const char *mustsign[] = { | 259 | static const char *mustsign[] = { |
259 | "op_endpoint", "return_to", "response_nonce", "assoc_handle", | 260 | "op_endpoint", "return_to", "response_nonce", "assoc_handle", |
260 | "claimed_id", "identity" }; | 261 | "claimed_id", "identity" }; |
261 | for(size_t ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) { | 262 | for(size_t ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) { |
262 | if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms])) | 263 | if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms])) |
263 | throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs"); | 264 | throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs"); |
264 | } | 265 | } |
265 | if( ( | 266 | if( ( |
266 | (om.has_field("claimed_id")?1:0) | 267 | (om.has_field("claimed_id")?1:0) |
267 | ^ | 268 | ^ |
268 | (om.has_field("identity")?1:0) | 269 | (om.has_field("identity")?1:0) |
269 | )&1 ) | 270 | )&1 ) |
270 | throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent"); | 271 | throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent"); |
271 | 272 | ||
272 | string turl = util::rfc_3986_normalize_uri(get_this_url()); | 273 | string turl = util::rfc_3986_normalize_uri(get_this_url()); |
273 | util::strip_uri_fragment_part(turl); | 274 | util::strip_uri_fragment_part(turl); |
274 | string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to")); | 275 | string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to")); |
275 | util::strip_uri_fragment_part(rurl); | 276 | util::strip_uri_fragment_part(rurl); |
276 | string::size_type | 277 | string::size_type |
277 | tq = turl.find('?'), rq = rurl.find('?'); | 278 | tq = turl.find('?'), rq = rurl.find('?'); |
278 | if( | 279 | if( |
279 | ((tq==string::npos)?turl:turl.substr(0,tq)) | 280 | ((tq==string::npos)?turl:turl.substr(0,tq)) |
280 | != | 281 | != |
281 | ((rq==string::npos)?rurl:rurl.substr(0,rq)) | 282 | ((rq==string::npos)?rurl:rurl.substr(0,rq)) |
282 | ) | 283 | ) |
283 | throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url"); | 284 | throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url"); |
284 | map<string,string> tp; parse_query(turl,tq,tp); | 285 | map<string,string> tp; parse_query(turl,tq,tp); |
285 | map<string,string> rp; parse_query(rurl,rq,rp); | 286 | map<string,string> rp; parse_query(rurl,rq,rp); |
286 | for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) { | 287 | for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) { |
287 | map<string,string>::const_iterator tpi = tp.find(rpi->first); | 288 | map<string,string>::const_iterator tpi = tp.find(rpi->first); |
288 | if(tpi==tp.end()) | 289 | if(tpi==tp.end()) |
289 | throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request"); | 290 | throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request"); |
290 | if(tpi->second!=rpi->second) | 291 | if(tpi->second!=rpi->second) |
291 | throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request"); | 292 | throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request"); |
292 | } | 293 | } |
293 | 294 | ||
294 | if(om.has_field("claimed_id")) { | 295 | if(om.has_field("claimed_id")) { |
295 | claimed_id = om.get_field("claimed_id"); | 296 | claimed_id = om.get_field("claimed_id"); |
296 | identity = om.get_field("identity"); | 297 | identity = om.get_field("identity"); |
297 | verify_OP( | 298 | verify_OP( |
298 | om.get_field("op_endpoint"), | 299 | om.get_field("op_endpoint"), |
299 | claimed_id, identity ); | 300 | claimed_id, identity ); |
300 | } | 301 | } |
301 | 302 | ||
302 | }else{ | 303 | }else{ |
303 | claimed_id = get_endpoint().claimed_id; | 304 | claimed_id = get_endpoint().claimed_id; |
304 | /* TODO: check if this is the identity we asked for */ | 305 | /* TODO: check if this is the identity we asked for */ |
305 | identity = om.get_field("identity"); | 306 | identity = om.get_field("identity"); |
306 | } | 307 | } |
307 | if(ext) ext->rp_id_res_hook(om,signeds); | 308 | if(ext) ext->rp_id_res_hook(om,signeds); |
308 | } | 309 | } |
309 | 310 | ||
310 | void basic_RP::check_authentication(const string& OP, | 311 | void basic_RP::check_authentication(const string& OP, |
311 | const basic_openid_message& om){ | 312 | const basic_openid_message& om){ |
312 | openid_message_t res; | 313 | openid_message_t res; |
313 | static const string checkauthmode = "check_authentication"; | 314 | static const string checkauthmode = "check_authentication"; |
314 | direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP); | 315 | direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP); |
315 | if(res.has_field("is_valid")) { | 316 | if(res.has_field("is_valid")) { |
316 | if(res.get_field("is_valid")=="true") { | 317 | if(res.get_field("is_valid")=="true") { |
317 | if(res.has_field("invalidate_handle")) | 318 | if(res.has_field("invalidate_handle")) |
318 | invalidate_assoc(OP,res.get_field("invalidate_handle")); | 319 | invalidate_assoc(OP,res.get_field("invalidate_handle")); |
319 | return; | 320 | return; |
320 | } | 321 | } |
321 | } | 322 | } |
322 | throw failed_check_authentication( | 323 | throw failed_check_authentication( |
323 | OPKELE_CP_ "failed to verify response"); | 324 | OPKELE_CP_ "failed to verify response"); |
324 | } | 325 | } |
325 | 326 | ||
326 | } | 327 | } |
diff --git a/lib/discovery.cc b/lib/discovery.cc index bd1f917..b4ed3b6 100644 --- a/lib/discovery.cc +++ b/lib/discovery.cc | |||
@@ -94,494 +94,517 @@ namespace opkele { | |||
94 | string save_html; | 94 | string save_html; |
95 | 95 | ||
96 | XRD_t *xrd; | 96 | XRD_t *xrd; |
97 | service_t *xrd_service; | 97 | service_t *xrd_service; |
98 | string* cdata; | 98 | string* cdata; |
99 | 99 | ||
100 | idigger_t() | 100 | idigger_t() |
101 | : util::curl_t(easy_init()), | 101 | : util::curl_t(easy_init()), |
102 | util::expat_t(0), | 102 | util::expat_t(0), |
103 | xri_proxy(XRI_PROXY_URL) { | 103 | xri_proxy(XRI_PROXY_URL) { |
104 | CURLcode r; | 104 | CURLcode r; |
105 | (r=misc_sets()) | 105 | (r=misc_sets()) |
106 | || (r=set_write()) | 106 | || (r=set_write()) |
107 | || (r=set_header()) | 107 | || (r=set_header()) |
108 | ; | 108 | ; |
109 | if(r) | 109 | if(r) |
110 | throw exception_curl(OPKELE_CP_ "failed to set curly options",r); | 110 | throw exception_curl(OPKELE_CP_ "failed to set curly options",r); |
111 | } | 111 | } |
112 | ~idigger_t() throw() { } | 112 | ~idigger_t() throw() { } |
113 | 113 | ||
114 | void yadiscover(endpoint_discovery_iterator oi,const string& yurl,const char **types,bool redirs) { | 114 | void yadiscover(endpoint_discovery_iterator oi,const string& yurl,const char **types,bool redirs) { |
115 | idiscovery_t idis; | 115 | idiscovery_t idis; |
116 | idis.xri_identity = false; | 116 | idis.xri_identity = false; |
117 | discover_at(idis,yurl,xmode_html|xmode_xrd|(redirs?0:xmode_noredirs)); | 117 | discover_at(idis,yurl,xmode_html|xmode_xrd|(redirs?0:xmode_noredirs)); |
118 | if(!xrds_location.empty()) { | 118 | if(!xrds_location.empty()) { |
119 | idis.clear(); | 119 | idis.clear(); |
120 | discover_at(idis,xrds_location,xmode_xrd); | 120 | discover_at(idis,xrds_location,xmode_xrd); |
121 | } | 121 | } |
122 | idis.normalized_id = idis.canonicalized_id = yurl; | 122 | idis.normalized_id = idis.canonicalized_id = yurl; |
123 | service_type_t st; | 123 | service_type_t st; |
124 | for(st.uri=*types;*types;st.uri=*(++types)) | 124 | for(st.uri=*types;*types;st.uri=*(++types)) |
125 | queue_endpoints(oi,idis,&st); | 125 | queue_endpoints(oi,idis,&st); |
126 | } | 126 | } |
127 | 127 | ||
128 | string discover(endpoint_discovery_iterator& oi,const string& identity) { | 128 | string discover(endpoint_discovery_iterator& oi,const string& identity) { |
129 | string rv; | 129 | string rv; |
130 | idiscovery_t idis; | 130 | idiscovery_t idis; |
131 | string::size_type fsc = identity.find_first_not_of(data::_whitespace_chars); | 131 | string::size_type fsc = identity.find_first_not_of(data::_whitespace_chars); |
132 | if(fsc==string::npos) | 132 | if(fsc==string::npos) |
133 | throw bad_input(OPKELE_CP_ "whitespace-only identity"); | 133 | throw bad_input(OPKELE_CP_ "whitespace-only identity"); |
134 | string::size_type lsc = identity.find_last_not_of(data::_whitespace_chars); | 134 | string::size_type lsc = identity.find_last_not_of(data::_whitespace_chars); |
135 | assert(lsc!=string::npos); | 135 | assert(lsc!=string::npos); |
136 | if(!strncasecmp(identity.c_str()+fsc,"xri://",sizeof("xri://")-1)) | 136 | if(!strncasecmp(identity.c_str()+fsc,"xri://",sizeof("xri://")-1)) |
137 | fsc += sizeof("xri://")-1; | 137 | fsc += sizeof("xri://")-1; |
138 | if((fsc+1)>=lsc) | 138 | if((fsc+1)>=lsc) |
139 | throw bad_input(OPKELE_CP_ "not a character of importance in identity"); | 139 | throw bad_input(OPKELE_CP_ "not a character of importance in identity"); |
140 | string id(identity,fsc,lsc-fsc+1); | 140 | string id(identity,fsc,lsc-fsc+1); |
141 | idis.clear(); | 141 | idis.clear(); |
142 | if(strchr(data::_iname_leaders,id[0])) { | 142 | if(strchr(data::_iname_leaders,id[0])) { |
143 | /* TODO: further normalize xri identity? Like folding case | 143 | /* TODO: further normalize xri identity? Like folding case |
144 | * or whatever... */ | 144 | * or whatever... */ |
145 | rv = id; | 145 | rv = id; |
146 | set<string> cids; | 146 | set<string> cids; |
147 | for(const struct service_type_t *st=op_service_types; | 147 | for(const struct service_type_t *st=op_service_types; |
148 | st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) { | 148 | st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) { |
149 | idis.clear(); | 149 | idis.clear(); |
150 | discover_at( idis, | 150 | discover_at( idis, |
151 | xri_proxy + util::url_encode(id)+ | 151 | xri_proxy + util::url_encode(id)+ |
152 | "?_xrd_t="+util::url_encode(st->uri)+ | 152 | "?_xrd_t="+util::url_encode(st->uri)+ |
153 | "&_xrd_r=application/xrd%2Bxml" | 153 | "&_xrd_r=application/xrd%2Bxml" |
154 | ";sep=true;refs=true", | 154 | ";sep=true;refs=true", |
155 | xmode_xrd ); | 155 | xmode_xrd ); |
156 | if(status_code==241) continue; | 156 | if(status_code==241) continue; |
157 | if(status_code!=100) | 157 | if(status_code!=100) |
158 | throw failed_xri_resolution(OPKELE_CP_ | 158 | throw failed_xri_resolution(OPKELE_CP_ |
159 | "XRI resolution failed with '"+status_string+"' message" | 159 | "XRI resolution failed with '"+status_string+"' message" |
160 | ", while looking for SEP with type '"+st->uri+"'", status_code); | 160 | ", while looking for SEP with type '"+st->uri+"'", status_code); |
161 | if(idis.xrd.canonical_ids.empty()) | 161 | if(idis.xrd.canonical_ids.empty()) |
162 | throw opkele::failed_discovery(OPKELE_CP_ "No CanonicalID for XRI identity found"); | 162 | throw opkele::failed_discovery(OPKELE_CP_ "No CanonicalID for XRI identity found"); |
163 | string cid = idis.xrd.canonical_ids.begin()->second; | 163 | string cid = idis.xrd.canonical_ids.begin()->second; |
164 | if(cids.find(cid)==cids.end()) { | 164 | if(cids.find(cid)==cids.end()) { |
165 | cids.insert(cid); | 165 | cids.insert(cid); |
166 | idis.clear(); | 166 | idis.clear(); |
167 | discover_at( idis, | 167 | discover_at( idis, |
168 | xri_proxy + util::url_encode(id)+ | 168 | xri_proxy + util::url_encode(id)+ |
169 | "?_xrd_t="+util::url_encode(st->uri)+ | 169 | "?_xrd_t="+util::url_encode(st->uri)+ |
170 | "&_xrd_r=application/xrd%2Bxml" | 170 | "&_xrd_r=application/xrd%2Bxml" |
171 | ";sep=true;refs=true", | 171 | ";sep=true;refs=true", |
172 | xmode_xrd ); | 172 | xmode_xrd ); |
173 | if(status_code==241) continue; | 173 | if(status_code==241) continue; |
174 | if(status_code!=100) | 174 | if(status_code!=100) |
175 | throw failed_xri_resolution(OPKELE_CP_ | 175 | throw failed_xri_resolution(OPKELE_CP_ |
176 | "XRI resolution failed with '"+status_string+"' message" | 176 | "XRI resolution failed with '"+status_string+"' message" |
177 | ", while looking for SEP with type '"+st->uri+"'" | 177 | ", while looking for SEP with type '"+st->uri+"'" |
178 | " on canonical id", status_code); | 178 | " on canonical id", status_code); |
179 | } | 179 | } |
180 | idis.canonicalized_id = cid; | 180 | idis.canonicalized_id = cid; |
181 | idis.normalized_id = rv; idis.xri_identity = true; | 181 | idis.normalized_id = rv; idis.xri_identity = true; |
182 | queue_endpoints(oi,idis,st); | 182 | queue_endpoints(oi,idis,st); |
183 | } | 183 | } |
184 | }else{ | 184 | }else{ |
185 | idis.xri_identity = false; | 185 | idis.xri_identity = false; |
186 | if(id.find("://")==string::npos) | 186 | if(id.find("://")==string::npos) |
187 | id.insert(0,"http://"); | 187 | id.insert(0,"http://"); |
188 | string::size_type fp = id.find('#'); | 188 | string::size_type fp = id.find('#'); |
189 | if(fp!=string::npos) { | 189 | if(fp!=string::npos) { |
190 | string::size_type qp = id.find('?'); | 190 | string::size_type qp = id.find('?'); |
191 | if(qp==string::npos || qp<fp) | 191 | if(qp==string::npos || qp<fp) |
192 | id.erase(fp); | 192 | id.erase(fp); |
193 | else if(qp>fp) | 193 | else if(qp>fp) |
194 | id.erase(fp,qp-fp); | 194 | id.erase(fp,qp-fp); |
195 | } | 195 | } |
196 | rv = idis.normalized_id = util::rfc_3986_normalize_uri(id); | 196 | rv = idis.normalized_id = util::rfc_3986_normalize_uri(id); |
197 | discover_at(idis,id,xmode_html|xmode_xrd); | 197 | discover_at(idis,id,xmode_html|xmode_xrd); |
198 | const char * eu = 0; | 198 | const char * eu = 0; |
199 | CURLcode r = easy_getinfo(CURLINFO_EFFECTIVE_URL,&eu); | 199 | CURLcode r = easy_getinfo(CURLINFO_EFFECTIVE_URL,&eu); |
200 | if(r) | 200 | if(r) |
201 | throw exception_curl(OPKELE_CP_ "failed to get CURLINFO_EFFECTIVE_URL",r); | 201 | throw exception_curl(OPKELE_CP_ "failed to get CURLINFO_EFFECTIVE_URL",r); |
202 | string cid = util::strip_uri_fragment_part( idis.canonicalized_id = util::rfc_3986_normalize_uri(eu) ); | 202 | string cid = util::strip_uri_fragment_part( idis.canonicalized_id = util::rfc_3986_normalize_uri(eu) ); |
203 | if(xrds_location.empty()) { | 203 | if(xrds_location.empty()) { |
204 | if(idis.xrd.empty()) | 204 | if(idis.xrd.empty()) |
205 | html2xrd(oi,idis); | 205 | html2xrd(oi,idis); |
206 | else{ | 206 | else{ |
207 | for(const service_type_t *st=op_service_types; | 207 | for(const service_type_t *st=op_service_types; |
208 | st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) | 208 | st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) |
209 | queue_endpoints(oi,idis,st); | 209 | queue_endpoints(oi,idis,st); |
210 | } | 210 | } |
211 | }else{ | 211 | }else{ |
212 | idis.clear(); | 212 | idis.clear(); |
213 | idis.canonicalized_id = cid; | 213 | idis.canonicalized_id = cid; |
214 | discover_at(idis,xrds_location,xmode_xrd); | 214 | discover_at(idis,xrds_location,xmode_xrd); |
215 | if(idis.xrd.empty()) | 215 | if(idis.xrd.empty()) |
216 | html2xrd(oi,idis); | 216 | html2xrd(oi,idis); |
217 | else{ | 217 | else{ |
218 | for(const service_type_t *st=op_service_types; | 218 | for(const service_type_t *st=op_service_types; |
219 | st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) | 219 | st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) |
220 | queue_endpoints(oi,idis,st); | 220 | queue_endpoints(oi,idis,st); |
221 | } | 221 | } |
222 | } | 222 | } |
223 | } | 223 | } |
224 | return rv; | 224 | return rv; |
225 | } | 225 | } |
226 | 226 | ||
227 | void discover_at(idiscovery_t& idis,const string& url,int xm) { | 227 | void discover_at(idiscovery_t& idis,const string& url,int xm) { |
228 | CURLcode r = easy_setopt(CURLOPT_MAXREDIRS, (xm&xmode_noredirs)?0:5); | 228 | CURLcode r = easy_setopt(CURLOPT_MAXREDIRS, (xm&xmode_noredirs)?0:5); |
229 | if(r) | 229 | if(r) |
230 | throw exception_curl(OPKELE_CP_ "failed to set curly maxredirs option"); | 230 | throw exception_curl(OPKELE_CP_ "failed to set curly maxredirs option"); |
231 | if( (r=easy_setopt(CURLOPT_URL,url.c_str())) ) | 231 | if( (r=easy_setopt(CURLOPT_URL,url.c_str())) ) |
232 | throw exception_curl(OPKELE_CP_ "failed to set curly urlie",r); | 232 | throw exception_curl(OPKELE_CP_ "failed to set curly urlie",r); |
233 | 233 | ||
234 | http_content_type.clear(); | 234 | http_content_type.clear(); |
235 | xmode = xm; | 235 | xmode = xm; |
236 | prepare_to_parse(); | 236 | prepare_to_parse(); |
237 | if(xmode&xmode_html) { | 237 | if(xmode&xmode_html) { |
238 | xrds_location.clear(); | 238 | xrds_location.clear(); |
239 | save_html.clear(); | 239 | save_html.clear(); |
240 | save_html.reserve(max_html); | 240 | save_html.reserve(max_html); |
241 | } | 241 | } |
242 | xrd = &idis.xrd; | 242 | xrd = &idis.xrd; |
243 | 243 | ||
244 | r = easy_perform(); | 244 | r = easy_perform(); |
245 | if(r && r!=CURLE_WRITE_ERROR) | 245 | if(r && r!=CURLE_WRITE_ERROR) |
246 | throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); | 246 | throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); |
247 | 247 | ||
248 | if(!parser_choked) { | 248 | if(!parser_choked) { |
249 | parse(0,0,true); | 249 | parse(0,0,true); |
250 | }else if(xmode&xmode_html){ | 250 | }else if(xmode&xmode_html){ |
251 | /* TODO: do not bother if we've seen xml */ | 251 | /* TODO: do not bother if we've seen xml */ |
252 | try { | 252 | try { |
253 | util::tidy_doc_t td = util::tidy_doc_t::create(); | 253 | util::tidy_doc_t td = util::tidy_doc_t::create(); |
254 | if(!td) | 254 | if(!td) |
255 | throw exception_tidy(OPKELE_CP_ "failed to create htmltidy document"); | 255 | throw exception_tidy(OPKELE_CP_ "failed to create htmltidy document"); |
256 | #ifdef NDEBUG | 256 | #ifdef NDEBUG |
257 | td.opt_set(TidyQuiet,true); | 257 | td.opt_set(TidyQuiet,true); |
258 | td.opt_set(TidyShowWarnings,false); | 258 | td.opt_set(TidyShowWarnings,false); |
259 | #else /* NDEBUG */ | 259 | #else /* NDEBUG */ |
260 | td.opt_set(TidyQuiet,false); | 260 | td.opt_set(TidyQuiet,false); |
261 | td.opt_set(TidyShowWarnings,true); | 261 | td.opt_set(TidyShowWarnings,true); |
262 | #endif /* NDEBUG */ | 262 | #endif /* NDEBUG */ |
263 | td.opt_set(TidyForceOutput,true); | 263 | td.opt_set(TidyForceOutput,true); |
264 | td.opt_set(TidyXhtmlOut,true); | 264 | td.opt_set(TidyXhtmlOut,true); |
265 | td.opt_set(TidyDoctypeMode,TidyDoctypeOmit); | 265 | td.opt_set(TidyDoctypeMode,TidyDoctypeOmit); |
266 | td.opt_set(TidyMark,false); | 266 | td.opt_set(TidyMark,false); |
267 | td.opt_set(TidyNumEntities,true); | 267 | td.opt_set(TidyNumEntities,true); |
268 | if(td.parse_string(save_html)<=0) | 268 | if(td.parse_string(save_html)<=0) |
269 | throw exception_tidy(OPKELE_CP_ "tidy failed to parse document"); | 269 | throw exception_tidy(OPKELE_CP_ "tidy failed to parse document"); |
270 | if(td.clean_and_repair()<=0) | 270 | if(td.clean_and_repair()<=0) |
271 | throw exception_tidy(OPKELE_CP_ "tidy failed to clean and repair"); | 271 | throw exception_tidy(OPKELE_CP_ "tidy failed to clean and repair"); |
272 | util::tidy_buf_t tide; | 272 | util::tidy_buf_t tide; |
273 | if(td.save_buffer(tide)<=0) | 273 | if(td.save_buffer(tide)<=0) |
274 | throw exception_tidy(OPKELE_CP_ "tidy failed to save buffer"); | 274 | throw exception_tidy(OPKELE_CP_ "tidy failed to save buffer"); |
275 | prepare_to_parse(); | 275 | prepare_to_parse(); |
276 | parse(tide.c_str(),tide.size(),true); | 276 | parse(tide.c_str(),tide.size(),true); |
277 | }catch(exception_tidy& et) { } | 277 | }catch(exception_tidy& et) { } |
278 | } | 278 | } |
279 | save_html.clear(); | 279 | save_html.clear(); |
280 | } | 280 | } |
281 | 281 | ||
282 | void prepare_to_parse() { | 282 | void prepare_to_parse() { |
283 | (*(expat_t*)this) = parser_create_ns(); | 283 | (*(expat_t*)this) = parser_create_ns(); |
284 | set_user_data(); set_element_handler(); | 284 | set_user_data(); set_element_handler(); |
285 | set_character_data_handler(); | 285 | set_character_data_handler(); |
286 | set_unknown_encoding_handler(); | ||
286 | 287 | ||
287 | if(xmode&xmode_html) { | 288 | if(xmode&xmode_html) { |
288 | html_openid1.clear(); html_openid2.clear(); | 289 | html_openid1.clear(); html_openid2.clear(); |
289 | parser_choked = false; | 290 | parser_choked = false; |
290 | } | 291 | } |
291 | 292 | ||
292 | cdata = 0; xrd_service = 0; skipping = 0; | 293 | cdata = 0; xrd_service = 0; skipping = 0; |
293 | pt_stack.clear(); | 294 | pt_stack.clear(); |
294 | status_code = 100; status_string.clear(); | 295 | status_code = 100; status_string.clear(); |
295 | } | 296 | } |
296 | 297 | ||
297 | void html2xrd(endpoint_discovery_iterator& oi,idiscovery_t& id) { | 298 | void html2xrd(endpoint_discovery_iterator& oi,idiscovery_t& id) { |
298 | XRD_t& x = id.xrd; | 299 | XRD_t& x = id.xrd; |
299 | if(!html_openid2.uris.empty()) { | 300 | if(!html_openid2.uris.empty()) { |
300 | html_openid2.types.insert(STURI_OPENID20); | 301 | html_openid2.types.insert(STURI_OPENID20); |
301 | x.services.add(-1,html_openid2); | 302 | x.services.add(-1,html_openid2); |
302 | queue_endpoints(oi,id,&op_service_types[st_index_2]); | 303 | queue_endpoints(oi,id,&op_service_types[st_index_2]); |
303 | } | 304 | } |
304 | if(!html_openid1.uris.empty()) { | 305 | if(!html_openid1.uris.empty()) { |
305 | html_openid1.types.insert(STURI_OPENID11); | 306 | html_openid1.types.insert(STURI_OPENID11); |
306 | x.services.add(-1,html_openid1); | 307 | x.services.add(-1,html_openid1); |
307 | queue_endpoints(oi,id,&op_service_types[st_index_1]); | 308 | queue_endpoints(oi,id,&op_service_types[st_index_1]); |
308 | } | 309 | } |
309 | } | 310 | } |
310 | 311 | ||
311 | size_t write(void *p,size_t s,size_t nm) { | 312 | size_t write(void *p,size_t s,size_t nm) { |
312 | /* TODO: limit total size */ | 313 | /* TODO: limit total size */ |
313 | size_t bytes = s*nm; | 314 | size_t bytes = s*nm; |
314 | const char *inbuf = (const char*)p; | 315 | const char *inbuf = (const char*)p; |
315 | if(xmode&xmode_html) { | 316 | if(xmode&xmode_html) { |
316 | size_t mbts = save_html.capacity()-save_html.size(); | 317 | size_t mbts = save_html.capacity()-save_html.size(); |
317 | size_t bts = 0; | 318 | size_t bts = 0; |
318 | if(mbts>0) { | 319 | if(mbts>0) { |
319 | bts = (bytes>mbts)?mbts:bytes; | 320 | bts = (bytes>mbts)?mbts:bytes; |
320 | save_html.append(inbuf,bts); | 321 | save_html.append(inbuf,bts); |
321 | } | 322 | } |
322 | if(skipping<0) return bts; | 323 | if(skipping<0) return bts; |
323 | } | 324 | } |
324 | if(skipping<0) return 0; | 325 | if(skipping<0) return 0; |
325 | bool rp = parse(inbuf,bytes,false); | 326 | bool rp = parse(inbuf,bytes,false); |
326 | if(!rp) { | 327 | if(!rp) { |
327 | parser_choked = true; | 328 | parser_choked = true; |
328 | skipping = -1; | 329 | skipping = -1; |
329 | if(!(xmode&xmode_html)) | 330 | if(!(xmode&xmode_html)) |
330 | bytes = 0; | 331 | bytes = 0; |
331 | } | 332 | } |
332 | return bytes; | 333 | return bytes; |
333 | } | 334 | } |
334 | size_t header(void *p,size_t s,size_t nm) { | 335 | size_t header(void *p,size_t s,size_t nm) { |
335 | size_t bytes = s*nm; | 336 | size_t bytes = s*nm; |
336 | const char *h = (const char*)p; | 337 | const char *h = (const char*)p; |
337 | const char *colon = (const char*)memchr(p,':',bytes); | 338 | const char *colon = (const char*)memchr(p,':',bytes); |
338 | const char *space = (const char*)memchr(p,' ',bytes); | 339 | const char *space = (const char*)memchr(p,' ',bytes); |
339 | if(space && ( (!colon) || space<colon ) ) { | 340 | if(space && ( (!colon) || space<colon ) ) { |
340 | xrds_location.clear(); http_content_type.clear(); | 341 | xrds_location.clear(); http_content_type.clear(); |
341 | }else if(colon) { | 342 | }else if(colon) { |
342 | const char *hv = ++colon; | 343 | const char *hv = ++colon; |
343 | size_t hnl = colon-h; | 344 | size_t hnl = colon-h; |
344 | int rb; | 345 | int rb; |
345 | for(rb = bytes-hnl-1;rb>0 && isspace(*hv);++hv,--rb) ; | 346 | for(rb = bytes-hnl-1;rb>0 && isspace(*hv);++hv,--rb) ; |
346 | while(rb>0 && isspace(hv[rb-1])) --rb; | 347 | while(rb>0 && isspace(hv[rb-1])) --rb; |
347 | if(rb) { | 348 | if(rb) { |
348 | if( (hnl>=sizeof(XRDS_HEADER)) | 349 | if( (hnl>=sizeof(XRDS_HEADER)) |
349 | && !strncasecmp(h,XRDS_HEADER":", | 350 | && !strncasecmp(h,XRDS_HEADER":", |
350 | sizeof(XRDS_HEADER)) ) { | 351 | sizeof(XRDS_HEADER)) ) { |
351 | xrds_location.assign(hv,rb); | 352 | xrds_location.assign(hv,rb); |
352 | }else if( (hnl>=sizeof(CT_HEADER)) | 353 | }else if( (hnl>=sizeof(CT_HEADER)) |
353 | && !strncasecmp(h,CT_HEADER":", | 354 | && !strncasecmp(h,CT_HEADER":", |
354 | sizeof(CT_HEADER)) ) { | 355 | sizeof(CT_HEADER)) ) { |
355 | const char *sc = (const char*)memchr( | 356 | const char *sc = (const char*)memchr( |
356 | hv,';',rb); | 357 | hv,';',rb); |
357 | http_content_type.assign(hv,sc?(sc-hv):rb); | 358 | http_content_type.assign(hv,sc?(sc-hv):rb); |
358 | } | 359 | } |
359 | } | 360 | } |
360 | } | 361 | } |
361 | return curl_t::header(p,s,nm); | 362 | return curl_t::header(p,s,nm); |
362 | } | 363 | } |
363 | 364 | ||
364 | void start_element(const XML_Char *n,const XML_Char **a) { | 365 | void start_element(const XML_Char *n,const XML_Char **a) { |
365 | if(skipping<0) return; | 366 | if(skipping<0) return; |
366 | if(skipping) { | 367 | if(skipping) { |
367 | if(xmode&xmode_html) | 368 | if(xmode&xmode_html) |
368 | html_start_element(n,a); | 369 | html_start_element(n,a); |
369 | ++skipping; return; | 370 | ++skipping; return; |
370 | } | 371 | } |
371 | if(pt_stack.empty()) { | 372 | if(pt_stack.empty()) { |
372 | if(is_qelement(n,NSURI_XRDS "\tXRDS")) | 373 | if(is_qelement(n,NSURI_XRDS "\tXRDS")) |
373 | return; | 374 | return; |
374 | if(is_qelement(n,NSURI_XRD "\tXRD")) { | 375 | if(is_qelement(n,NSURI_XRD "\tXRD")) { |
375 | assert(xrd); | 376 | assert(xrd); |
376 | xrd->clear(); | 377 | xrd->clear(); |
377 | pt_stack.push_back(n); | 378 | pt_stack.push_back(n); |
378 | }else if(xmode&xmode_html) { | 379 | }else if(xmode&xmode_html) { |
379 | html_start_element(n,a); | 380 | html_start_element(n,a); |
380 | }else{ | 381 | }else{ |
381 | skipping = -1; | 382 | skipping = -1; |
382 | } | 383 | } |
383 | }else{ | 384 | }else{ |
384 | int pt_s = pt_stack.size(); | 385 | int pt_s = pt_stack.size(); |
385 | if(pt_s==1) { | 386 | if(pt_s==1) { |
386 | if(is_qelement(n,NSURI_XRD "\tCanonicalID")) { | 387 | if(is_qelement(n,NSURI_XRD "\tCanonicalID")) { |
387 | assert(xrd); | 388 | assert(xrd); |
388 | cdata = &(xrd->canonical_ids.add(element_priority(a),string())); | 389 | cdata = &(xrd->canonical_ids.add(element_priority(a),string())); |
389 | }else if(is_qelement(n,NSURI_XRD "\tLocalID")) { | 390 | }else if(is_qelement(n,NSURI_XRD "\tLocalID")) { |
390 | assert(xrd); | 391 | assert(xrd); |
391 | cdata = &(xrd->local_ids.add(element_priority(a),string())); | 392 | cdata = &(xrd->local_ids.add(element_priority(a),string())); |
392 | }else if(is_qelement(n,NSURI_XRD "\tProviderID")) { | 393 | }else if(is_qelement(n,NSURI_XRD "\tProviderID")) { |
393 | assert(xrd); | 394 | assert(xrd); |
394 | cdata = &(xrd->provider_id); | 395 | cdata = &(xrd->provider_id); |
395 | }else if(is_qelement(n,NSURI_XRD "\tService")) { | 396 | }else if(is_qelement(n,NSURI_XRD "\tService")) { |
396 | assert(xrd); | 397 | assert(xrd); |
397 | xrd_service = &(xrd->services.add(element_priority(a), | 398 | xrd_service = &(xrd->services.add(element_priority(a), |
398 | service_t())); | 399 | service_t())); |
399 | pt_stack.push_back(n); | 400 | pt_stack.push_back(n); |
400 | }else if(is_qelement(n,NSURI_XRD "\tStatus")) { | 401 | }else if(is_qelement(n,NSURI_XRD "\tStatus")) { |
401 | for(;*a;) { | 402 | for(;*a;) { |
402 | if(!strcasecmp(*(a++),"code")) { | 403 | if(!strcasecmp(*(a++),"code")) { |
403 | if(sscanf(*(a++),"%ld",&status_code)==1 && status_code!=100) { | 404 | if(sscanf(*(a++),"%ld",&status_code)==1 && status_code!=100) { |
404 | cdata = &status_string; | 405 | cdata = &status_string; |
405 | pt_stack.push_back(n); | 406 | pt_stack.push_back(n); |
406 | break; | 407 | break; |
407 | } | 408 | } |
408 | }else | 409 | }else |
409 | ++a; | 410 | ++a; |
410 | } | 411 | } |
411 | }else if(is_qelement(n,NSURI_XRD "\tExpires")) { | 412 | }else if(is_qelement(n,NSURI_XRD "\tExpires")) { |
412 | assert(xrd); | 413 | assert(xrd); |
413 | cdata_buf.clear(); | 414 | cdata_buf.clear(); |
414 | cdata = &cdata_buf; | 415 | cdata = &cdata_buf; |
415 | }else if(xmode&xmode_html) { | 416 | }else if(xmode&xmode_html) { |
416 | html_start_element(n,a); | 417 | html_start_element(n,a); |
417 | }else{ | 418 | }else{ |
418 | skipping = 1; | 419 | skipping = 1; |
419 | } | 420 | } |
420 | }else if(pt_s==2) { | 421 | }else if(pt_s==2) { |
421 | if(is_qelement(pt_stack.back().c_str(), NSURI_XRD "\tService")) { | 422 | if(is_qelement(pt_stack.back().c_str(), NSURI_XRD "\tService")) { |
422 | if(is_qelement(n,NSURI_XRD "\tType")) { | 423 | if(is_qelement(n,NSURI_XRD "\tType")) { |
423 | assert(xrd); assert(xrd_service); | 424 | assert(xrd); assert(xrd_service); |
424 | cdata_buf.clear(); | 425 | cdata_buf.clear(); |
425 | cdata = &cdata_buf; | 426 | cdata = &cdata_buf; |
426 | }else if(is_qelement(n,NSURI_XRD "\tURI")) { | 427 | }else if(is_qelement(n,NSURI_XRD "\tURI")) { |
427 | assert(xrd); assert(xrd_service); | 428 | assert(xrd); assert(xrd_service); |
428 | const char *append = element_attr(a,"append"); | 429 | const char *append = element_attr(a,"append"); |
429 | xrd::uri_t& uri = xrd_service->uris.add(element_priority(a),xrd::uri_t("",append?append:"")); | 430 | xrd::uri_t& uri = xrd_service->uris.add(element_priority(a),xrd::uri_t("",append?append:"")); |
430 | cdata = &uri.uri; | 431 | cdata = &uri.uri; |
431 | }else if(is_qelement(n,NSURI_XRD "\tLocalID") | 432 | }else if(is_qelement(n,NSURI_XRD "\tLocalID") |
432 | || is_qelement(n,NSURI_OPENID10 "\tDelegate") ) { | 433 | || is_qelement(n,NSURI_OPENID10 "\tDelegate") ) { |
433 | assert(xrd); assert(xrd_service); | 434 | assert(xrd); assert(xrd_service); |
434 | cdata = &(xrd_service->local_ids.add(element_priority(a),string())); | 435 | cdata = &(xrd_service->local_ids.add(element_priority(a),string())); |
435 | }else if(is_qelement(n,NSURI_XRD "\tProviderID")) { | 436 | }else if(is_qelement(n,NSURI_XRD "\tProviderID")) { |
436 | assert(xrd); assert(xrd_service); | 437 | assert(xrd); assert(xrd_service); |
437 | cdata = &(xrd_service->provider_id); | 438 | cdata = &(xrd_service->provider_id); |
438 | }else{ | 439 | }else{ |
439 | skipping = 1; | 440 | skipping = 1; |
440 | } | 441 | } |
441 | }else | 442 | }else |
442 | skipping = 1; | 443 | skipping = 1; |
443 | }else if(xmode&xmode_html) { | 444 | }else if(xmode&xmode_html) { |
444 | html_start_element(n,a); | 445 | html_start_element(n,a); |
445 | }else{ | 446 | }else{ |
446 | skipping = 1; | 447 | skipping = 1; |
447 | } | 448 | } |
448 | } | 449 | } |
449 | } | 450 | } |
450 | void end_element(const XML_Char *n) { | 451 | void end_element(const XML_Char *n) { |
451 | if(skipping<0) return; | 452 | if(skipping<0) return; |
452 | if(skipping) { | 453 | if(skipping) { |
453 | --skipping; return; | 454 | --skipping; return; |
454 | } | 455 | } |
455 | if(is_qelement(n,NSURI_XRD "\tType")) { | 456 | if(is_qelement(n,NSURI_XRD "\tType")) { |
456 | assert(xrd); assert(xrd_service); assert(cdata==&cdata_buf); | 457 | if(xrd && xrd_service) { |
458 | assert(cdata==&cdata_buf); | ||
457 | xrd_service->types.insert(cdata_buf); | 459 | xrd_service->types.insert(cdata_buf); |
460 | } | ||
458 | }else if(is_qelement(n,NSURI_XRD "\tService")) { | 461 | }else if(is_qelement(n,NSURI_XRD "\tService")) { |
459 | assert(xrd); assert(xrd_service); | 462 | if(!(xrd && xrd_service)) { |
463 | skipping = -1; | ||
464 | }else{ | ||
460 | assert(!pt_stack.empty()); | 465 | assert(!pt_stack.empty()); |
461 | assert(pt_stack.back()==(NSURI_XRD "\tService")); | 466 | assert(pt_stack.back()==(NSURI_XRD "\tService")); |
462 | pt_stack.pop_back(); | 467 | pt_stack.pop_back(); |
463 | xrd_service = 0; | 468 | xrd_service = 0; |
469 | } | ||
464 | }else if(is_qelement(n,NSURI_XRD "\tStatus")) { | 470 | }else if(is_qelement(n,NSURI_XRD "\tStatus")) { |
465 | assert(xrd); | 471 | if(!xrd) { |
472 | skipping=-1; | ||
473 | }else{ | ||
466 | if(is_qelement(pt_stack.back().c_str(),n)) { | 474 | if(is_qelement(pt_stack.back().c_str(),n)) { |
467 | assert(cdata==&status_string); | 475 | assert(cdata==&status_string); |
468 | pt_stack.pop_back(); | 476 | pt_stack.pop_back(); |
469 | if(status_code!=100) | 477 | if(status_code!=100) |
470 | skipping = -1; | 478 | skipping = -1; |
471 | } | 479 | } |
480 | } | ||
472 | }else if(is_qelement(n,NSURI_XRD "\tExpires")) { | 481 | }else if(is_qelement(n,NSURI_XRD "\tExpires")) { |
473 | assert(xrd); | 482 | if(!xrd) { |
483 | skipping=-1; | ||
484 | }else{ | ||
474 | xrd->expires = util::w3c_to_time(cdata_buf); | 485 | xrd->expires = util::w3c_to_time(cdata_buf); |
486 | } | ||
487 | }else if(is_qelement(n,NSURI_XRD "\tXRD")) { | ||
488 | assert(!pt_stack.empty()); | ||
489 | assert(pt_stack.back()==(NSURI_XRD "\tXRD")); | ||
490 | pt_stack.pop_back(); | ||
475 | }else if((xmode&xmode_html) && is_element(n,"head")) { | 491 | }else if((xmode&xmode_html) && is_element(n,"head")) { |
476 | skipping = -1; | 492 | skipping = -1; |
477 | } | 493 | } |
478 | cdata = 0; | 494 | cdata = 0; |
479 | } | 495 | } |
480 | void character_data(const XML_Char *s,int l) { | 496 | void character_data(const XML_Char *s,int l) { |
481 | if(skipping) return; | 497 | if(skipping) return; |
482 | if(cdata) cdata->append(s,l); | 498 | if(cdata) cdata->append(s,l); |
483 | } | 499 | } |
484 | 500 | ||
485 | void html_start_element(const XML_Char *n,const XML_Char **a) { | 501 | void html_start_element(const XML_Char *n,const XML_Char **a) { |
486 | if(is_element(n,"meta")) { | 502 | if(is_element(n,"meta")) { |
487 | bool heq = false; | 503 | bool heq = false; |
488 | string l; | 504 | string l; |
489 | for(;*a;a+=2) { | 505 | for(;*a;a+=2) { |
490 | if(!( strcasecmp(a[0],"http-equiv") | 506 | if(!( strcasecmp(a[0],"http-equiv") |
491 | || strcasecmp(a[1],XRDS_HEADER) )) | 507 | || strcasecmp(a[1],XRDS_HEADER) )) |
492 | heq = true; | 508 | heq = true; |
493 | else if(!strcasecmp(a[0],"content")) | 509 | else if(!strcasecmp(a[0],"content")) |
494 | l.assign(a[1]); | 510 | l.assign(a[1]); |
495 | } | 511 | } |
496 | if(heq) | 512 | if(heq) |
497 | xrds_location = l; | 513 | xrds_location = l; |
498 | }else if(is_element(n,"link")) { | 514 | }else if(is_element(n,"link")) { |
499 | string rels; | 515 | string rels; |
500 | string href; | 516 | string href; |
501 | for(;*a;a+=2) { | 517 | for(;*a;a+=2) { |
502 | if( !strcasecmp(a[0],"rel") ) { | 518 | if( !strcasecmp(a[0],"rel") ) { |
503 | rels.assign(a[1]); | 519 | rels.assign(a[1]); |
504 | }else if( !strcasecmp(a[0],"href") ) { | 520 | }else if( !strcasecmp(a[0],"href") ) { |
505 | const char *ns = a[1]; | 521 | const char *ns = a[1]; |
506 | for(;*ns && isspace(*ns);++ns) ; | 522 | for(;*ns && isspace(*ns);++ns) ; |
507 | href.assign(ns); | 523 | href.assign(ns); |
508 | string::size_type lns=href.find_last_not_of(data::_whitespace_chars); | 524 | string::size_type lns=href.find_last_not_of(data::_whitespace_chars); |
509 | href.erase(lns+1); | 525 | href.erase(lns+1); |
510 | } | 526 | } |
511 | } | 527 | } |
512 | for(string::size_type ns=rels.find_first_not_of(data::_whitespace_chars); | 528 | for(string::size_type ns=rels.find_first_not_of(data::_whitespace_chars); |
513 | ns!=string::npos; ns=rels.find_first_not_of(data::_whitespace_chars,ns)) { | 529 | ns!=string::npos; ns=rels.find_first_not_of(data::_whitespace_chars,ns)) { |
514 | string::size_type s = rels.find_first_of(data::_whitespace_chars,ns); | 530 | string::size_type s = rels.find_first_of(data::_whitespace_chars,ns); |
515 | string rel; | 531 | string rel; |
516 | if(s==string::npos) { | 532 | if(s==string::npos) { |
517 | rel.assign(rels,ns,string::npos); | 533 | rel.assign(rels,ns,string::npos); |
518 | ns = string::npos; | 534 | ns = string::npos; |
519 | }else{ | 535 | }else{ |
520 | rel.assign(rels,ns,s-ns); | 536 | rel.assign(rels,ns,s-ns); |
521 | ns = s; | 537 | ns = s; |
522 | } | 538 | } |
523 | if(rel=="openid.server") | 539 | if(rel=="openid.server") |
524 | html_openid1.uris.add(-1,xrd::uri_t(href)); | 540 | html_openid1.uris.add(-1,xrd::uri_t(href)); |
525 | else if(rel=="openid.delegate") | 541 | else if(rel=="openid.delegate") |
526 | html_openid1.local_ids.add(-1,href); | 542 | html_openid1.local_ids.add(-1,href); |
527 | else if(rel=="openid2.provider") | 543 | else if(rel=="openid2.provider") |
528 | html_openid2.uris.add(-1,xrd::uri_t(href)); | 544 | html_openid2.uris.add(-1,xrd::uri_t(href)); |
529 | else if(rel=="openid2.local_id") | 545 | else if(rel=="openid2.local_id") |
530 | html_openid2.local_ids.add(-1,href); | 546 | html_openid2.local_ids.add(-1,href); |
531 | } | 547 | } |
532 | }else if(is_element(n,"body")) { | 548 | }else if(is_element(n,"body")) { |
533 | skipping = -1; | 549 | skipping = -1; |
534 | } | 550 | } |
535 | } | 551 | } |
536 | 552 | ||
537 | void queue_endpoints(endpoint_discovery_iterator& oi, | 553 | void queue_endpoints(endpoint_discovery_iterator& oi, |
538 | const idiscovery_t &id, | 554 | const idiscovery_t &id, |
539 | const service_type_t *st) { | 555 | const service_type_t *st) { |
540 | openid_endpoint_t ep; | 556 | openid_endpoint_t ep; |
541 | ep.claimed_id = id.canonicalized_id; | 557 | ep.claimed_id = id.canonicalized_id; |
542 | for(xrd::services_t::const_iterator isvc=id.xrd.services.begin(); | 558 | for(xrd::services_t::const_iterator isvc=id.xrd.services.begin(); |
543 | isvc!=id.xrd.services.end(); ++isvc) { | 559 | isvc!=id.xrd.services.end(); ++isvc) { |
544 | const xrd::service_t svc = isvc->second; | 560 | const xrd::service_t svc = isvc->second; |
545 | if(svc.types.find(st->uri)==svc.types.end()) continue; | 561 | if(svc.types.find(st->uri)==svc.types.end()) continue; |
546 | for(xrd::uris_t::const_iterator iu=svc.uris.begin();iu!=svc.uris.end();++iu) { | 562 | for(xrd::uris_t::const_iterator iu=svc.uris.begin();iu!=svc.uris.end();++iu) { |
547 | ep.uri = iu->second.uri; | 563 | ep.uri = iu->second.uri; |
548 | if(id.xri_identity) { | 564 | if(id.xri_identity) { |
549 | if(iu->second.append=="qxri") { | 565 | if(iu->second.append=="qxri") { |
550 | ep.uri += id.normalized_id; | 566 | ep.uri += id.normalized_id; |
551 | } /* TODO: else handle other append attribute values */ | 567 | } /* TODO: else handle other append attribute values */ |
552 | } | 568 | } |
553 | if(st->forceid) { | 569 | if(st->forceid) { |
554 | ep.local_id = ep.claimed_id = st->forceid; | 570 | ep.local_id = ep.claimed_id = st->forceid; |
555 | *(oi++) = ep; | 571 | *(oi++) = ep; |
556 | }else{ | 572 | }else{ |
557 | if(svc.local_ids.empty()) { | 573 | if(svc.local_ids.empty()) { |
558 | ep.local_id = ep.claimed_id; | 574 | ep.local_id = ep.claimed_id; |
559 | *(oi++) = ep; | 575 | *(oi++) = ep; |
560 | }else{ | 576 | }else{ |
561 | for(xrd::local_ids_t::const_iterator ilid=svc.local_ids.begin(); | 577 | for(xrd::local_ids_t::const_iterator ilid=svc.local_ids.begin(); |
562 | ilid!=svc.local_ids.end(); ++ilid) { | 578 | ilid!=svc.local_ids.end(); ++ilid) { |
563 | ep.local_id = ilid->second; | 579 | ep.local_id = ilid->second; |
564 | *(oi++) = ep; | 580 | *(oi++) = ep; |
565 | } | 581 | } |
566 | } | 582 | } |
567 | } | 583 | } |
568 | } | 584 | } |
569 | } | 585 | } |
570 | } | 586 | } |
571 | 587 | ||
588 | int unknown_encoding(const XML_Char* /* n */,XML_Encoding *i) { | ||
589 | for(unsigned int ii=0;ii < sizeof(i->map)/sizeof(i->map[0]);++ii) | ||
590 | i->map[ii] = ii; | ||
591 | i->convert = 0; i->release = 0; | ||
592 | return XML_STATUS_OK; | ||
593 | } | ||
594 | |||
572 | }; | 595 | }; |
573 | 596 | ||
574 | string idiscover(endpoint_discovery_iterator oi,const string& identity) { | 597 | string idiscover(endpoint_discovery_iterator oi,const string& identity) { |
575 | idigger_t idigger; | 598 | idigger_t idigger; |
576 | return idigger.discover(oi,identity); | 599 | return idigger.discover(oi,identity); |
577 | } | 600 | } |
578 | 601 | ||
579 | void yadiscover(endpoint_discovery_iterator oi,const string& yurl,const char **types,bool redirs) try { | 602 | void yadiscover(endpoint_discovery_iterator oi,const string& yurl,const char **types,bool redirs) try { |
580 | idigger_t idigger; | 603 | idigger_t idigger; |
581 | idigger.yadiscover(oi,yurl,types,redirs); | 604 | idigger.yadiscover(oi,yurl,types,redirs); |
582 | }catch(exception_curl& ec) { | 605 | }catch(exception_curl& ec) { |
583 | if(redirs || ec._error!=CURLE_TOO_MANY_REDIRECTS) | 606 | if(redirs || ec._error!=CURLE_TOO_MANY_REDIRECTS) |
584 | throw; | 607 | throw; |
585 | } | 608 | } |
586 | 609 | ||
587 | } | 610 | } |
diff --git a/lib/expat.cc b/lib/expat.cc index c4dab7e..fb58a9a 100644 --- a/lib/expat.cc +++ b/lib/expat.cc | |||
@@ -1,97 +1,106 @@ | |||
1 | #include <opkele/expat.h> | 1 | #include <opkele/expat.h> |
2 | 2 | ||
3 | namespace opkele { | 3 | namespace opkele { |
4 | 4 | ||
5 | namespace util { | 5 | namespace util { |
6 | 6 | ||
7 | expat_t::~expat_t() throw() { | 7 | expat_t::~expat_t() throw() { |
8 | if(_x) | 8 | if(_x) |
9 | XML_ParserFree(_x); | 9 | XML_ParserFree(_x); |
10 | } | 10 | } |
11 | 11 | ||
12 | expat_t& expat_t::operator=(XML_Parser x) { | 12 | expat_t& expat_t::operator=(XML_Parser x) { |
13 | if(_x) | 13 | if(_x) |
14 | XML_ParserFree(_x); | 14 | XML_ParserFree(_x); |
15 | _x = x; | 15 | _x = x; |
16 | return *this; | 16 | return *this; |
17 | } | 17 | } |
18 | 18 | ||
19 | static void _start_element(void* ud,const XML_Char *n,const XML_Char **a) { | 19 | static void _start_element(void* ud,const XML_Char *n,const XML_Char **a) { |
20 | ((expat_t*)ud)->start_element(n,a); | 20 | ((expat_t*)ud)->start_element(n,a); |
21 | } | 21 | } |
22 | static void _end_element(void *ud,const XML_Char *n) { | 22 | static void _end_element(void *ud,const XML_Char *n) { |
23 | ((expat_t*)ud)->end_element(n); | 23 | ((expat_t*)ud)->end_element(n); |
24 | } | 24 | } |
25 | 25 | ||
26 | void expat_t::set_element_handler() { | 26 | void expat_t::set_element_handler() { |
27 | assert(_x); | 27 | assert(_x); |
28 | XML_SetElementHandler(_x,_start_element,_end_element); | 28 | XML_SetElementHandler(_x,_start_element,_end_element); |
29 | } | 29 | } |
30 | 30 | ||
31 | static void _character_data(void *ud,const XML_Char *s,int l) { | 31 | static void _character_data(void *ud,const XML_Char *s,int l) { |
32 | ((expat_t*)ud)->character_data(s,l); | 32 | ((expat_t*)ud)->character_data(s,l); |
33 | } | 33 | } |
34 | 34 | ||
35 | void expat_t::set_character_data_handler() { | 35 | void expat_t::set_character_data_handler() { |
36 | assert(_x); | 36 | assert(_x); |
37 | XML_SetCharacterDataHandler(_x,_character_data); | 37 | XML_SetCharacterDataHandler(_x,_character_data); |
38 | } | 38 | } |
39 | 39 | ||
40 | static void _processing_instruction(void *ud,const XML_Char *t,const XML_Char *d) { | 40 | static void _processing_instruction(void *ud,const XML_Char *t,const XML_Char *d) { |
41 | ((expat_t*)ud)->processing_instruction(t,d); | 41 | ((expat_t*)ud)->processing_instruction(t,d); |
42 | } | 42 | } |
43 | 43 | ||
44 | void expat_t::set_processing_instruction_handler() { | 44 | void expat_t::set_processing_instruction_handler() { |
45 | assert(_x); | 45 | assert(_x); |
46 | XML_SetProcessingInstructionHandler(_x,_processing_instruction); | 46 | XML_SetProcessingInstructionHandler(_x,_processing_instruction); |
47 | } | 47 | } |
48 | 48 | ||
49 | static void _comment(void *ud,const XML_Char *d) { | 49 | static void _comment(void *ud,const XML_Char *d) { |
50 | ((expat_t*)ud)->comment(d); | 50 | ((expat_t*)ud)->comment(d); |
51 | } | 51 | } |
52 | 52 | ||
53 | void expat_t::set_comment_handler() { | 53 | void expat_t::set_comment_handler() { |
54 | assert(_x); | 54 | assert(_x); |
55 | XML_SetCommentHandler(_x,_comment); | 55 | XML_SetCommentHandler(_x,_comment); |
56 | } | 56 | } |
57 | 57 | ||
58 | static void _start_cdata_section(void *ud) { | 58 | static void _start_cdata_section(void *ud) { |
59 | ((expat_t*)ud)->start_cdata_section(); | 59 | ((expat_t*)ud)->start_cdata_section(); |
60 | } | 60 | } |
61 | static void _end_cdata_section(void *ud) { | 61 | static void _end_cdata_section(void *ud) { |
62 | ((expat_t*)ud)->end_cdata_section(); | 62 | ((expat_t*)ud)->end_cdata_section(); |
63 | } | 63 | } |
64 | 64 | ||
65 | void expat_t::set_cdata_section_handler() { | 65 | void expat_t::set_cdata_section_handler() { |
66 | assert(_x); | 66 | assert(_x); |
67 | XML_SetCdataSectionHandler(_x,_start_cdata_section,_end_cdata_section); | 67 | XML_SetCdataSectionHandler(_x,_start_cdata_section,_end_cdata_section); |
68 | } | 68 | } |
69 | 69 | ||
70 | static void _default_handler(void *ud,const XML_Char *s,int l) { | 70 | static void _default_handler(void *ud,const XML_Char *s,int l) { |
71 | ((expat_t*)ud)->default_handler(s,l); | 71 | ((expat_t*)ud)->default_handler(s,l); |
72 | } | 72 | } |
73 | 73 | ||
74 | void expat_t::set_default_handler() { | 74 | void expat_t::set_default_handler() { |
75 | assert(_x); | 75 | assert(_x); |
76 | XML_SetDefaultHandler(_x,_default_handler); | 76 | XML_SetDefaultHandler(_x,_default_handler); |
77 | } | 77 | } |
78 | void expat_t::set_default_handler_expand() { | 78 | void expat_t::set_default_handler_expand() { |
79 | assert(_x); | 79 | assert(_x); |
80 | XML_SetDefaultHandlerExpand(_x,_default_handler); | 80 | XML_SetDefaultHandlerExpand(_x,_default_handler); |
81 | } | 81 | } |
82 | 82 | ||
83 | static void _start_namespace_decl(void *ud,const XML_Char *p,const XML_Char *u) { | 83 | static void _start_namespace_decl(void *ud,const XML_Char *p,const XML_Char *u) { |
84 | ((expat_t*)ud)->start_namespace_decl(p,u); | 84 | ((expat_t*)ud)->start_namespace_decl(p,u); |
85 | } | 85 | } |
86 | static void _end_namespace_decl(void *ud,const XML_Char *p) { | 86 | static void _end_namespace_decl(void *ud,const XML_Char *p) { |
87 | ((expat_t*)ud)->end_namespace_decl(p); | 87 | ((expat_t*)ud)->end_namespace_decl(p); |
88 | } | 88 | } |
89 | 89 | ||
90 | void expat_t::set_namespace_decl_handler() { | 90 | void expat_t::set_namespace_decl_handler() { |
91 | assert(_x); | 91 | assert(_x); |
92 | XML_SetNamespaceDeclHandler(_x,_start_namespace_decl,_end_namespace_decl); | 92 | XML_SetNamespaceDeclHandler(_x,_start_namespace_decl,_end_namespace_decl); |
93 | } | 93 | } |
94 | 94 | ||
95 | static int _unknown_encoding(void *ehd,const XML_Char *n,XML_Encoding *i) { | ||
96 | return ((expat_t*)ehd)->unknown_encoding(n,i); | ||
97 | } | ||
98 | |||
99 | void expat_t::set_unknown_encoding_handler() { | ||
100 | assert(_x); | ||
101 | XML_SetUnknownEncodingHandler(_x,_unknown_encoding,this); | ||
102 | } | ||
103 | |||
95 | } | 104 | } |
96 | 105 | ||
97 | } | 106 | } |
@@ -1,195 +1,196 @@ | |||
1 | #include <uuid/uuid.h> | 1 | #include <uuid/uuid.h> |
2 | #include <iostream> | 2 | #include <iostream> |
3 | #include <cassert> | 3 | #include <cassert> |
4 | #include <cstdlib> | ||
4 | #include <stdexcept> | 5 | #include <stdexcept> |
5 | #include <string> | 6 | #include <string> |
6 | #include <set> | 7 | #include <set> |
7 | #include <iterator> | 8 | #include <iterator> |
8 | using namespace std; | 9 | using namespace std; |
9 | #include <kingate/exception.h> | 10 | #include <kingate/exception.h> |
10 | #include <kingate/plaincgi.h> | 11 | #include <kingate/plaincgi.h> |
11 | #include <kingate/cgi_gateway.h> | 12 | #include <kingate/cgi_gateway.h> |
12 | #include <opkele/exception.h> | 13 | #include <opkele/exception.h> |
13 | #include <opkele/types.h> | 14 | #include <opkele/types.h> |
14 | #include <opkele/util.h> | 15 | #include <opkele/util.h> |
15 | #include <opkele/uris.h> | 16 | #include <opkele/uris.h> |
16 | #include <opkele/discovery.h> | 17 | #include <opkele/discovery.h> |
17 | #include <opkele/association.h> | 18 | #include <opkele/association.h> |
18 | #include <opkele/sreg.h> | 19 | #include <opkele/sreg.h> |
19 | using namespace opkele; | 20 | using namespace opkele; |
20 | #include <opkele/prequeue_rp.h> | 21 | #include <opkele/prequeue_rp.h> |
21 | #include <opkele/debug.h> | 22 | #include <opkele/debug.h> |
22 | 23 | ||
23 | #include "sqlite.h" | 24 | #include "sqlite.h" |
24 | #include "kingate_openid_message.h" | 25 | #include "kingate_openid_message.h" |
25 | 26 | ||
26 | #undef DUMB_RP | 27 | #undef DUMB_RP |
27 | 28 | ||
28 | #ifdef DUMB_RP | 29 | #ifdef DUMB_RP |
29 | # define DUMBTHROW throw opkele::dumb_RP(OPKELE_CP_ "This RP is dumb") | 30 | # define DUMBTHROW throw opkele::dumb_RP(OPKELE_CP_ "This RP is dumb") |
30 | #else | 31 | #else |
31 | # define DUMBTHROW (void)0 | 32 | # define DUMBTHROW (void)0 |
32 | #endif | 33 | #endif |
33 | 34 | ||
34 | class rpdb_t : public sqlite3_t { | 35 | class rpdb_t : public sqlite3_t { |
35 | public: | 36 | public: |
36 | rpdb_t() | 37 | rpdb_t() |
37 | : sqlite3_t("/tmp/RP.db") { | 38 | : sqlite3_t("/tmp/RP.db") { |
38 | assert(_D); | 39 | assert(_D); |
39 | char **resp; int nrow,ncol; char *errm; | 40 | char **resp; int nrow,ncol; char *errm; |
40 | if(sqlite3_get_table( | 41 | if(sqlite3_get_table( |
41 | _D,"SELECT a_op FROM assoc LIMIT 0", | 42 | _D,"SELECT a_op FROM assoc LIMIT 0", |
42 | &resp,&nrow,&ncol,&errm)!=SQLITE_OK) { | 43 | &resp,&nrow,&ncol,&errm)!=SQLITE_OK) { |
43 | extern const char *__RP_db_bootstrap; | 44 | extern const char *__RP_db_bootstrap; |
44 | DOUT_("Bootstrapping DB"); | 45 | DOUT_("Bootstrapping DB"); |
45 | if(sqlite3_exec(_D,__RP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK) | 46 | if(sqlite3_exec(_D,__RP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK) |
46 | throw opkele::exception(OPKELE_CP_ string("Failed to bootstrap SQLite database: ")+errm); | 47 | throw opkele::exception(OPKELE_CP_ string("Failed to bootstrap SQLite database: ")+errm); |
47 | }else | 48 | }else |
48 | sqlite3_free_table(resp); | 49 | sqlite3_free_table(resp); |
49 | 50 | ||
50 | } | 51 | } |
51 | }; | 52 | }; |
52 | 53 | ||
53 | class example_rp_t : public opkele::prequeue_RP { | 54 | class example_rp_t : public opkele::prequeue_RP { |
54 | public: | 55 | public: |
55 | mutable rpdb_t db; | 56 | mutable rpdb_t db; |
56 | kingate::cookie htc; | 57 | kingate::cookie htc; |
57 | long as_id; | 58 | long as_id; |
58 | int ordinal; | 59 | int ordinal; |
59 | kingate::cgi_gateway& gw; | 60 | kingate::cgi_gateway& gw; |
60 | 61 | ||
61 | example_rp_t(kingate::cgi_gateway& g) | 62 | example_rp_t(kingate::cgi_gateway& g) |
62 | : as_id(-1), ordinal(0), gw(g), have_eqtop(false) { | 63 | : as_id(-1), ordinal(0), gw(g), have_eqtop(false) { |
63 | try { | 64 | try { |
64 | htc = gw.cookies.get_cookie("ht_session"); | 65 | htc = gw.cookies.get_cookie("ht_session"); |
65 | as_id = opkele::util::string_to_long(gw.get_param("asid")); | 66 | as_id = opkele::util::string_to_long(gw.get_param("asid")); |
66 | }catch(kingate::exception_notfound& kenf) { | 67 | }catch(kingate::exception_notfound& kenf) { |
67 | uuid_t uuid; uuid_generate(uuid); | 68 | uuid_t uuid; uuid_generate(uuid); |
68 | htc = kingate::cookie("ht_session",util::encode_base64(uuid,sizeof(uuid))); | 69 | htc = kingate::cookie("ht_session",util::encode_base64(uuid,sizeof(uuid))); |
69 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | 70 | sqlite3_mem_t<char*> S = sqlite3_mprintf( |
70 | "INSERT INTO ht_sessions (hts_id) VALUES (%Q)", | 71 | "INSERT INTO ht_sessions (hts_id) VALUES (%Q)", |
71 | htc.get_value().c_str()); | 72 | htc.get_value().c_str()); |
72 | db.exec(S); | 73 | db.exec(S); |
73 | } | 74 | } |
74 | } | 75 | } |
75 | 76 | ||
76 | /* Global persistent store */ | 77 | /* Global persistent store */ |
77 | 78 | ||
78 | opkele::assoc_t store_assoc( | 79 | opkele::assoc_t store_assoc( |
79 | const string& OP,const string& handle, | 80 | const string& OP,const string& handle, |
80 | const string& type,const secret_t& secret, | 81 | const string& type,const secret_t& secret, |
81 | int expires_in) { | 82 | int expires_in) { |
82 | DUMBTHROW; | 83 | DUMBTHROW; |
83 | DOUT_("Storing '" << handle << "' assoc with '" << OP << "'"); | 84 | DOUT_("Storing '" << handle << "' assoc with '" << OP << "'"); |
84 | time_t exp = time(0)+expires_in; | 85 | time_t exp = time(0)+expires_in; |
85 | sqlite3_mem_t<char*> | 86 | sqlite3_mem_t<char*> |
86 | S = sqlite3_mprintf( | 87 | S = sqlite3_mprintf( |
87 | "INSERT INTO assoc" | 88 | "INSERT INTO assoc" |
88 | " (a_op,a_handle,a_type,a_ctime,a_etime,a_secret)" | 89 | " (a_op,a_handle,a_type,a_ctime,a_etime,a_secret)" |
89 | " VALUES (" | 90 | " VALUES (" |
90 | " %Q,%Q,%Q," | 91 | " %Q,%Q,%Q," |
91 | " datetime('now'), datetime('now','+%d seconds')," | 92 | " datetime('now'), datetime('now','+%d seconds')," |
92 | " %Q" | 93 | " %Q" |
93 | " );", OP.c_str(), handle.c_str(), type.c_str(), | 94 | " );", OP.c_str(), handle.c_str(), type.c_str(), |
94 | expires_in, | 95 | expires_in, |
95 | util::encode_base64(&(secret.front()),secret.size()).c_str() ); | 96 | util::encode_base64(&(secret.front()),secret.size()).c_str() ); |
96 | db.exec(S); | 97 | db.exec(S); |
97 | return opkele::assoc_t(new opkele::association( | 98 | return opkele::assoc_t(new opkele::association( |
98 | OP, handle, type, secret, exp, false )); | 99 | OP, handle, type, secret, exp, false )); |
99 | } | 100 | } |
100 | 101 | ||
101 | opkele::assoc_t find_assoc( | 102 | opkele::assoc_t find_assoc( |
102 | const string& OP) { | 103 | const string& OP) { |
103 | DUMBTHROW; | 104 | DUMBTHROW; |
104 | DOUT_("Looking for an assoc with '" << OP << '\''); | 105 | DOUT_("Looking for an assoc with '" << OP << '\''); |
105 | sqlite3_mem_t<char*> | 106 | sqlite3_mem_t<char*> |
106 | S = sqlite3_mprintf( | 107 | S = sqlite3_mprintf( |
107 | "SELECT" | 108 | "SELECT" |
108 | " a_op,a_handle,a_type,a_secret," | 109 | " a_op,a_handle,a_type,a_secret," |
109 | " strftime('%%s',a_etime) AS a_etime" | 110 | " strftime('%%s',a_etime) AS a_etime" |
110 | " FROM assoc" | 111 | " FROM assoc" |
111 | " WHERE a_op=%Q AND a_itime IS NULL AND NOT a_stateless" | 112 | " WHERE a_op=%Q AND a_itime IS NULL AND NOT a_stateless" |
112 | " AND ( a_etime > datetime('now','-30 seconds') )" | 113 | " AND ( a_etime > datetime('now','-30 seconds') )" |
113 | " LIMIT 1", | 114 | " LIMIT 1", |
114 | OP.c_str()); | 115 | OP.c_str()); |
115 | sqlite3_table_t T; | 116 | sqlite3_table_t T; |
116 | int nr,nc; | 117 | int nr,nc; |
117 | db.get_table(S,T,&nr,&nc); | 118 | db.get_table(S,T,&nr,&nc); |
118 | if(nr<1) | 119 | if(nr<1) |
119 | throw opkele::failed_lookup(OPKELE_CP_ "Couldn't find unexpired handle"); | 120 | throw opkele::failed_lookup(OPKELE_CP_ "Couldn't find unexpired handle"); |
120 | assert(nr==1); | 121 | assert(nr==1); |
121 | assert(nc==5); | 122 | assert(nc==5); |
122 | secret_t secret; | 123 | secret_t secret; |
123 | util::decode_base64(T.get(1,3,nc),secret); | 124 | util::decode_base64(T.get(1,3,nc),secret); |
124 | DOUT_(" found '" << T.get(1,1,nc) << '\''); | 125 | DOUT_(" found '" << T.get(1,1,nc) << '\''); |
125 | return opkele::assoc_t(new opkele::association( | 126 | return opkele::assoc_t(new opkele::association( |
126 | T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), | 127 | T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), |
127 | secret, strtol(T.get(1,4,nc),0,0), false )); | 128 | secret, strtol(T.get(1,4,nc),0,0), false )); |
128 | } | 129 | } |
129 | 130 | ||
130 | opkele::assoc_t retrieve_assoc( | 131 | opkele::assoc_t retrieve_assoc( |
131 | const string& OP,const string& handle) { | 132 | const string& OP,const string& handle) { |
132 | DUMBTHROW; | 133 | DUMBTHROW; |
133 | DOUT_("Retrieving assoc '" << handle << "' with '" << OP << '\''); | 134 | DOUT_("Retrieving assoc '" << handle << "' with '" << OP << '\''); |
134 | sqlite3_mem_t<char*> | 135 | sqlite3_mem_t<char*> |
135 | S = sqlite3_mprintf( | 136 | S = sqlite3_mprintf( |
136 | "SELECT" | 137 | "SELECT" |
137 | " a_op,a_handle,a_type,a_secret," | 138 | " a_op,a_handle,a_type,a_secret," |
138 | " strftime('%%s',a_etime) AS a_etime" | 139 | " strftime('%%s',a_etime) AS a_etime" |
139 | " FROM assoc" | 140 | " FROM assoc" |
140 | " WHERE a_op=%Q AND a_handle=%Q" | 141 | " WHERE a_op=%Q AND a_handle=%Q" |
141 | " AND a_itime IS NULL AND NOT a_stateless" | 142 | " AND a_itime IS NULL AND NOT a_stateless" |
142 | " LIMIT 1", | 143 | " LIMIT 1", |
143 | OP.c_str(),handle.c_str()); | 144 | OP.c_str(),handle.c_str()); |
144 | sqlite3_table_t T; | 145 | sqlite3_table_t T; |
145 | int nr,nc; | 146 | int nr,nc; |
146 | db.get_table(S,T,&nr,&nc); | 147 | db.get_table(S,T,&nr,&nc); |
147 | if(nr<1) | 148 | if(nr<1) |
148 | throw opkele::failed_lookup(OPKELE_CP_ "couldn't retrieve valid association"); | 149 | throw opkele::failed_lookup(OPKELE_CP_ "couldn't retrieve valid association"); |
149 | assert(nr==1); assert(nc==5); | 150 | assert(nr==1); assert(nc==5); |
150 | secret_t secret; util::decode_base64(T.get(1,3,nc),secret); | 151 | secret_t secret; util::decode_base64(T.get(1,3,nc),secret); |
151 | DOUT_(" found. type=" << T.get(1,2,nc) << '\''); | 152 | DOUT_(" found. type=" << T.get(1,2,nc) << '\''); |
152 | return opkele::assoc_t(new opkele::association( | 153 | return opkele::assoc_t(new opkele::association( |
153 | T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), | 154 | T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), |
154 | secret, strtol(T.get(1,4,nc),0,0), false )); | 155 | secret, strtol(T.get(1,4,nc),0,0), false )); |
155 | } | 156 | } |
156 | 157 | ||
157 | void invalidate_assoc( | 158 | void invalidate_assoc( |
158 | const string& OP,const string& handle) { | 159 | const string& OP,const string& handle) { |
159 | DUMBTHROW; | 160 | DUMBTHROW; |
160 | DOUT_("Invalidating assoc '" << handle << "' with '" << OP << '\''); | 161 | DOUT_("Invalidating assoc '" << handle << "' with '" << OP << '\''); |
161 | sqlite3_mem_t<char*> | 162 | sqlite3_mem_t<char*> |
162 | S = sqlite3_mprintf( | 163 | S = sqlite3_mprintf( |
163 | "UPDATE assoc SET a_itime=datetime('now')" | 164 | "UPDATE assoc SET a_itime=datetime('now')" |
164 | " WHERE a_op=%Q AND a_handle=%Q", | 165 | " WHERE a_op=%Q AND a_handle=%Q", |
165 | OP.c_str(), handle.c_str() ); | 166 | OP.c_str(), handle.c_str() ); |
166 | db.exec(S); | 167 | db.exec(S); |
167 | } | 168 | } |
168 | 169 | ||
169 | void check_nonce(const string& OP,const string& nonce) { | 170 | void check_nonce(const string& OP,const string& nonce) { |
170 | DOUT_("Checking nonce '" << nonce << "' from '" << OP << '\''); | 171 | DOUT_("Checking nonce '" << nonce << "' from '" << OP << '\''); |
171 | sqlite3_mem_t<char*> | 172 | sqlite3_mem_t<char*> |
172 | S = sqlite3_mprintf( | 173 | S = sqlite3_mprintf( |
173 | "SELECT 1 FROM nonces WHERE n_op=%Q AND n_once=%Q", | 174 | "SELECT 1 FROM nonces WHERE n_op=%Q AND n_once=%Q", |
174 | OP.c_str(), nonce.c_str()); | 175 | OP.c_str(), nonce.c_str()); |
175 | sqlite3_table_t T; | 176 | sqlite3_table_t T; |
176 | int nr,nc; | 177 | int nr,nc; |
177 | db.get_table(S,T,&nr,&nc); | 178 | db.get_table(S,T,&nr,&nc); |
178 | if(nr) | 179 | if(nr) |
179 | throw opkele::id_res_bad_nonce(OPKELE_CP_ "already seen that nonce"); | 180 | throw opkele::id_res_bad_nonce(OPKELE_CP_ "already seen that nonce"); |
180 | sqlite3_mem_t<char*> | 181 | sqlite3_mem_t<char*> |
181 | SS = sqlite3_mprintf( | 182 | SS = sqlite3_mprintf( |
182 | "INSERT INTO nonces (n_op,n_once) VALUES (%Q,%Q)", | 183 | "INSERT INTO nonces (n_op,n_once) VALUES (%Q,%Q)", |
183 | OP.c_str(), nonce.c_str()); | 184 | OP.c_str(), nonce.c_str()); |
184 | db.exec(SS); | 185 | db.exec(SS); |
185 | } | 186 | } |
186 | 187 | ||
187 | /* Session perisistent store */ | 188 | /* Session perisistent store */ |
188 | 189 | ||
189 | void begin_queueing() { | 190 | void begin_queueing() { |
190 | assert(as_id>=0); | 191 | assert(as_id>=0); |
191 | DOUT_("Resetting queue for session '" << htc.get_value() << "'/" << as_id); | 192 | DOUT_("Resetting queue for session '" << htc.get_value() << "'/" << as_id); |
192 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | 193 | sqlite3_mem_t<char*> S = sqlite3_mprintf( |
193 | "DELETE FROM endpoints_queue" | 194 | "DELETE FROM endpoints_queue" |
194 | " WHERE as_id=%ld", | 195 | " WHERE as_id=%ld", |
195 | as_id); | 196 | as_id); |