diff options
author | Stef Walter <stef@memberwebs.com> | 2009-06-17 00:13:58 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2009-06-17 00:13:58 +0000 |
commit | a7557acb5423ea8e4c6bcce27472918c638d56f8 (patch) | |
tree | 3e3c0e5b811441d1231670ba034be6c4973fdb1d /module/consumer.cc | |
parent | 2e1c4b9fc834c8af9f1a31789b1dc614c13fcad5 (diff) |
Some coding work. Banged out generally how things will work. Nothing compiles yet.
Diffstat (limited to 'module/consumer.cc')
-rw-r--r-- | module/consumer.cc | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/module/consumer.cc b/module/consumer.cc new file mode 100644 index 0000000..8ade43a --- /dev/null +++ b/module/consumer.cc @@ -0,0 +1,243 @@ + +#include "consumer.h" + +using opkele::assoc_t; +using opkele::association; +using opkele::endpoint_t; +using opkele::failed_lookup; +using opkele::params; +using opkele::prequeue_RP; +using opkele::secret_t; + +using std::string; +using std::vector; + +class Consumer : + public prequeue_RP +{ +private: // types + vector<endpoint_t> endpoints; + +public: // interface + Consumer(const char *url, singleid_board_t *board) + : _url(url), _board(board) + { } + +public: // overrides + + virtual void begin_queueing() const + { _endpoints.clear(); } + + virtual void queue_endpoint(const openid_endpoint_t& oep) + { _endpoints.push(oep); } + + virtual void set_normalized_id(const string& nid) + { _normalized = nid; } + + virtual const string get_normalized_id() const + { return _normalized; } + + virtual const string get_this_url() + { return _url; } + + virtual assoc_t store_assoc(const string& server, const string& handle, + const string& type, const secret_t& secret, + int expires_in); + + virtual assoc_t find_assoc(const string& server); + + virtual assoc_t retrieve_assoc(const string& server, const string& handle); + + virtual assoc_t invalidate_assoc(const string& server, const string& handle); + + virtual void check_nonce(const string& server, const string& nonce); + +private: // data + singleid_board_t _board; + endpoints _endpoints; + string _normalized; + string _url; +}; + +assoc_t +Consumer::store_assoc(const string& server, const string& handle, + const string& type, const secret_t& secret, + int expires_in) +{ + singleid_assoc_t data; + int res; + + data.server = server.c_str(); + data.handle = handle.c_str(); + data.type = type.c_str(); + data.secret = secret.data(); + data.n_secret = secret.size(); + data.expires = expires_in; + + { + LockShared lock; /* scoped lock */ + res = singleid_board_store_assoc (_board, &data); + } + + if (!res) + throw dump_RP("association data was too large to fit in shared storage"); + + return assoc_t(new association(server, handle, type, secret, expires_on, false)); +} + +assoc_t +Consumer::find_assoc(const string& server) +{ + singleid_assoc_t data = { 0, }; + association assoc = NULL; + + { + LockShared lock; + if (singleid_board_find_assoc (_board, server.c_str(), NULL, &data)) + assoc = new association(data.server, data.handle, data.type, + secret_t(data.secret, data.secret + data.n_secret), + data.expires, false); + } + + if (!assoc) + throw failed_lookup("could not find association for server: " + server); + + return assoc_t(assoc); +} + +assoc_t +Consumer::retrieve_assoc(const string& server, const string& handle) +{ + singleid_assoc_t data = { 0, }; + association assoc = NULL; + + { + LockShared lock; + if (singleid_board_find_assoc (_board, server.c_str(), handle.c_str(), &data)) + assoc = new association(data.server, data.handle, data.type, + secret_t(data.secret, data.secret + data.n_secret), + data.expires, false); + } + + if (!assoc) + throw failed_lookup("could not retrieve association for server: " + server); + + return assoc_t(assoc); +} + +assoc_t +Consumer::invalidate_assoc(const string& server, const string& handle) +{ + LockShared lock; + singleid_board_invalidate_assoc (_board, server.c_str(), handle.c_str()); +} + + +void +Consumer::check_nonce(const string& server, const string& nonce) +{ + LockShared lock; + singleid_board_check_nonce (_board, server.c_str(), nonce.c_str()); +} + +/* ----------------------------------------------------------------------- + * AUTHENTICATION + */ + +static void +filter_openid_params (params_t ¶ms, params_t &extensions) +{ + for (params_t::iterator it = params.begin(); it != params.end(); ) { + const string& name = it->first; + if (name.find ("openid.") == 0) { + /* Extension params have at least a second dot */ + if (name.find ('.', sizeof ("openid."))) + extensions.insert(*it); + + /* We erase an increment together, must use post-increment operator */ + it->erase(it++); + } else { + /* Did not match, just go to next element */ + ++it; + } + } +} + +static void +start_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms, + const string& trust_root, const string &identity) +{ + /* Remove all openid params, and stash away extensions */ + filter_openid_params (params); + string return_to = params.append_query (consumer.get_this_url(), ""); + + params_t result; + + try { + openid_message_t cm; + consumer.initiate (identity); + result = consumer.checkid_ (cm, opkele::mode_checkid_setup, return_to, trust_root); + output = result.append_query (consumer.get_endpoint().uri); + + } catch (failed_xri_resolution &ex) { + sid_request_respond (xxx, xxx, xxx); + return; + + } catch (failed_discovery &ex) { + sid_request_respond (xxx, xxx, xxx); + return; + + } catch (bad_input &ex) { + sid_request_respond (xxx, xxx, xxx); + return; + + } catch (exception &ex) { + sid_request_respond (xxx, xxx, xxx); + xxx log xxx; + return; + } + + sid_request_respond (xxx, xxx, xxx); +} + +static void +complete_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms) +{ + try { + consumer.id_res(AdaptorFix(params)); + string identity = consumer.get_claimed_id(); + sid_request_authenticated (req, identity.c_str()); + } catch (exception &ex) { + sid_request_respond (xxx, xxx, xxx); + } +} + +static void +cancelled_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms) +{ + sid_request_respond (xxx, xxx, xxx); +} + +void +sid_consumer_authenticate(sid_request_t *req, sid_storage_t *store, const char *identity) +{ + params_t params; + + assert (req); + assert (store); + + const char *qs = sid_request_qs (req); + parse_query_string (qs, params); + + const char *url = sid_request_url (req); + Consumer consumer(url, store); + + if (params.has_param("openid.assoc_handle")) + complete_auth (req, consumer, params); + else if (params.has_param("openid.mode") && params.get_param("openid.mode") == "cancel") + cancelled_auth (req, consumer, params); + else + begin_auth (req, consumer, params, trust_root, identity); + + consumer.close(); +} |