Apache has several bugs in mod_rewrite and mod_vhost_alias that could
cause arbirtary files on the server to be exposed under certain configurations.
if you are using theses modules.


Apply by doing:
       cd /usr/src
       patch -p0 < 031_httpd_patch
       cd usr.sbin/httpd
       make -f Makefile.bsd-wrapper obj
       make -f Makefile.bsd-wrapper depend
       make -f Makefile.bsd-wrapper
       make -f Makefile.bsd-wrapper install

Index: usr.sbin/httpd/src/modules/standard/mod_rewrite.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/modules/standard/mod_rewrite.c,v
retrieving revision 1.5
diff -u -r1.5 mod_rewrite.c
--- usr.sbin/httpd/src/modules/standard/mod_rewrite.c   2000/01/25 18:30:02     1.5
+++ usr.sbin/httpd/src/modules/standard/mod_rewrite.c   2000/10/18 20:27:27
@@ -1130,20 +1130,7 @@
                       r->filename);
            return OK;
        }
-        else if (  (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "http://",   7) == 0)
-                || (strlen(r->filename) > 8 &&
-                    strncasecmp(r->filename, "https://",  8) == 0)
-                || (strlen(r->filename) > 9 &&
-                    strncasecmp(r->filename, "gopher://", 9) == 0)
-                || (strlen(r->filename) > 6 &&
-                    strncasecmp(r->filename, "ftp://",    6) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "ldap:",     5) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "news:",     5) == 0)
-                || (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "mailto:",   7) == 0)) {
+        else if (is_absolute_uri(r->filename)) {
            /* it was finally rewritten to a remote URL */

            /* skip 'scheme:' */
@@ -1394,20 +1381,7 @@
                       "%s [OK]", dconf->directory, r->filename);
            return OK;
        }
-        else if (  (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "http://",   7) == 0)
-                || (strlen(r->filename) > 8 &&
-                    strncasecmp(r->filename, "https://",  8) == 0)
-                || (strlen(r->filename) > 9 &&
-                    strncasecmp(r->filename, "gopher://", 9) == 0)
-                || (strlen(r->filename) > 6 &&
-                    strncasecmp(r->filename, "ftp://",    6) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "ldap:",     5) == 0)
-                || (strlen(r->filename) > 5 &&
-                    strncasecmp(r->filename, "news:",     5) == 0)
-                || (strlen(r->filename) > 7 &&
-                    strncasecmp(r->filename, "mailto:",   7) == 0)) {
+        else if (is_absolute_uri(r->filename)) {
            /* it was finally rewritten to a remote URL */

            /* because we are in a per-dir context
@@ -1745,7 +1719,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 +1886,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 +1921,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 +1933,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:
@@ -2012,16 +1949,8 @@
     *   location, i.e. if it's not starting with either a slash
     *   or a fully qualified URL scheme.
     */
-    i = strlen(r->filename);
-    if (   prefixstrip
-        && !(   r->filename[0] == '/'
-             || (   (i > 7 && strncasecmp(r->filename, "http://",   7) == 0)
-                 || (i > 8 && strncasecmp(r->filename, "https://",  8) == 0)
-                 || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0)
-                 || (i > 6 && strncasecmp(r->filename, "ftp://",    6) == 0)
-                 || (i > 5 && strncasecmp(r->filename, "ldap:",     5) == 0)
-                 || (i > 5 && strncasecmp(r->filename, "news:",     5) == 0)
-                 || (i > 7 && strncasecmp(r->filename, "mailto:",   7) == 0)))) {
+    if (prefixstrip && r->filename[0] != '/'
+       && !is_absolute_uri(r->filename)) {
        rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s",
                   perdir, r->filename, perdir, r->filename);
        r->filename = ap_pstrcat(r->pool, perdir, r->filename, NULL);
@@ -2085,14 +2014,7 @@
     *  redirection (`RewriteRule .. <scheme>://...') then
     *  directly force an external HTTP redirect.
     */
-    i = strlen(r->filename);
-    if (   (i > 7 && strncasecmp(r->filename, "http://",   7) == 0)
-        || (i > 8 && strncasecmp(r->filename, "https://",  8) == 0)
-        || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0)
-        || (i > 6 && strncasecmp(r->filename, "ftp://",    6) == 0)
-        || (i > 5 && strncasecmp(r->filename, "ldap:",     5) == 0)
-        || (i > 5 && strncasecmp(r->filename, "news:",     5) == 0)
-        || (i > 7 && strncasecmp(r->filename, "mailto:",   7) == 0) ) {
+    if (is_absolute_uri(r->filename)) {
        if (perdir == NULL) {
            rewritelog(r, 2,
                       "implicitly forcing redirect (rc=%d) with %s",
@@ -2163,16 +2085,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
@@ -2194,7 +2107,7 @@
        }
    }
    else if (strcmp(p->pattern, "-l") == 0) {
-#if !defined(OS2) && !defined(WIN32)
+#if !defined(OS2) && !defined(WIN32)  && !defined(NETWARE)
        if (lstat(input, &sb) == 0) {
            if (S_ISLNK(sb.st_mode)) {
                rc = 1;
@@ -2211,12 +2124,7 @@
    }
    else if (strcmp(p->pattern, "-U") == 0) {
        /* avoid infinite subrequest recursion */
-        if (strlen(input) > 0               /* nonempty path, and            */
-            && (   r->main == NULL          /* - either not in a subrequest  */
-                || (   r->main->uri != NULL /* - or in a subrequest...       */
-                    && r->uri != NULL       /*   ...and URIs aren't NULL...  */
-                                            /*   ...and sub/main URIs differ */
-                    && strcmp(r->main->uri, r->uri) != 0) ) ) {
+        if (strlen(input) > 0 && subreq_ok(r)) {

            /* run a URI-based subrequest */
            rsub = ap_sub_req_lookup_uri(input, r);
@@ -2235,12 +2143,7 @@
    }
    else if (strcmp(p->pattern, "-F") == 0) {
        /* avoid infinite subrequest recursion */
-        if (strlen(input) > 0               /* nonempty path, and            */
-            && (   r->main == NULL          /* - either not in a subrequest  */
-                || (   r->main->uri != NULL /* - or in a subrequest...       */
-                    && r->uri != NULL       /*   ...and URIs aren't NULL...  */
-                                            /*   ...and sub/main URIs differ */
-                    && strcmp(r->main->uri, r->uri) != 0) ) ) {
+        if (strlen(input) > 0 && subreq_ok(r)) {

            /* process a file-based subrequest:
             * this differs from -U in that no path translation is done.
@@ -2314,8 +2217,161 @@
** +-------------------------------------------------------+
*/

+
/*
**
+**  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 = 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 == NULL) {
+                   dflt = empty;
+               }
+               else {
+                   *dflt++ = '\0';
+               }
+               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 = xdflt;
+               }
+               span = ap_cpystrn(outp, result, space) - outp;
+               key[-1] = ':';
+               if (dflt != empty) {
+                   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
**  the current URI string
**
@@ -2442,20 +2498,12 @@

static void fully_qualify_uri(request_rec *r)
{
-    int i;
    char buf[32];
    const char *thisserver;
    char *thisport;
    int port;

-    i = strlen(r->filename);
-    if (!(   (i > 7 && strncasecmp(r->filename, "http://",   7) == 0)
-          || (i > 8 && strncasecmp(r->filename, "https://",  8) == 0)
-          || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0)
-          || (i > 6 && strncasecmp(r->filename, "ftp://",    6) == 0)
-          || (i > 5 && strncasecmp(r->filename, "ldap:",     5) == 0)
-          || (i > 5 && strncasecmp(r->filename, "news:",     5) == 0)
-          || (i > 7 && strncasecmp(r->filename, "mailto:",   7) == 0))) {
+    if (!is_absolute_uri(r->filename)) {

        thisserver = ap_get_server_name(r);
        port = ap_get_server_port(r);
@@ -2484,45 +2532,24 @@

/*
**
-**  Expand the %0-%9 or $0-$9 regex backreferences
+**  return non-zero if the URI is absolute (includes a scheme etc.)
**
*/

-static void expand_backref_inbuffer(pool *p, char *buf, int nbuf,
-                                    backrefinfo *bri, char c)
+static int is_absolute_uri(char *uri)
{
-    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 */
-        }
+    int i = strlen(uri);
+    if (   (i > 7 && strncasecmp(uri, "http://",   7) == 0)
+        || (i > 8 && strncasecmp(uri, "https://",  8) == 0)
+        || (i > 9 && strncasecmp(uri, "gopher://", 9) == 0)
+        || (i > 6 && strncasecmp(uri, "ftp://",    6) == 0)
+        || (i > 5 && strncasecmp(uri, "ldap:",     5) == 0)
+        || (i > 5 && strncasecmp(uri, "news:",     5) == 0)
+        || (i > 7 && strncasecmp(uri, "mailto:",   7) == 0) ) {
+       return 1;
    }
-
-    /* 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] = '$';
-        }
+    else {
+       return 0;
    }
}

@@ -2571,121 +2598,8 @@
}
#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
-
-
-
/*
** +-------------------------------------------------------+
** |                                                       |
@@ -3109,7 +3023,9 @@
    char *fname;
    piped_log *pl;
    int    rewritelog_flags = ( O_WRONLY|O_APPEND|O_CREAT );
-#ifdef WIN32
+#if defined(NETWARE)
+    mode_t rewritelog_mode  = ( S_IREAD|S_IWRITE );
+#elif defined(WIN32)
    mode_t rewritelog_mode  = ( _S_IREAD|_S_IWRITE );
#else
    mode_t rewritelog_mode  = ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH );
@@ -3267,7 +3183,9 @@
** +-------------------------------------------------------+
*/

-#ifdef WIN32
+#if defined(NETWARE)
+#define REWRITELOCK_MODE ( S_IREAD|S_IWRITE )
+#elif defined(WIN32)
#define REWRITELOCK_MODE ( _S_IREAD|_S_IWRITE )
#else
#define REWRITELOCK_MODE ( S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH )
@@ -3275,10 +3193,6 @@

static void rewritelock_create(server_rec *s, pool *p)
{
-    rewrite_server_conf *conf;
-
-    conf = ap_get_module_config(s->module_config, &rewrite_module);
-
    /* only operate if a lockfile is used */
    if (lockname == NULL || *(lockname) == '\0') {
        return;
@@ -3307,10 +3221,6 @@

static void rewritelock_open(server_rec *s, pool *p)
{
-    rewrite_server_conf *conf;
-
-    conf = ap_get_module_config(s->module_config, &rewrite_module);
-
    /* only operate if a lockfile is used */
    if (lockname == NULL || *(lockname) == '\0') {
        return;
@@ -3483,53 +3393,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;
@@ -3869,11 +3732,11 @@
    char *p;

    n = 0;
-    for (p=key; *p != '\0'; ++p) {
-        n = n * 53711 + 134561 + (unsigned)(*p & 0xff);
+    for (p = key; *p != '\0'; p++) {
+        n = ((n << 5) + n) ^ (unsigned long)(*p++);
    }

-    return n % CACHE_TLB_ROWS;
+    return (int)(n % CACHE_TLB_ROWS);
}

static cacheentry *cache_tlb_lookup(cachetlbentry *tlb, cacheentry *elt,
@@ -4156,6 +4019,23 @@
}


+/*
+**
+**  check that a subrequest won't cause infinite recursion
+**
+*/
+
+static int subreq_ok(request_rec *r)
+{
+    /*
+     * either not in a subrequest, or in a subrequest
+     * and URIs aren't NULL and sub/main URIs differ
+     */
+    return (r->main == NULL ||
+           (r->main->uri != NULL && r->uri != NULL &&
+            strcmp(r->main->uri, r->uri) != 0));
+}
+

/*
**
@@ -4291,12 +4171,27 @@
    }
    return 0;
}
+
+/*
+**
+**  Find end of bracketed expression
+**  s points after the opening bracket
+**
+*/

-#ifdef NETWARE
-int main(int argc, char *argv[])
+static char *find_closing_bracket(char *s, int left, int right)
{
-    ExitThread(TSR_THREAD, 0);
+    int depth;
+
+    for (depth = 1; *s; ++s) {
+       if (*s == right && --depth == 0) {
+           return s;
+       }
+       else if (*s == left) {
+           ++depth;
+       }
+    }
+    return NULL;
}
-#endif

/*EOF*/
Index: usr.sbin/httpd/src/modules/standard/mod_rewrite.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/modules/standard/mod_rewrite.h,v
retrieving revision 1.4
diff -u -r1.4 mod_rewrite.h
--- usr.sbin/httpd/src/modules/standard/mod_rewrite.h   2000/01/25 18:30:03     1.4
+++ usr.sbin/httpd/src/modules/standard/mod_rewrite.h   2000/10/18 20:27:27
@@ -168,7 +168,7 @@
#include <fcntl.h>
#endif
#endif
-#ifdef AIX
+#if defined(AIX) || defined(AIXIA64)
#undef USE_FLOCK
#define USE_FCNTL 1
#include <fcntl.h>
@@ -420,14 +420,17 @@
                              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 int   is_absolute_uri(char *uri);
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 +469,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);

@@ -486,6 +487,7 @@
static int    parseargline(char *str, char **a1, char **a2, char **a3);
static int    prefix_stat(const char *path, struct stat *sb);
static void   add_env_variable(request_rec *r, char *s);
+static int    subreq_ok(request_rec *r);

    /* File locking */
static void fd_lock(request_rec *r, int fd);
@@ -493,6 +495,9 @@

    /* 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 */

Index: usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c,v
retrieving revision 1.1
diff -u -r1.1 mod_vhost_alias.c
--- usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c       1999/09/29 06:29:57     1.1
+++ usr.sbin/httpd/src/modules/standard/mod_vhost_alias.c       2000/10/18 20:27:27
@@ -412,25 +412,23 @@
    mva_sconf_t *conf;
    const char *name, *map, *uri;
    mva_mode_e mode;
-    int cgi;
+    const char *cgi;

    conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config,
                                             &vhost_alias_module);
-    if (!strncmp(r->uri, "/cgi-bin/", 9)) {
+    cgi = strstr(r->uri, "cgi-bin/");
+    if (cgi && cgi - r->uri != strspn(r->uri, "/")) {
+        cgi = NULL;
+    }
+    if (cgi) {
       mode = conf->cgi_root_mode;
       map = conf->cgi_root;
-       uri = r->uri + 8;
-       /*
-        * can't force cgi immediately because we might not handle this
-        * call if the mode is wrong
-        */
-       cgi = 1;
+       uri = cgi + strlen("cgi-bin");
    }
    else if (r->uri[0] == '/') {
       mode = conf->doc_root_mode;
       map = conf->doc_root;
       uri = r->uri;
-       cgi = 0;
    }
    else {
       return DECLINED;