diff options
Diffstat (limited to 'module/consumer.cc')
-rw-r--r-- | module/consumer.cc | 198 |
1 files changed, 149 insertions, 49 deletions
diff --git a/module/consumer.cc b/module/consumer.cc index 15eadc8..91ab773 100644 --- a/module/consumer.cc +++ b/module/consumer.cc @@ -1,35 +1,77 @@ -#include "consumer.h" +#include "mod_auth_singleid.h" + +#include <opkele/association.h> +#include <opkele/exception.h> +#include <opkele/types.h> +#include <opkele/prequeue_rp.h> +#include <opkele/util.h> using opkele::assoc_t; using opkele::association; -using opkele::endpoint_t; +using opkele::bad_input; +using opkele::dumb_RP; +using opkele::exception; +using opkele::failed_discovery; using opkele::failed_lookup; -using opkele::params; +using opkele::failed_xri_resolution; +using opkele::no_endpoint; +using opkele::openid_endpoint_t; +using opkele::openid_message_t; +using opkele::params_t; using opkele::prequeue_RP; using opkele::secret_t; using std::string; using std::vector; +class LockShared +{ +public: + LockShared() + { sid_shared_lock (); } + ~LockShared() + { sid_shared_unlock (); } +}; + +class AdaptorFix : + public params_t +{ +public: + AdaptorFix(params_t& params) + { _params = params; }; + virtual bool has_field(const string& n) const + { return _params.has_param("openid." + n); } + virtual const string& get_field(const string& n) const + { return _params.get_param("openid." + n); } +private: + params_t _params; +}; + + class Consumer : public prequeue_RP { private: // types - vector<endpoint_t> endpoints; + typedef vector<openid_endpoint_t> endpoints; public: // interface - Consumer(const char *url, singleid_board_t *board) - : _url(url), _board(board) + Consumer(const char *url, sid_storage_t *store) + : _url(url), _store(store), _index(0) { } public: // overrides - virtual void begin_queueing() const - { _endpoints.clear(); } + virtual void begin_queueing() + { _endpoints.clear(); _index = 0; } virtual void queue_endpoint(const openid_endpoint_t& oep) - { _endpoints.push(oep); } + { _endpoints.push_back(oep); } + + virtual const openid_endpoint_t& get_endpoint() const; + + virtual void next_endpoint() + { _index++; } virtual void set_normalized_id(const string& nid) { _normalized = nid; } @@ -37,7 +79,7 @@ public: // overrides virtual const string get_normalized_id() const { return _normalized; } - virtual const string get_this_url() + virtual const string get_this_url() const { return _url; } virtual assoc_t store_assoc(const string& server, const string& handle, @@ -48,25 +90,37 @@ public: // overrides virtual assoc_t retrieve_assoc(const string& server, const string& handle); - virtual assoc_t invalidate_assoc(const string& server, const string& handle); + virtual void invalidate_assoc(const string& server, const string& handle); virtual void check_nonce(const string& server, const string& nonce); private: // data - singleid_board_t _board; + sid_storage_t *_store; endpoints _endpoints; string _normalized; string _url; + endpoints::size_type _index; }; +const openid_endpoint_t& +Consumer::get_endpoint() const +{ + if (_index >= _endpoints.size()) + throw no_endpoint("no more endpoints"); + return _endpoints[_index]; +} + 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; + sid_assoc_t data; int res; + if (!_store) + throw dumb_RP("no storage initialized"); + data.server = server.c_str(); data.handle = handle.c_str(); data.type = type.c_str(); @@ -76,27 +130,32 @@ Consumer::store_assoc(const string& server, const string& handle, { LockShared lock; /* scoped lock */ - res = singleid_board_store_assoc (_board, &data); + res = sid_storage_store_assoc (_store, &data); } if (!res) - throw dump_RP("association data was too large to fit in shared storage"); + throw dumb_RP("association data was too large to fit in shared storage"); - return assoc_t(new association(server, handle, type, secret, expires_on, false)); + return assoc_t(new association(server, handle, type, secret, expires_in, false)); } assoc_t Consumer::find_assoc(const string& server) { - singleid_assoc_t data = { 0, }; - association assoc = NULL; + sid_assoc_t data = { 0, }; + association *assoc = NULL; + + if (!_store) + throw dumb_RP("no storage initialized"); { LockShared lock; - if (singleid_board_find_assoc (_board, server.c_str(), NULL, &data)) + if (sid_storage_find_assoc (_store, server.c_str(), NULL, &data)) { + secret_t secret; + secret.assign(data.secret, data.secret + data.n_secret); assoc = new association(data.server, data.handle, data.type, - secret_t(data.secret, data.secret + data.n_secret), - data.expires, false); + secret, data.expires, false); + } } if (!assoc) @@ -108,15 +167,20 @@ Consumer::find_assoc(const string& server) assoc_t Consumer::retrieve_assoc(const string& server, const string& handle) { - singleid_assoc_t data = { 0, }; - association assoc = NULL; + sid_assoc_t data = { 0, }; + association *assoc = NULL; + + if (!_store) + throw dumb_RP("no storage initialized"); { LockShared lock; - if (singleid_board_find_assoc (_board, server.c_str(), handle.c_str(), &data)) + if (sid_storage_find_assoc (_store, server.c_str(), handle.c_str(), &data)) { + secret_t secret; + secret.assign(data.secret, data.secret + data.n_secret); assoc = new association(data.server, data.handle, data.type, - secret_t(data.secret, data.secret + data.n_secret), - data.expires, false); + secret, data.expires, false); + } } if (!assoc) @@ -125,19 +189,24 @@ Consumer::retrieve_assoc(const string& server, const string& handle) return assoc_t(assoc); } -assoc_t +void Consumer::invalidate_assoc(const string& server, const string& handle) { + if (!_store) + throw dumb_RP("no storage initialized"); + LockShared lock; - singleid_board_invalidate_assoc (_board, server.c_str(), handle.c_str()); + sid_storage_invalidate_assoc (_store, server.c_str(), handle.c_str()); } - void Consumer::check_nonce(const string& server, const string& nonce) { + if (!_store) + throw dumb_RP("no storage initialized"); + LockShared lock; - singleid_board_check_nonce (_board, server.c_str(), nonce.c_str()); + sid_storage_check_nonce (_store, server.c_str(), nonce.c_str()); } /* ----------------------------------------------------------------------- @@ -145,17 +214,13 @@ Consumer::check_nonce(const string& server, const string& nonce) */ static void -filter_openid_params (params_t ¶ms, params_t &extensions) +filter_openid_params (params_t ¶ms) { 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++); + params.erase (it++); } else { /* Did not match, just go to next element */ ++it; @@ -164,7 +229,32 @@ filter_openid_params (params_t ¶ms, params_t &extensions) } static void -start_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms, +parse_query_string (const char *qs, params_t ¶ms) +{ + string pair, key, value; + const char *at; + + while (qs && *qs) { + at = strchr (qs, '&'); + if (at == NULL) + at = qs + strlen (qs); + pair = string(qs, at); + string::size_type loc = pair.find('=', 0); + if (loc != string::npos) { + key = pair.substr (0, loc); + value = pair.substr (loc + 1); + } else { + key = pair; + value = ""; + } + + params[opkele::util::url_decode(key)] = opkele::util::url_decode(value); + qs = at; + } +} + +static void +begin_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 */ @@ -172,32 +262,43 @@ start_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms, string return_to = params.append_query (consumer.get_this_url(), ""); params_t result; + string redirect; 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); + consumer.checkid_ (cm, opkele::mode_checkid_setup, return_to, trust_root); + redirect = cm.append_query (consumer.get_endpoint().uri); } catch (failed_xri_resolution &ex) { - sid_request_respond (xxx, xxx, xxx); + sid_request_respond (req, 503, "Invalid Identifier", NULL, NULL); + sid_request_log_error (req, "failed xri resolution while while discovering identity provider", + ex.what ()); return; } catch (failed_discovery &ex) { - sid_request_respond (xxx, xxx, xxx); + sid_request_respond (req, 503, "Invalid Identifier", NULL, NULL); + sid_request_log_error (req, "failed discovery while while discovering identity provider", + ex.what ()); return; } catch (bad_input &ex) { - sid_request_respond (xxx, xxx, xxx); + sid_request_respond (req, 503, "Invalid Identifier", NULL, NULL); + sid_request_log_error (req, "bad input while while discovering identity provider", + ex.what()); return; } catch (exception &ex) { - sid_request_respond (xxx, xxx, xxx); - xxx log xxx; + sid_request_respond (req, 500, NULL, NULL, NULL); + sid_request_log_error (req, "error while while discovering identity provider", + ex.what()); return; } - sid_request_respond (xxx, xxx, xxx); + sid_request_respond (req, 307, "Moved Temporarily", NULL, + "Location", redirect.c_str(), + "Cache-Control", "no-cache", + NULL); } static void @@ -208,14 +309,15 @@ complete_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms) string identity = consumer.get_claimed_id(); sid_request_authenticated (req, identity.c_str()); } catch (exception &ex) { - sid_request_respond (xxx, xxx, xxx); + sid_request_respond (req, 500, NULL, NULL, NULL); + sid_request_log_error (req, "error while completing authentication: %s", ex.what()); } } static void cancelled_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms) { - sid_request_respond (xxx, xxx, xxx); + sid_request_respond (req, 401, "Authentication Required", NULL, NULL); } void @@ -239,6 +341,4 @@ sid_consumer_authenticate(sid_request_t *req, sid_storage_t *store, cancelled_auth (req, consumer, params); else begin_auth (req, consumer, params, trust_root, identity); - - consumer.close(); } |