From: Jeff Trawick Date: Mon, 20 Aug 2012 17:22:53 +0000 (+0000) Subject: Merge r1356115, r1356813, r1086662 (tiny subset), and r1032431 from trunk: X-Git-Tag: 2.2.23~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9fd5359994a2c42dac24e5c22fd67a6e0403bb5e;p=thirdparty%2Fapache%2Fhttpd.git Merge r1356115, r1356813, r1086662 (tiny subset), and r1032431 from trunk: mod_rewrite: Add "AllowAnyURI" option. PR 52774. [Joe Orton] mod_rewrite: Fix the RewriteEngine directive to work within a location. Previously, once RewriteEngine was switched on globally, it was impossible to switch off. [Graham Leggett] Reviewed by: rjung, wrowe, trawick git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1375113 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 853be7125d7..c9d213cfaa4 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,12 @@ Changes with Apache 2.2.23 *) mpm_event, mpm_worker: Remain active amidst prevalent child process resource shortages. [Jeff Trawick] + *) mod_rewrite: Add "AllowAnyURI" option. PR 52774. [Joe Orton] + + *) mod_rewrite: Fix the RewriteEngine directive to work within a + location. Previously, once RewriteEngine was switched on globally, + it was impossible to switch off. [Graham Leggett] + *) mod_proxy_balancer: Restore balancing after a failed worker has recovered when using lbmethod_bybusyness. PR 48735. [Jeff Trawick] diff --git a/STATUS b/STATUS index 6f188deff2e..553f663632b 100644 --- a/STATUS +++ b/STATUS @@ -93,21 +93,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mod_rewrite: add "AllowAnyURI" option. - Prerequisites: - - allow the user to configure which rules come first when RewriteRules - are merged with RewriteOptions Inherit. PR 39313 - - change signed single-bit fields to unsigned - trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1356115 and - http://svn.apache.org/viewvc?view=revision&revision=1356813 and - http://svn.apache.org/viewvc?view=revision&revision=1086662 and - http://svn.apache.org/viewvc?view=revision&revision=1032431 - 2.4.x patch: http://svn.apache.org/viewvc?view=revision&revision=1359687 and - http://svn.apache.org/viewvc?view=revision&revision=1086662 and - http://svn.apache.org/viewvc?view=revision&revision=1032431 - 2.2.x patch: http://people.apache.org/~rjung/patches/mod_rewrite-directory_conf-allowanyuri-2_2.patch - +1: rjung, wrowe, trawick - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/docs/manual/mod/mod_rewrite.xml b/docs/manual/mod/mod_rewrite.xml index 21864511da1..53003793864 100644 --- a/docs/manual/mod/mod_rewrite.xml +++ b/docs/manual/mod/mod_rewrite.xml @@ -187,6 +187,41 @@ later + +
AllowAnyURI
+
+ +

When RewriteRule + is used in VirtualHost or server context with + version 2.2.22 or later of httpd, mod_rewrite + will only process the rewrite rules if the request URI is a URL-path. This avoids + some security issues where particular rules could allow + "surprising" pattern expansions (see CVE-2011-3368 + and CVE-2011-4317). + To lift the restriction on matching a URL-path, the + AllowAnyURI option can be enabled, and + mod_rewrite will apply the rule set to any + request URI string, regardless of whether that string matches + the URL-path grammar required by the HTTP specification.

+ + + Security Warning + +

Enabling this option will make the server vulnerable to + security issues if used with rewrite rules which are not + carefully authored. It is strongly recommended + that this option is not used. In particular, beware of input + strings containing the '@' character which could + change the interpretation of the transformed URI, as per the + above CVE names.

+
+
+ + + diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 89b5af55bf3..c334e712e10 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -168,6 +168,7 @@ #define OPTION_NONE 1<<0 #define OPTION_INHERIT 1<<1 +#define OPTION_ANYURI 1<<4 #ifndef RAND_MAX #define RAND_MAX 32767 @@ -287,6 +288,8 @@ typedef struct { apr_array_header_t *rewriteconds; /* the RewriteCond entries (temp.) */ apr_array_header_t *rewriterules; /* the RewriteRule entries */ server_rec *server; /* the corresponding server indicator */ + unsigned int state_set:1; + unsigned int options_set:1; } rewrite_server_conf; typedef struct { @@ -296,6 +299,9 @@ typedef struct { apr_array_header_t *rewriterules; /* the RewriteRule entries */ char *directory; /* the directory where it applies */ const char *baseurl; /* the base-URL where it applies */ + unsigned int state_set:1; + unsigned int options_set:1; + unsigned int baseurl_set:1; } rewrite_perdir_conf; /* the (per-child) cache structures. @@ -2690,8 +2696,11 @@ static void *config_server_merge(apr_pool_t *p, void *basev, void *overridesv) base = (rewrite_server_conf *)basev; overrides = (rewrite_server_conf *)overridesv; - a->state = overrides->state; - a->options = overrides->options; + a->state = (overrides->state_set == 0) ? base->state : overrides->state; + a->state_set = overrides->state_set || base->state_set; + a->options = (overrides->options_set == 0) ? base->options : overrides->options; + a->options_set = overrides->options_set || base->options_set; + a->server = overrides->server; if (a->options & OPTION_INHERIT) { @@ -2772,10 +2781,14 @@ static void *config_perdir_merge(apr_pool_t *p, void *basev, void *overridesv) base = (rewrite_perdir_conf *)basev; overrides = (rewrite_perdir_conf *)overridesv; - a->state = overrides->state; - a->options = overrides->options; - a->directory = overrides->directory; - a->baseurl = overrides->baseurl; + a->state = (overrides->state_set == 0) ? base->state : overrides->state; + a->state_set = overrides->state_set || base->state_set; + a->options = (overrides->options_set == 0) ? base->options : overrides->options; + a->options_set = overrides->options_set || base->options_set; + a->baseurl = (overrides->baseurl_set == 0) ? base->baseurl : overrides->baseurl; + a->baseurl_set = overrides->baseurl_set || base->baseurl_set; + + a->directory = overrides->directory; if (a->options & OPTION_INHERIT) { a->rewriteconds = apr_array_append(p, overrides->rewriteconds, @@ -2799,11 +2812,17 @@ static const char *cmd_rewriteengine(cmd_parms *cmd, sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module); - if (cmd->path == NULL) { /* is server command */ + /* server command? set both global scope and base directory scope */ + if (cmd->path == NULL) { sconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED); + sconf->state_set = 1; + dconf->state = sconf->state; + dconf->state_set = 1; } - else /* is per-directory command */ { + /* directory command? set directory scope only */ + else { dconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED); + dconf->state_set = 1; } return NULL; @@ -2828,24 +2847,33 @@ static const char *cmd_rewriteoptions(cmd_parms *cmd, "LimitInternalRecursion directive and will be " "ignored."); } + else if (!strcasecmp(w, "allowanyuri")) { + options |= OPTION_ANYURI; + } else { return apr_pstrcat(cmd->pool, "RewriteOptions: unknown option '", w, "'", NULL); } } - /* put it into the appropriate config */ + /* server command? set both global scope and base directory scope */ if (cmd->path == NULL) { /* is server command */ - rewrite_server_conf *conf = + rewrite_perdir_conf *dconf = in_dconf; + rewrite_server_conf *sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module); - conf->options |= options; + sconf->options |= options; + sconf->options_set = 1; + dconf->options |= options; + dconf->options_set = 1; } + /* directory command? set directory scope only */ else { /* is per-directory command */ - rewrite_perdir_conf *conf = in_dconf; + rewrite_perdir_conf *dconf = in_dconf; - conf->options |= options; + dconf->options |= options; + dconf->options_set = 1; } return NULL; @@ -3045,6 +3073,7 @@ static const char *cmd_rewritebase(cmd_parms *cmd, void *in_dconf, } dconf->baseurl = a1; + dconf->baseurl_set = 1; return NULL; } @@ -4232,6 +4261,7 @@ static void init_child(apr_pool_t *p, server_rec *s) */ static int hook_uri2file(request_rec *r) { + rewrite_perdir_conf *dconf; rewrite_server_conf *conf; const char *saved_rulestatus; const char *var; @@ -4246,11 +4276,14 @@ static int hook_uri2file(request_rec *r) */ conf = ap_get_module_config(r->server->module_config, &rewrite_module); + dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config, + &rewrite_module); + /* * only do something under runtime if the engine is really enabled, * else return immediately! */ - if (conf->state == ENGINE_DISABLED) { + if (!dconf || dconf->state == ENGINE_DISABLED) { return DECLINED; } @@ -4266,8 +4299,16 @@ static int hook_uri2file(request_rec *r) return DECLINED; } - if ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0') - || !r->uri || r->uri[0] != '/') { + /* Unless the anyuri option is set, ensure that the input to the + * first rule really is a URL-path, avoiding security issues with + * poorly configured rules. See CVE-2011-3368, CVE-2011-4317. */ + if ((dconf->options & OPTION_ANYURI) == 0 + && ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0') + || !r->uri || r->uri[0] != '/')) { + rewritelog((r, 8, NULL, "Declining, request-URI '%s' is not a URL-path. " + "Consult the manual entry for the RewriteOptions directive " + "for options and caveats about matching other strings.", + r->uri)); return DECLINED; } @@ -4560,7 +4601,7 @@ static int hook_fixup(request_rec *r) * only do something under runtime if the engine is really enabled, * for this directory, else return immediately! */ - if (dconf->state == ENGINE_DISABLED) { + if (!dconf || dconf->state == ENGINE_DISABLED) { return DECLINED; }