diff options
author | manu@netbsd.org <manu@netbsd.org@a716ebb1-153a-0410-b759-cfb97c6a1b53> | 2009-11-09 13:46:28 +0000 |
---|---|---|
committer | manu@netbsd.org <manu@netbsd.org@a716ebb1-153a-0410-b759-cfb97c6a1b53> | 2009-11-09 13:46:28 +0000 |
commit | 24d4e2221912ea900648354ada2866802c219e3e (patch) | |
tree | 49931ccc90ca983705c483e89e6edcc9e434867f | |
parent | 727a60258202b95c3321507c76593cf81980e4e4 (diff) | |
download | mod_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
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | README | 19 | ||||
-rw-r--r-- | auth_mellon.h | 10 | ||||
-rw-r--r-- | auth_mellon_config.c | 55 | ||||
-rw-r--r-- | auth_mellon_handler.c | 235 | ||||
-rw-r--r-- | auth_mellon_util.c | 352 | ||||
-rw-r--r-- | mod_auth_mellon.c | 3 |
7 files changed, 614 insertions, 65 deletions
@@ -1,3 +1,8 @@ +Version 0.2.5 +--------------------------------------------------------------------------- + +* Replay POST requests after been sent to the IdP + Version 0.2.4 --------------------------------------------------------------------------- @@ -104,6 +104,25 @@ MellonCacheSize 100 # Default: MellonLockFile "/tmp/mellonLock" MellonLockFile "/tmp/mellonLock" +# MellonPostDir is the full path of a directory where POST requests are +# saved during authentication. This directory must be owned by the Apache +# user and be mode 700. We will attempt to create it if it does not exist. +# Default: MellonPostDir "/var/tmp/mellonpost" +MellonPostDir "/var/tmp/mellonpost" + +# MellonPostTTL is the delay in seconds before a saved POST request can +# be flushed. +# Default: MellonPostTTL 900 (15 mn) +MellonPostTTL 900 + +# MellonPostSize is the maximum size for saved POST requests +# Default: MellonPostSize 1073741824 (1 MB) +MellonPostSize 1073741824 + +# MellonPostCount is the maxmimum amount of saved POST requests +# Default: MellonPostCount 100 +MellonPostCount 100 + ########################################################################### # End of global configuration for mod_auth_mellon. ########################################################################### diff --git a/auth_mellon.h b/auth_mellon.h index be56b6d..807668a 100644 --- a/auth_mellon.h +++ b/auth_mellon.h @@ -89,6 +89,10 @@ typedef struct am_mod_cfg_rec { int cache_size; const char *lock_file; + const char *post_dir; + apr_time_t post_ttl; + int post_count; + apr_size_t post_size; /* These variables can't be allowed to change after the session store * has been initialized. Therefore we copy them before initializing @@ -257,11 +261,15 @@ char *am_urlencode(apr_pool_t *pool, const char *str); int am_urldecode(char *data); char *am_generate_session_id(request_rec *r); char *am_getfile(apr_pool_t *conf, server_rec *s, const char *file); +char *am_get_endpoint_url(request_rec *r); +int am_postdir_cleanup(request_rec *s); +char *am_htmlencode(request_rec *r, const char *str); +int am_save_post(request_rec *r, const char **relay_state); int am_auth_mellon_user(request_rec *r); int am_check_uid(request_rec *r); -int am_handle_metadata(request_rec *r); +int am_handler(request_rec *r); int am_httpclient_get(request_rec *r, const char *uri, diff --git a/auth_mellon_config.c b/auth_mellon_config.c index e99062d..ada0ee6 100644 --- a/auth_mellon_config.c +++ b/auth_mellon_config.c @@ -56,6 +56,25 @@ static const int default_dump_saml_response = 0; */ static const char *default_login_path = "/"; +/* This is the directory for storing saved POST sessions + * the MellonPostDirectory configuration directive if you change this. + */ +static const char *post_dir = "/var/tmp/mellonpost"; + +/* saved POST session time to live + * the MellonPostTTL configuration directive if you change this. + */ +static const apr_time_t post_ttl = 15 * 60; + +/* saved POST session maximum size + * the MellonPostSize configuration directive if you change this. + */ +static const apr_size_t post_size = 1024 * 1024 * 1024; + +/* maximum saved POST sessions + * the MellonPostCount configuration directive if you change this. + */ +static const int post_count = 100; /* This function handles configuration directives which set a file * slot in the module configuration. If lasso is recent enough, it @@ -454,6 +473,38 @@ const command_rec auth_mellon_commands[] = { "The lock file for session synchronization." " Default value is \"/tmp/mellonLock\"." ), + AP_INIT_TAKE1( + "MellonPostDirectory", + am_set_module_config_string_slot, + (void *)APR_OFFSETOF(am_mod_cfg_rec, post_dir), + RSRC_CONF, + "The directory for saving POST requests." + " Default value is \"/var/tmp/mellonpost\"." + ), + AP_INIT_TAKE1( + "MellonPostTTL", + am_set_module_config_int_slot, + (void *)APR_OFFSETOF(am_mod_cfg_rec, post_ttl), + RSRC_CONF, + "The time to live for saved POST requests in seconds." + " Default value is 15 mn." + ), + AP_INIT_TAKE1( + "MellonPostCount", + am_set_module_config_int_slot, + (void *)APR_OFFSETOF(am_mod_cfg_rec, post_count), + RSRC_CONF, + "The maximum saved POST sessions at once." + " Default value is 100." + ), + AP_INIT_TAKE1( + "MellonPostSize", + am_set_module_config_int_slot, + (void *)APR_OFFSETOF(am_mod_cfg_rec, post_size), + RSRC_CONF, + "The maximum size of a saved POST, in bytes." + " Default value is 1 MB." + ), /* Per-location configuration directives. */ @@ -870,6 +921,10 @@ void *auth_mellon_server_config(apr_pool_t *p, server_rec *s) mod->cache_size = 100; /* ought to be enough for everybody */ mod->lock_file = "/tmp/mellonLock"; + mod->post_dir = post_dir; + mod->post_ttl = post_ttl; + mod->post_count = post_count; + mod->post_size = post_size; mod->init_cache_size = 0; mod->init_lock_file = NULL; 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 diff --git a/auth_mellon_util.c b/auth_mellon_util.c index 8f4e3bb..57dc653 100644 --- a/auth_mellon_util.c +++ b/auth_mellon_util.c @@ -587,3 +587,355 @@ char *am_getfile(apr_pool_t *conf, server_rec *s, const char *file) return data; } + +/* + * Create a directory for saved POST sessions, check for proper permissions + * + * Parameters: + * request_rec *r The current request + * + * Returns: + * OK on success, or HTTP_INTERNAL_SERVER on failure. + */ +static int am_postdir_mkdir(request_rec *r) +{ + apr_int32_t wanted; + apr_finfo_t afi; + apr_status_t rv; + char buffer[512]; + am_mod_cfg_rec *mod_cfg; + apr_fileperms_t mode; + apr_uid_t user; + apr_uid_t group; + apr_fileperms_t prot; + + mod_cfg = am_get_mod_cfg(r->server); + + mode = APR_FPROT_UREAD|APR_FPROT_UWRITE|APR_FPROT_UEXECUTE; + if ((rv = apr_dir_make_recursive(mod_cfg->post_dir, mode, r->pool)) != OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "cannot create POST directory \"%s\": %s", + mod_cfg->post_dir, + apr_strerror(rv, buffer, sizeof(buffer))); + return HTTP_INTERNAL_SERVER_ERROR; + } + + /* + * The directory may have already existed. Check we really own it + */ + wanted = APR_FINFO_USER|APR_FINFO_UPROT|APR_FINFO_GPROT|APR_FINFO_WPROT; + if (apr_stat(&afi, mod_cfg->post_dir, wanted, r->pool) == OK) { + if (apr_uid_current(&user, &group, r->pool) != OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "apr_uid_current failed"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (afi.user != user) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "POST directory \"%s\" must be owned by the same " + "user as the web server is running as.", + mod_cfg->post_dir); + return HTTP_INTERNAL_SERVER_ERROR; + } + + prot = APR_FPROT_UREAD|APR_FPROT_UWRITE|APR_FPROT_UEXECUTE; + if (afi.protection != prot) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Premissions on POST directory \"%s\" must be 0700.", + mod_cfg->post_dir); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + + return OK; +} + +/* + * Purge outdated saved POST requests. If the MellonPostDir directory + * does not exist, create it first. + * + * Parameters: + * request_rec *r The current request + * + * Returns: + * OK on success, or HTTP_INTERNAL_SERVER on failure. + */ +int am_postdir_cleanup(request_rec *r) +{ + am_mod_cfg_rec *mod_cfg; + apr_dir_t *postdir; + apr_status_t rv; + apr_finfo_t afi; + char *fname; + int count; + + mod_cfg = am_get_mod_cfg(r->server); + + /* + * Open our POST directory or create it. + */ + if (apr_dir_open(&postdir, mod_cfg->post_dir, r->pool) != OK) + return am_postdir_mkdir(r); + + /* + * Purge outdated items + */ + count = 0; + do { + rv = apr_dir_read(&afi, APR_FINFO_NAME|APR_FINFO_CTIME, postdir); + if (rv != OK) + break; + + /* Skip dot_files */ + if (afi.name[0] == '.') + continue; + + if (afi.ctime + mod_cfg->post_ttl > apr_time_sec(apr_time_now())) { + fname = apr_psprintf(r->pool, "%s/%s", mod_cfg->post_dir, afi.name); + (void)apr_file_remove(fname , r->pool); + } else { + count++; + } + } while (1 /* CONSTCOND */); + + (void)apr_dir_close(postdir); + + if (count >= mod_cfg->post_count) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Too many saved POST sessions. " + "Increase MellonPostCount directive."); + return HTTP_INTERNAL_SERVER_ERROR; + } + + return OK; +} + +/* + * HTML-encode a string + * + * Parameters: + * request_rec *r The current request + * const char *str The string to encode + * + * Returns: + * The encoded string + */ +char *am_htmlencode(request_rec *r, const char *str) +{ + const char *cp; + char *output; + apr_size_t outputlen; + int i; + + outputlen = 0; + for (cp = str; *cp; cp++) { + switch (*cp) { + case '&': + outputlen += 5; + break; + case '"': + outputlen += 6; + break; + default: + outputlen += 1; + break; + } + } + + i = 0; + output = apr_palloc(r->pool, outputlen + 1); + for (cp = str; *cp; cp++) { + switch (*cp) { + case '&': + (void)strcpy(&output[i], "&"); + i += 5; + break; + case '"': + (void)strcpy(&output[i], """); + i += 6; + break; + default: + output[i] = *cp; + i += 1; + break; + } + } + output[i] = '\0'; + + return output; +} + +/* This function produces the endpoint URL + * + * Parameters: + * request_rec *r The request we received. + * + * Returns: + * the endpoint URL + */ +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); +} + +/* + * The two functions below extract an HTTP header from the request. + * + * Parameters: + * request_rec *r The current request. + * + * Returns: + * 1 if multipart/form-data, 0 otherwise. + */ +struct am_get_header_state { + request_rec *req; + const char *header; + const char *value; +}; + +static int am_get_header_callback(void *s, const char *key, const char *val) +{ + struct am_get_header_state *state; + + state = (struct am_get_header_state *)s; + + if (strcmp(key, state->header) != 0) + return 1; + + state->value = val; + return 0; +} + +static const char *am_get_header(request_rec *r, const char *header) +{ + struct am_get_header_state state; + + state.req = r; + state.header = header; + state.value = NULL; + + (void)apr_table_do(am_get_header_callback, &state, r->headers_in, NULL); + + return state.value; +} + +/* + * This function saves a POST request for later replay and updates + * the return URL. + * + * Parameters: + * request_rec *r The current request. + * const char **relay_state The returl URL + * + * Returns: + * OK on success, HTTP_INTERNAL_SERVER_ERROR otherwise + */ +int am_save_post(request_rec *r, const char **relay_state) +{ + am_mod_cfg_rec *mod_cfg; + const char *content_type; + const char *psf_id; + char *psf_name; + char *post_data; + apr_size_t post_data_len; + apr_size_t written; + apr_file_t *psf; + + if (am_postdir_cleanup(r) != OK) + return HTTP_INTERNAL_SERVER_ERROR; + + /* Check Content-Type */ + content_type = am_get_header(r, "Content-Type"); + if ((content_type != NULL) && + (strcmp(content_type, "application/x-www-form-urlencoded") != 0)) { + /* + * This is probably "multipart/form-data; boundary=XXXXXXXXXX" + * The POST request then contains MIME data. We are not yet + * able to manage that, so issue an error 500. + */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Unsupported POST Content-Type \"%s\"", content_type); + return HTTP_INTERNAL_SERVER_ERROR; + } + + mod_cfg = am_get_mod_cfg(r->server); + + if ((psf_id = am_generate_session_id(r)) == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "cannot generate id"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + psf_name = apr_psprintf(r->pool, "%s/%s", mod_cfg->post_dir, psf_id); + + if (apr_file_open(&psf, psf_name, + APR_WRITE|APR_CREATE|APR_BINARY, + APR_FPROT_UREAD|APR_FPROT_UWRITE, + r->pool) != OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "cannot create POST session file"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (am_read_post_data(r, &post_data, &post_data_len) != OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "cannot read POST data"); + (void)apr_file_close(psf); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (post_data_len > mod_cfg->post_size) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "POST data size %" APR_SIZE_T_FMT + " exceeds maximum %" APR_SIZE_T_FMT ". " + "Increase MellonPostSize directive.", + post_data_len, mod_cfg->post_size); + (void)apr_file_close(psf); + return HTTP_INTERNAL_SERVER_ERROR; + } + + written = post_data_len; + if ((apr_file_write(psf, post_data, &written) != OK) || + (written != post_data_len)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "cannot write to POST session file"); + (void)apr_file_close(psf); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (apr_file_close(psf) != OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "cannot close POST session file"); + return HTTP_INTERNAL_SERVER_ERROR; + } + + *relay_state = apr_psprintf(r->pool, "%srepost?id=%s&ReturnTo=%s", + am_get_endpoint_url(r), psf_id, + am_urlencode(r->pool, *relay_state)); + + return OK; +} diff --git a/mod_auth_mellon.c b/mod_auth_mellon.c index 809ce5d..b7d8349 100644 --- a/mod_auth_mellon.c +++ b/mod_auth_mellon.c @@ -94,7 +94,6 @@ static int am_global_init(apr_pool_t *conf, apr_pool_t *log, mod->init_cache_size = mod->cache_size; mod->init_lock_file = apr_pstrdup(conf, mod->lock_file); - /* find out the memory size of the cache */ mem_size = sizeof(am_cache_entry_t) * mod->init_cache_size; @@ -195,7 +194,7 @@ static void register_hooks(apr_pool_t *p) ap_hook_check_user_id(am_check_uid, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_post_config(am_global_init, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_child_init(am_child_init, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_handler(am_handle_metadata, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_handler(am_handler, NULL, NULL, APR_HOOK_MIDDLE); return; } |