summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2005-07-19 13:08:32 (UTC)
committer Michael Krelin <hacker@klever.net>2005-07-19 13:08:32 (UTC)
commit4c82851dd5d5644a89d4f269079bf901f763ee33 (patch) (unidiff)
treeb64c8b3c9a1be88e2a9c3f762272e0b4509ba7d9
parent907343b0c973eb295bec8795902a6d49744e9174 (diff)
downloadlibopkele-4c82851dd5d5644a89d4f269079bf901f763ee33.zip
libopkele-4c82851dd5d5644a89d4f269079bf901f763ee33.tar.gz
libopkele-4c82851dd5d5644a89d4f269079bf901f763ee33.tar.bz2
initial commit of libopkele - OpenID support library
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitignore21
-rw-r--r--AUTHORS3
-rw-r--r--COPYING19
-rw-r--r--ChangeLog0
-rw-r--r--Doxyfile.in247
-rw-r--r--Makefile.am23
-rw-r--r--NEWS.xml6
-rw-r--r--NEWS.xsl24
-rw-r--r--README0
-rw-r--r--acinclude.d/libcurl.m4209
-rw-r--r--acinclude.m4213
-rwxr-xr-xautogen.sh9
-rw-r--r--configure.ac87
-rw-r--r--include/.gitignore2
-rw-r--r--include/Makefile.am11
-rw-r--r--include/opkele/.gitignore2
-rw-r--r--include/opkele/acconfig.h.in3
-rw-r--r--include/opkele/association.h89
-rw-r--r--include/opkele/consumer.h135
-rw-r--r--include/opkele/data.h12
-rw-r--r--include/opkele/exception.h206
-rw-r--r--include/opkele/opkele-config.h6
-rw-r--r--include/opkele/server.h95
-rw-r--r--include/opkele/types.h168
-rw-r--r--include/opkele/util.h60
-rw-r--r--lib/.gitignore7
-rw-r--r--lib/Makefile.am24
-rw-r--r--lib/consumer.cc316
-rw-r--r--lib/data.cc11
-rw-r--r--lib/exception.cc22
-rw-r--r--lib/params.cc96
-rw-r--r--lib/secret.cc61
-rw-r--r--lib/server.cc169
-rw-r--r--lib/util.cc138
-rw-r--r--libopkele.pc.in11
35 files changed, 2505 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..87771db
--- a/dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
1configure
2Makefile.in
3Doxyfile
4config.log
5depcomp
6config.guess
7config.h
8config.sub
9ltmain.sh
10INSTALL
11NEWS
12Makefile
13config.status
14stamp-h1
15config.h.in
16libtool
17autom4te.cache
18libopkele.pc
19missing
20aclocal.m4
21install-sh
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..a9fb0c7
--- a/dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
1Klever dissected:
2 Michael 'hacker' Krelin <hacker@klever.net>
3 Leonid Ivanov <kamel@klever.net>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..7c61600
--- a/dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
1Copyright (c) 2005 Klever Group (http://www.klever.net/)
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/ChangeLog
diff --git a/Doxyfile.in b/Doxyfile.in
new file mode 100644
index 0000000..fac9a29
--- a/dev/null
+++ b/Doxyfile.in
@@ -0,0 +1,247 @@
1# Doxyfile 1.3.9.1
2
3#---------------------------------------------------------------------------
4# Project related configuration options
5#---------------------------------------------------------------------------
6PROJECT_NAME = @PACKAGE@
7PROJECT_NUMBER = @VERSION@
8OUTPUT_DIRECTORY = @builddir@/doxydox
9CREATE_SUBDIRS = NO
10OUTPUT_LANGUAGE = English
11USE_WINDOWS_ENCODING = NO
12BRIEF_MEMBER_DESC = YES
13REPEAT_BRIEF = YES
14ABBREVIATE_BRIEF =
15ALWAYS_DETAILED_SEC = NO
16INLINE_INHERITED_MEMB = NO
17FULL_PATH_NAMES = YES
18STRIP_FROM_PATH = include
19STRIP_FROM_INC_PATH = include
20SHORT_NAMES = NO
21JAVADOC_AUTOBRIEF = NO
22MULTILINE_CPP_IS_BRIEF = NO
23DETAILS_AT_TOP = NO
24INHERIT_DOCS = YES
25DISTRIBUTE_GROUP_DOC = NO
26TAB_SIZE = 8
27ALIASES =
28OPTIMIZE_OUTPUT_FOR_C = NO
29OPTIMIZE_OUTPUT_JAVA = NO
30SUBGROUPING = YES
31
32#---------------------------------------------------------------------------
33# Build related configuration options
34#---------------------------------------------------------------------------
35
36EXTRACT_ALL = NO
37EXTRACT_PRIVATE = NO
38EXTRACT_STATIC = NO
39EXTRACT_LOCAL_CLASSES = YES
40EXTRACT_LOCAL_METHODS = NO
41HIDE_UNDOC_MEMBERS = NO
42HIDE_UNDOC_CLASSES = NO
43HIDE_FRIEND_COMPOUNDS = NO
44HIDE_IN_BODY_DOCS = NO
45INTERNAL_DOCS = NO
46CASE_SENSE_NAMES = YES
47HIDE_SCOPE_NAMES = NO
48SHOW_INCLUDE_FILES = NO
49INLINE_INFO = YES
50SORT_MEMBER_DOCS = YES
51SORT_BRIEF_DOCS = NO
52SORT_BY_SCOPE_NAME = YES
53GENERATE_TODOLIST = YES
54GENERATE_TESTLIST = YES
55GENERATE_BUGLIST = YES
56GENERATE_DEPRECATEDLIST= YES
57ENABLED_SECTIONS =
58MAX_INITIALIZER_LINES = 30
59SHOW_USED_FILES = NO
60SHOW_DIRECTORIES = YES
61
62#---------------------------------------------------------------------------
63# configuration options related to warning and progress messages
64#---------------------------------------------------------------------------
65
66QUIET = NO
67WARNINGS = YES
68WARN_IF_UNDOCUMENTED = YES
69WARN_IF_DOC_ERROR = YES
70WARN_FORMAT = "$file:$line: $text"
71WARN_LOGFILE =
72
73#---------------------------------------------------------------------------
74# configuration options related to the input files
75#---------------------------------------------------------------------------
76
77INPUT = \
78 @srcdir@/include/opkele/
79FILE_PATTERNS = *.h
80RECURSIVE = NO
81EXCLUDE =
82EXCLUDE_SYMLINKS = NO
83EXCLUDE_PATTERNS =
84EXAMPLE_PATH =
85EXAMPLE_PATTERNS =
86EXAMPLE_RECURSIVE = NO
87IMAGE_PATH =
88INPUT_FILTER =
89FILTER_PATTERNS =
90FILTER_SOURCE_FILES = NO
91
92#---------------------------------------------------------------------------
93# configuration options related to source browsing
94#---------------------------------------------------------------------------
95
96SOURCE_BROWSER = NO
97INLINE_SOURCES = NO
98STRIP_CODE_COMMENTS = YES
99REFERENCED_BY_RELATION = YES
100REFERENCES_RELATION = YES
101VERBATIM_HEADERS = YES
102
103#---------------------------------------------------------------------------
104# configuration options related to the alphabetical class index
105#---------------------------------------------------------------------------
106
107ALPHABETICAL_INDEX = YES
108COLS_IN_ALPHA_INDEX = 2
109IGNORE_PREFIX =
110
111#---------------------------------------------------------------------------
112# configuration options related to the HTML output
113#---------------------------------------------------------------------------
114
115GENERATE_HTML = YES
116HTML_OUTPUT = html
117HTML_FILE_EXTENSION = .html
118HTML_HEADER =
119HTML_FOOTER =
120HTML_STYLESHEET =
121HTML_ALIGN_MEMBERS = YES
122GENERATE_HTMLHELP = NO
123CHM_FILE =
124HHC_LOCATION =
125GENERATE_CHI = NO
126BINARY_TOC = NO
127TOC_EXPAND = NO
128DISABLE_INDEX = NO
129ENUM_VALUES_PER_LINE = 4
130GENERATE_TREEVIEW = NO
131TREEVIEW_WIDTH = 250
132
133#---------------------------------------------------------------------------
134# configuration options related to the LaTeX output
135#---------------------------------------------------------------------------
136
137GENERATE_LATEX = NO
138LATEX_OUTPUT = latex
139LATEX_CMD_NAME = latex
140MAKEINDEX_CMD_NAME = makeindex
141COMPACT_LATEX = NO
142PAPER_TYPE = a4wide
143EXTRA_PACKAGES =
144LATEX_HEADER =
145PDF_HYPERLINKS = NO
146USE_PDFLATEX = NO
147LATEX_BATCHMODE = NO
148LATEX_HIDE_INDICES = NO
149
150#---------------------------------------------------------------------------
151# configuration options related to the RTF output
152#---------------------------------------------------------------------------
153
154GENERATE_RTF = NO
155RTF_OUTPUT = rtf
156COMPACT_RTF = NO
157RTF_HYPERLINKS = NO
158RTF_STYLESHEET_FILE =
159RTF_EXTENSIONS_FILE =
160
161#---------------------------------------------------------------------------
162# configuration options related to the man page output
163#---------------------------------------------------------------------------
164
165GENERATE_MAN = NO
166MAN_OUTPUT = man
167MAN_EXTENSION = .3
168MAN_LINKS = YES
169
170#---------------------------------------------------------------------------
171# configuration options related to the XML output
172#---------------------------------------------------------------------------
173
174GENERATE_XML = YES
175XML_OUTPUT = xml
176XML_SCHEMA =
177XML_DTD =
178XML_PROGRAMLISTING = YES
179
180#---------------------------------------------------------------------------
181# configuration options for the AutoGen Definitions output
182#---------------------------------------------------------------------------
183
184GENERATE_AUTOGEN_DEF = NO
185
186#---------------------------------------------------------------------------
187# configuration options related to the Perl module output
188#---------------------------------------------------------------------------
189
190GENERATE_PERLMOD = NO
191PERLMOD_LATEX = NO
192PERLMOD_PRETTY = YES
193PERLMOD_MAKEVAR_PREFIX =
194
195#---------------------------------------------------------------------------
196# Configuration options related to the preprocessor
197#---------------------------------------------------------------------------
198
199ENABLE_PREPROCESSING = YES
200MACRO_EXPANSION = NO
201EXPAND_ONLY_PREDEF = NO
202SEARCH_INCLUDES = YES
203INCLUDE_PATH =
204INCLUDE_FILE_PATTERNS =
205PREDEFINED =
206EXPAND_AS_DEFINED =
207SKIP_FUNCTION_MACROS = YES
208
209#---------------------------------------------------------------------------
210# Configuration::additions related to external references
211#---------------------------------------------------------------------------
212
213TAGFILES =
214GENERATE_TAGFILE =
215ALLEXTERNALS = NO
216EXTERNAL_GROUPS = YES
217PERL_PATH = /usr/bin/perl
218
219#---------------------------------------------------------------------------
220# Configuration options related to the dot tool
221#---------------------------------------------------------------------------
222
223CLASS_DIAGRAMS = YES
224HIDE_UNDOC_RELATIONS = YES
225HAVE_DOT = @HAVE_DOT@
226CLASS_GRAPH = YES
227COLLABORATION_GRAPH = YES
228UML_LOOK = NO
229TEMPLATE_RELATIONS = YES
230INCLUDE_GRAPH = YES
231INCLUDED_BY_GRAPH = YES
232CALL_GRAPH = NO
233GRAPHICAL_HIERARCHY = YES
234DOT_IMAGE_FORMAT = png
235DOT_PATH = @DOT@
236DOTFILE_DIRS =
237MAX_DOT_GRAPH_WIDTH = 1024
238MAX_DOT_GRAPH_HEIGHT = 1024
239MAX_DOT_GRAPH_DEPTH = 0
240GENERATE_LEGEND = YES
241DOT_CLEANUP = YES
242
243#---------------------------------------------------------------------------
244# Configuration::additions related to the search engine
245#---------------------------------------------------------------------------
246
247SEARCHENGINE = NO
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..c577ef8
--- a/dev/null
+++ b/Makefile.am
@@ -0,0 +1,23 @@
1
2SUBDIRS=include lib
3EXTRA_DIST= NEWS NEWS.xml NEWS.xsl
4
5DISTCHECK_CONFIGURE_FLAGS=--with-pkgconfigdir=$${dc_install_base}/lib/pkgconfig
6if HAVE_PKGCONFIG
7pkgconfigdir=@PKGCONFIG_DIR@
8pkgconfig_DATA=libopkele.pc
9endif
10
11all-local: NEWS
12if HAVE_DOXYGEN
13clean-local:
14 rm -rf doxydox
15endif
16
17NEWS: NEWS.xsl NEWS.xml
18 ${XSLTPROC} -o $@ NEWS.xsl NEWS.xml
19
20if HAVE_DOXYGEN
21dox: Doxyfile
22 ${DOXYGEN}
23endif
diff --git a/NEWS.xml b/NEWS.xml
new file mode 100644
index 0000000..f8f3331
--- a/dev/null
+++ b/NEWS.xml
@@ -0,0 +1,6 @@
1<?xml version="1.0" encoding="us-ascii"?>
2<news>
3 <version version="0.0" date="July 16th, 2005">
4 <ni>Initial release</ni>
5 </version>
6</news>
diff --git a/NEWS.xsl b/NEWS.xsl
new file mode 100644
index 0000000..7c71307
--- a/dev/null
+++ b/NEWS.xsl
@@ -0,0 +1,24 @@
1<?xml version="1.0" encoding="us-ascii"?>
2<xsl:stylesheet version="1.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4 >
5 <xsl:output
6 method="text"
7 encoding="us-ascii"
8 media-type="text/plain" />
9
10 <xsl:template match="news">
11 <xsl:apply-templates/>
12 </xsl:template>
13 <xsl:template match="version">
14 <xsl:value-of select="concat(@version,' (',@date,')&#xA;')"/>
15 <xsl:apply-templates/>
16 </xsl:template>
17 <xsl:template match="ni">
18 <xsl:text> - </xsl:text>
19 <xsl:apply-templates mode="text"/>
20 <xsl:text>&#xA;</xsl:text>
21 </xsl:template>
22 <xsl:template match="*|text()"/>
23
24</xsl:stylesheet>
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/README
diff --git a/acinclude.d/libcurl.m4 b/acinclude.d/libcurl.m4
new file mode 100644
index 0000000..e80c206
--- a/dev/null
+++ b/acinclude.d/libcurl.m4
@@ -0,0 +1,209 @@
1# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
2# [ACTION-IF-YES], [ACTION-IF-NO])
3# ----------------------------------------------------------
4# David Shaw <dshaw@jabberwocky.com> Jan-23-2005
5#
6# Checks for libcurl. DEFAULT-ACTION is the string yes or no to
7# specify whether to default to --with-libcurl or --without-libcurl.
8# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
9# minimum version of libcurl to accept. Pass the version as a regular
10# version number like 7.10.1. If not supplied, any version is
11# accepted. ACTION-IF-YES is a list of shell commands to run if
12# libcurl was successfully found and passed the various tests.
13# ACTION-IF-NO is a list of shell commands that are run otherwise.
14# Note that using --without-libcurl does run ACTION-IF-NO.
15#
16# This macro defines HAVE_LIBCURL if a working libcurl setup is found,
17# and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary values.
18# Other useful defines are LIBCURL_FEATURE_xxx where xxx are the
19# various features supported by libcurl, and LIBCURL_PROTOCOL_yyy
20# where yyy are the various protocols supported by libcurl. Both xxx
21# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of
22# the macro for the complete list of possible defines. Shell
23# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also
24# defined to 'yes' for those features and protocols that were found.
25# Note that xxx and yyy keep the same capitalization as in the
26# curl-config list (e.g. it's "HTTP" and not "http").
27#
28# Users may override the detected values by doing something like:
29# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure
30#
31# For the sake of sanity, this macro assumes that any libcurl that is
32# found is after version 7.7.2, the first version that included the
33# curl-config script. Note that it is very important for people
34# packaging binary versions of libcurl to include this script!
35# Without curl-config, we can only make educated guesses as to what
36# protocols are available. Specifically, we assume that all of HTTP,
37# FTP, GOPHER, FILE, TELNET, LDAP, and DICT exist, and (if SSL exists)
38# HTTPS is present. All of these protocols existed when libcurl was
39# first created in version 7, so this is a safe assumption. If the
40# version is 7.11.0 or later, FTPS is assumed to be present as well.
41# FTPS existed before then, but was not yet fully standards compliant.
42
43AC_DEFUN([LIBCURL_CHECK_CONFIG],
44[
45 AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL])
46 AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4])
47 AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6])
48 AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz])
49 AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS])
50
51 AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
52 AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
53 AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP])
54 AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS])
55 AH_TEMPLATE([LIBCURL_PROTOCOL_GOPHER],[Defined if libcurl supports GOPHER])
56 AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE])
57 AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET])
58 AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
59 AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
60
61 AC_ARG_WITH(libcurl,
62 AC_HELP_STRING([--with-libcurl=DIR],[look for the curl library in DIR]),
63 [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])])
64
65 if test "$_libcurl_with" != "no" ; then
66
67 AC_PROG_AWK
68
69 _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
70
71 _libcurl_try_link=yes
72
73 if test -d "$_libcurl_with" ; then
74 CPPFLAGS="${CPPFLAGS} -I$withval/include"
75 LDFLAGS="${LDFLAGS} -L$withval/lib"
76 fi
77
78 AC_PATH_PROG([_libcurl_config],[curl-config])
79
80 if test x$_libcurl_config != "x" ; then
81 AC_CACHE_CHECK([for the version of libcurl],
82 [libcurl_cv_lib_curl_version],
83 [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`])
84
85 _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse`
86 _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse`
87
88 if test $_libcurl_wanted -gt 0 ; then
89 AC_CACHE_CHECK([for libcurl >= version $2],
90 [libcurl_cv_lib_version_ok],
91 [
92 if test $_libcurl_version -ge $_libcurl_wanted ; then
93 libcurl_cv_lib_version_ok=yes
94 else
95 libcurl_cv_lib_version_ok=no
96 fi
97 ])
98 fi
99
100 if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then
101 if test x"$LIBCURL_CPPFLAGS" = "x" ; then
102 LIBCURL_CPPFLAGS=`$_libcurl_config --cflags`
103 fi
104 if test x"$LIBCURL" = "x" ; then
105 LIBCURL=`$_libcurl_config --libs`
106 fi
107
108 # All curl-config scripts support --feature
109 _libcurl_features=`$_libcurl_config --feature`
110
111 # Is it modern enough to have --protocols? (7.12.4)
112 if test $_libcurl_version -ge 461828 ; then
113 _libcurl_protocols=`$_libcurl_config --protocols`
114 fi
115 else
116 _libcurl_try_link=no
117 fi
118
119 unset _libcurl_wanted
120 fi
121
122 if test $_libcurl_try_link = yes ; then
123
124 # we didn't find curl-config, so let's see if the user-supplied
125 # link line (or failing that, "-lcurl") is enough.
126 LIBCURL=${LIBCURL-"-lcurl"}
127
128 AC_CACHE_CHECK([whether libcurl is usable],
129 [libcurl_cv_lib_curl_usable],
130 [
131 _libcurl_save_cppflags=$CPPFLAGS
132 CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS"
133 _libcurl_save_ldflags=$LDFLAGS
134 LDFLAGS="$LDFLAGS $LIBCURL"
135
136 AC_LINK_IFELSE(AC_LANG_PROGRAM([#include <curl/curl.h>],[
137/* Try and use a few common options to force a failure if we are
138 missing symbols or can't link. */
139int x;
140curl_easy_setopt(NULL,CURLOPT_URL,NULL);
141x=CURL_ERROR_SIZE;
142x=CURLOPT_WRITEFUNCTION;
143x=CURLOPT_FILE;
144x=CURLOPT_ERRORBUFFER;
145x=CURLOPT_STDERR;
146x=CURLOPT_VERBOSE;
147]),libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no)
148
149 CPPFLAGS=$_libcurl_save_cppflags
150 LDFLAGS=$_libcurl_save_ldflags
151 unset _libcurl_save_cppflags
152 unset _libcurl_save_ldflags
153 ])
154
155 if test $libcurl_cv_lib_curl_usable = yes ; then
156 AC_DEFINE(HAVE_LIBCURL,1,
157 [Define to 1 if you have a functional curl library.])
158 AC_SUBST(LIBCURL_CPPFLAGS)
159 AC_SUBST(LIBCURL)
160
161 for _libcurl_feature in $_libcurl_features ; do
162 AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1])
163 eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes
164 done
165
166 if test "x$_libcurl_protocols" = "x" ; then
167
168 # We don't have --protocols, so just assume that all
169 # protocols are available
170 _libcurl_protocols="HTTP FTP GOPHER FILE TELNET LDAP DICT"
171
172 if test x$libcurl_feature_SSL = xyes ; then
173 _libcurl_protocols="$_libcurl_protocols HTTPS"
174
175 # FTPS wasn't standards-compliant until version
176 # 7.11.0
177 if test $_libcurl_version -ge 461568; then
178 _libcurl_protocols="$_libcurl_protocols FTPS"
179 fi
180 fi
181 fi
182
183 for _libcurl_protocol in $_libcurl_protocols ; do
184 AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
185 eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
186 done
187 fi
188 fi
189
190 unset _libcurl_try_link
191 unset _libcurl_version_parse
192 unset _libcurl_config
193 unset _libcurl_feature
194 unset _libcurl_features
195 unset _libcurl_protocol
196 unset _libcurl_protocols
197 unset _libcurl_version
198 fi
199
200 if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then
201 # This is the IF-NO path
202 ifelse([$4],,:,[$4])
203 else
204 # This is the IF-YES path
205 ifelse([$3],,:,[$3])
206 fi
207
208 unset _libcurl_with
209])dnl
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..9c9f945
--- a/dev/null
+++ b/acinclude.m4
@@ -0,0 +1,213 @@
1dnl AC_WITH_PKGCONFIG([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
2dnl Outputs:
3dnl AC_SUBST: PKGCONFIG_PKGCONFIG PKGCONFIG_DIR
4dnl AM_CONDTIONAL: HAVE_PKGCONFIG
5AC_DEFUN([AC_WITH_PKGCONFIG],[
6 PKGCONFIG_PKGCONFIG=""
7 PKGCONFIG_DIR=""
8 HAVE_PKGCONFIG="no"
9 EXPLICIT_PKGCONFIGDIR="no"
10 test -z "${WANT_PKGCONFIG}" && WANT_PKGCONFIG=""
11 AC_PATH_PROG([PKGCONFIG_PKGCONFIG],[pkg-config],[false])
12 if test "${PKGCONFIG_PKGCONFIG}" != "false" ; then
13 AC_ARG_WITH([pkgconfigdir],
14 AC_HELP_STRING([--with-pkgconfigdir=dir],[Specify pkgconfig directory]),
15 [
16 if test "${withval}" = "no" ; then
17 WANT_PKGCONFIG="no"
18 else
19 PKGCONFIG_DIR="${withval}"
20 EXPLICIT_PKGCONFIGDIR="yes"
21 fi
22 ],[
23 AC_MSG_CHECKING([for pkgconfig directory])
24 PKGCONFIG_DIR="`${PKGCONFIG_PKGCONFIG} --debug 2>&1 | grep '^Scanning'| head -n 1 | cut -d\' -f2-|cut -d\' -f1`"
25 AC_MSG_RESULT([${PKGCONFIG_DIR}])
26 ]
27 )
28 if test -d "${PKGCONFIG_DIR}" ; then
29 HAVE_PKGCONFIG=yes
30 AC_SUBST([PKGCONFIG_PKGCONFIG])
31 AC_SUBST([PKGCONFIG_DIR])
32 else
33 AC_MSG_NOTICE([unexistent pkgconfig directory: ${PKGCONFIG_DIR}])
34 if test "${EXPLICIT_PKGCONFIGDIR}" = "yes" ; then
35 HAVE_PKGCONFIG=yes
36 AC_SUBST([PKGCONFIG_PKGCONFIG])
37 AC_SUBST([PKGCONFIG_DIR])
38 else
39 ifelse([$2], , :, [$2])
40 fi
41 fi
42 fi
43 AM_CONDITIONAL([HAVE_PKGCONFIG],[test "${HAVE_PKGCONFIG}" = "yes"])
44])
45
46dnl AC_WITH_DOXYGEN([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
47dnl Outputs:
48dnl AC_SUBST: DOXYGEN HAVE_DOXYGEN
49dnl AM_CONDTIONAL: HAVE_DOXYGEN
50AC_DEFUN([AC_WITH_DOXYGEN],[
51 HAVE_DOXYGEN="no"
52 AC_PATH_PROG([DOXYGEN],[doxygen],[false])
53 if test "${DOXYGEN}" = "false" ; then
54 ifelse([$2], , :, [$2])
55 else
56 HAVE_DOXYGEN="yes"
57 AC_SUBST([DOXYGEN])
58 $1
59 fi
60 AC_SUBST([HAVE_DOXYGEN])
61 AM_CONDITIONAL([HAVE_DOXYGEN],[test "${HAVE_DOXYGEN}" = "yes"])
62])
63
64dnl AC_WITH_DOT([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
65dnl Outputs:
66dnl AC_SUBST: DOT HAVE_DOT
67dnl AM_CONDITIONAL: HAVE_DOT
68AC_DEFUN([AC_WITH_DOT],[
69 HAVE_DOT="no"
70 AC_PATH_PROG([DOT],[dot],[false])
71 if test "${DOT}" = "false" ; then
72 ifelse([$2], , :, [$2])
73 else
74 HAVE_DOT="yes"
75 AC_SUBST([DOT])
76 $1
77 fi
78AC_SUBST([HAVE_DOT])
79 AM_CONDITIONAL([HAVE_DOT],[test "${HAVE_DOT}" = "yes"])
80])
81
82dnl AC_WITH_PCRE([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
83dnl Outputs:
84dnl AC_SUBST: PCRE_CONFIG PCRE_PREFIX PCRE_EXEC_PREFIX
85dnl PCRE_VERSION PCRE_CFLAGS PCRE_LIBS
86dnl PCRE_LIBS_POSIX PCRE_CFLAGS_POSIX
87dnl AM_CONDITIONAL: HAVE_PCRE
88dnl AC_DEFINE: HAVE_PCRE PCRE_VERSION
89AC_DEFUN([AC_WITH_PCRE],[
90 HAVE_PCRE="no"
91 PCRE_CONFIG=""
92 PCRE_PREFIX=""
93 PCRE_EXEC_PREFIX=""
94 PCRE_VERSION=""
95 PCRE_CFLAGS=""
96 PCRE_LIBS=""
97 PCRE_LOCATIONS="${PATH}:/usr/local/bin:/usr/bin"
98 test -z "$WANT_PCRE" && WANT_PCRE=""
99 AC_ARG_WITH([pcre],
100 AC_HELP_STRING([--with-pcre=location],[Look for pcre in specified locations]),
101 [
102 if test "${withval}" = "no" ; then
103 WANT_PCRE="no"
104 else
105 if test -x "${withval}" ; then
106 PCRE_CONFIG="${withval}"
107 elif test -x "${withval}/pcre-config" ; then
108 PCRE_CONFIG="${withval}/pcre-config"
109 elif test -x "${withval}/bin/pcre-config" ; then
110 PCRE_CONFIG="${withval}/bin/pcre-config"
111 fi
112 fi
113 ]
114 )
115 if test "${WANT_PCRE}" = "no" ; then
116 ifelse([$2], , :, [$2])
117 else
118 if test -z "${PCRE_CONFIG}" ; then
119 AC_PATH_PROG(PCRE_CONFIG,[pcre-config],false,[${PCRE_LOCATIONS}])
120 if test "${PCRE_CONFIG}" = "false" ; then
121 ifelse([$2], , :, [$2])
122 else
123 HAVE_PCRE="yes"
124 PCRE_PREFIX="`${PCRE_CONFIG} --prefix`"
125 PCRE_EXEC_PREFIX="`${PCRE_CONFIG} --exec-prefix`"
126 PCRE_VERSION="`${PCRE_CONFIG} --version`"
127 PCRE_CFLAGS="`${PCRE_CONFIG} --cflags`"
128 PCRE_LIBS="`${PCRE_CONFIG} --libs`"
129 PCRE_CFLAGS_POSIX="`${PCRE_CONFIG} --cflags-posix`"
130 PCRE_LIBS_POSIX="`${PCRE_CONFIG} --libs-posix`"
131 AC_SUBST([PCRE_CONFIG])
132 AC_SUBST([PCRE_PREFIX])
133 AC_SUBST([PCRE_EXEC_PREFIX])
134 AC_SUBST([PCRE_VERSION])
135 AC_SUBST([PCRE_CFLAGS])
136 AC_SUBST([PCRE_LIBS])
137 AC_SUBST([PCRE_CFLAGS_POSIX])
138 AC_SUBST([PCRE_LIBS_POSIX])
139 AC_DEFINE([HAVE_PCRE],,[pcre support])
140 AC_DEFINE_UNQUOTED([PCRE_VERSION],["${PCRE_VERSION}"],[pcre version])
141 $1
142 fi
143 fi
144 fi
145 AM_CONDITIONAL([HAVE_PCRE],[test "${HAVE_PCRE}" = "yes"])
146])
147
148dnl AC_WITH_PCREPP([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
149dnl Outputs:
150dnl AC_SUBST: PCREPP_CONFIG PCREPP_PREFIX PCREPP_EXEC_PREFIX
151dnl PCREPP_VERSION PCREPP_CFLAGS PCREPP_LIBS
152dnl AM_CONDITIONAL: HAVE_PCREPP
153dnl AC_DEFINE: HAVE_PCREPP PCREPP_VERSION
154AC_DEFUN([AC_WITH_PCREPP],[
155 HAVE_PCREPP="no"
156 PCREPP_CONFIG=""
157 PCREPP_PREFIX=""
158 PCREPP_EXEC_PREFIX=""
159 PCREPP_VERSION=""
160 PCREPP_CFLAGS=""
161 PCREPP_LIBS=""
162 PCREPP_LOCATIONS="${PATH}:/usr/local/bin:/usr/bin"
163 test -z "$WANT_PCREPP" && WANT_PCREPP=""
164 AC_ARG_WITH([pcre++],
165 AC_HELP_STRING([--with-pcre++=location],[Look for pcre++ in specified locations]),
166 [
167 if test "${withval}" = "no" ; then
168 WANT_PCREPP="no"
169 else
170 if test -x "${withval}" ; then
171 PCREPP_CONFIG="${withval}"
172 elif test -x "${withval}/pcre++-config" ; then
173 PCREPP_CONFIG="${withval}/pcre++-config"
174 elif test -x "${withval}/bin/pcre++-config" ; then
175 PCREPP_CONFIG="${withval}/bin/pcre++-config"
176 fi
177 fi
178 ]
179 )
180 if test "${WANT_PCREPP}" = "no" ; then
181 ifelse([$2], , :, [$2])
182 else
183 if test "${HAVE_PCRE}" != "yes" ; then
184 ifelse([$2], , :, [$2])
185 else
186 if test -z "${PCREPP_CONFIG}" ; then
187 AC_PATH_PROG([PCREPP_CONFIG],[pcre++-config],false,[${PCREPP_LOCATIONS}])
188 if test "${PCREPP_CONFIG}" = "false" ; then
189 ifelse([$2], , :, [$2])
190 else
191 HAVE_PCREPP="yes"
192 PCREPP_PREFIX="`${PCREPP_CONFIG} --prefix`"
193 PCREPP_EXEC_PREFIX="`${PCREPP_CONFIG} --exec-prefix`"
194 PCREPP_VERSION="`${PCREPP_CONFIG} --version`"
195 PCREPP_CFLAGS="`${PCREPP_CONFIG} --cflags` ${PCRE_CFLAGS}"
196 PCREPP_LIBS="`${PCREPP_CONFIG} --libs` ${PCRE_LIBS}"
197 AC_SUBST([PCREPP_CONFIG])
198 AC_SUBST([PCREPP_PREFIX])
199 AC_SUBST([PCREPP_EXEC_PREFIX])
200 AC_SUBST([PCREPP_VERSION])
201 AC_SUBST([PCREPP_CFLAGS])
202 AC_SUBST([PCREPP_LIBS])
203 AC_DEFINE([HAVE_PCREPP],,[pcre++ support])
204 AC_DEFINE_UNQUOTED([PCREPP_VERSION],["${PCREPP_VERSION}"],[pcre++ version])
205 $1
206 fi
207 fi
208 fi
209 fi
210 AM_CONDITIONAL([HAVE_PCREPP],[test "${HAVE_PCREPP}" = "yes"])
211])
212
213m4_include([acinclude.d/libcurl.m4])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..ba27501
--- a/dev/null
+++ b/autogen.sh
@@ -0,0 +1,9 @@
1#!/bin/sh
2WANT_AUTOMAKE=1.8
3export WANT_AUTOMAKE
4libtoolize -f \
5&& aclocal \
6&& autoheader \
7&& automake -a \
8&& autoconf \
9&& ./configure "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..a31f5b1
--- a/dev/null
+++ b/configure.ac
@@ -0,0 +1,87 @@
1AC_INIT([libopkele], [0.0], [libopkele-bugs@klever.net])
2AC_CONFIG_SRCDIR([include/opkele/opkele-config.h])
3AC_CONFIG_HEADERS([config.h include/opkele/acconfig.h])
4AM_INIT_AUTOMAKE([dist-bzip2])
5
6AC_PROG_INSTALL
7AC_PROG_CXX
8AC_PROG_CC
9AC_PROG_LIBTOOL
10
11AC_HEADER_STDC
12
13AC_PATH_PROG([XSLTPROC],[xsltproc],[true])
14AC_WITH_PKGCONFIG
15
16PKG_CHECK_MODULES([OPENSSL],[openssl],[
17 AC_MSG_RESULT([yes])
18 ],[
19 AC_MSG_ERROR([no openssl library found. get one from http://www.openssl.org/])
20 ]
21)
22
23WANT_KONFORKA="yes"
24AC_ARG_ENABLE([konforka],
25 AC_HELP_STRING([--disable-konforka],[do not use konforka library (default: use if found)]),
26 [
27 test "${enableval}" = "no" && WANT_KONFORKA="no"
28 ]
29)
30if test "${WANT_KONFORKA}" = "yes" ; then
31 PKG_CHECK_MODULES([KONFORKA],[konforka],[
32 AC_MSG_RESULT([yes])
33 AC_SUBST([KONFORKA_CFLAGS])
34 AC_SUBST([KONFORKA_LIBS])
35 AC_DEFINE([HAVE_KONFORKA],,[defined in presence of konforka library])
36 AC_DEFINE([OPKELE_HAVE_KONFORKA],,[defined in presence of konforka library])
37 AC_SUBST([KONFORKA_KONFORKA],[konforka])
38 ]
39 )
40fi
41
42AC_LANG_PUSH([C++])
43 AC_CHECK_LIB([mimetic],[main],[
44 MIMETIC_LIBS=-lmimetic
45 AC_SUBST([MIMETIC_CFLAGS])
46 AC_SUBST([MIMETIC_LIBS])
47 ],[
48 AC_MSG_ERROR([no mimetic library found. get one from http://codesink.org/mimetic_mime_library.html])
49 ]
50 )
51AC_LANG_POP([C++])
52
53WANT_DOXYGEN="yes"
54AC_ARG_ENABLE([doxygen],
55 AC_HELP_STRING([--disable-doxygen],[do not generate documentation]),
56 [
57 test "${enableval}" = "no" && WANT_DOXYGEN="no"
58 ]
59)
60if test "${WANT_DOXYGEN}" = "yes" ; then
61 AC_WITH_DOXYGEN
62 AC_WITH_DOT
63else
64 AM_CONDITIONAL([HAVE_DOXYGEN],[false])
65 AM_CONDITIONAL([HAVE_DOT],[false])
66fi
67
68LIBCURL_CHECK_CONFIG(,,,[
69 AC_MSG_ERROR([no required libcurl library. get one from http://curl.haxx.se/])
70])
71AC_WITH_PCRE([
72 AC_WITH_PCREPP(,[
73 AC_MSG_ERROR([no pcre++ library found. get one at http://www.daemon.de/PCRE])
74 ])
75 ],[
76 AC_MSG_ERROR([no pcre library found. get one at http://www.pcre.org/])
77 ]
78)
79
80AC_CONFIG_FILES([
81 Makefile
82 libopkele.pc
83 Doxyfile
84 include/Makefile
85 lib/Makefile
86])
87AC_OUTPUT
diff --git a/include/.gitignore b/include/.gitignore
new file mode 100644
index 0000000..3dda729
--- a/dev/null
+++ b/include/.gitignore
@@ -0,0 +1,2 @@
1Makefile.in
2Makefile
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..b014752
--- a/dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,11 @@
1nobase_include_HEADERS = \
2 opkele/acconfig.h \
3 opkele/opkele-config.h \
4 opkele/types.h \
5 opkele/association.h \
6 opkele/exception.h \
7 opkele/server.h \
8 opkele/consumer.h
9EXTRA_DIST = \
10 opkele/data.h \
11 opkele/util.h
diff --git a/include/opkele/.gitignore b/include/opkele/.gitignore
new file mode 100644
index 0000000..ffa24dc
--- a/dev/null
+++ b/include/opkele/.gitignore
@@ -0,0 +1,2 @@
1acconfig.h
2stamp-h2
diff --git a/include/opkele/acconfig.h.in b/include/opkele/acconfig.h.in
new file mode 100644
index 0000000..d56a1cd
--- a/dev/null
+++ b/include/opkele/acconfig.h.in
@@ -0,0 +1,3 @@
1
2/* defined in presence of konforka library */
3#undef OPKELE_HAVE_KONFORKA
diff --git a/include/opkele/association.h b/include/opkele/association.h
new file mode 100644
index 0000000..5eb1cc3
--- a/dev/null
+++ b/include/opkele/association.h
@@ -0,0 +1,89 @@
1#ifndef __OPKELE_ASSOCIATION_H
2#define __OPKELE_ASSOCIATION_H
3
4#include <time.h>
5#include <opkele/types.h>
6
7/**
8 * @file
9 * @brief reference implementation of association_t
10 */
11
12/**
13 * @brief the main opkele namespace
14 */
15namespace opkele {
16
17 /**
18 * reference implementation of association_t class.
19 */
20 class association : public association_t {
21 public:
22 /**
23 * OpenID server name
24 */
25 string _server;
26 /**
27 * association handle
28 */
29 string _handle;
30 /**
31 * association type
32 */
33 string _assoc_type;
34 /**
35 * the secret
36 */
37 secret_t _secret;
38 /**
39 * expiration time
40 */
41 time_t _expires;
42 /**
43 * statelessness of the assoc_handle
44 */
45 bool _stateless;
46
47 /**
48 * @param __server the server name
49 * @param __handle association handle
50 * @param __assoc_type association type
51 * @param __secret the secret
52 * @param __expires expiration time
53 * @param __stateless statelessness of the assoc_handle
54 */
55 association(const string& __server, const string& __handle,
56 const string& __assoc_type, const secret_t& __secret,
57 time_t __expires, bool __stateless)
58 : _server(__server), _handle(__handle), _assoc_type(__assoc_type),
59 _secret(__secret), _expires(__expires), _stateless(__stateless) { }
60
61 /**
62 * @overload association_t::server()
63 */
64 virtual string server() const { return _server; }
65 /**
66 * @overload association_t::handle()
67 */
68 virtual string handle() const { return _handle; }
69 /**
70 * @overload association_t::assoc_type()
71 */
72 virtual string assoc_type() const { return _assoc_type; }
73 /**
74 * @overload association_t::secret()
75 */
76 virtual secret_t secret() const { return _secret; }
77 /**
78 * @overload association_t::expires_in()
79 */
80 virtual int expires_in() const { return _expires-time(0); }
81 /**
82 * @overload associationn_t::stateless()
83 */
84 virtual bool stateless() const { return _stateless; }
85 };
86
87}
88
89#endif /* __OPKELE_ASSOCIATION_H */
diff --git a/include/opkele/consumer.h b/include/opkele/consumer.h
new file mode 100644
index 0000000..b9c29bd
--- a/dev/null
+++ b/include/opkele/consumer.h
@@ -0,0 +1,135 @@
1#ifndef __OPKELE_CONSUMER_H
2#define __OPKELE_CONSUMER_H
3
4#include <opkele/types.h>
5
6/**
7 * @file
8 * @brief OpenID consumer-side functionality
9 */
10
11/**
12 * @brief the main opkele namespace
13 */
14namespace opkele {
15
16 /**
17 * implementation of basic consumer functionality
18 */
19 class consumer_t {
20 public:
21
22 /**
23 * store association. The function should be overridden in the real
24 * implementation to provide persistent associations store.
25 * @param server the OpenID server
26 * @param handle association handle
27 * @param secret the secret associated with the server and handle
28 * @param expires_in the number of seconds until the handle is expired
29 * @return the auto_ptr<> for the newly allocated association_t object
30 */
31 virtual assoc_t store_assoc(const string& server,const string& handle,const secret_t& secret,int expires_in) = 0;
32 /**
33 * retrieve stored association. The function should be overridden
34 * in the real implementation to provide persistent assocations
35 * store.
36 * @param server the OpenID server
37 * @param handle association handle
38 * @return the autho_ptr<> for the newly allocated association_t object
39 * @throw failed_lookup in case of error
40 */
41 virtual assoc_t retrieve_assoc(const string& server,const string& handle) = 0;
42 /**
43 * invalidate stored association. The function should be overridden
44 * in the real implementation of the consumer.
45 * @param server the OpenID server
46 * @param handle association handle
47 */
48 virtual void invalidate_assoc(const string& server,const string& handle) = 0;
49 /**
50 * retrieve any unexpired association for the server. If the
51 * function is not overridden in the real implementation, the new
52 * association will be established for each request.
53 * @param server the OpenID server
54 * @return the auto_ptr<> for the newly allocated association_t object
55 * @throw failed_lookup in case of absence of the handle
56 */
57 virtual assoc_t find_assoc(const string& server);
58
59 /**
60 * retrieve the metainformation contained in link tags from the
61 * page pointed by url. the function may implement caching of the
62 * information.
63 * @param url url to harvest for link tags
64 * @param server reference to the string object where to put
65 * openid.server value
66 * @param delegate reference to the string object where to put the
67 * openid.delegate value (if any)
68 */
69 virtual void retrieve_links(const string& url,string& server,string& delegate);
70
71 /**
72 * perform the associate request to OpenID server.
73 * @param server the OpenID server
74 * @return the auto_ptr<> for the newly allocated association_t
75 * object, representing established association
76 * @throw exception in case of error
77 */
78 assoc_t associate(const string& server);
79 /**
80 * prepare the parameters for the checkid_immediate
81 * request.
82 * @param identity the identity to verify
83 * @param return_to the return_to url to pass with the request
84 * @param trust_root the trust root to advertise with the request
85 * @return the location string
86 * @throw exception in case of error
87 */
88 string checkid_immediate(const string& identity,const string& return_to,const string& trust_root="");
89 /**
90 * prepare the parameters for the checkid_setup
91 * request.
92 * @param identity the identity to verify
93 * @param return_to the return_to url to pass with the request
94 * @param trust_root the trust root to advertise with the request
95 * @return the location string
96 * @throw exception in case of error
97 */
98 string checkid_setup(const string& identity,const string& return_to,const string& trust_root="");
99 /**
100 * the actual implementation behind checkid_immediate() and
101 * checkid_setup() functions.
102 * @param mode checkid_* mode - either mode_checkid_immediate or mode_checkid_setup
103 * @param identity the identity to verify
104 * @param return_to the return_to url to pass with the request
105 * @param trust_root the trust root to advertise with the request
106 * @return the location string
107 * @throw exception in case of error
108 */
109 string checkid_(mode_t mode,const string& identity,const string& return_to,const string& trust_root="");
110 /**
111 * verify the id_res response
112 * @param pin the response parameters
113 * @param identity the identity being checked (if not specified, extracted
114 * from the openid.identity parameter
115 * @throw id_res_mismatch in case of signature
116 * mismatch
117 * @throw id_res_setup in case of
118 * openid.user_setup_url failure (supposedly
119 * checkid_immediate only)
120 * @throw id_res_failed in case of failure
121 * @throw exception in case of other failures
122 */
123 void id_res(const params_t& pin,const string& identity="");
124 /**
125 * perform a check_authentication request.
126 * @param server the OpenID server
127 * @param p request parameters
128 */
129 void check_authentication(const string& server,const params_t& p);
130
131 };
132
133}
134
135#endif /* __OPKELE_CONSUMER_H */
diff --git a/include/opkele/data.h b/include/opkele/data.h
new file mode 100644
index 0000000..7fc635b
--- a/dev/null
+++ b/include/opkele/data.h
@@ -0,0 +1,12 @@
1#ifndef __OPKELE_DATA_H
2#define __OPKELE_DATA_H
3
4namespace opkele {
5
6 namespace data {
7 extern const char *_default_p;
8 extern const char *_default_g;
9 }
10}
11
12#endif /* __OPKELE_DATA_H */
diff --git a/include/opkele/exception.h b/include/opkele/exception.h
new file mode 100644
index 0000000..2ac0661
--- a/dev/null
+++ b/include/opkele/exception.h
@@ -0,0 +1,206 @@
1#ifndef __OPKELE_EXCEPTION_H
2#define __OPKELE_EXCEPTION_H
3
4/**
5 * @file
6 * @brief opkele exceptions
7 */
8
9#include <curl/curl.h>
10
11#include <opkele/opkele-config.h>
12#ifdef OPKELE_HAVE_KONFORKA
13# include <konforka/exception.h>
14/**
15 * the exception parameters declaration
16 */
17# define OPKELE_E_PARS const string& fi,const string&fu,int l,const string& w
18/**
19 * the exception parameters list to pass to constructor
20 */
21# define OPKELE_E_CONS_ fi,fu,l,
22/**
23 * the exception codepoint specification
24 */
25# define OPKELE_CP_ CODEPOINT,
26/**
27 * the simple rethrow of konforka-based exception
28 */
29# define OPKELE_RETHROW catch(konforka::exception& e) { e.see(CODEPOINT); throw }
30#else /* OPKELE_HAVE_KONFORKA */
31# include <stdexcept>
32/**
33 * the exception parameter declaration
34 */
35# define OPKELE_E_PARS const string& w
36/**
37 * the dummy prefix for exception parameters list to prepend in the absence of
38 * konforka library
39 */
40# define OPKELE_E_CONS_
41/**
42 * the dummy placeholder for konforka exception codepoint specification
43 */
44# define OPKELE_CP_
45/**
46 * the dummy define for the konforka-based rethrow of exception
47 */
48# define OPKELE_RETHROW
49#endif /* OPKELE_HAVE_KONFORKA */
50/**
51 * the exception parameters list to pass to constructor
52 */
53# define OPKELE_E_CONS OPKELE_E_CONS_ w
54
55/*
56 * @brief the main opkele namespace
57 */
58namespace opkele {
59 using std::string;
60
61 /**
62 * the base opkele exception class
63 */
64 class exception : public
65# ifdef OPKELE_HAVE_KONFORKA
66 konforka::exception
67# else
68 std::exception
69# endif
70 {
71 public:
72# ifdef OPKELE_HAVE_KONFORKA
73 explicit
74 exception(const string& fi,const string& fu,int l,const string& w)
75 : konforka::exception(fi,fu,l,w) { }
76# else /* OPKELE_HAVE_KONFORKA */
77 explicit
78 exception(const string& w)
79 : std::exception(w) { }
80# endif /* OPKELE_HAVE_KONFORKA */
81 };
82
83 /**
84 * thrown in case of failed conversion
85 */
86 class failed_conversion : public exception {
87 public:
88 failed_conversion(OPKELE_E_PARS)
89 : exception(OPKELE_E_CONS) { }
90 };
91 /**
92 * thrown in case of failed lookup (either parameter or persistent store)
93 */
94 class failed_lookup : public exception {
95 public:
96 failed_lookup(OPKELE_E_PARS)
97 : exception(OPKELE_E_CONS) { }
98 };
99 /**
100 * thrown in case of bad input (either local or network)
101 */
102 class bad_input : public exception {
103 public:
104 bad_input(OPKELE_E_PARS)
105 : exception(OPKELE_E_CONS) { }
106 };
107
108 /**
109 * thrown on failed assertion
110 */
111 class failed_assertion : public exception {
112 public:
113 failed_assertion(OPKELE_E_PARS)
114 : exception(OPKELE_E_CONS) { }
115 };
116
117 /**
118 * thrown if the handle being retrieved is invalid
119 */
120 class invalid_handle : public exception {
121 public:
122 invalid_handle(OPKELE_E_PARS)
123 : exception(OPKELE_E_CONS) { }
124 };
125 /**
126 * thrown if the handle passed to check_authentication request is not
127 * stateless
128 */
129 class stateful_handle : public exception {
130 public:
131 stateful_handle(OPKELE_E_PARS)
132 : exception(OPKELE_E_CONS) { }
133 };
134
135 /**
136 * thrown if check_authentication request fails
137 */
138 class failed_check_authentication : public exception {
139 public:
140 failed_check_authentication(OPKELE_E_PARS)
141 : exception(OPKELE_E_CONS) { }
142 };
143
144 /**
145 * thrown if the id_res request result is negative
146 */
147 class id_res_failed : public exception {
148 public:
149 id_res_failed(OPKELE_E_PARS)
150 : exception(OPKELE_E_CONS) { }
151 };
152 /**
153 * thrown if the user_setup_url is provided with negative response
154 */
155 class id_res_setup : public id_res_failed {
156 public:
157 string setup_url;
158 id_res_setup(OPKELE_E_PARS,const string& su)
159 : id_res_failed(OPKELE_E_CONS), setup_url(su) { }
160 ~id_res_setup() throw() { }
161 };
162 /**
163 * thrown in case of signature mismatch
164 */
165 class id_res_mismatch : public id_res_failed {
166 public:
167 id_res_mismatch(OPKELE_E_PARS)
168 : id_res_failed(OPKELE_E_CONS) { }
169 };
170
171 /**
172 * openssl malfunction occured
173 */
174 class exception_openssl : public exception {
175 public:
176 unsigned long _error;
177 string _ssl_string;
178 exception_openssl(OPKELE_E_PARS);
179 ~exception_openssl() throw() { }
180 };
181
182 /**
183 * network operation related error occured
184 */
185 class exception_network : public exception {
186 public:
187 exception_network(OPKELE_E_PARS)
188 : exception(OPKELE_E_CONS) { }
189 };
190
191 /**
192 * network operation related error occured, specifically, related to
193 * libcurl
194 */
195 class exception_curl : public exception_network {
196 public:
197 CURLcode _error;
198 string _curl_string;
199 exception_curl(OPKELE_E_PARS);
200 exception_curl(OPKELE_E_PARS,CURLcode e);
201 ~exception_curl() throw() { }
202 };
203
204}
205
206#endif /* __OPKELE_EXCEPTION_H */
diff --git a/include/opkele/opkele-config.h b/include/opkele/opkele-config.h
new file mode 100644
index 0000000..70c2d26
--- a/dev/null
+++ b/include/opkele/opkele-config.h
@@ -0,0 +1,6 @@
1#ifndef __OPKELE_OPKELE_CONFIG_H
2#define __OPKELE_OPKELE_CONFIG_H
3
4#include "opkele/acconfig.h"
5
6#endif /* __OPKELE_OPKELE_CONFIG_H */
diff --git a/include/opkele/server.h b/include/opkele/server.h
new file mode 100644
index 0000000..fe07448
--- a/dev/null
+++ b/include/opkele/server.h
@@ -0,0 +1,95 @@
1#ifndef __OPKELE_SERVER_H
2#define __OPKELE_SERVER_H
3
4/**
5 * @file
6 * @brief OpenID server-side functionality
7 */
8
9#include <opkele/types.h>
10
11/**
12 * @brief the main opkele namespace
13 */
14namespace opkele {
15
16 /**
17 * implementation of basic server functionality
18 */
19 class server_t {
20 public:
21
22 /**
23 * allocate the new association. The function should be overridden
24 * in the real implementation to provide persistent assocations
25 * store.
26 * @param mode the mode of request being processed to base the
27 * statelessness of the association upon
28 * @return the auto_ptr<> for the newly allocated association_t object
29 */
30 virtual assoc_t alloc_assoc(mode_t mode) = 0;
31 /**
32 * retrieve the association. The function should be overridden in
33 * the reqal implementation to provide persistent assocations
34 * store.
35 * @param h association handle
36 * @return the auto_ptr<> for the newly allocated association_t object
37 * @throw failed_lookup in case of failure
38 */
39 virtual assoc_t retrieve_assoc(const string& h) = 0;
40
41 /**
42 * validate the identity.
43 * @param assoc association object
44 * @param pin incoming request parameters
45 * @param identity being verified
46 * @param trust_root presented in the request
47 * @throw exception if identity can not be confirmed
48 */
49 virtual void validate(const association_t& assoc,const params_t& pin,const string& identity,const string& trust_root) = 0;
50
51
52 /**
53 * process the associate request.
54 * @param pin the incoming request parameters
55 * @param pout the store for the response parameters
56 */
57 void associate(const params_t& pin,params_t& pout);
58 /**
59 * process the checkid_immediate request.
60 * @param pin the incoming request parameters
61 * @param return_to reference to the object to store return_to url to
62 * @param pout the response parameters
63 * @throw exception in case of errors or negative reply
64 */
65 void checkid_immediate(const params_t& pin,string& return_to,params_t& pout);
66 /**
67 * process the checkid_setup request.
68 * @param pin the incoming request parameters
69 * @param return_to reference to the object to store return_to url to
70 * @param pout the response parameters
71 * @throw exception in case of errors or negative reply
72 */
73 void checkid_setup(const params_t& pin,string& return_to,params_t& pout);
74 /**
75 * the actual functionality behind checkid_immediate() and
76 * checkid_setup()
77 * @param mode the request being processed (either
78 * mode_checkid_immediate or mode_checkid_setup)
79 * @param pin the incoming request parameters
80 * @param return_to reference to the object to store return_to url to
81 * @param pout the response parameters
82 * @throw exception in case of errors or negative reply
83 */
84 void checkid_(mode_t mode,const params_t& pin,string& return_to,params_t& pout);
85 /**
86 * process the check_authentication request.
87 * @param pin incoming request parameters
88 * @param pout response parameters
89 */
90 void check_authentication(const params_t& pin,params_t& pout);
91 };
92
93}
94
95#endif /* __OPKELE_SERVER_H */
diff --git a/include/opkele/types.h b/include/opkele/types.h
new file mode 100644
index 0000000..ba06776
--- a/dev/null
+++ b/include/opkele/types.h
@@ -0,0 +1,168 @@
1#ifndef __OPKELE_TYPES_H
2#define __OPKELE_TYPES_H
3
4/**
5 * @file
6 * @brief various types declarations
7 */
8
9#include <ostream>
10#include <vector>
11#include <string>
12#include <map>
13#include <memory>
14
15/**
16 * @brief the main opkele namespace
17 */
18namespace opkele {
19 using std::vector;
20 using std::string;
21 using std::map;
22 using std::ostream;
23 using std::auto_ptr;
24
25 /**
26 * the OpenID operation mode
27 */
28 typedef enum _mode_t {
29 mode_associate,
30 mode_checkid_immediate,
31 mode_checkid_setup,
32 mode_check_association
33 } mode_t;
34
35 /**
36 * the association secret container
37 */
38 class secret_t : public vector<unsigned char> {
39 public:
40
41 /**
42 * xor the secret and hmac together and encode, using base64
43 * @param key_sha1 pointer to the sha1 digest
44 * @param rv reference to the return value
45 */
46 void enxor_to_base64(const unsigned char *key_sha1,string& rv) const;
47 /**
48 * decode base64-encoded secret and xor it with the sha1 digest
49 * @param key_sha1 pointer to the message digest
50 * @param b64 base64-encoded secret value
51 */
52 void enxor_from_base64(const unsigned char *key_sha1,const string& b64);
53 /**
54 * plainly encode to base64 representation
55 * @param rv reference to the return value
56 */
57 void to_base64(string& rv) const;
58 /**
59 * decode cleartext secret from base64
60 * @param b64 base64-encoded representation of the secret value
61 */
62 void from_base64(const string& b64);
63 };
64
65 /**
66 * Interface to the association.
67 */
68 class association_t {
69 public:
70
71 /**
72 * retrieve the server with which association was established.
73 * @return server name
74 */
75 virtual string server() const = 0;
76 /**
77 * retrieve the association handle.
78 * @return handle
79 */
80 virtual string handle() const = 0;
81 /**
82 * retrieve the association type.
83 * @return association type
84 */
85 virtual string assoc_type() const = 0;
86 /**
87 * retrieve the association secret.
88 * @return association secret
89 */
90 virtual secret_t secret() const = 0;
91 /**
92 * retrieve the number of seconds the association expires in.
93 * @return seconds till expiration
94 */
95 virtual int expires_in() const = 0;
96 /**
97 * check whether the association is stateless.
98 * @return true if stateless
99 */
100 virtual bool stateless() const = 0;
101 };
102
103 /**
104 * the auto_ptr<> for association_t object type
105 */
106 typedef auto_ptr<association_t> assoc_t;
107
108 /**
109 * request/response parameters map
110 */
111 class params_t : public map<string,string> {
112 public:
113
114 /**
115 * check whether the parameter is present.
116 * @param n the parameter name
117 * @return true if yes
118 */
119 bool has_param(const string& n) const;
120 /**
121 * retrieve the parameter (const version)
122 * @param n the parameter name
123 * @return the parameter value
124 * @throw failed_lookup if there is no such parameter
125 */
126 const string& get_param(const string& n) const;
127 /**
128 * retrieve the parameter.
129 * @param n the parameter name
130 * @return the parameter value
131 * @throw failed_lookup if there is no such parameter
132 */
133 string& get_param(const string& n);
134
135 /**
136 * parse the OpenID key/value data.
137 * @param kv the OpenID key/value data
138 */
139 void parse_keyvalues(const string& kv);
140 /**
141 * sign the fields.
142 * @param secret the secret used for signing
143 * @param sig reference to the string, containing base64-encoded
144 * result
145 * @param slist the comma-separated list of fields to sign
146 * @param prefix the string to prepend to parameter names
147 */
148 void sign(secret_t secret,string& sig,const string& slist,const char *prefix=0) const;
149
150 /**
151 * append parameters to the URL as a GET-request parameters.
152 * @param url the base URL
153 * @param prefix the string to prepend to parameter names
154 * @return the ready-to-use location
155 */
156 string append_query(const string& url,const char *prefix = "openid.") const;
157 };
158
159 /**
160 * dump the key/value pairs for the parameters to the stream.
161 * @param o output stream
162 * @param p the parameters
163 */
164 ostream& operator << (ostream& o,const params_t& p);
165
166}
167
168#endif /* __OPKELE_TYPES_H */
diff --git a/include/opkele/util.h b/include/opkele/util.h
new file mode 100644
index 0000000..fbbef93
--- a/dev/null
+++ b/include/opkele/util.h
@@ -0,0 +1,60 @@
1#ifndef __OPKELE_UTIL_H
2#define __OPKELE_UTIL_H
3
4#include <time.h>
5#include <string>
6#include <openssl/bn.h>
7#include <openssl/dh.h>
8
9namespace opkele {
10 using std::string;
11
12 namespace util {
13
14 class bignum_t {
15 public:
16 BIGNUM *_bn;
17
18 bignum_t() : _bn(0) { }
19 bignum_t(BIGNUM *bn) : _bn(bn) { }
20 ~bignum_t() throw() { if(_bn) BN_free(_bn); }
21
22 bignum_t& operator=(BIGNUM *bn) { if(_bn) BN_free(_bn); _bn = bn; return *this; }
23
24 operator const BIGNUM*(void) const { return _bn; }
25 operator BIGNUM*(void) { return _bn; }
26 };
27 class dh_t {
28 public:
29 DH *_dh;
30
31 dh_t() : _dh(0) { }
32 dh_t(DH *dh) : _dh(dh) { }
33 ~dh_t() throw() { if(_dh) DH_free(_dh); }
34
35 dh_t& operator=(DH *dh) { if(_dh) DH_free(_dh); _dh = dh; return *this; }
36
37 operator const DH*(void) const { return _dh; }
38 operator DH*(void) { return _dh; }
39
40 DH* operator->() { return _dh; }
41 const DH* operator->() const { return _dh; }
42 };
43
44 BIGNUM *base64_to_bignum(const string& b64);
45 BIGNUM *dec_to_bignum(const string& dec);
46 string bignum_to_base64(const BIGNUM *bn);
47
48 string time_to_w3c(time_t t);
49 time_t w3c_to_time(const string& w);
50
51 string canonicalize_url(const string& url);
52 string url_encode(const string& str);
53
54 string long_to_string(long l);
55 long string_to_long(const string& s);
56 }
57
58}
59
60#endif /* __OPKELE_UTIL_H */
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..2325be6
--- a/dev/null
+++ b/lib/.gitignore
@@ -0,0 +1,7 @@
1*.lo
2*.o
3Makefile.in
4libopkele.la
5.libs
6.deps
7Makefile
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..6f3f9f3
--- a/dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,24 @@
1lib_LTLIBRARIES = libopkele.la
2
3INCLUDES = \
4 -I${top_srcdir}/include/ \
5 ${KONFORKA_CFLAGS} \
6 ${OPENSSL_CFLAGS} \
7 ${MIMETIC_CFLAGS} \
8 ${LIBCURL_CPPFLAGS} \
9 ${PCREPP_CFLAGS}
10LDADD = \
11 ${LIBCURL} \
12 ${PCREPP_LIBS} \
13 ${MIMETIC_LIBS} \
14 ${OPENSSL_LIBS} \
15 ${KONFORKA_LIBS}
16
17libopkele_la_SOURCES = \
18 params.cc \
19 util.cc \
20 server.cc \
21 secret.cc \
22 data.cc \
23 consumer.cc \
24 exception.cc
diff --git a/lib/consumer.cc b/lib/consumer.cc
new file mode 100644
index 0000000..bd76b61
--- a/dev/null
+++ b/lib/consumer.cc
@@ -0,0 +1,316 @@
1#include <algorithm>
2#include <opkele/util.h>
3#include <opkele/exception.h>
4#include <opkele/data.h>
5#include <opkele/consumer.h>
6#include <openssl/sha.h>
7#include <openssl/hmac.h>
8#include <mimetic/mimetic.h>
9#include <curl/curl.h>
10#include <pcre++.h>
11
12#include <iostream>
13
14/* silly mimetic */
15#undef PACKAGE
16#undef PACKAGE_BUGREPORT
17#undef PACKAGE_NAME
18#undef PACKAGE_STRING
19#undef PACKAGE_TARNAME
20#undef PACKAGE_VERSION
21#undef VERSION
22
23#include "config.h"
24
25namespace opkele {
26 using namespace std;
27
28 class curl_t {
29 public:
30 CURL *_c;
31
32 curl_t() : _c(0) { }
33 curl_t(CURL *c) : _c(c) { }
34 ~curl_t() throw() { if(_c) curl_easy_cleanup(_c); }
35
36 curl_t& operator=(CURL *c) { if(_c) curl_easy_cleanup(_c); _c=c; return *this; }
37
38 operator const CURL*(void) const { return _c; }
39 operator CURL*(void) { return _c; }
40 };
41
42 static CURLcode curl_misc_sets(CURL* c) {
43 CURLcode r;
44 (r=curl_easy_setopt(c,CURLOPT_FOLLOWLOCATION,1))
45 || (r=curl_easy_setopt(c,CURLOPT_MAXREDIRS,5))
46 || (r=curl_easy_setopt(c,CURLOPT_DNS_CACHE_TIMEOUT,120))
47 || (r=curl_easy_setopt(c,CURLOPT_DNS_USE_GLOBAL_CACHE,1))
48 || (r=curl_easy_setopt(c,CURLOPT_USERAGENT,PACKAGE_NAME"/"PACKAGE_VERSION))
49 || (r=curl_easy_setopt(c,CURLOPT_TIMEOUT,20))
50 ;
51 return r;
52 }
53
54 static size_t _curl_tostring(void *ptr,size_t size,size_t nmemb,void *stream) {
55 string *str = (string*)stream;
56 size_t bytes = size*nmemb;
57 size_t get = min(16384-str->length(),bytes);
58 str->append((const char*)ptr,get);
59 return get;
60 }
61
62 assoc_t consumer_t::associate(const string& server) {
63 util::dh_t dh = DH_new();
64 if(!dh)
65 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
66 dh->p = util::dec_to_bignum(data::_default_p);
67 dh->g = util::dec_to_bignum(data::_default_g);
68 if(!DH_generate_key(dh))
69 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
70 string request =
71 "openid.mode=associate"
72 "&openid.assoc_type=HMAC-SHA1"
73 "&openid.session_type=DH-SHA1"
74 "&openid.dh_consumer_public=";
75 request += util::url_encode(util::bignum_to_base64(dh->pub_key));
76 curl_t curl = curl_easy_init();
77 if(!curl)
78 throw exception_curl(OPKELE_CP_ "failed to curl_easy_init()");
79 string response;
80 CURLcode r;
81 (r=curl_misc_sets(curl))
82 || (r=curl_easy_setopt(curl,CURLOPT_URL,server.c_str()))
83 || (r=curl_easy_setopt(curl,CURLOPT_POST,1))
84 || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDS,request.data()))
85 || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,request.length()))
86 || (r=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,_curl_tostring))
87 || (r=curl_easy_setopt(curl,CURLOPT_WRITEDATA,&response))
88 ;
89 if(r)
90 throw exception_curl(OPKELE_CP_ "failed to curl_easy_setopt()",r);
91 if(r=curl_easy_perform(curl))
92 throw exception_curl(OPKELE_CP_ "failed to curl_easy_perform()",r);
93 params_t p; p.parse_keyvalues(response);
94 if(p.has_param("assoc_type") && p.get_param("assoc_type")!="HMAC-SHA1")
95 throw bad_input(OPKELE_CP_ "unsupported assoc_type");
96 string st;
97 if(p.has_param("session_type")) st = p.get_param("session_type");
98 if((!st.empty()) && st!="DH-SHA1")
99 throw bad_input(OPKELE_CP_ "unsupported session_type");
100 secret_t secret;
101 if(st.empty()) {
102 secret.from_base64(p.get_param("mac_key"));
103 }else{
104 util::bignum_t s_pub = util::base64_to_bignum(p.get_param("dh_server_public"));
105 vector<unsigned char> ck(DH_size(dh));
106 int cklen = DH_compute_key(&(ck.front()),s_pub,dh);
107 if(cklen<0)
108 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
109 ck.resize(cklen);
110 // OpenID algorithm requires extra zero in case of set bit here
111 if(ck[0]&0x80) ck.insert(ck.begin(),1,0);
112 unsigned char key_sha1[SHA_DIGEST_LENGTH];
113 SHA1(&(ck.front()),ck.size(),key_sha1);
114 secret.enxor_from_base64(key_sha1,p.get_param("enc_mac_key"));
115 }
116 int expires_in = 0;
117 if(p.has_param("expires_in")) {
118 expires_in = util::string_to_long(p.get_param("expires_in"));
119 }else if(p.has_param("issued") && p.has_param("expiry")) {
120 expires_in = util::w3c_to_time(p.get_param("expiry"))-util::w3c_to_time(p.get_param("issued"));
121 }else
122 throw bad_input(OPKELE_CP_ "no expiration information");
123 return store_assoc(server,p.get_param("assoc_handle"),secret,expires_in);
124 }
125
126 string consumer_t::checkid_immediate(const string& identity,const string& return_to,const string& trust_root) {
127 return checkid_(mode_checkid_immediate,identity,return_to,trust_root);
128 }
129 string consumer_t::checkid_setup(const string& identity,const string& return_to,const string& trust_root) {
130 return checkid_(mode_checkid_setup,identity,return_to,trust_root);
131 }
132 string consumer_t::checkid_(mode_t mode,const string& identity,const string& return_to,const string& trust_root) {
133 params_t p;
134 if(mode==mode_checkid_immediate)
135 p["mode"]="checkid_immediate";
136 else if(mode==mode_checkid_setup)
137 p["mode"]="checkid_setup";
138 else
139 throw bad_input(OPKELE_CP_ "unknown checkid_* mode");
140 string iurl = util::canonicalize_url(identity);
141 string server, delegate;
142 retrieve_links(iurl,server,delegate);
143 p["identity"] = delegate.empty()?iurl:delegate;
144 if(!trust_root.empty())
145 p["trust_root"] = trust_root;
146 p["return_to"] = return_to;
147 try {
148 try {
149 string ah = find_assoc(server)->handle();
150 p["assoc_handle"] = ah;
151 }catch(failed_lookup& fl) {
152 string ah = associate(server)->handle();
153 p["assoc_handle"] = ah;
154 }
155 }catch(exception& e) { }
156 return p.append_query(server);
157 }
158
159 void consumer_t::id_res(const params_t& pin,const string& identity) {
160 if(pin.has_param("openid.user_setup_url"))
161 throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided",pin.get_param("openid.user_setup_url"));
162 string server,delegate;
163 retrieve_links(identity.empty()?pin.get_param("openid.identity"):util::canonicalize_url(identity),server,delegate);
164 try {
165 assoc_t assoc = retrieve_assoc(server,pin.get_param("openid.assoc_handle"));
166 const string& sigenc = pin.get_param("openid.sig");
167 mimetic::Base64::Decoder b;
168 vector<unsigned char> sig;
169 mimetic::decode(
170 sigenc.begin(),sigenc.end(), b,
171 back_insert_iterator<vector<unsigned char> >(sig) );
172 const string& slist = pin.get_param("openid.signed");
173 string kv;
174 string::size_type p = 0;
175 while(true) {
176 string::size_type co = slist.find(',',p);
177 string f = (co==string::npos)?slist.substr(p):slist.substr(p,co-p);
178 kv += f;
179 kv += ':';
180 f.insert(0,"openid.");
181 kv += pin.get_param(f);
182 kv += '\n';
183 if(co==string::npos)
184 break;
185 p = co+1;
186 }
187 secret_t secret = assoc->secret();
188 unsigned int md_len = 0;
189 unsigned char *md = HMAC(
190 EVP_sha1(),
191 &(secret.front()),secret.size(),
192 (const unsigned char *)kv.data(),kv.length(),
193 0,&md_len);
194 if(sig.size()!=md_len || memcmp(&(sig.front()),md,md_len))
195 throw id_res_mismatch(OPKELE_CP_ "signature mismatch");
196 }catch(failed_lookup& e) { /* XXX: more specific? */
197 const string& slist = pin.get_param("openid.signed");
198 string::size_type pp = 0;
199 params_t p;
200 while(true) {
201 string::size_type co = slist.find(',',pp);
202 string f = "openid.";
203 f += (co==string::npos)?slist.substr(pp):slist.substr(pp,co-pp);
204 p[f] = pin.get_param(f);
205 if(co==string::npos)
206 break;
207 pp = co+1;
208 }
209 p["openid.assoc_handle"] = pin.get_param("openid.assoc_handle");
210 p["openid.sig"] = pin.get_param("openid.sig");
211 p["openid.signed"] = pin.get_param("openid.signed");
212 try {
213 string ih = pin.get_param("openid.invalidate_handle");
214 p["openid.invalidate_handle"] = ih;
215 }catch(failed_lookup& fl) { }
216 try {
217 check_authentication(server,p);
218 }catch(failed_check_authentication& fca) {
219 throw id_res_failed(OPKELE_CP_ "failed to check_authentication()");
220 }
221 }
222 }
223
224 void consumer_t::check_authentication(const string& server,const params_t& p) {
225 string request = "openid.mode=check_authentication";
226 for(params_t::const_iterator i=p.begin();i!=p.end();++i) {
227 if(i->first!="openid.mode") {
228 request += '&';
229 request += i->first;
230 request += '=';
231 request += util::url_encode(i->second);
232 }
233 }
234 curl_t curl = curl_easy_init();
235 if(!curl)
236 throw exception_curl(OPKELE_CP_ "failed to curl_easy_init()");
237 string response;
238 CURLcode r;
239 (r=curl_misc_sets(curl))
240 || (r=curl_easy_setopt(curl,CURLOPT_URL,server.c_str()))
241 || (r=curl_easy_setopt(curl,CURLOPT_POST,1))
242 || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDS,request.data()))
243 || (r=curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,request.length()))
244 || (r=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,_curl_tostring))
245 || (r=curl_easy_setopt(curl,CURLOPT_WRITEDATA,&response))
246 ;
247 if(r)
248 throw exception_curl(OPKELE_CP_ "failed to curl_easy_setopt()",r);
249 if(r=curl_easy_perform(curl))
250 throw exception_curl(OPKELE_CP_ "failed to curl_easy_perform()",r);
251 params_t pp; pp.parse_keyvalues(response);
252 if(pp.has_param("invalidate_handle"))
253 invalidate_assoc(server,pp.get_param("invalidate_handle"));
254 if(pp.has_param("is_valid")) {
255 if(pp.get_param("is_valid")=="true")
256 return;
257 }else if(pp.has_param("lifetime")) {
258 if(util::string_to_long(pp.get_param("lifetime")))
259 return;
260 }
261 throw failed_check_authentication(OPKELE_CP_ "failed to verify response");
262 }
263
264 void consumer_t::retrieve_links(const string& url,string& server,string& delegate) {
265 server.erase();
266 delegate.erase();
267 curl_t curl = curl_easy_init();
268 if(!curl)
269 throw exception_curl(OPKELE_CP_ "failed to curl_easy_init()");
270 string html;
271 CURLcode r;
272 (r=curl_misc_sets(curl))
273 || (r=curl_easy_setopt(curl,CURLOPT_URL,url.c_str()))
274 || (r=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,_curl_tostring))
275 || (r=curl_easy_setopt(curl,CURLOPT_WRITEDATA,&html))
276 ;
277 if(r)
278 throw exception_curl(OPKELE_CP_ "failed to curl_easy_setopt()",r);
279 r = curl_easy_perform(curl);
280 if(r && r!=CURLE_WRITE_ERROR)
281 throw exception_curl(OPKELE_CP_ "failed to curl_easy_perform()",r);
282 pcrepp::Pcre bre("<body\\b",PCRE_CASELESS);
283 // strip out everything past body
284 if(bre.search(html))
285 html.erase(bre.get_match_start());
286 pcrepp::Pcre hdre("<head[^>]*>",PCRE_CASELESS);
287 if(!hdre.search(html))
288 throw bad_input(OPKELE_CP_ "failed to find head");
289 html.erase(0,hdre.get_match_end()+1);
290 pcrepp::Pcre lre("<link\\b([^>]+)>",PCRE_CASELESS),
291 rre("\\brel=['\"]([^'\"]+)['\"]",PCRE_CASELESS),
292 hre("\\bhref=['\"]([^'\"]+)['\"]",PCRE_CASELESS);
293 while(lre.search(html)) {
294 string attrs = lre[0];
295 html.erase(0,lre.get_match_end()+1);
296 if(!(rre.search(attrs)&&hre.search(attrs)))
297 continue;
298 if(rre[0]=="openid.server") {
299 server = hre[0];
300 if(!delegate.empty())
301 break;
302 }else if(rre[0]=="openid.delegate") {
303 delegate = hre[0];
304 if(!server.empty())
305 break;
306 }
307 }
308 if(server.empty())
309 throw failed_assertion(OPKELE_CP_ "The location has no openid.server declaration");
310 }
311
312 assoc_t consumer_t::find_assoc(const string& server) {
313 throw failed_lookup(OPKELE_CP_ "no find_assoc() provided");
314 }
315
316}
diff --git a/lib/data.cc b/lib/data.cc
new file mode 100644
index 0000000..c040430
--- a/dev/null
+++ b/lib/data.cc
@@ -0,0 +1,11 @@
1#include <opkele/data.h>
2
3namespace opkele {
4
5 namespace data {
6
7 const char *_default_p = "155172898181473697471232257763715539915724801966915404479707795314057629378541917580651227423698188993727816152646631438561595825688188889951272158842675419950341258706556549803580104870537681476726513255747040765857479291291572334510643245094715007229621094194349783925984760375594985848253359305585439638443";
8 const char *_default_g = "2";
9
10 }
11}
diff --git a/lib/exception.cc b/lib/exception.cc
new file mode 100644
index 0000000..b7c1702
--- a/dev/null
+++ b/lib/exception.cc
@@ -0,0 +1,22 @@
1#include <openssl/err.h>
2#include <curl/curl.h>
3#include <opkele/exception.h>
4
5namespace opkele {
6
7 exception_openssl::exception_openssl(OPKELE_E_PARS)
8 : _error(ERR_peek_last_error()),
9 _ssl_string(ERR_error_string(_error,0)),
10 exception(OPKELE_E_CONS_ w+" ["+_ssl_string+']') {
11 }
12
13 exception_curl::exception_curl(OPKELE_E_PARS)
14 : _error(CURLE_OK),
15 exception_network(OPKELE_E_CONS) { }
16 exception_curl::exception_curl(OPKELE_E_PARS,CURLcode e)
17 : _error(e),
18 _curl_string(curl_easy_strerror(e)),
19 exception_network(OPKELE_E_CONS_ w+" ["+_curl_string+']') {
20 }
21
22}
diff --git a/lib/params.cc b/lib/params.cc
new file mode 100644
index 0000000..14f1a53
--- a/dev/null
+++ b/lib/params.cc
@@ -0,0 +1,96 @@
1#include <opkele/types.h>
2#include <opkele/exception.h>
3#include <opkele/util.h>
4#include <openssl/sha.h>
5#include <openssl/hmac.h>
6#include <mimetic/mimetic.h>
7
8namespace opkele {
9 using namespace std;
10
11 bool params_t::has_param(const string& n) const {
12 return find(n)!=end();
13 }
14 const string& params_t::get_param(const string& n) const {
15 const_iterator i = find(n);
16 if(i==end())
17 throw failed_lookup(OPKELE_CP_ n+": no such parameter");
18 return i->second;
19 }
20 string& params_t::get_param(const string& n) {
21 iterator i = find(n);
22 if(i==end())
23 throw failed_lookup(OPKELE_CP_ n+": no such parameter");
24 return i->second;
25 }
26
27 void params_t::parse_keyvalues(const string& kv) {
28 clear();
29 string::size_type p = 0;
30 while(true) {
31 string::size_type co = kv.find(':',p);
32 if(co==string::npos)
33 break;
34 string::size_type nl = kv.find('\n',co+1);
35 if(nl==string::npos)
36 throw bad_input(OPKELE_CP_ "malformed input");
37 insert(value_type(kv.substr(p,co-p),kv.substr(co+1,nl-co-1)));
38 p = nl+1;
39 }
40 }
41
42 void params_t::sign(secret_t secret,string& sig,const string& slist,const char *prefix) const {
43 string kv;
44 string::size_type p = 0;
45 while(true) {
46 string::size_type co = slist.find(',',p);
47 string f = (co==string::npos)?slist.substr(p):slist.substr(p,co-p);
48 kv += f;
49 kv += ':';
50 if(prefix) f.insert(0,prefix);
51 kv += get_param(f);
52 kv += '\n';
53 if(co==string::npos)
54 break;
55 p = co+1;
56 }
57 unsigned int md_len = 0;
58 unsigned char *md = HMAC(
59 EVP_sha1(),
60 &(secret.front()),secret.size(),
61 (const unsigned char *)kv.data(),kv.length(),
62 0,&md_len);
63 mimetic::Base64::Encoder b(0);
64 sig.erase();
65 mimetic::encode(
66 md,md+md_len, b,
67 back_insert_iterator<string>(sig) );
68 }
69
70 string params_t::append_query(const string& url,const char *prefix) const {
71 string rv = url;
72 bool p = true;
73 if(rv.find('?')==string::npos) {
74 rv += '?';
75 p = false;
76 }
77 for(const_iterator i=begin();i!=end();++i) {
78 if(p)
79 rv += '&';
80 else
81 p = true;
82 rv += prefix;
83 rv += i->first;
84 rv += '=';
85 rv += util::url_encode(i->second);
86 }
87 return rv;
88 }
89
90 ostream& operator << (ostream& o,const params_t& p) {
91 for(params_t::const_iterator i=p.begin();i!=p.end();++i)
92 o << i->first << ':' << i->second << '\n';
93 return o;
94 }
95
96}
diff --git a/lib/secret.cc b/lib/secret.cc
new file mode 100644
index 0000000..ae8a3c5
--- a/dev/null
+++ b/lib/secret.cc
@@ -0,0 +1,61 @@
1#include <algorithm>
2#include <functional>
3#include <opkele/types.h>
4#include <opkele/exception.h>
5#include <mimetic/mimetic.h>
6
7namespace opkele {
8 using namespace std;
9
10 template<class __a1,class __a2,class __r>
11 struct bitwise_xor : public binary_function<__a1,__a2,__r> {
12 __r operator() (const __a1& a1,const __a2& a2) const {
13 return a1^a2;
14 }
15 };
16
17 void secret_t::enxor_to_base64(const unsigned char *key_sha1,string& rv) const {
18 if(size()!=20)
19 throw bad_input(OPKELE_CP_ "wrong secret size");
20 vector<unsigned char> tmp;
21 transform(
22 begin(), end(),
23 key_sha1,
24 back_insert_iterator<vector<unsigned char> >(tmp),
25 bitwise_xor<unsigned char,unsigned char,unsigned char>() );
26 mimetic::Base64::Encoder b(0);
27 mimetic::encode(
28 tmp.begin(),tmp.end(), b,
29 back_insert_iterator<string>(rv) );
30 }
31
32 void secret_t::enxor_from_base64(const unsigned char *key_sha1,const string& b64) {
33 mimetic::Base64::Decoder b;
34 clear();
35 mimetic::decode(
36 b64.begin(),b64.end(), b,
37 back_insert_iterator<secret_t>(*this) );
38 transform(
39 begin(), end(),
40 key_sha1,
41 begin(),
42 bitwise_xor<unsigned char,unsigned char,unsigned char>() );
43 }
44
45 void secret_t::to_base64(string& rv) const {
46 if(size()!=20)
47 throw bad_input(OPKELE_CP_ "wrong secret size");
48 mimetic::Base64::Encoder b(0);
49 mimetic::encode(
50 begin(),end(), b,
51 back_insert_iterator<string>(rv) );
52 }
53
54 void secret_t::from_base64(const string& b64) {
55 mimetic::Base64::Decoder b;
56 mimetic::decode(
57 b64.begin(),b64.end(), b,
58 back_insert_iterator<secret_t>(*this) );
59 }
60
61}
diff --git a/lib/server.cc b/lib/server.cc
new file mode 100644
index 0000000..51d4554
--- a/dev/null
+++ b/lib/server.cc
@@ -0,0 +1,169 @@
1#include <vector>
2#include <openssl/sha.h>
3#include <openssl/hmac.h>
4#include <mimetic/mimetic.h>
5#include <opkele/util.h>
6#include <opkele/exception.h>
7#include <opkele/server.h>
8#include <opkele/data.h>
9
10namespace opkele {
11 using namespace std;
12
13 void server_t::associate(const params_t& pin,params_t& pout) {
14 util::dh_t dh;
15 util::bignum_t c_pub;
16 unsigned char key_sha1[SHA_DIGEST_LENGTH];
17 enum {
18 sess_cleartext,
19 sess_dh_sha1
20 } st = sess_cleartext;
21 if(
22 pin.has_param("openid.session_type")
23 && pin.get_param("openid.session_type")=="DH-SHA1" ) {
24 /* TODO: fallback to cleartext in case of exceptions here? */
25 if(!(dh = DH_new()))
26 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
27 c_pub = util::base64_to_bignum(pin.get_param("openid.dh_consumer_public"));
28 if(pin.has_param("openid.dh_modulus"))
29 dh->p = util::base64_to_bignum(pin.get_param("openid.dh_modulus"));
30 else
31 dh->p = util::dec_to_bignum(data::_default_p);
32 if(pin.has_param("openid.dh_gen"))
33 dh->g = util::base64_to_bignum(pin.get_param("openid.dh_gen"));
34 else
35 dh->g = util::dec_to_bignum(data::_default_g);
36 if(!DH_generate_key(dh))
37 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
38 vector<unsigned char> ck(DH_size(dh));
39 int cklen = DH_compute_key(&(ck.front()),c_pub,dh);
40 if(cklen<0)
41 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
42 ck.resize(cklen);
43 // OpenID algorithm requires extra zero in case of set bit here
44 if(ck[0]&0x80) ck.insert(ck.begin(),1,0);
45 SHA1(&(ck.front()),ck.size(),key_sha1);
46 st = sess_dh_sha1;
47 }
48 assoc_t assoc = alloc_assoc(mode_associate);
49 time_t now = time(0);
50 pout.clear();
51 pout["assoc_type"] = assoc->assoc_type();
52 pout["assoc_handle"] = assoc->handle();
53 /* TODO: eventually remove deprecated stuff */
54 pout["issued"] = util::time_to_w3c(now);
55 pout["expiry"] = util::time_to_w3c(now+assoc->expires_in());
56 pout["expires_in"] = util::long_to_string(assoc->expires_in());
57 secret_t secret = assoc->secret();
58 switch(st) {
59 case sess_dh_sha1:
60 pout["session_type"] = "DH-SHA1";
61 pout["dh_server_public"] = util::bignum_to_base64(dh->pub_key);
62 secret.enxor_to_base64(key_sha1,pout["enc_mac_key"]);
63 break;
64 default:
65 secret.to_base64(pout["mac_key"]);
66 break;
67 }
68 }
69
70 void server_t::checkid_immediate(const params_t& pin,string& return_to,params_t& pout) {
71 checkid_(mode_checkid_immediate,pin,return_to,pout);
72 }
73
74 void server_t::checkid_setup(const params_t& pin,string& return_to,params_t& pout) {
75 checkid_(mode_checkid_setup,pin,return_to,pout);
76 }
77
78 void server_t::checkid_(mode_t mode,const params_t& pin,string& return_to,params_t& pout) {
79 if(mode!=mode_checkid_immediate && mode!=mode_checkid_setup)
80 throw bad_input(OPKELE_CP_ "invalid checkid_* mode");
81 assoc_t assoc;
82 try {
83 assoc = retrieve_assoc(pin.get_param("openid.assoc_handle"));
84 }catch(failed_lookup& fl) {
85 // no handle specified or no valid handle found, going dumb
86 assoc = alloc_assoc(mode_checkid_setup);
87 }
88 string trust_root;
89 try {
90 trust_root = pin.get_param("openid.trust_root");
91 }catch(failed_lookup& fl) { }
92 string identity = pin.get_param("openid.identity");
93 return_to = pin.get_param("openid.return_to");
94 validate(*assoc,pin,identity,trust_root);
95 pout.clear();
96 pout["mode"] = "id_res";
97 pout["assoc_handle"] = assoc->handle();
98 if(pin.has_param("openid.assoc_handle") && assoc->stateless())
99 pout["invalidate_handle"] = pin.get_param("openid.assoc_handle");
100 pout["identity"] = identity;
101 pout["return_to"] = return_to;
102 /* TODO: eventually remove deprecated stuff */
103 time_t now = time(0);
104 pout["issued"] = util::time_to_w3c(now);
105 pout["valid_to"] = util::time_to_w3c(now+120);
106 pout["exipres_in"] = "120";
107 pout.sign(assoc->secret(),pout["sig"],pout["signed"]="mode,identity,return_to");
108 }
109
110 void server_t::check_authentication(const params_t& pin,params_t& pout) {
111 vector<unsigned char> sig;
112 mimetic::Base64::Decoder b;
113 const string& sigenc = pin.get_param("openid.sig");
114 mimetic::decode(
115 sigenc.begin(),sigenc.end(), b,
116 back_insert_iterator<vector<unsigned char> >(sig));
117 assoc_t assoc;
118 try {
119 assoc = retrieve_assoc(pin.get_param("openid.assoc_handle"));
120 }catch(failed_lookup& fl) {
121 throw failed_assertion(OPKELE_CP_ "invalid handle or handle not specified");
122 }
123 if(!assoc->stateless())
124 throw stateful_handle(OPKELE_CP_ "will not do check_authentication on a stateful handle");
125 const string& slist = pin.get_param("openid.signed");
126 string kv;
127 string::size_type p =0;
128 while(true) {
129 string::size_type co = slist.find(',',p);
130 string f = (co==string::npos)?slist.substr(p):slist.substr(p,co-p);
131 kv += f;
132 kv += ':';
133 if(f=="mode")
134 kv += "id_res";
135 else {
136 f.insert(0,"openid.");
137 kv += pin.get_param(f);
138 }
139 kv += '\n';
140 if(co==string::npos)
141 break;
142 p = co+1;
143 }
144 secret_t secret = assoc->secret();
145 unsigned int md_len = 0;
146 unsigned char *md = HMAC(
147 EVP_sha1(),
148 &(secret.front()),secret.size(),
149 (const unsigned char *)kv.data(),kv.length(),
150 0,&md_len);
151 pout.clear();
152 if(sig.size()==md_len && !memcmp(&(sig.front()),md,md_len)) {
153 pout["is_valid"]="true";
154 pout["lifetime"]="60"; /* TODO: eventually remove deprecated stuff */
155 }else{
156 pout["is_valid"]="false";
157 pout["lifetime"]="0"; /* TODO: eventually remove deprecated stuff */
158 }
159 if(pin.has_param("openid.invalidate_handle")) {
160 string h = pin.get_param("openid.invalidate_handle");
161 try {
162 assoc_t assoc = retrieve_assoc(h);
163 }catch(invalid_handle& ih) {
164 pout["invalidate_handle"] = h;
165 }catch(failed_lookup& fl) { }
166 }
167 }
168
169}
diff --git a/lib/util.cc b/lib/util.cc
new file mode 100644
index 0000000..1e7335c
--- a/dev/null
+++ b/lib/util.cc
@@ -0,0 +1,138 @@
1#include <errno.h>
2#include <cassert>
3#include <vector>
4#include <string>
5#include <mimetic/mimetic.h>
6#include <curl/curl.h>
7#include "opkele/util.h"
8#include "opkele/exception.h"
9
10namespace opkele {
11 using namespace std;
12
13 namespace util {
14
15 /*
16 * big numerics
17 */
18
19 BIGNUM *base64_to_bignum(const string& b64) {
20 vector<unsigned char> bin;
21 mimetic::Base64::Decoder b;
22 mimetic::decode(
23 b64.begin(),b64.end(), b,
24 back_insert_iterator<vector<unsigned char> >(bin) );
25 BIGNUM *rv = BN_bin2bn(&(bin.front()),bin.size(),0);
26 if(!rv)
27 throw failed_conversion(OPKELE_CP_ "failed to BN_bin2bn()");
28 return rv;
29 }
30
31 BIGNUM *dec_to_bignum(const string& dec) {
32 BIGNUM *rv = 0;
33 if(!BN_dec2bn(&rv,dec.c_str()))
34 throw failed_conversion(OPKELE_CP_ "failed to BN_dec2bn()");
35 return rv;
36 }
37
38 string bignum_to_base64(const BIGNUM *bn) {
39 vector<unsigned char> bin(BN_num_bytes(bn));
40 int l = BN_bn2bin(bn,&(bin.front()));
41 string rv;
42 mimetic::Base64::Encoder b(0);
43 mimetic::encode(
44 bin.begin(),bin.begin()+l, b,
45 back_insert_iterator<string>(rv) );
46 return rv;
47 }
48
49 /*
50 * w3c times
51 */
52
53 string time_to_w3c(time_t t) {
54 struct tm tm_t;
55 if(!gmtime_r(&t,&tm_t))
56 throw failed_conversion(OPKELE_CP_ "failed to BN_dec2bn()");
57 char rv[25];
58 if(!strftime(rv,sizeof(rv)-1,"%Y-%m-%dT%H:%M:%SZ",&tm_t))
59 throw failed_conversion(OPKELE_CP_ "failed to strftime()");
60 return rv;
61 }
62
63 time_t w3c_to_time(const string& w) {
64 struct tm tm_t;
65 memset(&tm_t,0,sizeof(tm_t));
66 if(
67 sscanf(
68 w.c_str(),
69 "%04d-%02d-%02dT%02d:%02d:%02dZ",
70 &tm_t.tm_year,&tm_t.tm_mon,&tm_t.tm_mday,
71 &tm_t.tm_hour,&tm_t.tm_min,&tm_t.tm_sec
72 ) != 6 )
73 throw failed_conversion(OPKELE_CP_ "failed to sscanf()");
74 tm_t.tm_mon--;
75 tm_t.tm_year-=1900;
76 time_t rv = mktime(&tm_t);
77 if(rv==(time_t)-1)
78 throw failed_conversion(OPKELE_CP_ "failed to mktime()");
79 return rv;
80 }
81
82 /*
83 *
84 */
85
86 string canonicalize_url(const string& url) {
87 string rv = url;
88 // strip leading and trailing spaces
89 string::size_type i = rv.find_first_not_of(" \t\r\n");
90 if(i==string::npos)
91 throw bad_input(OPKELE_CP_ "empty URL");
92 if(i)
93 rv.erase(0,i);
94 i = rv.find_last_not_of(" \t\r\n");
95 assert(i!=string::npos);
96 if(i<(rv.length()-1))
97 rv.erase(i+1);
98 // add missing http://
99 i = rv.find("://");
100 if(i==string::npos) { // primitive. but do we need more?
101 rv.insert(0,"http://");
102 i = sizeof("http://")-1;
103 }else{
104 i += sizeof("://")-1;
105 }
106 if(rv.find('/',i)==string::npos)
107 rv += '/';
108 return rv;
109 }
110
111 string url_encode(const string& str) {
112 char * t = curl_escape(str.c_str(),str.length());
113 if(!t)
114 throw failed_conversion(OPKELE_CP_ "failed to curl_escape()");
115 string rv(t);
116 curl_free(t);
117 return rv;
118 }
119
120 string long_to_string(long l) {
121 char rv[32];
122 int r=snprintf(rv,sizeof(rv),"%ld",l);
123 if(r<0 || r>=sizeof(rv))
124 throw failed_conversion(OPKELE_CP_ "failed to snprintf()");
125 return rv;
126 }
127
128 long string_to_long(const string& s) {
129 char *endptr = 0;
130 long rv = strtol(s.c_str(),&endptr,10);
131 if((!endptr) || endptr==s.c_str())
132 throw failed_conversion(OPKELE_CP_ "failed to strtol()");
133 return rv;
134 }
135
136 }
137
138}
diff --git a/libopkele.pc.in b/libopkele.pc.in
new file mode 100644
index 0000000..60bca34
--- a/dev/null
+++ b/libopkele.pc.in
@@ -0,0 +1,11 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: libopkele
7Description: C++ implementation of OpenID protocol
8Version: @VERSION@
9Requires: openssl @KONFORKA_KONFORKA@
10Cflags: -I${includedir} @LIBCURL_CPPFLAGS@ @PCREPP_CFLAGS@
11Libs: -L${libdir} -lopkele @LIBCURL@ @PCREPP_LIBS@ @MIMETIC_LIBS@