httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From n.@apache.org
Subject cvs commit: apache-1.3/src/main http_core.c http_request.c
Date Mon, 07 Jul 2003 00:34:10 GMT
nd          2003/07/06 17:34:10

  Modified:    src      CHANGES
               src/include ap_mmn.h http_core.h
               src/main http_core.c http_request.c
  Log:
  well, (kinda) backport LimitInternalRecursion. This prevents
  the server from crashing if someone configure an infinite loop of
  internal redirects and subrequests. Default value is 20/20
  (subsequent redirects/nested subrequests), 0 means unlimited.
  
  The patch works fine on my box, but is required to be tested
  extensively before the next release.
  
  PR: 19753 (and probably more)
  Obtained from: 2.0 patch
  Reviewed by:	original 2.0 port by Justin and BrianP (?)
  
  Revision  Changes    Path
  1.1898    +6 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1897
  retrieving revision 1.1898
  diff -u -r1.1897 -r1.1898
  --- CHANGES	6 Jul 2003 17:52:26 -0000	1.1897
  +++ CHANGES	7 Jul 2003 00:34:09 -0000	1.1898
  @@ -1,5 +1,11 @@
   Changes with Apache 1.3.28
   
  +  *) Prevent the server from crashing when entering infinite loops. The
  +     new LimitInternalRecursion directive configures limits of subsequent
  +     internal redirects and nested subrequests, after which the request
  +     will be aborted.  PR 19753 (and probably others).
  +     [William Rowe, Jeff Trawick, Jim Jagielski, André Malo]
  +
     *) Fix NULL-pointer issue in ab when parsing an incomplete or non-HTTP
        response. PR 21085. [Glenn Nielsen <glenn@apache.org>, André Malo]
   
  
  
  
  1.64      +2 -1      apache-1.3/src/include/ap_mmn.h
  
  Index: ap_mmn.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/include/ap_mmn.h,v
  retrieving revision 1.63
  retrieving revision 1.64
  diff -u -r1.63 -r1.64
  --- ap_mmn.h	3 Feb 2003 17:13:18 -0000	1.63
  +++ ap_mmn.h	7 Jul 2003 00:34:09 -0000	1.64
  @@ -242,6 +242,7 @@
    *                        ap_note_cleanups_for_socket_ex(),
    *                        ap_note_cleanups_for_file_ex(),
    *                        ap_popenf_ex() and ap_psocket_ex().
  + * 19990320.15          - ap_is_recursion_limit_exceeded()
    */
   
   #define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */
  @@ -249,7 +250,7 @@
   #ifndef MODULE_MAGIC_NUMBER_MAJOR
   #define MODULE_MAGIC_NUMBER_MAJOR 19990320
   #endif
  -#define MODULE_MAGIC_NUMBER_MINOR 14                    /* 0...n */
  +#define MODULE_MAGIC_NUMBER_MINOR 15                    /* 0...n */
   
   /* Useful for testing for features. */
   #define AP_MODULE_MAGIC_AT_LEAST(major,minor)		\
  
  
  
  1.71      +17 -0     apache-1.3/src/include/http_core.h
  
  Index: http_core.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/include/http_core.h,v
  retrieving revision 1.70
  retrieving revision 1.71
  diff -u -r1.70 -r1.71
  --- http_core.h	3 Feb 2003 17:13:18 -0000	1.70
  +++ http_core.h	7 Jul 2003 00:34:09 -0000	1.71
  @@ -115,6 +115,12 @@
   #define SATISFY_ANY 1
   #define SATISFY_NOSPEC 2
   
  +/* default maximum of internal redirects */
  +# define AP_DEFAULT_MAX_INTERNAL_REDIRECTS 20
  +
  +/* default maximum subrequest nesting level */
  +# define AP_DEFAULT_MAX_SUBREQ_DEPTH 20
  +
   API_EXPORT(int) ap_allow_options (request_rec *);
   API_EXPORT(int) ap_allow_overrides (request_rec *);
   API_EXPORT(const char *) ap_default_type (request_rec *);     
  @@ -136,6 +142,12 @@
   API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string);
   API_EXPORT(int) ap_exists_config_define(char *name);
   
  +/* Check if the current request is beyond the configured max. number of redirects or subrequests
  + * @param r The current request
  + * @return true (is exceeded) or false
  + */
  +API_EXPORT(int) ap_is_recursion_limit_exceeded(const request_rec *r);
  +
   /* Authentication stuff.  This is one of the places where compatibility
    * with the old config files *really* hurts; they don't discriminate at
    * all between different authentication schemes, meaning that we need
  @@ -364,6 +376,11 @@
       char *access_name;
       array_header *sec;
       array_header *sec_url;
  +
  +    /* recursion backstopper */
  +    int recursion_limit_set; /* boolean */
  +    int redirect_limit;      /* maximum number of internal redirects */
  +    int subreq_limit;        /* maximum nesting level of subrequests */
   } core_server_config;
   
   /* for http_config.c */
  
  
  
  1.324     +146 -1    apache-1.3/src/main/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v
  retrieving revision 1.323
  retrieving revision 1.324
  diff -u -r1.323 -r1.324
  --- http_core.c	8 Apr 2003 15:18:29 -0000	1.323
  +++ http_core.c	7 Jul 2003 00:34:10 -0000	1.324
  @@ -366,7 +366,12 @@
       conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
       conf->sec = ap_make_array(a, 40, sizeof(void *));
       conf->sec_url = ap_make_array(a, 40, sizeof(void *));
  -    
  +
  +    /* recursion stopper */
  +    conf->redirect_limit = 0;
  +    conf->subreq_limit = 0;
  +    conf->recursion_limit_set = 0;
  +
       return (void *)conf;
   }
   
  @@ -387,6 +392,14 @@
       conf->sec = ap_append_arrays(p, base->sec, virt->sec);
       conf->sec_url = ap_append_arrays(p, base->sec_url, virt->sec_url);
   
  +    conf->redirect_limit = virt->recursion_limit_set
  +                           ? virt->redirect_limit
  +                           : base->redirect_limit;
  +
  +    conf->subreq_limit = virt->recursion_limit_set
  +                         ? virt->subreq_limit
  +                         : base->subreq_limit;
  +
       return conf;
   }
   
  @@ -3196,6 +3209,134 @@
       return NULL;
   }
   
  +static const char *set_recursion_limit(cmd_parms *cmd, void *dummy,
  +                                       const char *arg1, const char *arg2)
  +{
  +    core_server_config *conf = ap_get_module_config(cmd->server->module_config,
  +                                                    &core_module);
  +    int limit = atoi(arg1);
  +
  +    if (limit < 0) {
  +        return "The recursion limit must be greater than zero.";
  +    }
  +    if (limit && limit < 4) {
  +        ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, cmd->server,
  +                     "Limiting internal redirects to very low numbers may "
  +                     "cause normal requests to fail.");
  +    }
  +
  +    conf->redirect_limit = limit;
  +
  +    if (arg2) {
  +        limit = atoi(arg2);
  +
  +        if (limit < 0) {
  +            return "The recursion limit must be greater than zero.";
  +        }
  +        if (limit && limit < 4) {
  +            ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, cmd->server,
  +                         "Limiting the subrequest depth to a very low level may"
  +                         " cause normal requests to fail.");
  +        }
  +    }
  +
  +    conf->subreq_limit = limit;
  +    conf->recursion_limit_set = 1;
  +
  +    return NULL;
  +}
  +
  +static void log_backtrace(const request_rec *r)
  +{
  +    const request_rec *top = r;
  +
  +    ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
  +                  "r->uri = %s", r->uri ? r->uri : "(unexpectedly NULL)");
  +
  +    while (top && (top->prev || top->main)) {
  +        if (top->prev) {
  +            top = top->prev;
  +            ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
  +                          "redirected from r->uri = %s",
  +                          top->uri ? top->uri : "(unexpectedly NULL)");
  +        }
  +
  +        if (!top->prev && top->main) {
  +            top = top->main;
  +            ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
  +                          "subrequested from r->uri = %s",
  +                          top->uri ? top->uri : "(unexpectedly NULL)");
  +        }
  +    }
  +}
  +
  +/*
  + * check whether redirect limit is reached
  + */
  +API_EXPORT(int) ap_is_recursion_limit_exceeded(const request_rec *r)
  +{
  +    core_server_config *conf = ap_get_module_config(r->server->module_config,
  +                                                    &core_module);
  +    const request_rec *top = r;
  +    int redirects = 0, subreqs = 0;
  +    int rlimit = conf->recursion_limit_set
  +                 ? conf->redirect_limit
  +                 : AP_DEFAULT_MAX_INTERNAL_REDIRECTS;
  +    int slimit = conf->recursion_limit_set
  +                 ? conf->subreq_limit
  +                 : AP_DEFAULT_MAX_SUBREQ_DEPTH;
  +
  +    /* fast exit (unlimited) */
  +    if (!rlimit && !slimit) {
  +        return 0;
  +    }
  +
  +    while (top->prev || top->main) {
  +        if (top->prev) {
  +            if (rlimit && ++redirects >= rlimit) {
  +                /* uuh, too much. */
  +                ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
  +                              "Request exceeded the limit of %d internal "
  +                              "redirects due to probable configuration error. "
  +                              "Use 'LimitInternalRecursion' to increase the "
  +                              "limit if necessary. Use 'LogLevel debug' to get "
  +                              "a backtrace.", rlimit);
  +
  +                /* post backtrace */
  +                log_backtrace(r);
  +
  +                /* return failure */
  +                return 1;
  +            }
  +
  +            top = top->prev;
  +        }
  +
  +        if (!top->prev && top->main) {
  +            if (slimit && ++subreqs >= slimit) {
  +                /* uuh, too much. */
  +                ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
  +                              "Request exceeded the limit of %d subrequest "
  +                              "nesting levels due to probable confguration "
  +                              "error. Use 'LimitInternalRecursion' to increase "
  +                              "the limit if necessary. Use 'LogLevel debug' to "
  +                              "get a backtrace.", slimit);
  +
  +                /* post backtrace */
  +                log_backtrace(r);
  +
  +                /* return failure */
  +                return 1;
  +            }
  +
  +            top = top->main;
  +        }
  +    }
  +
  +    /* recursion state: ok */
  +    return 0;
  +}
  +
   /* Note --- ErrorDocument will now work from .htaccess files.  
    * The AllowOverride of Fileinfo allows webmasters to turn it off
    */
  @@ -3495,6 +3636,10 @@
   
   { "FileETag", set_etag_bits, NULL, OR_FILEINFO, RAW_ARGS,
     "Specify components used to construct a file's ETag"},
  +
  +{ "LimitInternalRecursion", set_recursion_limit, NULL, RSRC_CONF, TAKE12,
  +  "maximum recursion depth of internal redirects and subrequests"},
  +
   { NULL }
   };
   
  
  
  
  1.170     +32 -5     apache-1.3/src/main/http_request.c
  
  Index: http_request.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/main/http_request.c,v
  retrieving revision 1.169
  retrieving revision 1.170
  diff -u -r1.169 -r1.170
  --- http_request.c	13 May 2003 15:19:30 -0000	1.169
  +++ http_request.c	7 Jul 2003 00:34:10 -0000	1.170
  @@ -827,6 +827,13 @@
           ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file));
       }
   
  +    /* We cannot return NULL without violating the API. So just turn this
  +     * subrequest into a 500 to indicate the failure. */
  +    if (ap_is_recursion_limit_exceeded(r)) {
  +        rnew->status = HTTP_INTERNAL_SERVER_ERROR;
  +        return rnew;
  +    }
  +
       res = ap_unescape_url(rnew->uri);
       if (res) {
           rnew->status = res;
  @@ -903,6 +910,13 @@
       ap_set_sub_req_protocol(rnew, r);
       fdir = ap_make_dirstr_parent(rnew->pool, r->filename);
   
  +    /* We cannot return NULL without violating the API. So just turn this
  +     * subrequest into a 500. */
  +    if (ap_is_recursion_limit_exceeded(r)) {
  +        rnew->status = HTTP_INTERNAL_SERVER_ERROR;
  +        return rnew;
  +    }
  +
       /*
        * Check for a special case... if there are no '/' characters in new_file
        * at all, then we are looking at a relative lookup in the same
  @@ -1363,7 +1377,14 @@
   static request_rec *internal_internal_redirect(const char *new_uri, request_rec *r)
   {
       int access_status;
  -    request_rec *new = (request_rec *) ap_pcalloc(r->pool, sizeof(request_rec));
  +    request_rec *new;
  +
  +    if (ap_is_recursion_limit_exceeded(r)) {
  +        ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
  +        return NULL;
  +    }
  +
  +    new = (request_rec *) ap_pcalloc(r->pool, sizeof(request_rec));
   
       new->connection = r->connection;
       new->server     = r->server;
  @@ -1435,7 +1456,10 @@
   API_EXPORT(void) ap_internal_redirect(const char *new_uri, request_rec *r)
   {
       request_rec *new = internal_internal_redirect(new_uri, r);
  -    process_request_internal(new);
  +
  +    if (new) {
  +        process_request_internal(new);
  +    }
   }
   
   /* This function is designed for things like actions or CGI scripts, when
  @@ -1445,9 +1469,12 @@
   API_EXPORT(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r)
   {
       request_rec *new = internal_internal_redirect(new_uri, r);
  -    if (r->handler)
  -        new->content_type = r->content_type;
  -    process_request_internal(new);
  +
  +    if (new) {
  +        if (r->handler)
  +            new->content_type = r->content_type;
  +        process_request_internal(new);
  +    }
   }
   
   /*
  
  
  

Mime
View raw message