summaryrefslogtreecommitdiffabout
path: root/include
authorMichael Krelin <hacker@klever.net>2008-01-20 21:08:05 (UTC)
committer Michael Krelin <hacker@klever.net>2008-01-20 21:08:05 (UTC)
commit9bfb6fadf71c46bf4cb5adabba0c96c32e84c1bc (patch) (side-by-side diff)
tree702473142242e80538c4801cc379ec98fba199dd /include
parent395a126cbf59b7a50f44da3096b68bab412ab33d (diff)
downloadlibopkele-9bfb6fadf71c46bf4cb5adabba0c96c32e84c1bc.zip
libopkele-9bfb6fadf71c46bf4cb5adabba0c96c32e84c1bc.tar.gz
libopkele-9bfb6fadf71c46bf4cb5adabba0c96c32e84c1bc.tar.bz2
the whole library rewritten
Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (limited to 'include') (more/less context) (ignore whitespace changes)
-rw-r--r--include/Makefile.am21
-rw-r--r--include/opkele/basic_rp.h218
-rw-r--r--include/opkele/discovery.h88
-rw-r--r--include/opkele/exception.h19
-rw-r--r--include/opkele/extension.h7
-rw-r--r--include/opkele/extension_chain.h6
-rw-r--r--include/opkele/prequeue_rp.h81
-rw-r--r--include/opkele/sreg.h8
-rw-r--r--include/opkele/types.h171
-rw-r--r--include/opkele/util.h8
10 files changed, 495 insertions, 132 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 51dcea1..50fcb62 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,21 +1,32 @@
-nobase_include_HEADERS = \
+NODIST_HEADERS_ = \
opkele/acconfig.h \
+ opkele/tr1-mem.h
+
+nobase_include_HEADERS = \
opkele/opkele-config.h \
opkele/types.h \
opkele/association.h \
opkele/exception.h \
opkele/server.h \
opkele/consumer.h \
opkele/extension.h \
opkele/sreg.h \
opkele/extension_chain.h \
opkele/xconsumer.h \
opkele/xserver.h \
- opkele/discovery.h \
opkele/uris.h \
- opkele/tr1-mem.h
-EXTRA_DIST = \
+ opkele/tr1-mem.h \
+ opkele/basic_rp.h \
+ opkele/prequeue_rp.h \
+ opkele/iterator.h \
+ ${NODIST_HEADERS_}
+
+noinst_HEADERS = \
opkele/data.h \
opkele/curl.h opkele/expat.h opkele/tidy.h \
opkele/util.h \
- opkele/debug.h
+ opkele/debug.h \
+ opkele/discovery.h
+
+dist-hook:
+ rm -f $(addprefix ${distdir}/,${NODIST_HEADERS_})
diff --git a/include/opkele/basic_rp.h b/include/opkele/basic_rp.h
new file mode 100644
index 0000000..3f17fd9
--- a/dev/null
+++ b/include/opkele/basic_rp.h
@@ -0,0 +1,218 @@
+#ifndef __OPKELE_BASIC_RP_H
+#define __OPKELE_BASIC_RP_H
+
+#include <cstring>
+#include <string>
+#include <opkele/types.h>
+#include <opkele/extension.h>
+
+namespace opkele {
+ using std::string;
+
+ struct openid_endpoint_t {
+ string uri;
+ string claimed_id;
+ string local_id;
+
+ openid_endpoint_t() { }
+ openid_endpoint_t(const string& u,const string& cid,const string& lid)
+ : uri(u), claimed_id(cid), local_id(lid) { }
+
+ bool operator==(const openid_endpoint_t& x) const {
+ return uri==x.uri && local_id==x.local_id; }
+ bool operator<(const openid_endpoint_t& x) const {
+ int c;
+ return (c=strcmp(uri.c_str(),x.uri.c_str()))
+ ? (c<0) : (strcmp(local_id.c_str(),x.local_id.c_str())<0); }
+ };
+
+ class basic_RP {
+ public:
+
+ virtual ~basic_RP() { }
+
+ /**
+ * @name Global persistent store API
+ * These are functions related to the associations with OP storage
+ * and retrieval and nonce records. They provide an interface to
+ * the persistent storage which is shared by all sessions. If the
+ * implementor prefers the dumb mode instead, the function should
+ * throw dumb_RP exception instead.
+ * @see opkele::dumb_RP
+ * @{
+ */
+ /**
+ * Store association and return allocated association object.
+ * @param OP OP endpoint
+ * @param handle association handle
+ * @param type association type
+ * @param secret association secret
+ * @params expires_in the number of seconds association expires in
+ * @return the association object
+ * @throw dumb_RP for dumb RP
+ */
+ virtual assoc_t store_assoc(
+ const string& OP,const string& handle,
+ const string& type,const secret_t& secret,
+ int expires_in) = 0;
+ /**
+ * Find valid unexpired association with an OP.
+ * @param OP OP endpoint URL
+ * @return association found
+ * @throw failed_lookup if no association found
+ * @throw dumb_RP for dumb RP
+ */
+ virtual assoc_t find_assoc(
+ const string& OP) = 0;
+ /**
+ * Retrieve valid association handle for an OP by handle.
+ * @param OP OP endpoint URL
+ * @param handle association handle
+ * @return association found
+ * @throw failed_lookup if no association found
+ * @throw dumb_RP for dumb RP
+ */
+ virtual assoc_t retrieve_assoc(
+ const string& OP,const string& handle) = 0;
+ /**
+ * Invalidate association with OP
+ * @param OP OP endpoint URL
+ * @param handle association handle
+ * @throw dumb_RP for dumb RP
+ */
+ virtual void invalidate_assoc(const string& OP,const string& handle) = 0;
+
+ /**
+ * Check the nonce validity. That is, check that we haven't
+ * accepted request with this nonce from this OP, yet. May involve
+ * cutting off by the timestamp and checking the rest against the
+ * store of seen nonces.
+ * @param OP OP endpoint URL
+ * @param nonce nonce value
+ * @throw id_res_bad_nonce if the nonce is not to be accepted, i.e.
+ * either too old or seen.
+ */
+ virtual void check_nonce(const string& OP,const string& nonce) = 0;
+ /**
+ * @}
+ */
+
+ /**
+ * @name Session persistent store API
+ * @{
+ */
+ /**
+ * Retrieve OpenID endpoint being currently used for
+ * authentication. If there is no endpoint available, throw a
+ * no_endpoint exception.
+ * @return reference to the service endpoint object
+ * @see next_endpoint
+ * @throw no_endpoint if no endpoint available
+ */
+ virtual const openid_endpoint_t& get_endpoint() const = 0;
+ /**
+ * Advance to the next endpoint to try.
+ * @see get_endpoint()
+ * @throw no_endpoint if there are no more endpoints
+ */
+ virtual void next_endpoint() = 0;
+ /**
+ * @}
+ */
+
+ /**
+ * @name Site particulars API
+ * @{
+ */
+ /**
+ * Return an absolute URL of the page being processed, includining
+ * query parameters. It is used to validate return_to URL on
+ * positive assertions.
+ * @return fully qualified url of the page being processed.
+ */
+ virtual const string get_this_url() const = 0;
+ /**
+ * @}
+ */
+
+ /**
+ * @name OpenID actions
+ * @{
+ */
+ /**
+ * Initiates authentication session, doing discovery, normalization
+ * and whatever implementor wants to do at this point.
+ * @param usi User-supplied identity
+ */
+ virtual void initiate(const string& usi) = 0;
+ /**
+ * Prepare checkid_request.
+ * @param rv reference to the openid message to prepare
+ * @param mode checkid_setup or checkid_immediate
+ * @param return_to the URL OP should redirect to after completion
+ * @param realm authentication realm to pass to OP
+ * @param ext pointer to extension to use in request preparation
+ * @return reference to the openid message
+ */
+ basic_openid_message& checkid_(
+ basic_openid_message& rv,
+ mode_t mode,
+ const string& return_to,const string& realm,
+ extension_t *ext=0);
+ /**
+ * Verify assertion at the end of round-trip.
+ * @param om incoming openid message
+ * @param ext pointer to extention to use in parsing assertion
+ * @throw id_res_setup if checkid_immediate request could not be
+ * completed
+ * @throw id_res_cancel if authentication request was canceled
+ * @throw id_res_mismatch in case of signature mismatch
+ * @throw id_res_bad_return_to if return_to url seems to be
+ * tampered with
+ * @throw id_res_unauthorized if OP is not authorized to make
+ * assertions regarding the identity
+ */
+ void id_res(const basic_openid_message& om,extension_t *ext=0);
+
+ /**
+ * Establish association with OP
+ * @param OP OP to establish association with
+ * @throw dumb_RP if for a dumb RP
+ */
+ virtual assoc_t associate(const string& OP);
+ /**
+ * Check authentication with OP and invalidate handle if requested
+ * and confirmed
+ * @param OP OP to check with
+ * @param om message to check
+ * @throw failed_check_authentication if OP fails to confirm
+ * authenticity of the assertion
+ */
+ void check_authentication(const string& OP,const basic_openid_message& om);
+ /**
+ * @}
+ */
+
+ /**
+ * @name Miscellanea
+ * @{
+ */
+ /**
+ * Verify OP authority. Return normally if OP is authorized to make
+ * an assertion, throw an exception otherwise.
+ * @param OP OP endpoint
+ * @param claimed_id claimed identity
+ * @param identity OP-Local identifier
+ * @throw id_res_unauthorized if OP is not authorized to make
+ * assertion regarding this identity.
+ */
+ virtual void verify_OP(const string& OP,
+ const string& claimed_id,const string& identity) const = 0;
+ /**
+ * @}
+ */
+ };
+
+}
+
+#endif /* __OPKELE_BASIC_RP_H */
diff --git a/include/opkele/discovery.h b/include/opkele/discovery.h
index af4aa29..ab4b9d9 100644
--- a/include/opkele/discovery.h
+++ b/include/opkele/discovery.h
@@ -1,40 +1,104 @@
#ifndef __OPKELE_DISCOVERY_H
#define __OPKELE_DISCOVERY_H
#include <string>
#include <opkele/types.h>
+#include <opkele/basic_rp.h>
namespace opkele {
using std::string;
- struct idiscovery_t;
+ namespace xrd {
- void idiscover(idiscovery_t& result,const string& identity);
+ struct priority_compare {
+ inline bool operator()(long a,long b) const {
+ return (a<0) ? false : (b<0) ? true : (a<b);
+ }
+ };
+
+ template <typename _DT>
+ class priority_map : public multimap<long,_DT,priority_compare> {
+ typedef multimap<long,_DT,priority_compare> map_type;
+ public:
+
+ inline _DT& add(long priority,const _DT& d) {
+ return insert(typename map_type::value_type(priority,d))->second;
+ }
+
+ bool has_value(const _DT& d) const {
+ for(typename map_type::const_iterator i=this->begin();i!=this->end();++i)
+ if(i->second==d) return true;
+ return false;
+ }
+ };
+
+ typedef priority_map<string> canonical_ids_t;
+ typedef priority_map<string> local_ids_t;
+ typedef set<string> types_t;
+ typedef priority_map<string> uris_t;
+
+ class service_t {
+ public:
+ types_t types;
+ uris_t uris;
+ local_ids_t local_ids;
+ string provider_id;
+
+ void clear() {
+ types.clear();
+ uris.clear(); local_ids.clear();
+ provider_id.clear();
+ }
+ };
+ typedef priority_map<service_t> services_t;
+
+ class XRD_t {
+ public:
+ time_t expires;
+
+ canonical_ids_t canonical_ids;
+ local_ids_t local_ids;
+ services_t services;
+ string provider_id;
+
+ void clear() {
+ expires = 0;
+ canonical_ids.clear(); local_ids.clear();
+ services.clear();
+ provider_id.clear();
+ }
+ bool empty() const {
+ return
+ canonical_ids.empty()
+ && local_ids.empty()
+ && services.empty();
+ }
+
+ };
+
+ }
+
+ typedef util::output_iterator_proxy<openid_endpoint_t>
+ endpoint_discovery_iterator;
+
+ string idiscover(
+ endpoint_discovery_iterator oi,
+ const string& identity);
struct idiscovery_t {
bool xri_identity;
string normalized_id;
string canonicalized_id;
xrd::XRD_t xrd;
idiscovery_t() { }
- idiscovery_t(const string& i) {
- idiscover(*this,i);
- }
- idiscovery_t(const char *i) {
- idiscover(*this,i);
- }
void clear() {
normalized_id.clear(); canonicalized_id.clear();
xrd.clear();
}
- idiscovery_t& operator=(const string& i) {
- idiscover(*this,i); return *this; }
- idiscovery_t& operator=(const char *i) {
- idiscover(*this,i); return *this; }
};
}
#endif /* __OPKELE_DISCOVERY_H */
diff --git a/include/opkele/exception.h b/include/opkele/exception.h
index a8c3339..ccb39d9 100644
--- a/include/opkele/exception.h
+++ b/include/opkele/exception.h
@@ -1,316 +1,335 @@
#ifndef __OPKELE_EXCEPTION_H
#define __OPKELE_EXCEPTION_H
/**
* @file
* @brief opkele exceptions
*/
#include <curl/curl.h>
#include <opkele/opkele-config.h>
#ifdef OPKELE_HAVE_KONFORKA
# include <konforka/exception.h>
/**
* the exception parameters declaration
*/
# define OPKELE_E_PARS const string& fi,const string&fu,int l,const string& w
/**
* the exception parameters list to pass to constructor
*/
# define OPKELE_E_CONS_ fi,fu,l,
/**
* the exception codepoint specification
*/
# define OPKELE_CP_ CODEPOINT,
/**
* open function-try-block
*/
# define OPKELE_FUNC_TRY try
/**
* the simple rethrow of konforka-based exception
*/
# define OPKELE_RETHROW catch(konforka::exception& e) { e.see(CODEPOINT); throw; }
#else /* OPKELE_HAVE_KONFORKA */
# include <exception>
# include <string>
/**
* the exception parameter declaration
*/
# define OPKELE_E_PARS const string& w
/**
* the dummy prefix for exception parameters list to prepend in the absence of
* konforka library
*/
# define OPKELE_E_CONS_
/**
* the dummy placeholder for konforka exception codepoint specification
*/
# define OPKELE_CP_
/**
* the dummy define for the opening function-try-block
*/
# define OPKELE_FUNC_TRY
/**
* the dummy define for the konforka-based rethrow of exception
*/
# define OPKELE_RETHROW
#endif /* OPKELE_HAVE_KONFORKA */
/**
* the exception parameters list to pass to constructor
*/
# define OPKELE_E_CONS OPKELE_E_CONS_ w
namespace opkele {
using std::string;
/**
* the base opkele exception class
*/
class exception : public
# ifdef OPKELE_HAVE_KONFORKA
konforka::exception
# else
std::exception
# endif
{
public:
# ifdef OPKELE_HAVE_KONFORKA
explicit
exception(const string& fi,const string& fu,int l,const string& w);
# else /* OPKELE_HAVE_KONFORKA */
string _what;
explicit exception(const string& w);
virtual ~exception() throw();
virtual const char * what() const throw();
# endif /* OPKELE_HAVE_KONFORKA */
};
/**
* thrown in case of failed conversion
*/
class failed_conversion : public exception {
public:
failed_conversion(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown in case of failed lookup (either parameter or persistent store)
*/
class failed_lookup : public exception {
public:
failed_lookup(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown in case of bad input (either local or network)
*/
class bad_input : public exception {
public:
bad_input(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown on failed assertion
*/
class failed_assertion : public exception {
public:
failed_assertion(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown if the handle being retrieved is invalid
*/
class invalid_handle : public exception {
public:
invalid_handle(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown if the handle passed to check_authentication request is not
* stateless
*/
class stateful_handle : public exception {
public:
stateful_handle(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown if check_authentication request fails
*/
class failed_check_authentication : public exception {
public:
failed_check_authentication(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown if the id_res request result is negative
*/
class id_res_failed : public exception {
public:
id_res_failed(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown if the user_setup_url is provided with negative response
*/
class id_res_setup : public id_res_failed {
public:
string setup_url;
id_res_setup(OPKELE_E_PARS,const string& su="")
: id_res_failed(OPKELE_E_CONS), setup_url(su) { }
~id_res_setup() throw() { }
};
/**
* thrown in case of signature mismatch
*/
class id_res_mismatch : public id_res_failed {
public:
id_res_mismatch(OPKELE_E_PARS)
: id_res_failed(OPKELE_E_CONS) { }
};
/**
* thrown if the association has expired before it could've been verified.
*/
class id_res_expired_on_delivery : public id_res_failed {
public:
id_res_expired_on_delivery(OPKELE_E_PARS)
: id_res_failed(OPKELE_E_CONS) { }
};
/**
* thown when the user cancelled authentication process.
*/
class id_res_cancel : public id_res_failed {
public:
id_res_cancel(OPKELE_E_PARS)
: id_res_failed(OPKELE_E_CONS) { }
};
/**
* thrown in case of nonce reuse or otherwise imperfect nonce.
*/
class id_res_bad_nonce : public id_res_failed {
public:
id_res_bad_nonce(OPKELE_E_PARS)
: id_res_failed(OPKELE_E_CONS) { }
};
/**
* thrown if return_to didn't pass verification
*/
class id_res_bad_return_to : public id_res_failed {
public:
id_res_bad_return_to(OPKELE_E_PARS)
: id_res_failed(OPKELE_E_CONS) { }
};
/**
* thrown if OP isn't authorized to make an assertion
*/
class id_res_unauthorized : public id_res_failed {
public:
id_res_unauthorized(OPKELE_E_PARS)
: id_res_failed(OPKELE_E_CONS) { }
};
/**
* openssl malfunction occured
*/
class exception_openssl : public exception {
public:
unsigned long _error;
string _ssl_string;
exception_openssl(OPKELE_E_PARS);
~exception_openssl() throw() { }
};
/**
* network operation related error occured
*/
class exception_network : public exception {
public:
exception_network(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* network operation related error occured, specifically, related to
* libcurl
*/
class exception_curl : public exception_network {
public:
CURLcode _error;
string _curl_string;
exception_curl(OPKELE_E_PARS);
exception_curl(OPKELE_E_PARS,CURLcode e);
~exception_curl() throw() { }
};
/**
* htmltidy related error occured
*/
class exception_tidy : public exception {
public:
int _rc;
exception_tidy(OPKELE_E_PARS);
exception_tidy(OPKELE_E_PARS,int r);
~exception_tidy() throw() { }
};
/**
* exception thrown in case of failed discovery
*/
class failed_discovery : public exception {
public:
failed_discovery(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* unsuccessfull xri resolution
*/
class failed_xri_resolution : public failed_discovery {
public:
long _code;
failed_xri_resolution(OPKELE_E_PARS,long _c=-1)
: failed_discovery(OPKELE_E_CONS), _code(_c) { }
};
/**
* not implemented (think pure virtual) member function executed, signfies
* programmer error
*/
class not_implemented : public exception {
public:
not_implemented(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* internal error, indicates internal libopkele problem
*/
class internal_error : public exception {
public:
internal_error(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
/**
* thrown in case of unsupported parameter encountered (e.g. unsupported
* association type).
*/
class unsupported : public exception {
public:
unsupported(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
+ /**
+ * thrown by associations store related functions in case of dumb RP.
+ */
+ class dumb_RP : public exception {
+ public:
+ dumb_RP(OPKELE_E_PARS)
+ : exception(OPKELE_E_CONS) { }
+ };
+
+ /**
+ * thrown by endpoint-queue related function if endpoint is being
+ * accessed but there's no endpoint available.
+ */
+ class no_endpoint : public exception {
+ public:
+ no_endpoint(OPKELE_E_PARS)
+ : exception(OPKELE_E_CONS) { }
+ };
+
}
#endif /* __OPKELE_EXCEPTION_H */
diff --git a/include/opkele/extension.h b/include/opkele/extension.h
index 513672f..3ee25ee 100644
--- a/include/opkele/extension.h
+++ b/include/opkele/extension.h
@@ -1,65 +1,66 @@
#ifndef __OPKELE_EXTENSION_H
#define __OPKELE_EXTENSION_H
/**
* @file
* @brief extensions framework basics
*/
#include <opkele/types.h>
namespace opkele {
/**
* OpenID extension hooks base class
*/
class extension_t {
public:
virtual ~extension_t() { }
+
/**
* hook called by consumer before submitting data to OpenID server.
* It is supposed to manipulate parameters list.
* @param p parameters about to be submitted to server
* @param identity identity being verified. It may differ from the
* one available in parameters list in case of delegation
* @see consumer_t::checkid_
* @see consumer_t::checkid_immediate
* @see consumer_t::checkid_setup
*/
- virtual void checkid_hook(params_t& p,const string& identity);
+ virtual void checkid_hook(basic_openid_message& om);
/**
* hook called by consumer after identity information received from
* OpenID server is verified.
* @param p parameters received from server
* @param sp signed parameters received from server with 'openid.'
* leader stripped
* @param identity identity confirmed. May differ from the one
* available in parameters list in case of delegation. May also be
* empty which means - extract one from parameters
* @see consumer_t::id_res
*/
- virtual void id_res_hook(const params_t& p,const params_t& sp,const string& identity);
+ virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp);
/**
* hook called by server before returning information to consumer.
* The hook may manipulate output parameters. It is important to
* note that modified pout["signed"] is used for signing response.
* @param pin request parameters list with "openid." prefix
* @param pout response parameters list without "openid." prefix
* @see server_t::checkid_
* @see server_t::checkid_immediate
* @see server_t::checkid_setup
*/
- virtual void checkid_hook(const params_t& pin,params_t& pout);
+ virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
/**
* Casts the object to pointer to itself. For convenient passing
* of pointer.
*/
operator extension_t*(void) { return this; }
};
}
#endif /* __OPKELE_EXTENSION_H */
diff --git a/include/opkele/extension_chain.h b/include/opkele/extension_chain.h
index f0eea94..fb9bc84 100644
--- a/include/opkele/extension_chain.h
+++ b/include/opkele/extension_chain.h
@@ -1,38 +1,38 @@
#ifndef __OPKELE_EXTENSION_CHAIN_H
#define __OPKELE_EXTENSION_CHAIN_H
/**
* @file
* @brief extension chain extension
*/
#include <list>
#include <opkele/extension.h>
namespace opkele {
using std::list;
/**
* OpenID extensions chain used to combine extensions, it is actually an
* stl list of pointers to extensions.
*/
class extension_chain_t : public extension_t, public list<extension_t*> {
public:
/**
* Default constructor creates an empty chain
*/
extension_chain_t() { }
/**
* Create extension chain with a single extension in it
*/
extension_chain_t(extension_t *e) { push_back(e); }
- virtual void checkid_hook(params_t& p,const string& identity);
- virtual void id_res_hook(const params_t& p,const params_t& sp,const string& identity);
- virtual void checkid_hook(const params_t& pin,params_t& pout);
+ virtual void checkid_hook(basic_openid_message& om);
+ virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp);
+ virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
};
}
#endif /* __OPKELE_EXTENSION_CHAIN_H */
diff --git a/include/opkele/prequeue_rp.h b/include/opkele/prequeue_rp.h
new file mode 100644
index 0000000..b98dd5a
--- a/dev/null
+++ b/include/opkele/prequeue_rp.h
@@ -0,0 +1,81 @@
+#ifndef __OPKELE_RP_H
+#define __OPKELE_RP_H
+
+#include <string>
+#include <set>
+#include <iterator>
+#include <opkele/basic_rp.h>
+
+namespace opkele {
+ using std::string;
+ using std::set;
+ using std::iterator;
+ using std::output_iterator_tag;
+
+ class prequeue_RP : public basic_RP {
+ public:
+ /**
+ * @name Session persistent store API
+ * @{
+ */
+ /**
+ * Called before queueing discovered endpoints. Typically happens
+ * while initiating authentication session.
+ * @see queue_endpoint()
+ * @see end_queueing()
+ */
+ virtual void begin_queueing() { }
+ /**
+ * Used to queue discovered endpoint. It is implementors
+ * responsibility to store the endpoint wherever he choses to store
+ * it.
+ * @param oep the endpoint to queue
+ * @see begin_queueing()
+ * @see end_queueing()
+ */
+ virtual void queue_endpoint(const openid_endpoint_t& oep) = 0;
+ /**
+ * Called after all discovered endpoints were queued. Implementor
+ * may chose to use this virtual to commit endpoints queue to
+ * persistent store.
+ * @see begin_queueing()
+ * @see queue_endpoint()
+ */
+ virtual void end_queueing() { }
+
+ /**
+ * Used to store normalized id when initiating request.
+ * The default implementation does nothing, because implementor
+ * doesn't have to care.
+ * @param nid normalized id
+ * @see get_normalzied_id()
+ */
+ virtual void set_normalized_id(const string& nid);
+ /**
+ * Return the normalized id previously set by set_normalized_id().
+ * Provided for the sake of completeness because default
+ * implementation doesn't use it.
+ * @return the normalized identity
+ */
+ virtual const string get_normalized_id() const;
+ /**
+ * @}
+ */
+
+ /**
+ * @name Actions
+ * @{
+ */
+ void initiate(const string& usi);
+
+ /**
+ * @}
+ */
+
+ void verify_OP(const string& OP,
+ const string& claimed_id,const string& identity) const;
+ };
+
+}
+
+#endif /* __OPKELE_RP_H */
diff --git a/include/opkele/sreg.h b/include/opkele/sreg.h
index df37a86..24cb315 100644
--- a/include/opkele/sreg.h
+++ b/include/opkele/sreg.h
@@ -1,203 +1,203 @@
#ifndef __OPKELE_SREG_H
#define __OPKELE_SREG_H
/**
* @file
* @brief Simple registration extension
*/
#include <opkele/extension.h>
namespace opkele {
using std::map;
/**
* OpenID simple registration extension implementation
* http://openid.net/specs/openid-simple-registration-extension-1_0.html
*/
class sreg_t : public extension_t {
public:
/**
* sreg fields enumeration
*/
enum fieldbit_t {
/**
* Any UTF-8 string that the End User wants to use as a nickname.
*/
field_nickname = 1,
/**
* The email address of the End User as specified in section 3.4.1 of [RFC2822]
*/
field_email = 2,
/**
* UTF-8 string free text representation of the End User's full name.
*/
field_fullname = 4,
/**
* The End User's date of birth as YYYY-MM-DD. Any values whose
* representation uses fewer than the specified number of
* digits should be zero-padded. The length of this value MUST
* always be 10. If the End User user does not want to reveal
* any particular component of this value, it MUST be set to
* zero.
*
* For instance, if a End User wants to specify that his date
* of birth is in 1980, but not the month or day, the value
* returned SHALL be "1980-00-00".
*/
field_dob = 8,
/**
* Alias to field_dob
*/
field_birthdate = field_dob,
/**
* The End User's gender, "M" for male, "F" for female.
*/
field_gender = 16,
/**
* Alias to field_gender
*/
field_sex = field_gender,
/**
* UTF-8 string free text that SHOULD conform to the End User's
* country's postal system.
*/
field_postcode = 32,
/**
* The End User's country of residence as specified by ISO3166
*/
field_country = 64,
/**
* End User's preferred language as specified by ISO639
*/
field_language = 128,
/**
* ASCII string from TimeZone database
*
* For example, "Europe/Paris" or "America/Los_Angeles".
*/
field_timezone = 256,
/**
* All fields bits combined
*/
fields_ALL = 511,
/**
* No fields
*/
fields_NONE = 0
};
/**
* Bitmask for fields which, if absent from the response, will
* prevent the Consumer from completing the registration without
* End User interation.
*/
long fields_required;
/**
* Bitmask for fields that will be used by the Consumer, but whose
* absence will not prevent the registration from completing.
*/
long fields_optional;
/**
* A URL which the Consumer provides to give the End User a place
* to read about the how the profile data will be used. The
* Identity Provider SHOULD display this URL to the End User if it
* is given.
*/
string policy_url;
/**
* Bitmask for fields present in response
*/
long has_fields;
/**
* Container type for response fields values
*/
typedef map<fieldbit_t,string> response_t;
/**
* Response contents
*/
response_t response;
/**
* Fields bitmask to send in response
*/
long fields_response;
/**
* Consumer constructor.
* @param fr required fields
* @see fields_required
* @param fo optional fields
* @see fields_optional
* @param pu policy url
* @see policy_url
*/
sreg_t(long fr=fields_NONE,long fo=fields_NONE,const string& pu="")
: fields_required(fr), fields_optional(fo), policy_url(pu), has_fields(0) { }
/**
* Implementation of consumer's checkid hook
*/
- virtual void checkid_hook(params_t& p,const string& identity);
+ virtual void checkid_hook(basic_openid_message& om);
/**
* Implementation of consumer's id_res hook
*/
- virtual void id_res_hook(const params_t& p,const params_t& sp,const string& identity);
+ virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp);
/**
* Implementation of server's checkid_hook
*/
- virtual void checkid_hook(const params_t& pin,params_t& pout);
+ virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
/**
* Check and see if we have value for some particular field.
* @param fb field in question
* @see fieldbit_t
* @return true if the value is available
*/
bool has_field(fieldbit_t fb) const { return has_fields&fb; }
/**
* Retrieve the value for a field.
* @param fb field in question
* @see fieldbit_t
* @return field value
* @throw failed_lookup if no data avaialble
*/
const string& get_field(fieldbit_t fb) const;
/**
* Set the value for a field.
* @param fb field in question
* @see fieldbit_t
* @param fv field value
*/
void set_field(fieldbit_t fb,const string& fv);
/**
* Remove the value for a field.
* @param fb field in question
* @see fieldbit_t
*/
void reset_field(fieldbit_t fb);
/**
* Reset field data
*/
void clear();
/**
* Function called after parsing sreg request to set up response
* fields. The default implementation tries to send as much fields
* as we have. The function is supposed to set the data and
* fields_response.
* @see fields_response
* @param pin input request parameters with "openid." prefix
* @param pout output request parameters without "openid." prefix.
* @see checkid_hook(const params_t&,params_t&)
*/
- virtual void setup_response(const params_t& pin,params_t& pout);
+ virtual void setup_response(const basic_openid_message& inm,basic_openid_message& oum);
};
}
#endif /* __OPKELE_SREG_H */
diff --git a/include/opkele/types.h b/include/opkele/types.h
index de44a5c..d5ad258 100644
--- a/include/opkele/types.h
+++ b/include/opkele/types.h
@@ -1,246 +1,207 @@
#ifndef __OPKELE_TYPES_H
#define __OPKELE_TYPES_H
/**
* @file
* @brief various types declarations
*/
#include <ostream>
#include <vector>
#include <string>
#include <map>
#include <set>
+#include <list>
+#include <opkele/iterator.h>
#include <opkele/tr1-mem.h>
namespace opkele {
using std::vector;
using std::string;
using std::map;
using std::ostream;
using std::multimap;
using std::set;
+ using std::list;
+ using std::iterator;
+ using std::forward_iterator_tag;
/**
* the OpenID operation mode
*/
typedef enum _mode_t {
mode_associate,
mode_checkid_immediate,
mode_checkid_setup,
mode_check_association
} mode_t;
/**
* the association secret container
*/
class secret_t : public vector<unsigned char> {
public:
/**
* xor the secret and hmac together and encode, using base64
* @param key_d pointer to the message digest
* @param rv reference to the return value
*/
void enxor_to_base64(const unsigned char *key_d,string& rv) const;
/**
* decode base64-encoded secret and xor it with the message digest
* @param key_d pointer to the message digest
* @param b64 base64-encoded secret value
*/
void enxor_from_base64(const unsigned char *key_d,const string& b64);
/**
* plainly encode to base64 representation
* @param rv reference to the return value
*/
void to_base64(string& rv) const;
/**
* decode cleartext secret from base64
* @param b64 base64-encoded representation of the secret value
*/
void from_base64(const string& b64);
};
/**
* Interface to the association.
*/
class association_t {
public:
virtual ~association_t() { }
/**
* retrieve the server with which association was established.
* @return server name
*/
virtual string server() const = 0;
/**
* retrieve the association handle.
* @return handle
*/
virtual string handle() const = 0;
/**
* retrieve the association type.
* @return association type
*/
virtual string assoc_type() const = 0;
/**
* retrieve the association secret.
* @return association secret
*/
virtual secret_t secret() const = 0;
/**
* retrieve the number of seconds the association expires in.
* @return seconds till expiration
*/
virtual int expires_in() const = 0;
/**
* check whether the association is stateless.
* @return true if stateless
*/
virtual bool stateless() const = 0;
/**
* check whether the association is expired.
* @return true if expired
*/
virtual bool is_expired() const = 0;
};
/**
* the shared_ptr<> for association_t object type
*/
typedef tr1mem::shared_ptr<association_t> assoc_t;
+ class basic_openid_message {
+ public:
+ typedef list<string> fields_t;
+ typedef util::forward_iterator_proxy<
+ string,const string&,const string*
+ > fields_iterator;
+
+ basic_openid_message() { }
+ basic_openid_message(const basic_openid_message& x);
+ void copy_to(basic_openid_message& x) const;
+
+ virtual bool has_field(const string& n) const = 0;
+ virtual const string& get_field(const string& n) const = 0;
+
+ virtual bool has_ns(const string& uri) const;
+ virtual string get_ns(const string& uri) const;
+
+ virtual fields_iterator fields_begin() const = 0;
+ virtual fields_iterator fields_end() const = 0;
+
+ virtual string append_query(const string& url) const;
+ virtual string query_string() const;
+
+
+ virtual void reset_fields();
+ virtual void set_field(const string& n,const string& v);
+ virtual void reset_field(const string& n);
+
+ virtual void from_keyvalues(const string& kv);
+
+ void add_to_signed(const string& fields);
+ string find_ns(const string& uri,const char *pfx) const;
+ string allocate_ns(const string& uri,const char *pfx);
+ };
+
+ class openid_message_t : public basic_openid_message, public map<string,string> {
+ public:
+ openid_message_t() { }
+ openid_message_t(const basic_openid_message& x)
+ : basic_openid_message(x) { }
+
+ void copy_to(basic_openid_message& x) const;
+
+ bool has_field(const string& n) const;
+ const string& get_field(const string& n) const;
+ virtual fields_iterator fields_begin() const;
+ virtual fields_iterator fields_end() const;
+
+ void reset_fields();
+ void set_field(const string& n,const string& v);
+ void reset_field(const string& n);
+ };
+
/**
* request/response parameters map
*/
- class params_t : public map<string,string> {
+ class params_t : public openid_message_t {
public:
/**
* check whether the parameter is present.
* @param n the parameter name
* @return true if yes
*/
- bool has_param(const string& n) const;
+ bool has_param(const string& n) const {
+ return has_field(n); }
/**
* retrieve the parameter (const version)
* @param n the parameter name
* @return the parameter value
* @throw failed_lookup if there is no such parameter
*/
- const string& get_param(const string& n) const;
- /**
- * retrieve the parameter.
- * @param n the parameter name
- * @return the parameter value
- * @throw failed_lookup if there is no such parameter
- */
- string& get_param(const string& n);
+ const string& get_param(const string& n) const {
+ return get_field(n); }
/**
* parse the OpenID key/value data.
* @param kv the OpenID key/value data
*/
- void parse_keyvalues(const string& kv);
- /**
- * sign the fields.
- * @param secret the secret used for signing
- * @param sig reference to the string, containing base64-encoded
- * result
- * @param slist the comma-separated list of fields to sign
- * @param prefix the string to prepend to parameter names
- */
- void sign(secret_t secret,string& sig,const string& slist,const char *prefix=0) const;
+ void parse_keyvalues(const string& kv) {
+ from_keyvalues(kv); }
- /**
- * append parameters to the URL as a GET-request parameters.
- * @param url the base URL
- * @param prefix the string to prepend to parameter names
- * @return the ready-to-use location
- */
- string append_query(const string& url,const char *prefix = "openid.") const;
+ string append_query(const string& url,const char *prefix="openid.") const;
- /**
- * make up a query string suitable for use in GET and POST
- * requests.
- * @param prefix string to prened to parameter names
- * @return query string
- */
- string query_string(const char *prefix = "openid.") const;
};
- /**
- * dump the key/value pairs for the parameters to the stream.
- * @param o output stream
- * @param p the parameters
- */
- ostream& operator << (ostream& o,const params_t& p);
-
- namespace xrd {
-
- struct priority_compare {
- inline bool operator()(long a,long b) const {
- return (a<0) ? false : (b<0) ? true : (a<b);
- }
- };
-
- template <typename _DT>
- class priority_map : public multimap<long,_DT,priority_compare> {
- typedef multimap<long,_DT,priority_compare> map_type;
- public:
-
- inline _DT& add(long priority,const _DT& d) {
- return insert(typename map_type::value_type(priority,d))->second;
- }
- };
-
- typedef priority_map<string> canonical_ids_t;
- typedef priority_map<string> local_ids_t;
- typedef set<string> types_t;
- typedef priority_map<string> uris_t;
-
- class service_t {
- public:
- types_t types;
- uris_t uris;
- local_ids_t local_ids;
- string provider_id;
-
- void clear() {
- types.clear();
- uris.clear(); local_ids.clear();
- provider_id.clear();
- }
- };
- typedef priority_map<service_t> services_t;
-
- class XRD_t {
- public:
- time_t expires;
-
- canonical_ids_t canonical_ids;
- local_ids_t local_ids;
- services_t services;
- string provider_id;
-
- void clear() {
- expires = 0;
- canonical_ids.clear(); local_ids.clear();
- services.clear();
- provider_id.clear();
- }
- bool empty() const {
- return
- canonical_ids.empty()
- && local_ids.empty()
- && services.empty();
- }
-
- };
-
- }
-
}
#endif /* __OPKELE_TYPES_H */
diff --git a/include/opkele/util.h b/include/opkele/util.h
index 085c9e6..e9176b0 100644
--- a/include/opkele/util.h
+++ b/include/opkele/util.h
@@ -1,143 +1,151 @@
#ifndef __OPKELE_UTIL_H
#define __OPKELE_UTIL_H
#include <time.h>
#include <string>
#include <vector>
#include <openssl/bn.h>
#include <openssl/dh.h>
+#include <opkele/types.h>
namespace opkele {
using std::string;
using std::vector;
/**
* @brief opkele utils namespace
*/
namespace util {
/**
* Convenience class encapsulating SSL BIGNUM object for the purpose of
* automatical freeing.
*/
class bignum_t {
public:
BIGNUM *_bn;
bignum_t() : _bn(0) { }
bignum_t(BIGNUM *bn) : _bn(bn) { }
~bignum_t() throw() { if(_bn) BN_free(_bn); }
bignum_t& operator=(BIGNUM *bn) { if(_bn) BN_free(_bn); _bn = bn; return *this; }
operator const BIGNUM*(void) const { return _bn; }
operator BIGNUM*(void) { return _bn; }
};
/**
* Convenience clas encapsulating SSL DH object for the purpose of
* automatic freeing.
*/
class dh_t {
public:
DH *_dh;
dh_t() : _dh(0) { }
dh_t(DH *dh) : _dh(dh) { }
~dh_t() throw() { if(_dh) DH_free(_dh); }
dh_t& operator=(DH *dh) { if(_dh) DH_free(_dh); _dh = dh; return *this; }
operator const DH*(void) const { return _dh; }
operator DH*(void) { return _dh; }
DH* operator->() { return _dh; }
const DH* operator->() const { return _dh; }
};
/**
* Convert base64-encoded SSL BIGNUM to internal representation.
* @param b64 base64-encoded number
* @return SSL BIGNUM
* @throw failed_conversion in case of error
*/
BIGNUM *base64_to_bignum(const string& b64);
/**
* Convert decimal representation to SSL BIGNUM.
* @param dec decimal representation
* @return resulting BIGNUM
* @throw failed_conversion in case of error
*/
BIGNUM *dec_to_bignum(const string& dec);
/**
* Convert SSL BIGNUM data to base64 encoded string.
* @param bn BIGNUM
* @return base64encoded string
*/
string bignum_to_base64(const BIGNUM *bn);
/**
* Convert internal time representation to w3c format
* @param t internal representation
* @return w3c time
* @throw failed_conversion in case of error
*/
string time_to_w3c(time_t t);
/**
* Convert W3C time representation to internal time_t
* @param w w3c representation
* @return converted time
* @throw failed_conversion in case of error
*/
time_t w3c_to_time(const string& w);
/**
* Encode string to the representation suitable for using in URL.
* @param str string to encode
* @return encoded string
* @throw failed_conversion in case of failure
*/
string url_encode(const string& str);
/**
* Convert number to string
* @param l number
* @return string representation
* @throw failed_conversion in case of failure
*/
string long_to_string(long l);
/**
* Convert string to number
* @param s string, containing the number
* @return the number
* @throw failed_conversion in case of failure
*/
long string_to_long(const string& s);
/**
* Encode binary data using base64.
* @param data pointer to binary data
* @param length length of data
* @return encoded data
*/
string encode_base64(const void *data,size_t length);
/**
* Decode binary data from base64 representation.
* @param data base64-encoded data
* @param rv container for decoded binary
*/
void decode_base64(const string& data,vector<unsigned char>& rv);
/**
* Normalize http(s) URI according to RFC3986, section 6. URI is
* expected to have scheme: in front of it.
* @param uri URI
* @return normalized URI
* @throw not_implemented in case of non-httpi(s) URI
* @throw bad_input in case of malformed URI
*/
string rfc_3986_normalize_uri(const string& uri);
+
+ string& strip_uri_fragment_part(string& uri);
+
+ string abi_demangle(const char* mn);
+
+ string base64_signature(const assoc_t& assoc,const basic_openid_message& om);
+
}
}
#endif /* __OPKELE_UTIL_H */