From 12b11896a7de7298a90ec1d08ea80a59099a3ac4 Mon Sep 17 00:00:00 2001 From: Ken Coar Date: Thu, 23 Jan 2003 21:34:13 +0000 Subject: [PATCH] here we go. add a directive that will keep %2f from being decoded into '/', allowing the *_walk to do their magic and return 404 if it's in the path, and allowing it in the path-info. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@98479 13f79535-47bb-0310-9956-ffa450edef68 --- include/ap_mmn.h | 3 ++- include/http_core.h | 3 ++- include/httpd.h | 8 ++++++- server/core.c | 18 ++++++++++++++++ server/request.c | 19 ++++++++++++----- server/util.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 94 insertions(+), 8 deletions(-) diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 54ec08eed2..24ba923c26 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -111,6 +111,7 @@ * 20020625 (2.0.40-dev) Changed conn_rec->keepalive to an enumeration * 20020628 (2.0.40-dev) Added filter_init to filter registration functions * 20020903 (2.0.41-dev) APR's error constants changed + * 20020903.1 (2.0.44-dev) allow_encoded_slashes added to core_dir_config */ #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */ @@ -118,7 +119,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20020903 #endif -#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 1 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_core.h b/include/http_core.h index 86a8dd380a..44027cee23 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -537,7 +537,8 @@ typedef struct { #define ENABLE_SENDFILE_ON (1) #define ENABLE_SENDFILE_UNSET (2) unsigned int enable_sendfile : 2; /* files in this dir can be mmap'ed */ - + unsigned int allow_encoded_slashes : 1; /* URLs may contain %2f w/o being + * pitched indiscriminately */ } core_dir_config; /* Per-server core configuration */ diff --git a/include/httpd.h b/include/httpd.h index 3fae59e73f..b1f7423ac9 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1309,10 +1309,16 @@ AP_DECLARE(int) ap_is_url(const char *u); /** * Unescape a URL - * @param url The url to unescapte + * @param url The url to unescape * @return 0 on success, non-zero otherwise */ AP_DECLARE(int) ap_unescape_url(char *url); +/** + * Unescape a URL, but leaving %2f (slashes) escaped + * @param url The url to unescape + * @return 0 on success, non-zero otherwise + */ +AP_DECLARE(int) ap_unescape_url_keep2f(char *url); /** * Convert all double slashes to single slashes * @param name The string to convert diff --git a/server/core.c b/server/core.c index 62b2fa509a..b919c3229f 100644 --- a/server/core.c +++ b/server/core.c @@ -180,6 +180,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir) conf->enable_mmap = ENABLE_MMAP_UNSET; conf->enable_sendfile = ENABLE_SENDFILE_UNSET; + conf->allow_encoded_slashes = 0; return (void *)conf; } @@ -446,6 +447,8 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv) conf->enable_sendfile = new->enable_sendfile; } + conf->allow_encoded_slashes = new->allow_encoded_slashes; + return (void*)conf; } @@ -2066,6 +2069,19 @@ static const char *set_timeout(cmd_parms *cmd, void *dummy, const char *arg) return NULL; } +static const char *set_allow2f(cmd_parms *cmd, void *d_, int arg) +{ + core_dir_config *d = d_; + const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT); + + if (err != NULL) { + return err; + } + + d->allow_encoded_slashes = arg != 0; + return NULL; +} + static const char *set_hostname_lookups(cmd_parms *cmd, void *d_, const char *arg) { @@ -3054,6 +3070,8 @@ AP_INIT_TAKE1("SetInputFilter", ap_set_string_slot, AP_INIT_ITERATE2("AddOutputFilterByType", add_ct_output_filters, (void *)APR_OFFSETOF(core_dir_config, ct_output_filters), OR_FILEINFO, "output filter name followed by one or more content-types"), +AP_INIT_FLAG("AllowEncodedSlashes", set_allow2f, NULL, RSRC_CONF, + "Allow URLs containing '/' encoded as '%2F'"), /* * These are default configuration directives that mpms can/should diff --git a/server/request.c b/server/request.c index 051c224f26..b255e8b828 100644 --- a/server/request.c +++ b/server/request.c @@ -147,13 +147,22 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) /* Ignore embedded %2F's in path for proxy requests */ if (!r->proxyreq && r->parsed_uri.path) { - access_status = ap_unescape_url(r->parsed_uri.path); + core_dir_config *d; + d = ap_get_module_config(r->per_dir_config, &core_module); + if (d->allow_encoded_slashes) { + access_status = ap_unescape_url_keep2f(r->parsed_uri.path); + } + else { + access_status = ap_unescape_url(r->parsed_uri.path); + } if (access_status) { if (access_status == HTTP_NOT_FOUND) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "found %%2f (encoded '/') in URI " - "(decoded='%s'), returning 404", - r->parsed_uri.path); + if (! d->allow_encoded_slashes) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "found %%2f (encoded '/') in URI " + "(decoded='%s'), returning 404", + r->parsed_uri.path); + } } return access_status; } diff --git a/server/util.c b/server/util.c index c028bf51c6..65da169f31 100644 --- a/server/util.c +++ b/server/util.c @@ -1595,6 +1595,57 @@ AP_DECLARE(int) ap_unescape_url(char *url) return OK; } +AP_DECLARE(int) ap_unescape_url_keep2f(char *url) +{ + register int badesc, badpath; + char *x, *y; + + badesc = 0; + badpath = 0; + /* Initial scan for first '%'. Don't bother writing values before + * seeing a '%' */ + y = strchr(url, '%'); + if (y == NULL) { + return OK; + } + for (x = y; *y; ++x, ++y) { + if (*y != '%') { + *x = *y; + } + else { + if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) { + badesc = 1; + *x = '%'; + } + else { + char decoded; + decoded = x2c(y + 1); + if (IS_SLASH(decoded)) { + *x++ = *y++; + *x = *y; + } + else { + *x = decoded; + y += 2; + if (decoded == '\0') { + badpath = 1; + } + } + } + } + } + *x = '\0'; + if (badesc) { + return HTTP_BAD_REQUEST; + } + else if (badpath) { + return HTTP_NOT_FOUND; + } + else { + return OK; + } +} + AP_DECLARE(char *) ap_construct_server(apr_pool_t *p, const char *hostname, apr_port_t port, const request_rec *r) { -- 2.50.1