Commit d8ce0f1a authored by Jeff Trawick's avatar Jeff Trawick
Browse files

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
parent 08dbbdef
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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]

+0 −15
Original line number Diff line number Diff line
@@ -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 ]

+35 −0
Original line number Diff line number Diff line
@@ -187,6 +187,41 @@ later</compatibility>
      
      </dd>
      </dl>

      <dt><code>AllowAnyURI</code></dt>
      <dd>

      <p>When <directive module="mod_rewrite">RewriteRule</directive>
      is used in <code>VirtualHost</code> or server context with
      version 2.2.22 or later of httpd, <module>mod_rewrite</module>
      will only process the rewrite rules if the request URI is a <a
      href="./directive-dict.html#Syntax">URL-path</a>.  This avoids
      some security issues where particular rules could allow
      "surprising" pattern expansions (see <a
      href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3368">CVE-2011-3368</a>
      and <a
      href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4317">CVE-2011-4317</a>).
      To lift the restriction on matching a URL-path, the
      <code>AllowAnyURI</code> option can be enabled, and
      <module>mod_rewrite</module> 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.</p>

      <note type="warning">
      <title>Security Warning</title> 

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

      </dl>

</usage>

</directivesynopsis>
+58 −17
Original line number Diff line number Diff line
@@ -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->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;
    a->baseurl   = overrides->baseurl;

    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;
    }