From 0aa07647feea216dfe7a0b58eb93af69e5f4d41b Mon Sep 17 00:00:00 2001 From: Ken Coar Date: Thu, 8 May 2003 20:49:33 +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. backported from 2.1 dev. PR: 14639 (et alia) Reviewed by: nd, stoddard git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@99741 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 6 ++++++ STATUS | 25 +--------------------- 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 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 101 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index fb3f0a945de..7ab401cba56 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,11 @@ Changes with Apache 2.0.46 + *) Added AllowEncodedSlashes directive to permit control of whether + the server will accept encoded slashes ('%2f') in the URI path. + Default condition is off (the historical behaviour). This permits + environments in which the path-info needs to contain encoded + slashes. [Ken Coar] + *) When using Redirect in directory context, append requested query string if there's no one supplied by configuration. PR 10961. [André Malo] diff --git a/STATUS b/STATUS index ba8c7b38b91..edc37aed235 100644 --- a/STATUS +++ b/STATUS @@ -1,5 +1,5 @@ APACHE 2.0 STATUS: -*-text-*- -Last modified at [$Date: 2003/05/08 14:21:11 $] +Last modified at [$Date: 2003/05/08 20:49:31 $] Release: @@ -63,29 +63,6 @@ PATCHES TO PORT FROM 2.1 [ please place file names and revisions from HEAD here, so it is easy to identify exactly what the proposed changes are! ] - * AllowEncodedSlashes patch to permit %2f in path-info. - CHANGES r1.1038 - include/ap_mmn.h r1.54 (based on r1.53) - include/http_core.h r1.73 - include/httpd.h r1.193 - server/core.c r1.230 - server/request.c r1.123 - server/util.c r1.135 - +1: coar, nd, stoddard - -0: wrowe - nd: since it's inherited carefully (namely: not) and has to - be explicitely turned on, I see no harm with that patch. - (needs docs anyway!) - wrowe: no veto here. But I am now 100% convinced that it - is altogether wrong to be rejecting any codes within - the supposedly 'generic' ap_unparse_uri - and that the - rejection of %2f should occur elsewhere. - So in spirit I accept a more extreme version of coar's - patch, where a 'pure' _unparse_uri becomes the default. - But protection must be placed in dir_walk and some - consideration given to how this changes - block evaluation. - * Rewrite how proxy sends its request to allow input bodies to morph the request bodies. Previously, if an input filter changed the request body, the original C-L would be sent which diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 3a5f8e556a1..e3c79c1e8a3 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -112,6 +112,7 @@ * 20020628 (2.0.40-dev) Added filter_init to filter registration functions * 20020903 (2.0.41-dev) APR's error constants changed * 20020903.2 (2.0.46-dev) add ap_escape_logitem (.1 is waiting for backport) + * 20020903.3 (2.0.46-dev) allow_encoded_slashes added to core_dir_config */ #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */ @@ -119,7 +120,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20020903 #endif -#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 3 /* 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 136e5f0b668..e94647f8e01 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -539,7 +539,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 7f7df1e6f3e..733355c8f06 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1314,10 +1314,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 d6275dc045a..baee8f8325c 100644 --- a/server/core.c +++ b/server/core.c @@ -182,6 +182,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; } @@ -452,6 +453,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; } @@ -2087,6 +2090,19 @@ static const char *set_idcheck(cmd_parms *cmd, void *d_, int 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) { @@ -3077,6 +3093,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 388c9a4b586..8f7e6fe7cb8 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 e5fb193131e..eaac9b80dd4 100644 --- a/server/util.c +++ b/server/util.c @@ -1598,6 +1598,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.47.3