summaryrefslogtreecommitdiff
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rw-r--r--module/consumer.cc70
-rw-r--r--module/mod_auth_singleid.c54
-rw-r--r--module/mod_auth_singleid.h10
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 &params,
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 &params,
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 &params)
+cancelled_auth (sid_request_t *req, Consumer &consumer, params_t &params, 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);