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/19 15:01:08 UTC

cvs commit: apache-1.3/src/modules/standard mod_rewrite.c mod_rewrite.h

nd          2003/03/19 06:01:08

  Modified:    src      CHANGES
               src/modules/standard mod_rewrite.c mod_rewrite.h
  Log:
  backport from 2.x:
  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).
  
  PR: 17462
  Reviewed by: Will Rowe, Ian Holsman
  
  Revision  Changes    Path
  1.1884    +5 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1883
  retrieving revision 1.1884
  diff -u -r1.1883 -r1.1884
  --- CHANGES	28 Feb 2003 13:36:03 -0000	1.1883
  +++ CHANGES	19 Mar 2003 14:01:05 -0000	1.1884
  @@ -1,5 +1,10 @@
   Changes with Apache 1.3.28
   
  +  *) backport from 2.x series: 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]
  +
     *) Use the correct locations of srm.conf and access.conf when tailoring
        the httpd.conf during the install process. PR 9446.
        [Stanislav Brabec <ut...@penguin.cz>]
  
  
  
  1.183     +107 -22   apache-1.3/src/modules/standard/mod_rewrite.c
  
  Index: mod_rewrite.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_rewrite.c,v
  retrieving revision 1.182
  retrieving revision 1.183
  diff -u -r1.182 -r1.183
  --- mod_rewrite.c	27 Feb 2003 03:47:37 -0000	1.182
  +++ mod_rewrite.c	19 Mar 2003 14:01:07 -0000	1.183
  @@ -252,6 +252,7 @@
       a->rewriteconds    = ap_make_array(p, 2, sizeof(rewritecond_entry));
       a->rewriterules    = ap_make_array(p, 2, sizeof(rewriterule_entry));
       a->server          = s;
  +    a->redirect_limit  = 0; /* unset (use default) */
   
       return (void *)a;
   }
  @@ -267,6 +268,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) {
           /*
  @@ -323,6 +327,7 @@
       a->baseurl         = NULL;
       a->rewriteconds    = ap_make_array(p, 2, sizeof(rewritecond_entry));
       a->rewriterules    = ap_make_array(p, 2, sizeof(rewriterule_entry));
  +    a->redirect_limit  = 0; /* unset (use server config) */
   
       if (path == NULL) {
           a->directory = NULL;
  @@ -353,6 +358,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 = ap_append_arrays(p, overrides->rewriteconds,
  @@ -395,36 +403,50 @@
   }
   
   static const char *cmd_rewriteoptions(cmd_parms *cmd,
  -                                      rewrite_perdir_conf *dconf, char *option)
  +                                      void *in_dconf, const char *option)
   {
  -    rewrite_server_conf *sconf;
  -    const char *err;
  +    int options = 0, limit = 0;
  +    char *w;
   
  -    sconf = (rewrite_server_conf *)
  -            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 ap_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(pool *p, int *options,
  -                                                char *name)
  -{
  -    if (strcasecmp(name, "inherit") == 0) {
  -        *options |= OPTION_INHERIT;
  +        conf->options |= options;
  +        conf->redirect_limit = limit;
       }
  -    else {
  -        return ap_pstrcat(p, "RewriteOptions: unknown option '",
  -                          name, "'\n", NULL);
  +    else {                  /* is per-directory command */
  +        rewrite_perdir_conf *conf = in_dconf;
  +
  +        conf->options |= options;
  +        conf->redirect_limit = limit;
       }
  +
       return NULL;
   }
   
  @@ -1598,12 +1620,75 @@
           return DECLINED;
       }
   
  +    if (is_redirect_limit_exceeded(r)) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 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(ap_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 = ap_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|APLOG_NOERRNO, 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.84      +15 -4     apache-1.3/src/modules/standard/mod_rewrite.h
  
  Index: mod_rewrite.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_rewrite.h,v
  retrieving revision 1.83
  retrieving revision 1.84
  diff -u -r1.83 -r1.84
  --- mod_rewrite.h	3 Feb 2003 17:13:29 -0000	1.83
  +++ mod_rewrite.h	19 Mar 2003 14:01:08 -0000	1.84
  @@ -255,6 +255,9 @@
   
   #define MAX_NMATCH    10
   
  +/* default maximum number of internal redirects */
  +#define REWRITE_REDIRECT_LIMIT 10
  +
   /*
   **
   **  our private data structures we handle with
  @@ -309,6 +312,7 @@
       array_header *rewriteconds;    /* the RewriteCond entries (temporary) */
       array_header *rewriterules;    /* the RewriteRule entries */
       server_rec   *server;          /* the corresponding server indicator */
  +    int          redirect_limit;   /* maximum number of internal redirects */
   } rewrite_server_conf;
   
   
  @@ -322,8 +326,16 @@
       array_header *rewriterules;    /* the RewriteRule entries */
       char         *directory;       /* the directory where it applies */
       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 table with LRU functionality
  @@ -376,10 +388,8 @@
   static const char *cmd_rewriteengine(cmd_parms *cmd,
                                        rewrite_perdir_conf *dconf, int flag);
   static const char *cmd_rewriteoptions(cmd_parms *cmd,
  -                                      rewrite_perdir_conf *dconf,
  -                                      char *option);
  -static const char *cmd_rewriteoptions_setoption(pool *p, int *options,
  -                                                char *name);
  +                                      void *in_dconf,
  +                                      const char *option);
   static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, char *a1);
   static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
   static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1,
  @@ -489,6 +499,7 @@
   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);
  +static int    is_redirect_limit_exceeded(request_rec *r);
   
       /* File locking */
   static void fd_lock(request_rec *r, int fd);