You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by nd...@apache.org on 2003/03/01 19:35:51 UTC

cvs commit: httpd-2.0/modules/mappers mod_rewrite.c mod_rewrite.h

nd          2003/03/01 10:35:51

  Modified:    .        CHANGES
               modules/mappers mod_rewrite.c mod_rewrite.h
  Log:
  Prevent endless loops of internal redirects in mod_rewrite by
  aborting after exceeding a limit of internal redirects. The
  limit defaults to 10 and can be changed using the RewriteOptions
  directive with the new MaxRedirects=n argument.
  (The latter required some restructuring of the RewriteOptions
   evaluation code).
  
  (Documentation patch follows asap)
  
  PR: 17462
  
  Revision  Changes    Path
  1.1098    +6 -1      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.1097
  retrieving revision 1.1098
  diff -u -r1.1097 -r1.1098
  --- CHANGES	28 Feb 2003 13:47:11 -0000	1.1097
  +++ CHANGES	1 Mar 2003 18:35:50 -0000	1.1098
  @@ -2,12 +2,17 @@
   
     [Remove entries to the current 2.0 section below, when backported]
   
  +  *) Prevent endless loops of internal redirects in mod_rewrite by
  +     aborting after exceeding a limit of internal redirects. The
  +     limit defaults to 10 and can be changed using the RewriteOptions
  +     directive. PR 17462.  [Andr� Malo]
  +
     *) mod_rewrite: Fix some problems reporting errors with mapping
        programs (RewriteMap prg:/something).  [Jeff Trawick]
   
     *) Win32: Avoid busy wait (consuming all the CPU idle cycles) when
        all worker threads are busy. 
  -    [Igor Nazarenko <ig...@hotmail.com>]
  +     [Igor Nazarenko <ig...@hotmail.com>]
   
     *) When using Redirect in directory context, append requested query
        string if there's no one supplied by configuration. PR 10961.
  
  
  
  1.148     +106 -21   httpd-2.0/modules/mappers/mod_rewrite.c
  
  Index: mod_rewrite.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_rewrite.c,v
  retrieving revision 1.147
  retrieving revision 1.148
  diff -u -r1.147 -r1.148
  --- mod_rewrite.c	28 Feb 2003 13:13:39 -0000	1.147
  +++ mod_rewrite.c	1 Mar 2003 18:35:50 -0000	1.148
  @@ -206,6 +206,7 @@
       a->rewriteconds    = apr_array_make(p, 2, sizeof(rewritecond_entry));
       a->rewriterules    = apr_array_make(p, 2, sizeof(rewriterule_entry));
       a->server          = s;
  +    a->redirect_limit  = 0; /* unset (use default) */
   
       return (void *)a;
   }
  @@ -222,6 +223,9 @@
       a->state   = overrides->state;
       a->options = overrides->options;
       a->server  = overrides->server;
  +    a->redirect_limit = overrides->redirect_limit
  +                          ? overrides->redirect_limit
  +                          : base->redirect_limit;
   
       if (a->options & OPTION_INHERIT) {
           /*
  @@ -278,6 +282,7 @@
       a->baseurl         = NULL;
       a->rewriteconds    = apr_array_make(p, 2, sizeof(rewritecond_entry));
       a->rewriterules    = apr_array_make(p, 2, sizeof(rewriterule_entry));
  +    a->redirect_limit  = 0; /* unset (use server config) */
   
       if (path == NULL) {
           a->directory = NULL;
  @@ -308,6 +313,9 @@
       a->options   = overrides->options;
       a->directory = overrides->directory;
       a->baseurl   = overrides->baseurl;
  +    a->redirect_limit = overrides->redirect_limit
  +                          ? overrides->redirect_limit
  +                          : base->redirect_limit;
   
       if (a->options & OPTION_INHERIT) {
           a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
  @@ -351,34 +359,48 @@
   static const char *cmd_rewriteoptions(cmd_parms *cmd,
                                         void *in_dconf, const char *option)
   {
  -    rewrite_perdir_conf *dconf = in_dconf;
  -    rewrite_server_conf *sconf;
  -    const char *err;
  +    int options = 0, limit = 0;
  +    char *w;
   
  -    sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
  +    while (*option) {
  +        w = ap_getword_conf(cmd->pool, &option);
   
  -    if (cmd->path == NULL) { /* is server command */
  -        err = cmd_rewriteoptions_setoption(cmd->pool,
  -                                           &(sconf->options), option);
  -    }
  -    else {                 /* is per-directory command */
  -        err = cmd_rewriteoptions_setoption(cmd->pool,
  -                                           &(dconf->options), option);
  +        if (!strcasecmp(w, "inherit")) {
  +            options |= OPTION_INHERIT;
  +        }
  +        else if (!strncasecmp(w, "MaxRedirects=", 13)) {
  +            limit = atoi(&w[13]);
  +            if (limit <= 0) {
  +                return "RewriteOptions: MaxRedirects takes a number greater "
  +                       "than zero.";
  +            }
  +        }
  +        else if (!strcasecmp(w, "MaxRedirects")) { /* be nice */
  +            return "RewriteOptions: MaxRedirects has the format MaxRedirects"
  +                   "=n.";
  +        }
  +        else {
  +            return apr_pstrcat(cmd->pool, "RewriteOptions: unknown option '",
  +                               w, "'", NULL);
  +        }
       }
   
  -    return err;
  -}
  +    /* put it into the appropriate config */
  +    if (cmd->path == NULL) { /* is server command */
  +        rewrite_server_conf *conf =
  +            ap_get_module_config(cmd->server->module_config,
  +                                 &rewrite_module);
   
  -static const char *cmd_rewriteoptions_setoption(apr_pool_t *p, int *options,
  -                                                const char *name)
  -{
  -    if (strcasecmp(name, "inherit") == 0) {
  -        *options |= OPTION_INHERIT;
  +        conf->options |= options;
  +        conf->redirect_limit = limit;
       }
  -    else {
  -        return apr_pstrcat(p, "RewriteOptions: unknown option '",
  -                          name, "'", NULL);
  +    else {                  /* is per-directory command */
  +        rewrite_perdir_conf *conf = in_dconf;
  +
  +        conf->options |= options;
  +        conf->redirect_limit = limit;
       }
  +
       return NULL;
   }
   
  @@ -1656,12 +1678,75 @@
           return DECLINED;
       }
   
  +    if (is_redirect_limit_exceeded(r)) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +                      "mod_rewrite: maximum number of internal redirects "
  +                      "reached. Assuming configuration error. Use "
  +                      "'RewriteOptions MaxRedirects' to increase the limit "
  +                      "if neccessary.");
  +        return HTTP_INTERNAL_SERVER_ERROR;
  +    }
  +
       /* now do the internal redirect */
       ap_internal_redirect(apr_pstrcat(r->pool, r->filename+9,
                                        r->args ? "?" : NULL, r->args, NULL), r);
   
       /* and return gracefully */
       return OK;
  +}
  +
  +/*
  + * check whether redirect limit is reached
  + */
  +static int is_redirect_limit_exceeded(request_rec *r)
  +{
  +    request_rec *top = r;
  +    rewrite_request_conf *reqc;
  +    rewrite_perdir_conf *dconf;
  +
  +    /* we store it in the top request */
  +    while (top->main) {
  +        top = top->main;
  +    }
  +    while (top->prev) {
  +        top = top->prev;
  +    }
  +
  +    /* fetch our config */
  +    reqc = (rewrite_request_conf *) ap_get_module_config(top->request_config,
  +                                                         &rewrite_module);
  +
  +    /* no config there? create one. */
  +    if (!reqc) {
  +        rewrite_server_conf *sconf;
  +
  +        reqc = apr_palloc(top->pool, sizeof(rewrite_request_conf));
  +        sconf = ap_get_module_config(r->server->module_config, &rewrite_module);
  +
  +        reqc->redirects = 0;
  +        reqc->redirect_limit = sconf->redirect_limit
  +                                 ? sconf->redirect_limit
  +                                 : REWRITE_REDIRECT_LIMIT;
  +
  +        /* associate it with this request */
  +        ap_set_module_config(top->request_config, &rewrite_module, reqc);
  +    }
  +
  +    /* allow to change the limit during redirects. */
  +    dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config,
  +                                                        &rewrite_module);
  +
  +    /* 0 == unset; take server conf ... */
  +    if (dconf->redirect_limit) {
  +        reqc->redirect_limit = dconf->redirect_limit;
  +    }
  +
  +    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
  +                  "mod_rewrite's internal redirect status: %d/%d.",
  +                  reqc->redirects, reqc->redirect_limit);
  +
  +    /* and now give the caller a hint */
  +    return (reqc->redirects++ >= reqc->redirect_limit);
   }
   
   
  
  
  
  1.43      +13 -2     httpd-2.0/modules/mappers/mod_rewrite.h
  
  Index: mod_rewrite.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_rewrite.h,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- mod_rewrite.h	27 Feb 2003 02:50:04 -0000	1.42
  +++ mod_rewrite.h	1 Mar 2003 18:35:50 -0000	1.43
  @@ -212,6 +212,8 @@
   
   #define MAX_NMATCH    10
   
  +/* default maximum number of internal redirects */
  +#define REWRITE_REDIRECT_LIMIT 10
   
   
   /*
  @@ -271,6 +273,7 @@
       apr_array_header_t *rewriteconds;    /* the RewriteCond entries (temporary) */
       apr_array_header_t *rewriterules;    /* the RewriteRule entries */
       server_rec   *server;          /* the corresponding server indicator */
  +    int          redirect_limit;   /* maximum number of internal redirects */
   } rewrite_server_conf;
   
   
  @@ -284,9 +287,18 @@
       apr_array_header_t *rewriterules;    /* the RewriteRule entries */
       char         *directory;       /* the directory where it applies */
       const char   *baseurl;         /* the base-URL  where it applies */
  +    int          redirect_limit;   /* maximum number of internal redirects */
   } rewrite_perdir_conf;
   
   
  +    /* the per-request configuration
  +     */
  +typedef struct {
  +    int           redirects;       /* current number of redirects */
  +    int           redirect_limit;  /* maximum number of redirects */
  +} rewrite_request_conf;
  +
  +
       /* the cache structures,
        * a 4-way hash apr_table_t with LRU functionality
        */
  @@ -343,8 +355,6 @@
   static const char *cmd_rewriteoptions(cmd_parms *cmd,
                                         void *dconf,
                                         const char *option);
  -static const char *cmd_rewriteoptions_setoption(apr_pool_t *p, int *options,
  -                                                const char *name);
   static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, const char *a1);
   static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, const char *a1);
   static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, 
  @@ -467,6 +477,7 @@
   static void   add_env_variable(request_rec *r, char *s);
   static void   add_cookie(request_rec *r, char *s);
   static int    subreq_ok(request_rec *r);
  +static int    is_redirect_limit_exceeded(request_rec *r);
   
       /* Lexicographic Comparison */
   static int compare_lexicography(char *cpNum1, char *cpNum2);