summaryrefslogtreecommitdiffabout
path: root/include/opkele
Side-by-side diff
Diffstat (limited to 'include/opkele') (more/less context) (ignore whitespace changes)
-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
9 files changed, 479 insertions, 127 deletions
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
@@ -3,13 +3,87 @@
#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;
@@ -18,22 +92,12 @@ namespace opkele {
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; }
};
}
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
@@ -311,6 +311,25 @@ namespace opkele {
: 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
@@ -17,6 +17,7 @@ namespace opkele {
public:
virtual ~extension_t() { }
+
/**
* hook called by consumer before submitting data to OpenID server.
* It is supposed to manipulate parameters list.
@@ -27,7 +28,7 @@ namespace opkele {
* @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.
@@ -39,7 +40,7 @@ namespace opkele {
* 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.
@@ -51,7 +52,7 @@ namespace opkele {
* @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
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
@@ -28,9 +28,9 @@ namespace opkele {
*/
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);
};
}
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
@@ -138,15 +138,15 @@ namespace opkele {
/**
* 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.
@@ -195,7 +195,7 @@ namespace opkele {
* @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);
};
}
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
@@ -11,6 +11,8 @@
#include <string>
#include <map>
#include <set>
+#include <list>
+#include <opkele/iterator.h>
#include <opkele/tr1-mem.h>
namespace opkele {
@@ -20,6 +22,9 @@ namespace opkele {
using std::ostream;
using std::multimap;
using std::set;
+ using std::list;
+ using std::iterator;
+ using std::forward_iterator_tag;
/**
* the OpenID operation mode
@@ -111,10 +116,63 @@ namespace opkele {
*/
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:
/**
@@ -122,125 +180,28 @@ namespace opkele {
* @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
@@ -6,6 +6,7 @@
#include <vector>
#include <openssl/bn.h>
#include <openssl/dh.h>
+#include <opkele/types.h>
namespace opkele {
using std::string;
@@ -136,6 +137,13 @@ namespace opkele {
* @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);
+
}
}