diff options
author | Stef Walter <stef@memberwebs.com> | 2009-07-08 20:44:22 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2009-07-08 20:44:22 +0000 |
commit | c7c67be49fb2b7307900db7e3da4b460f5603ac6 (patch) | |
tree | cd7644507e393bfc608c0113ee2e5cbdf47e5314 | |
parent | 922f89e86245d6653fee4d97fd82168f73620189 (diff) |
Add various messages when things go wrong. Don't try to authenticate POST.
-rw-r--r-- | module/consumer.cc | 70 | ||||
-rw-r--r-- | module/mod_auth_singleid.c | 54 | ||||
-rw-r--r-- | module/mod_auth_singleid.h | 10 |
3 files changed, 107 insertions, 27 deletions
diff --git a/module/consumer.cc b/module/consumer.cc index bc248ad..cbdcfe3 100644 --- a/module/consumer.cc +++ b/module/consumer.cc @@ -12,6 +12,7 @@ using opkele::association; using opkele::bad_input; using opkele::dumb_RP; using opkele::exception; +using opkele::exception_curl; using opkele::failed_discovery; using opkele::failed_lookup; using opkele::failed_xri_resolution; @@ -460,6 +461,14 @@ begin_auth (sid_request_t *req, Consumer &consumer, const string& trust_root, params_t result; string redirect; + /* We cannot authenticate anything but a GET request */ + if (strcmp (sid_request_method (req), "GET") != 0) { + sid_request_respond_html (req, 401, "Must Login", + "<h1>Must Login</h1><p>You must be logged in before you can complete this action.</p>", + "<p><a href='", trust_root.c_str(), "'>Login</a></p>", NULL); + return; + } + try { openid_message_t cm; consumer.initiate (identity); @@ -468,34 +477,44 @@ begin_auth (sid_request_t *req, Consumer &consumer, const string& trust_root, redirect = cm.append_query (consumer.get_endpoint().uri); } catch (failed_xri_resolution &ex) { - sid_request_respond (req, 503, "Invalid Identifier", NULL); - sid_request_log_error (req, "failed xri resolution while while discovering identity provider", - ex.what ()); + sid_request_respond_html (req, 503, "Invalid Identifier", + "<h1>Invalid identifier</h1><p>Details: Could not resolve identity provider.</p>", NULL); + sid_request_log_error (req, "failed xri resolution while while discovering identity provider", ex.what ()); return; } catch (failed_discovery &ex) { - sid_request_respond (req, 503, "Invalid Identifier", NULL); - sid_request_log_error (req, "failed discovery while while discovering identity provider", - ex.what ()); + sid_request_respond_html (req, 503, "Invalid Identifier", + "<h1>Invalid identifier</h1><p>Details: Could not discover identity provider.</p>", NULL); + sid_request_log_error (req, "failed discovery while while discovering identity provider", ex.what ()); return; } catch (bad_input &ex) { - sid_request_respond (req, 503, "Invalid Identifier", NULL); - sid_request_log_error (req, "bad input while while discovering identity provider", - ex.what()); + sid_request_respond_headers (req, 500, "Internal Server Error", NULL); + sid_request_log_error (req, "bad input to libopkele", ex.what()); + return; + + } catch (no_endpoint &ex) { + sid_request_respond_html (req, 503, "No Identity Provider", + "<h1>No identity provider</h1><p>Details: Could not contact a valid identity provider to authenticate you.</p>", NULL); + sid_request_log_error (req, "no more endpoints", ex.what()); + return; + + } catch (exception_curl &ex) { + sid_request_respond_html (req, 503, "Bad Identity Provider", + "<h1>Bad identity provider</h1><p>Details: Could not communicate with the identity provider to authenticate you.</p>", NULL); + sid_request_log_error (req, "could not contact identity provider", ex.what()); return; } catch (exception &ex) { - sid_request_respond (req, 500, NULL, NULL); - sid_request_log_error (req, "error while while discovering identity provider", - ex.what()); + sid_request_respond_headers (req, 500, NULL, NULL); + sid_request_log_error (req, "error while while discovering identity provider", ex.what()); return; } - sid_request_respond (req, 307, "Moved Temporarily", - "Location", redirect.c_str(), - "Cache-Control", "no-cache", - NULL); + sid_request_respond_headers (req, 307, "Moved Temporarily", + "Location", redirect.c_str(), + "Cache-Control", "no-cache", + NULL); } static void @@ -509,13 +528,13 @@ complete_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms, sid_request_authenticated (req, identity.c_str()); parse_ax_attributes(req, params, attributes); } catch (id_res_mismatch &ex) { - sid_request_respond (req, 403, "Signature mismatch", NULL); + sid_request_respond_headers (req, 403, "Signature mismatch", NULL); sid_request_log_error (req, "signature did not match data", ex.what()); } catch (bad_input &ex) { - sid_request_respond (req, 403, "Bad authentication input", NULL); + sid_request_respond_headers (req, 403, "Bad authentication input", NULL); sid_request_log_error (req, "bad input", ex.what()); } catch (id_res_bad_return_to &ex) { - sid_request_respond (req, 403, "Bad authenticated address", NULL); + sid_request_respond_headers (req, 403, "Bad authenticated address", NULL); sid_request_log_error (req, "bad return to", ex.what()); } catch (id_res_failed &ex) { /* If we don't have this association, then try again */ @@ -523,19 +542,22 @@ complete_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms, sid_request_log_error (req, "response from invalid association, retrying authentication", NULL); finished = false; } else { - sid_request_respond (req, 503, "Service error, try again", NULL); + sid_request_respond_headers (req, 503, "Service error, try again", NULL); sid_request_log_error (req, "checking response failed", ex.what()); } } catch (exception &ex) { - sid_request_respond (req, 500, NULL, NULL); + sid_request_respond_headers (req, 500, NULL, NULL); sid_request_log_error (req, "error while completing authentication", ex.what()); } } static void -cancelled_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms) +cancelled_auth (sid_request_t *req, Consumer &consumer, params_t ¶ms, const string& return_to) { - sid_request_respond (req, 401, "Authentication Required", NULL); + sid_request_respond_html (req, 401, "Login Cancelled", + "<h1>Login Cancelled</h1>" + "<p>This website requires authentication, but the authentication process was cancelled.</p>", + "<p><a href='", return_to.c_str(), "'>Retry login</a></p>", NULL); } extern "C" void @@ -567,7 +589,7 @@ sid_consumer_authenticate(sid_request_t *req, sid_storage_t *store, /* Returning cancelled authentication */ if (openid.has_param("mode") && openid.get_param("mode") == "cancel") { - cancelled_auth (req, consumer, openid); + cancelled_auth (req, consumer, openid, url); /* Begin a new authentication */ } else { diff --git a/module/mod_auth_singleid.c b/module/mod_auth_singleid.c index 203b40f..5847829 100644 --- a/module/mod_auth_singleid.c +++ b/module/mod_auth_singleid.c @@ -739,6 +739,7 @@ struct sid_request { int result; request_rec *rec; sid_session_t *sess; + apr_bucket_brigade *output; }; void @@ -758,6 +759,12 @@ sid_request_qs (sid_request_t *req) } const char* +sid_request_method (sid_request_t *req) +{ + return req->rec->method; +} + +const char* sid_request_url (sid_request_t *req, int with_path) { /* function to determine if a connection is using https */ @@ -789,8 +796,8 @@ sid_request_url (sid_request_t *req, int with_path) } void -sid_request_respond (sid_request_t *req, int code, const char *reason, - const char *header, ...) +sid_request_respond_headers (sid_request_t *req, int code, const char *reason, + const char *header, ...) { const char *value; va_list va; @@ -810,6 +817,38 @@ sid_request_respond (sid_request_t *req, int code, const char *reason, } void +sid_request_respond_html (sid_request_t *req, int code, const char *reason, + const char *data, ...) +{ + apr_bucket_brigade *bb; + apr_bucket *b; + conn_rec *con; + va_list va; + + if (reason) + req->rec->status_line = apr_pstrdup (req->rec->pool, reason); + + ap_set_content_type (req->rec, "text/html"); + + con = req->rec->connection; + bb = apr_brigade_create(req->rec->pool, con->bucket_alloc); + + va_start(va, data); + while (data) { + b = apr_bucket_pool_create (data, strlen (data), req->rec->pool, con->bucket_alloc); + APR_BRIGADE_INSERT_TAIL (bb, b); + data = va_arg (va, const char*); + } + va_end(va); + + b = apr_bucket_eos_create (con->bucket_alloc); + APR_BRIGADE_INSERT_TAIL (bb, b); + + req->result = code; + req->output = bb; +} + +void sid_request_authenticated (sid_request_t *req, const char *identifier) { sid_session_t *sess; @@ -959,6 +998,7 @@ hook_authenticate (request_rec* r) const char* authtype; request_rec* mainreq; int authenticated = 0; + int res; /* Make sure it's for us */ if (!(authtype = ap_auth_type (r)) || strcasecmp (SID_AUTHTYPE, authtype) != 0) @@ -979,6 +1019,7 @@ hook_authenticate (request_rec* r) req.result = OK; req.rec = r; req.sess = NULL; + req.output = NULL; /* Check if we've already authenticated this request */ sess = ap_get_module_config (mainreq->request_config, &auth_singleid_module); @@ -1011,6 +1052,15 @@ hook_authenticate (request_rec* r) session_send_info (ctx, r, sess); } + /* If any output, send it */ + if (req.output) { + r->status = req.result; + res = ap_pass_brigade (r->output_filters, req.output); + if (res != APR_SUCCESS) + return res; + req.result = DONE; + } + return req.result; } diff --git a/module/mod_auth_singleid.h b/module/mod_auth_singleid.h index 61e2c91..2619c3f 100644 --- a/module/mod_auth_singleid.h +++ b/module/mod_auth_singleid.h @@ -31,12 +31,20 @@ const char* sid_request_qs (sid_request_t *req); const char* sid_request_url (sid_request_t *req, int with_path); -void sid_request_respond (sid_request_t *req, +const char* sid_request_method (sid_request_t *req); + +void sid_request_respond_headers (sid_request_t *req, int code, const char *reason, const char *header, ...); +void sid_request_respond_html (sid_request_t *req, + int code, + const char *reason, + const char *data, + ...); + void sid_request_authenticated (sid_request_t *req, const char *identifier); |