summaryrefslogtreecommitdiff
path: root/module/consumer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'module/consumer.cc')
-rw-r--r--module/consumer.cc198
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 &params, params_t &extensions)
+filter_openid_params (params_t &params)
{
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 &params, params_t &extensions)
}
static void
-start_auth (sid_request_t *req, Consumer &consumer, params_t &params,
+parse_query_string (const char *qs, params_t &params)
+{
+ 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 &params,
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 &params,
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 &params)
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 &params)
{
- 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();
}