]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Fold in the CAN-2003-0542 regex patch.
authorSander Striker <striker@apache.org>
Fri, 24 Oct 2003 16:20:28 +0000 (16:20 +0000)
committerSander Striker <striker@apache.org>
Fri, 24 Oct 2003 16:20:28 +0000 (16:20 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@101556 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/httpd.h
modules/filters/mod_include.c
modules/mappers/mod_alias.c
modules/mappers/mod_rewrite.c
modules/metadata/mod_setenvif.c
modules/proxy/proxy_ftp.c

diff --git a/CHANGES b/CHANGES
index 2909ba6502d067da68a3f2e5b31903c262d7417c..6017250e03936c892a84c467842fc89f4d3cbca4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -210,6 +210,11 @@ Changes with Apache 2.1.0-dev
 
 Changes with Apache 2.0.48
 
+  *) SECURITY: CAN-2003-0542 (cve.mitre.org)
+     Fix buffer overflows in mod_alias and mod_rewrite which occurred if
+     one configured a regular expression with more than 9 captures.
+     [AndrĂ© Malo]
+
   *) mod_include: fix segfault which occured if the filename was not
      set, for example, when processing some error conditions.
      PR 23836.  [Brian Akins <bakins@web.turner.com>, AndrĂ© Malo]
index 4f43931b3c011b1fa3ee098bf8c29ff92a2fef80..7512e93ba6bd2f45bcb0467034e201fff1c79b18 100644 (file)
@@ -316,6 +316,9 @@ extern "C" {
 /** The size of the server's internal read-write buffers */
 #define AP_IOBUFSIZE 8192
 
+/** The max number of regex captures that can be expanded by ap_pregsub */
+#define AP_MAX_REG_MATCH 10
+
 /**
  * APR_HAS_LARGE_FILES introduces the problem of spliting sendfile into 
  * mutiple buckets, no greater than MAX(apr_size_t), and more granular 
index f9551c07980ed3fe69e633281b53f27cfd166de0..6170695607011d5ac64ca9dab3c28b1651d058f5 100644 (file)
@@ -201,13 +201,11 @@ typedef struct arg_item {
     apr_size_t        value_len;
 } arg_item_t;
 
-#define MAX_NMATCH 10
-
 typedef struct {
     const char *source;
     const char *rexp;
     apr_size_t  nsub;
-    regmatch_t  match[MAX_NMATCH];
+    regmatch_t  match[AP_MAX_REG_MATCH];
 } backref_t;
 
 typedef struct {
@@ -712,7 +710,7 @@ static const char *get_include_var(const char *var, include_ctx_t *ctx)
             return NULL;
         }
         else {
-            if (re->nsub < idx) {
+            if (re->nsub < idx || idx >= AP_MAX_REG_MATCH) {
                 ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
                               "regex capture $%" APR_SIZE_T_FMT
                               " is out of range (last regex was: '%s') in %s",
@@ -987,7 +985,7 @@ static APR_INLINE int re_check(include_ctx_t *ctx, const char *string,
     re->source = apr_pstrdup(ctx->pool, string);
     re->rexp = apr_pstrdup(ctx->pool, rexp);
     re->nsub = compiled->re_nsub;
-    rc = !ap_regexec(compiled, string, MAX_NMATCH, re->match, 0);
+    rc = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 0);
 
     ap_pregfree(ctx->dpool, compiled);
     return rc;
index 9ceb4ad02f8544f30d76f738474d0201e92f9a9d..1068f82dbc8f8bbe0e904fdfad7b6a105259d45e 100644 (file)
@@ -354,7 +354,7 @@ static char *try_alias_list(request_rec *r, apr_array_header_t *aliases,
                             int doesc, int *status)
 {
     alias_entry *entries = (alias_entry *) aliases->elts;
-    regmatch_t regm[10];
+    regmatch_t regm[AP_MAX_REG_MATCH];
     char *found = NULL;
     int i;
 
@@ -363,11 +363,10 @@ static char *try_alias_list(request_rec *r, apr_array_header_t *aliases,
         int l;
 
         if (p->regexp) {
-            if (!ap_regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm,
-                            0)) {
+            if (!ap_regexec(p->regexp, r->uri, AP_MAX_REG_MATCH, regm, 0)) {
                 if (p->real) {
                     found = ap_pregsub(r->pool, p->real, r->uri,
-                                    p->regexp->re_nsub + 1, regm);
+                                       AP_MAX_REG_MATCH, regm);
                     if (found && doesc) {
                         apr_uri_t uri;
                         apr_uri_parse(r->pool, found, &uri);
index 5ccee38c5bbd88d0013fb26c72127ffef5291a44..e308c2592683f0bcb0efb23f2469c01fb1cb9c06 100644 (file)
 /* XXX: not used at all. We should do a check somewhere and/or cut the cookie */
 #define MAX_COOKIE_LEN 4096
 
-/* max number of regex captures */
-#define MAX_NMATCH 10
-
 /* default maximum number of internal redirects */
 #define REWRITE_REDIRECT_LIMIT 10
 
@@ -368,7 +365,7 @@ typedef struct {
 typedef struct backrefinfo {
     char *source;
     int nsub;
-    regmatch_t regmatch[10];
+    regmatch_t regmatch[AP_MAX_REG_MATCH];
 } backrefinfo;
 
 /* single linked list used for
@@ -2152,7 +2149,7 @@ static char *do_expand(char *input, rewrite_ctx *ctx)
             backrefinfo *bri = (*p == '$') ? &ctx->briRR : &ctx->briRC;
 
             /* see ap_pregsub() in server/util.c */
-            if (bri->source && n <= bri->nsub
+            if (bri->source && n < AP_MAX_REG_MATCH
                 && bri->regmatch[n].rm_eo > bri->regmatch[n].rm_so) {
                 span = bri->regmatch[n].rm_eo - bri->regmatch[n].rm_so;
 
@@ -3356,7 +3353,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
     char *input = do_expand(p->input, ctx);
     apr_finfo_t sb;
     request_rec *rsub, *r = ctx->r;
-    regmatch_t regmatch[MAX_NMATCH];
+    regmatch_t regmatch[AP_MAX_REG_MATCH];
     int rc = 0;
 
     switch (p->ptype) {
@@ -3437,7 +3434,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
 
     default:
         /* it is really a regexp pattern, so apply it */
-        rc = !ap_regexec(p->regexp, input, p->regexp->re_nsub+1, regmatch, 0);
+        rc = !ap_regexec(p->regexp, input, AP_MAX_REG_MATCH, regmatch, 0);
 
         /* update briRC backref info */
         if (rc && !(p->flags & CONDFLAG_NOTMATCH)) {
@@ -3466,7 +3463,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
  */
 static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx)
 {
-    regmatch_t regmatch[MAX_NMATCH];
+    regmatch_t regmatch[AP_MAX_REG_MATCH];
     apr_array_header_t *rewriteconds;
     rewritecond_entry *conds;
     int i, rc;
@@ -3505,7 +3502,7 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx)
     rewritelog((r, 3, ctx->perdir, "applying pattern '%s' to uri '%s'",
                 p->pattern, ctx->uri));
 
-    rc = !ap_regexec(p->regexp, ctx->uri, p->regexp->re_nsub+1, regmatch, 0);
+    rc = !ap_regexec(p->regexp, ctx->uri, AP_MAX_REG_MATCH, regmatch, 0);
     if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) ||
            (!rc &&  (p->flags & RULEFLAG_NOTMATCH))   ) ) {
         return 0;
index 6b2d033967698c15fa7116a839d5e5d00733743a..5a1268eb0f4a03f2b6a33f66a85ddc60154263a7 100644 (file)
@@ -489,7 +489,7 @@ static int match_headers(request_rec *r)
     apr_size_t val_len = 0;
     int i, j;
     char *last_name;
-    regmatch_t regm[10];
+    regmatch_t regm[AP_MAX_REG_MATCH];
 
     if (!ap_get_module_config(r->request_config, &setenvif_module)) {
         ap_set_module_config(r->request_config, &setenvif_module,
@@ -577,8 +577,8 @@ static int match_headers(request_rec *r)
         }
 
         if ((b->pattern && apr_strmatch(b->pattern, val, val_len)) ||
-            (!b->pattern && !ap_regexec(b->preg, val, b->preg->re_nsub + 1,
-                                        regm, 0))) {
+            (!b->pattern && !ap_regexec(b->preg, val, AP_MAX_REG_MATCH, regm,
+                                        0))) {
             const apr_array_header_t *arr = apr_table_elts(b->features);
             elts = (const apr_table_entry_t *) arr->elts;
 
@@ -589,7 +589,7 @@ static int match_headers(request_rec *r)
                 else {
                     if (!b->pattern) {
                         char *replaced = ap_pregsub(r->pool, elts[j].val, val,
-                                                    b->preg->re_nsub + 1, regm);
+                                                    AP_MAX_REG_MATCH, regm);
                         if (replaced) {
                             apr_table_setn(r->subprocess_env, elts[j].key,
                                            replaced);
index 8df516a6805c1540a1c38f09fd3a91758de0d63e..bd9d9c07b118b11f91c419219433dbc9c7e62e21 100644 (file)
@@ -319,6 +319,10 @@ typedef struct {
     }    state;
 }      proxy_dir_ctx_t;
 
+/* fallback regex for ls -s1;  ($0..$2) == 3 */
+#define LS_REG_PATTERN "^ *([0-9]+) +([^ ]+)$"
+#define LS_REG_MATCH   3
+
 apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in)
 {
     request_rec *r = f->r;
@@ -462,10 +466,10 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in)
         int eos = 0;
 
         regex_t *re = NULL;
-        regmatch_t re_result[3];
+        regmatch_t re_result[LS_REG_MATCH];
 
         /* Compile the output format of "ls -s1" as a fallback for non-unix ftp listings */
-        re = ap_pregcomp(p, "^ *([0-9]+) +([^ ]+)$", REG_EXTENDED);
+        re = ap_pregcomp(p, LS_REG_PATTERN, REG_EXTENDED);
 
         /* get a complete line */
         /* if the buffer overruns - throw data away */
@@ -581,7 +585,7 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in)
             }
         }
         /* Try a fallback for listings in the format of "ls -s1" */
-        else if (0 == ap_regexec(re, ctx->buffer, 3, re_result, 0)) {
+        else if (0 == ap_regexec(re, ctx->buffer, LS_REG_MATCH, re_result, 0)) {
 
             filename = apr_pstrndup(p, &ctx->buffer[re_result[2].rm_so], re_result[2].rm_eo - re_result[2].rm_so);