-rw-r--r-- | include/opkele/discovery.h | 3 | ||||
-rw-r--r-- | include/opkele/prequeue_rp.h | 8 | ||||
-rw-r--r-- | include/opkele/types.h | 3 | ||||
-rw-r--r-- | lib/prequeue_rp.cc | 9 |
4 files changed, 19 insertions, 4 deletions
diff --git a/include/opkele/discovery.h b/include/opkele/discovery.h index 4471597..f2721a6 100644 --- a/include/opkele/discovery.h +++ b/include/opkele/discovery.h @@ -1,115 +1,114 @@ #ifndef __OPKELE_DISCOVERY_H #define __OPKELE_DISCOVERY_H #include <string> #include <opkele/types.h> namespace opkele { using std::string; 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; } 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; struct uri_t { string uri; string append; uri_t() { } uri_t(const string& u) : uri(u) { } uri_t(const string& u,const string& a) : uri(u), append(a) { } }; typedef priority_map<uri_t> 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; + typedef openid_endpoint_output_iterator endpoint_discovery_iterator; string idiscover( endpoint_discovery_iterator oi, const string& identity); void yadiscover( endpoint_discovery_iterator oi, const string& yurl, const char **types, bool redirs=false); struct idiscovery_t { bool xri_identity; string normalized_id; string canonicalized_id; xrd::XRD_t xrd; idiscovery_t() { } void clear() { normalized_id.clear(); canonicalized_id.clear(); xrd.clear(); } }; } #endif /* __OPKELE_DISCOVERY_H */ diff --git a/include/opkele/prequeue_rp.h b/include/opkele/prequeue_rp.h index 68fe03d..6f1fda9 100644 --- a/include/opkele/prequeue_rp.h +++ b/include/opkele/prequeue_rp.h @@ -1,88 +1,96 @@ #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; /** * discovery-enabled RP implementation, prequeueing discovered endpoints */ 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 * @{ */ /** * In addition to base class implementation it does endpoints * discovery and queueing * @param usi User-suppled identifier */ void initiate(const string& usi); /** * @} */ void verify_OP(const string& OP, const string& claimed_id,const string& identity) const; + + /** + * Perform full discovery on identity + * @param it iterator used for feeding discovered endpoints back to caller + * @param id user supplied identity + * @returns normalized identity (canonical identifier can be found in endpoints) + */ + virtual const string discover(openid_endpoint_output_iterator it,const string& id) const; }; } #endif /* __OPKELE_RP_H */ diff --git a/include/opkele/types.h b/include/opkele/types.h index 1f48362..1fab869 100644 --- a/include/opkele/types.h +++ b/include/opkele/types.h @@ -36,195 +36,198 @@ namespace opkele { 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() { } virtual ~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); virtual void to_keyvalues(ostream& o) const; virtual void to_htmlhiddens(ostream& o,const char* pfx=0) const; 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 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 { 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 { return get_field(n); } /** * parse the OpenID key/value data. * @param kv the OpenID key/value data */ void parse_keyvalues(const string& kv) { from_keyvalues(kv); } string append_query(const string& url,const char *prefix="openid.") const; }; 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); } }; + typedef util::output_iterator_proxy<openid_endpoint_t> + openid_endpoint_output_iterator; + } #endif /* __OPKELE_TYPES_H */ diff --git a/lib/prequeue_rp.cc b/lib/prequeue_rp.cc index 3aa960f..ed1ddfe 100644 --- a/lib/prequeue_rp.cc +++ b/lib/prequeue_rp.cc @@ -1,81 +1,86 @@ #include <iostream> #include <openssl/sha.h> #include <openssl/hmac.h> #include <opkele/exception.h> #include <opkele/prequeue_rp.h> #include <opkele/discovery.h> #include <opkele/uris.h> #include <opkele/data.h> #include <opkele/util.h> #include <opkele/curl.h> #include <opkele/debug.h> namespace opkele { class __OP_verifier_good_input : public exception { public: __OP_verifier_good_input(OPKELE_E_PARS) : exception(OPKELE_E_CONS) { } }; class OP_verifier : public iterator<output_iterator_tag,openid_endpoint_t,void> { public: const string& OP; const string& id; OP_verifier(const string& o,const string& i) : OP(o), id(i) { } OP_verifier& operator*() { return *this; } OP_verifier& operator=(const openid_endpoint_t& oep) { if(oep.uri==OP) { if(oep.claimed_id==IDURI_SELECT20 || oep.local_id==IDURI_SELECT20 ) throw bad_input(OPKELE_CP_ "claimed_id is an OP-Id"); if(oep.local_id==id) throw __OP_verifier_good_input(OPKELE_CP_ "Found corresponding endpoint"); } return *this; } OP_verifier& operator++() { return *this; } OP_verifier& operator++(int) { return *this; } }; void prequeue_RP::verify_OP(const string& OP,const string& claimed_id,const string& identity) const { try { - idiscover(OP_verifier(OP,identity),claimed_id); + discover(OP_verifier(OP,identity),claimed_id); throw id_res_unauthorized(OPKELE_CP_ "OP is not authorized to make an assertion regarding the identity"); }catch(__OP_verifier_good_input& ovgi) { } } class endpoint_queuer : public iterator<output_iterator_tag,openid_endpoint_t,void> { public: prequeue_RP& rp; endpoint_queuer(prequeue_RP& r) : rp(r) { } endpoint_queuer& operator*() { return *this; } endpoint_queuer& operator=(const openid_endpoint_t& oep) { rp.queue_endpoint(oep); return *this; } endpoint_queuer& operator++() { return *this; } endpoint_queuer& operator++(int) { return *this; } }; void prequeue_RP::initiate(const string& usi) { begin_queueing(); - set_normalized_id( idiscover(endpoint_queuer(*this),usi) ); + set_normalized_id( discover(endpoint_queuer(*this),usi) ); end_queueing(); } void prequeue_RP::set_normalized_id(const string&) { } const string prequeue_RP::get_normalized_id() const { throw not_implemented(OPKELE_CP_ "get_normalized_id() is not implemented"); } + const string prequeue_RP::discover(openid_endpoint_output_iterator it, + const string& id) const { + return idiscover(it,id); + } + } |