summaryrefslogtreecommitdiffstats
path: root/auth_mellon_handler.c
diff options
context:
space:
mode:
authormanu@netbsd.org <manu@netbsd.org@a716ebb1-153a-0410-b759-cfb97c6a1b53>2009-11-09 13:46:28 +0000
committermanu@netbsd.org <manu@netbsd.org@a716ebb1-153a-0410-b759-cfb97c6a1b53>2009-11-09 13:46:28 +0000
commit24d4e2221912ea900648354ada2866802c219e3e (patch)
tree49931ccc90ca983705c483e89e6edcc9e434867f /auth_mellon_handler.c
parent727a60258202b95c3321507c76593cf81980e4e4 (diff)
downloadmod_auth_mellon-24d4e2221912ea900648354ada2866802c219e3e.tar.gz
mod_auth_mellon-24d4e2221912ea900648354ada2866802c219e3e.tar.xz
mod_auth_mellon-24d4e2221912ea900648354ada2866802c219e3e.zip
Replay POST requets after been sent to the IdP
git-svn-id: https://modmellon.googlecode.com/svn/trunk@67 a716ebb1-153a-0410-b759-cfb97c6a1b53
Diffstat (limited to 'auth_mellon_handler.c')
-rw-r--r--auth_mellon_handler.c235
1 files changed, 173 insertions, 62 deletions
diff --git a/auth_mellon_handler.c b/auth_mellon_handler.c
index b8bc25c..c9b4af4 100644
--- a/auth_mellon_handler.c
+++ b/auth_mellon_handler.c
@@ -30,43 +30,6 @@
#endif /* HAVE_lasso_server_new_from_buffers */
-/* This function produces the endpoint URL
- *
- * Parameters:
- * request_rec *r The request we received.
- *
- * Returns:
- * the endpoint URL
- */
-static char *am_get_endpoint_url(request_rec *r)
-{
- static APR_OPTIONAL_FN_TYPE(ssl_is_https) *am_is_https = NULL;
- am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
- apr_pool_t *p = r->pool;
- server_rec *s = r->server;
- apr_port_t default_port;
- char *port;
- char *scheme;
-
- am_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
-
- if (am_is_https && am_is_https(r->connection)) {
- scheme = "https://";
- default_port = DEFAULT_HTTPS_PORT;
- } else {
- scheme = "http://";
- default_port = DEFAULT_HTTP_PORT;
- }
-
- if (s->addrs->host_port != default_port)
- port = apr_psprintf(p, ":%d", s->addrs->host_port);
- else
- port = "";
-
- return apr_psprintf(p, "%s%s%s%s", scheme,
- s->server_hostname,
- port, cfg->endpoint_path);
-}
#ifdef HAVE_lasso_server_new_from_buffers
/* This function generates optional metadata for a given element
@@ -1730,6 +1693,129 @@ static int am_handle_artifact_reply(request_rec *r)
return am_handle_reply_common(r, login, relay_state, "");
}
+/* This function handles responses to repost request
+ *
+ * Parameters:
+ * request_rec *r The request we received.
+ *
+ * Returns:
+ * OK on success, or an error on failure.
+ */
+static int am_handle_repost(request_rec *r)
+{
+ am_mod_cfg_rec *mod_cfg;
+ const char *query;
+ char *cp;
+ char *psf_id;
+ char *psf_filename;
+ char *post_data;
+ char *post_form;
+ char *output;
+ char *last;
+ char *return_url;
+
+ mod_cfg = am_get_mod_cfg(r->server);
+ query = r->parsed_uri.query;
+
+ psf_id = am_extract_query_parameter(r->pool, query, "id");
+ if (psf_id == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Bad repost query: missing id");
+ return HTTP_BAD_REQUEST;
+ }
+
+ /* Check that Id is sane */
+ for (cp = psf_id; *cp; cp++) {
+ if (!apr_isalnum(*cp)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Bad repost query: invalid id \"%s\"", psf_id);
+ return HTTP_BAD_REQUEST;
+ }
+ }
+
+
+ return_url = am_extract_query_parameter(r->pool, query, "ReturnTo");
+ if (return_url == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Invalid or missing query ReturnTo parameter.");
+ return HTTP_BAD_REQUEST;
+ }
+
+ if (am_urldecode(return_url) != OK) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Bad repost query: return");
+ return HTTP_BAD_REQUEST;
+ }
+
+ psf_filename = apr_psprintf(r->pool, "%s/%s", mod_cfg->post_dir, psf_id);
+ if ((post_data = am_getfile(r->pool, r->server, psf_filename)) == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Bad repost query: cannot find \"%s\"", psf_filename);
+ return HTTP_BAD_REQUEST;
+ }
+
+ post_form = "";
+ for (cp = apr_strtok(post_data, "&", &last); cp;
+ cp = apr_strtok(NULL, "&", &last)) {
+ char *item;
+ char *last2;
+ char *name;
+ char *value;
+ char *input_item;
+
+ item = apr_pstrdup(r->pool, cp);
+
+ name = apr_strtok(item, "=", &last2);
+ value = apr_strtok(NULL, "=", &last2);
+
+ if (name == NULL)
+ continue;
+
+ if (value == NULL)
+ value = (char *)"";
+
+ if (am_urldecode(name) != OK) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "urldecode(\"%s\") failed", name);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ if (am_urldecode(value) != OK) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "urldecode(\"%s\") failed", value);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ input_item = apr_psprintf(r->pool,
+ " <input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
+ am_htmlencode(r, name), am_htmlencode(r, value));
+ post_form = apr_pstrcat(r->pool, post_form, input_item, NULL);
+ }
+
+ r->content_type = "text/html";
+ output = apr_psprintf(r->pool,
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
+ "<html>\n"
+ " <head>\n"
+ " <title>SAML rePOST request</title>\n"
+ " </head>\n"
+ " <body onload=\"document.getElementById('form').submit();\">\n"
+ " <noscript>\n"
+ " Your browser does not support Javascript, \n"
+ " you must click the button below to proceed.\n"
+ " </noscript>\n"
+ " <form id=\"form\" method=\"POST\" action=\"%s\">\n%s"
+ " <noscript>\n"
+ " <input type=\"submit\">\n"
+ " </noscript>\n"
+ " </form>\n"
+ " </body>\n"
+ "</html>\n",
+ return_url, post_form);
+
+ ap_rputs(output, r);
+ return OK;
+}
+
/* This function handles responses to metadata request
*
@@ -1739,14 +1825,46 @@ static int am_handle_artifact_reply(request_rec *r)
* Returns:
* OK on success, or an error on failure.
*/
-int am_handle_metadata(request_rec *r)
+static int am_handle_metadata(request_rec *r)
{
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
- const char *endpoint;
#ifdef HAVE_lasso_server_new_from_buffers
LassoServer *server;
const char *data;
+
+ server = am_get_lasso_server(r);
+ if(server == NULL)
+ return HTTP_INTERNAL_SERVER_ERROR;
+
+ data = cfg->sp_metadata_file;
+ if (data == NULL)
+ return HTTP_INTERNAL_SERVER_ERROR;
+
+ r->content_type = "application/samlmetadata+xml";
+
+ ap_rputs(data, r);
+
+ return OK;
+#else /* ! HAVE_lasso_server_new_from_buffers */
+
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "metadata publishing require lasso 2.2.2 or higher");
+ return HTTP_NOT_FOUND;
#endif
+}
+
+/* This function handles responses to request on our endpoint
+ *
+ * Parameters:
+ * request_rec *r The request we received.
+ *
+ * Returns:
+ * OK on success, or an error on failure.
+ */
+int am_handler(request_rec *r)
+{
+ am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
+ const char *endpoint;
/* Check if this is a request for one of our endpoints. We check if
* the uri starts with the path set with the MellonEndpointPath
@@ -1755,11 +1873,6 @@ int am_handle_metadata(request_rec *r)
if(strstr(r->uri, cfg->endpoint_path) != r->uri)
return DECLINED;
- endpoint = &r->uri[strlen(cfg->endpoint_path)];
- if (strcmp(endpoint, "metadata") != 0)
- return DECLINED;
-
-#ifdef HAVE_lasso_server_new_from_buffers
/* Make sure that this is a GET request. */
if(r->method_number != M_GET) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
@@ -1779,27 +1892,17 @@ int am_handle_metadata(request_rec *r)
return DECLINED;
}
- server = am_get_lasso_server(r);
- if(server == NULL)
- return HTTP_INTERNAL_SERVER_ERROR;
-
- data = cfg->sp_metadata_file;
- if (data == NULL)
- return HTTP_INTERNAL_SERVER_ERROR;
-
- r->content_type = "application/samlmetadata+xml";
-
- ap_rputs(data, r);
-
- return OK;
-#else /* ! HAVE_lasso_server_new_from_buffers */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "metadata publishing require lasso 2.2.2 or higher");
- return HTTP_NOT_FOUND;
-#endif
+ endpoint = &r->uri[strlen(cfg->endpoint_path)];
+ if (strcmp(endpoint, "metadata") == 0)
+ return am_handle_metadata(r);
+ else if (strcmp(endpoint, "repost") == 0)
+ return am_handle_repost(r);
+ else
+ return DECLINED;
}
+
static int am_auth_new_ticket(request_rec *r)
{
am_dir_cfg_rec *cfg = am_get_dir_cfg(r);
@@ -1812,6 +1915,12 @@ static int am_auth_new_ticket(request_rec *r)
relay_state = am_reconstruct_url(r);
+ /* If this is a POST request, attempt to save it */
+ if (r->method_number == M_POST) {
+ if (am_save_post(r, &relay_state) != OK)
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
/* Check if IdP discovery is in use and no IdP was selected yet */
if ((cfg->discovery_url != NULL) &&
(am_builtin_discovery_timeout(r) == -1) && /* no built-in discovery */
@@ -1965,6 +2074,8 @@ static int am_endpoint_handler(request_rec *r)
return am_auth_new_ticket(r);
} else if(!strcmp(endpoint, "metadata")) {
return OK;
+ } else if(!strcmp(endpoint, "repost")) {
+ return OK;
} else if(!strcmp(endpoint, "logout")
|| !strcmp(endpoint, "logoutRequest")) {
/* logoutRequest is included for backwards-compatibility