From: Tony Finch Date: Wed, 18 Oct 2000 04:50:25 +0000 (+0000) Subject: Restore functionality broken by the mod_rewrite security fix: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=78802fd943d27dc36a2f762ebf3a6c89a3db995f;p=apache Restore functionality broken by the mod_rewrite security fix: rewrite map lookup keys and default values are now expanded so that the lookup can depend on the requested URI etc. Because the new code is recursive you can now write configurations like the following (with nested map lookups) which wasn't directly possible before -- you had to use a RewriteCond and a %N backref instead, as in http://www.apache.org/docs/vhosts/mass.html#xtra-conf RewriteMap tolower int:tolower RewriteMap host2user txt:/home/www/conf/virtusertbl RewriteRule /(.*) /home/${host2user:${tolower:%{HTTP_HOST}}|www}/public_html PR: 6671 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86638 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 4ff21fa69d..a5e48940ec 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -2320,30 +2320,50 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf, /* now we have a '$' or a '%' */ if (inp[1] == '{') { char *endp; - endp = strchr(inp, '}'); + endp = find_closing_bracket(inp+2, '{', '}'); if (endp == NULL) { goto skip; } *endp = '\0'; if (inp[0] == '$') { /* ${...} map lookup expansion */ + /* + * To make rewrite maps useful the lookup key and + * default values must be expanded, so we make + * recursive calls to do the work. For security + * reasons we must never expand a string that includes + * verbatim data from the network. The recursion here + * isn't a problem because the result of expansion is + * only passed to lookup_map() so it cannot be + * re-expanded, only re-looked-up. Another way of + * looking at it is that the recursion is entirely + * driven by the syntax of the nested curly brackets. + */ char *key, *dflt, *result; + char xkey[MAX_STRING_LEN]; + char xdflt[MAX_STRING_LEN]; + char *empty = ""; key = strchr(inp, ':'); if (key == NULL) { goto skip; } *key++ = '\0'; dflt = strchr(key, '|'); - if (dflt) { + if (dflt == NULL) { + dflt = empty; + } + else *dflt++ = '\0'; } - result = lookup_map(r, inp+2, key); + do_expand(r, key, xkey, sizeof(xkey), briRR, briRC); + do_expand(r, dflt, xdflt, sizeof(xdflt), briRR, briRC); + result = lookup_map(r, inp+2, xkey); if (result == NULL) { - result = dflt ? dflt : ""; + result = xdflt; } span = apr_cpystrn(outp, result, space) - outp; key[-1] = ':'; - if (dflt) { + if (dflt != empty) { dflt[-1] = '|'; } } @@ -4086,6 +4106,28 @@ static int compare_lexicography(char *cpNum1, char *cpNum2) return 0; } +/* +** +** Find end of bracketed expression +** s points after the opening bracket +** +*/ + +static char *find_closing_bracket(char *s, int left, int right) +{ + int depth; + + for (depth = 1; *s; ++s) { + if (*s == right && --depth == 0) { + return s; + } + else if (*s == left) { + ++depth; + } + } + return NULL; +} + #ifdef NETWARE int main(int argc, char *argv[]) { diff --git a/modules/mappers/mod_rewrite.h b/modules/mappers/mod_rewrite.h index ed497d7b6e..d70f32fdc9 100644 --- a/modules/mappers/mod_rewrite.h +++ b/modules/mappers/mod_rewrite.h @@ -469,6 +469,9 @@ static int subreq_ok(request_rec *r); /* Lexicographic Comparison */ static int compare_lexicography(char *cpNum1, char *cpNum2); + /* Find end of bracketed expression */ +static char *find_closing_bracket(char *s, int left, int right); + #endif /* _MOD_REWRITE_H */ /*EOF*/