]> git.pld-linux.org Git - packages/apache.git/commitdiff
- fix security bug in mod_rewrite (patch from Caldera).
authorkloczek <kloczek@pld-linux.org>
Thu, 12 Oct 2000 20:04:55 +0000 (20:04 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    apache-rewrite.patch -> 1.1

apache-rewrite.patch [new file with mode: 0644]

diff --git a/apache-rewrite.patch b/apache-rewrite.patch
new file mode 100644 (file)
index 0000000..c913d7c
--- /dev/null
@@ -0,0 +1,491 @@
+diff -uNr apache_1.3.11.orig/src/modules/standard/mod_rewrite.c apache_1.3.11/src/modules/standard/mod_rewrite.c
+--- apache_1.3.11.orig/src/modules/standard/mod_rewrite.c      Sun Jan 16 19:06:30 2000
++++ apache_1.3.11/src/modules/standard/mod_rewrite.c   Thu Oct  5 14:50:43 2000
+@@ -1745,7 +1745,6 @@
+     char *output;
+     const char *vary;
+     char newuri[MAX_STRING_LEN];
+-    char env[MAX_STRING_LEN];
+     regex_t *regexp;
+     regmatch_t regmatch[MAX_NMATCH];
+     backrefinfo *briRR = NULL;
+@@ -1913,20 +1912,7 @@
+      *  (`RewriteRule <pat> - [E=...]')
+      */
+     if (strcmp(output, "-") == 0) {
+-        for (i = 0; p->env[i] != NULL; i++) {
+-            /*  1. take the string  */
+-            ap_cpystrn(env, p->env[i], sizeof(env));
+-            /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
+-            expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$');
+-            /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
+-            expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%');
+-            /*  4. expand %{...} (i.e. variables) */
+-            expand_variables_inbuffer(r, env, sizeof(env));
+-            /*  5. expand ${...} (RewriteMap lookups)  */
+-            expand_map_lookups(r, env, sizeof(env));
+-            /*  and add the variable to Apache's structures  */
+-            add_env_variable(r, env);
+-        }
++      do_expand_env(r, p->env, briRR, briRC);
+         if (p->forced_mimetype != NULL) {
+             if (perdir == NULL) {
+                 /* In the per-server context we can force the MIME-type
+@@ -1961,17 +1947,7 @@
+      *  that there is something to replace, so we create the
+      *  substitution URL string in `newuri'.
+      */
+-    /*  1. take the output string  */
+-    ap_cpystrn(newuri, output, sizeof(newuri));
+-    /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
+-    expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRR, '$');
+-    /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
+-    expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRC, '%');
+-    /*  4. expand %{...} (i.e. variables) */
+-    expand_variables_inbuffer(r, newuri, sizeof(newuri));
+-    /*  5. expand ${...} (RewriteMap lookups)  */
+-    expand_map_lookups(r, newuri, sizeof(newuri));
+-    /*  and log the result... */
++    do_expand(r, output, newuri, sizeof(newuri), briRR, briRC);
+     if (perdir == NULL) {
+         rewritelog(r, 2, "rewrite %s -> %s", uri, newuri);
+     }
+@@ -1983,20 +1959,7 @@
+      *  Additionally do expansion for the environment variable
+      *  strings (`RewriteRule .. .. [E=<string>]').
+      */
+-    for (i = 0; p->env[i] != NULL; i++) {
+-        /*  1. take the string  */
+-        ap_cpystrn(env, p->env[i], sizeof(env));
+-        /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
+-        expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$');
+-        /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
+-        expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%');
+-        /*  4. expand %{...} (i.e. variables) */
+-        expand_variables_inbuffer(r, env, sizeof(env));
+-        /*  5. expand ${...} (RewriteMap lookups)  */
+-        expand_map_lookups(r, env, sizeof(env));
+-        /*  and add the variable to Apache's structures  */
+-        add_env_variable(r, env);
+-    }
++    do_expand_env(r, p->env, briRR, briRC);
+     /*
+      *  Now replace API's knowledge of the current URI:
+@@ -2163,16 +2126,7 @@
+      *   Construct the string we match against
+      */
+-    /*  1. take the string  */
+-    ap_cpystrn(input, p->input, sizeof(input));
+-    /*  2. expand $N (i.e. backrefs to RewriteRule pattern)  */
+-    expand_backref_inbuffer(r->pool, input, sizeof(input), briRR, '$');
+-    /*  3. expand %N (i.e. backrefs to latest RewriteCond pattern)  */
+-    expand_backref_inbuffer(r->pool, input, sizeof(input), briRC, '%');
+-    /*  4. expand %{...} (i.e. variables) */
+-    expand_variables_inbuffer(r, input, sizeof(input));
+-    /*  5. expand ${...} (RewriteMap lookups)  */
+-    expand_map_lookups(r, input, sizeof(input));
++    do_expand(r, p->input, input, sizeof(input), briRR, briRC);
+     /*
+      *   Apply the patterns
+@@ -2314,6 +2268,139 @@
+ ** +-------------------------------------------------------+
+ */
++
++/*
++**
++**  perform all the expansions on the input string
++**  leaving the result in the supplied buffer
++**
++*/
++
++static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
++                     backrefinfo *briRR, backrefinfo *briRC)
++{
++    char *inp, *outp;
++    size_t span, space;
++
++    /*
++     * for security reasons this expansion must be perfomed in a
++     * single pass, otherwise an attacker can arrange for the result
++     * of an earlier expansion to include expansion specifiers that
++     * are interpreted by a later expansion, producing results that
++     * were not intended by the administrator.
++     */
++
++    inp = input;
++    outp = buffer;
++    space = nbuf - 1; /* room for '\0' */
++
++    for (;;) {
++      span = strcspn(inp, "$%");
++      if (span > space) {
++          span = space;
++      }
++      memcpy(outp, inp, span);
++      inp += span;
++      outp += span;
++      space -= span;
++      if (space == 0 || *inp == '\0') {
++          break;
++      }
++      /* now we have a '$' or a '%' */
++      if (inp[1] == '{') {
++          char *endp;
++          endp = strchr(inp, '}');
++          if (endp == NULL) {
++              goto skip;
++          }
++          *endp = '\0';
++          if (inp[0] == '$') {
++              /* ${...} map lookup expansion */
++              char *key, *dflt, *result;
++              key = strchr(inp, ':');
++              if (key == NULL) {
++                  goto skip;
++              }
++              *key++ = '\0';
++              dflt = strchr(key, '|');
++              if (dflt) {
++                  *dflt++ = '\0';
++              }
++              result = lookup_map(r, inp+2, key);
++              if (result == NULL) {
++                  result = dflt ? dflt : "";
++              }
++              span = ap_cpystrn(outp, result, space) - outp;
++              key[-1] = ':';
++              if (dflt) {
++                  dflt[-1] = '|';
++              }
++          }
++          else if (inp[0] == '%') {
++              /* %{...} variable lookup expansion */
++              span = ap_cpystrn(outp, lookup_variable(r, inp+2), space) - outp;
++          }
++          else {
++              span = 0;
++          }
++          *endp = '}';
++          inp = endp+1;
++          outp += span;
++          space -= span;
++          continue;
++      }
++      else if (ap_isdigit(inp[1])) {
++          int n = inp[1] - '0';
++          backrefinfo *bri = NULL;
++          if (inp[0] == '$') {
++              /* $N RewriteRule regexp backref expansion */
++              bri = briRR;
++          }
++          else if (inp[0] == '%') {
++              /* %N RewriteCond regexp backref expansion */
++              bri = briRC;
++          }
++          /* see ap_pregsub() in src/main/util.c */
++            if (bri && n <= bri->nsub &&
++              bri->regmatch[n].rm_eo > bri->regmatch[n].rm_so) {
++              span = bri->regmatch[n].rm_eo - bri->regmatch[n].rm_so;
++              if (span > space) {
++                  span = space;
++              }
++              memcpy(outp, bri->source + bri->regmatch[n].rm_so, span);
++              outp += span;
++              space -= span;
++          }
++          inp += 2;
++          continue;
++      }
++    skip:
++      *outp++ = *inp++;
++      space--;
++    }
++    *outp++ = '\0';
++}
++
++
++/*
++**
++**  perform all the expansions on the environment variables
++**
++*/
++
++static void do_expand_env(request_rec *r, char *env[],
++                        backrefinfo *briRR, backrefinfo *briRC)
++{
++    int i;
++    char buf[MAX_STRING_LEN];
++
++    for (i = 0; env[i] != NULL; i++) {
++      do_expand(r, env[i], buf, sizeof(buf), briRR, briRC);
++      add_env_variable(r, buf);
++    }
++}
++
++
+ /*
+ **
+ **  split out a QUERY_STRING part from
+@@ -2484,51 +2571,6 @@
+ /*
+ **
+-**  Expand the %0-%9 or $0-$9 regex backreferences
+-**
+-*/
+-
+-static void expand_backref_inbuffer(pool *p, char *buf, int nbuf,
+-                                    backrefinfo *bri, char c)
+-{
+-    register int i;
+-
+-    /* protect existing $N and & backrefs and replace <c>N with $N backrefs */
+-    for (i = 0; buf[i] != '\0' && i < nbuf; i++) {
+-        if (buf[i] == '\\' && (buf[i+1] != '\0' && i < (nbuf-1))) {
+-            i++; /* protect next */
+-        }
+-        else if (buf[i] == '&') {
+-            buf[i] = '\001';
+-        }
+-        else if (c != '$' && buf[i] == '$' && (buf[i+1] >= '0' && buf[i+1] <= '9')) {
+-            buf[i] = '\002';
+-            i++; /* speedup */
+-        }
+-        else if (buf[i] == c && (buf[i+1] >= '0' && buf[i+1] <= '9')) {
+-            buf[i] = '$';
+-            i++; /* speedup */
+-        }
+-    }
+-
+-    /* now apply the standard regex substitution function */
+-    ap_cpystrn(buf, ap_pregsub(p, buf, bri->source,
+-                               bri->nsub+1, bri->regmatch), nbuf);
+-
+-    /* restore the original $N and & backrefs */
+-    for (i = 0; buf[i] != '\0' && i < nbuf; i++) {
+-        if (buf[i] == '\001') {
+-            buf[i] = '&';
+-        }
+-        else if (buf[i] == '\002') {
+-            buf[i] = '$';
+-        }
+-    }
+-}
+-
+-
+-/*
+-**
+ **  Expand tilde-paths (/~user) through
+ **  Unix /etc/passwd database information
+ **
+@@ -2571,120 +2613,6 @@
+ }
+ #endif
+-/*
+-**
+-**  mapfile expansion support
+-**  i.e. expansion of MAP lookup directives
+-**  ${<mapname>:<key>} in RewriteRule rhs
+-**
+-*/
+-
+-#define limit_length(n) (n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n)
+-
+-static void expand_map_lookups(request_rec *r, char *uri, int uri_len)
+-{
+-    char newuri[MAX_STRING_LEN];
+-    char *cpI;
+-    char *cpIE;
+-    char *cpO;
+-    char *cpT;
+-    char *cpT2;
+-    char mapname[LONG_STRING_LEN];
+-    char mapkey[LONG_STRING_LEN];
+-    char defaultvalue[LONG_STRING_LEN];
+-    int n;
+-
+-    cpI = uri;
+-    cpIE = cpI+strlen(cpI);
+-    cpO = newuri;
+-    while (cpI < cpIE) {
+-        if (cpI+6 < cpIE && strncmp(cpI, "${", 2) == 0) {
+-            /* missing delimiter -> take it as plain text */
+-            if (   strchr(cpI+2, ':') == NULL
+-                || strchr(cpI+2, '}') == NULL) {
+-                memcpy(cpO, cpI, 2);
+-                cpO += 2;
+-                cpI += 2;
+-                continue;
+-            }
+-            cpI += 2;
+-
+-            cpT = strchr(cpI, ':');
+-            n = cpT-cpI;
+-            memcpy(mapname, cpI, limit_length(n));
+-            mapname[limit_length(n)] = '\0';
+-            cpI += n+1;
+-
+-            cpT2 = strchr(cpI, '|');
+-            cpT = strchr(cpI, '}');
+-            if (cpT2 != NULL && cpT2 < cpT) {
+-                n = cpT2-cpI;
+-                memcpy(mapkey, cpI, limit_length(n));
+-                mapkey[limit_length(n)] = '\0';
+-                cpI += n+1;
+-
+-                n = cpT-cpI;
+-                memcpy(defaultvalue, cpI, limit_length(n));
+-                defaultvalue[limit_length(n)] = '\0';
+-                cpI += n+1;
+-            }
+-            else {
+-                n = cpT-cpI;
+-                memcpy(mapkey, cpI, limit_length(n));
+-                mapkey[limit_length(n)] = '\0';
+-                cpI += n+1;
+-
+-                defaultvalue[0] = '\0';
+-            }
+-
+-            cpT = lookup_map(r, mapname, mapkey);
+-            if (cpT != NULL) {
+-                n = strlen(cpT);
+-                if (cpO + n >= newuri + sizeof(newuri)) {
+-                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
+-                                 r, "insufficient space in "
+-                                 "expand_map_lookups, aborting");
+-                    return;
+-                }
+-                memcpy(cpO, cpT, n);
+-                cpO += n;
+-            }
+-            else {
+-                n = strlen(defaultvalue);
+-                if (cpO + n >= newuri + sizeof(newuri)) {
+-                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 
+-                                 r, "insufficient space in "
+-                                 "expand_map_lookups, aborting");
+-                    return;
+-                }
+-                memcpy(cpO, defaultvalue, n);
+-                cpO += n;
+-            }
+-        }
+-        else {
+-            cpT = strstr(cpI, "${");
+-            if (cpT == NULL)
+-                cpT = cpI+strlen(cpI);
+-            n = cpT-cpI;
+-            if (cpO + n >= newuri + sizeof(newuri)) {
+-                ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 
+-                             r, "insufficient space in "
+-                             "expand_map_lookups, aborting");
+-                return;
+-            }
+-            memcpy(cpO, cpI, n);
+-            cpO += n;
+-            cpI += n;
+-        }
+-    }
+-    *cpO = '\0';
+-    ap_cpystrn(uri, newuri, uri_len);
+-    return;
+-}
+-
+-#undef limit_length
+-
+-
+ /*
+ ** +-------------------------------------------------------+
+@@ -3483,53 +3411,6 @@
+ */
+-static void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len)
+-{
+-    char *newbuf;
+-    newbuf = expand_variables(r, buf);
+-    if (strcmp(newbuf, buf) != 0) {
+-        ap_cpystrn(buf, newbuf, buf_len);
+-    }
+-    return;
+-}
+-
+-static char *expand_variables(request_rec *r, char *str)
+-{
+-    char output[MAX_STRING_LEN];
+-    char input[MAX_STRING_LEN];
+-    char *cp;
+-    char *cp2;
+-    char *cp3;
+-    int expanded;
+-    char *outp;
+-    char *endp;
+-
+-    ap_cpystrn(input, str, sizeof(input));
+-    output[0] = '\0';
+-    outp = output;
+-    endp = output + sizeof(output);
+-    expanded = 0;
+-    for (cp = input; cp < input+MAX_STRING_LEN; ) {
+-        if ((cp2 = strstr(cp, "%{")) != NULL) {
+-            if ((cp3 = strstr(cp2, "}")) != NULL) {
+-                *cp2 = '\0';
+-                outp = ap_cpystrn(outp, cp, endp - outp);
+-
+-                cp2 += 2;
+-                *cp3 = '\0';
+-                outp = ap_cpystrn(outp, lookup_variable(r, cp2), endp - outp);
+-
+-                cp = cp3+1;
+-                expanded = 1;
+-                continue;
+-            }
+-        }
+-        outp = ap_cpystrn(outp, cp, endp - outp);
+-        break;
+-    }
+-    return expanded ? ap_pstrdup(r->pool, output) : str;
+-}
+-
+ static char *lookup_variable(request_rec *r, char *var)
+ {
+     const char *result;
+diff -uNr apache_1.3.11.orig/src/modules/standard/mod_rewrite.h apache_1.3.11/src/modules/standard/mod_rewrite.h
+--- apache_1.3.11.orig/src/modules/standard/mod_rewrite.h      Thu Oct 21 22:45:38 1999
++++ apache_1.3.11/src/modules/standard/mod_rewrite.h   Thu Oct  5 14:48:43 2000
+@@ -420,14 +420,16 @@
+                               char *perdir, backrefinfo *briRR,
+                               backrefinfo *briRC);
++static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
++                     backrefinfo *briRR, backrefinfo *briRC);
++static void do_expand_env(request_rec *r, char *env[],
++                        backrefinfo *briRR, backrefinfo *briRC);
++
+     /* URI transformation function */
+ static void  splitout_queryargs(request_rec *r, int qsappend);
+ static void  fully_qualify_uri(request_rec *r);
+ static void  reduce_uri(request_rec *r);
+-static void  expand_backref_inbuffer(pool *p, char *buf, int nbuf,
+-                                     backrefinfo *bri, char c);
+ static char *expand_tildepaths(request_rec *r, char *uri);
+-static void  expand_map_lookups(request_rec *r, char *uri, int uri_len);
+     /* rewrite map support functions */
+ static char *lookup_map(request_rec *r, char *name, char *key);
+@@ -466,8 +468,6 @@
+ static int   rewritemap_program_child(void *cmd, child_info *pinfo);
+     /* env variable support */
+-static void  expand_variables_inbuffer(request_rec *r, char *buf, int buf_len);
+-static char *expand_variables(request_rec *r, char *str);
+ static char *lookup_variable(request_rec *r, char *var);
+ static char *lookup_header(request_rec *r, const char *name);
This page took 0.093975 seconds and 4 git commands to generate.