fielding    98/08/11 02:26:25

  Modified:    src      CHANGES
               src/include http_config.h httpd.h
               src/main http_config.c http_core.c http_protocol.c
  Log:
  Once more, with feeling... add back limit_req_line, limit_req_fieldsize,
  and limit_req_fields to server_rec so that they can be configurable by
  the new directives LimitRequestLine, LimitRequestFieldsize, and
  LimitRequestFields.  Do not allow the user to set LimitRequestLine and
  LimitRequestFieldsize higher than the compiled buffer sizes.
  
  Revision  Changes    Path
  1.1018    +7 -6      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1017
  retrieving revision 1.1018
  diff -u -r1.1017 -r1.1018
  --- CHANGES   1998/08/11 00:09:41     1.1017
  +++ CHANGES   1998/08/11 09:26:20     1.1018
  @@ -7,12 +7,13 @@
     *) SECURITY: Eliminate O(n^2) space DoS attacks (and other O(n^2)
        cpu time attacks) in header parsing.  [Dean Gaudet]
   
  -  *) SECURITY: Added compile-time limits for various aspects of reading a
  -     client request to avoid some simple denial of service attacks,
  -     including limits on maximum request-line size, number of header
  -     fields, and size of any one header field.  Also added a configurable
  -     directive LimitRequestBody for limiting the size of the request
  -     message body.  [Roy Fielding]
  +  *) SECURITY: Added compile-time and configurable limits for
  +     various aspects of reading a client request to avoid some simple
  +     denial of service attacks, including limits on maximum request-line
  +     size (LimitRequestLine), number of header fields (LimitRequestFields),
  +     and size of any one header field (LimitRequestFieldsize).  Also added
  +     a configurable directive LimitRequestBody for limiting the size of the
  +     request message body.  [Roy Fielding]
   
     *) Make status module aware of DNS and logging states, even if
        STATUS not defined.  [Jim Jagielski]
  
  
  
  1.94      +1 -1      apache-1.3/src/include/http_config.h
  
  Index: http_config.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/include/http_config.h,v
  retrieving revision 1.93
  retrieving revision 1.94
  diff -u -r1.93 -r1.94
  --- http_config.h     1998/08/10 04:16:12     1.93
  +++ http_config.h     1998/08/11 09:26:22     1.94
  @@ -275,7 +275,7 @@
    * handle it back-compatibly, or at least signal an error).
    */
   
  -#define MODULE_MAGIC_NUMBER 19980809
  +#define MODULE_MAGIC_NUMBER 19980811
   #define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL, NULL
   
   /* Generic accessors for other modules to get at their own module-specific
  
  
  
  1.235     +18 -9     apache-1.3/src/include/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v
  retrieving revision 1.234
  retrieving revision 1.235
  diff -u -r1.234 -r1.235
  --- httpd.h   1998/08/10 04:23:02     1.234
  +++ httpd.h   1998/08/11 09:26:22     1.235
  @@ -377,18 +377,23 @@
    * smaller limits than we use below.  The request message body size can
    * be limited by the per-dir config directive LimitRequestBody.
    *
  - * Internal buffer sizes are two bytes more than the AP_LIMIT_REQUEST_LINE
  - * and AP_LIMIT_REQUEST_FIELDSIZE below, which explains the 8190.
  + * Internal buffer sizes are two bytes more than the 
DEFAULT_LIMIT_REQUEST_LINE
  + * and DEFAULT_LIMIT_REQUEST_FIELDSIZE below, which explains the 8190.
  + * These two limits can be lowered (but not raised) by the server config
  + * directives LimitRequestLine and LimitRequestFieldsize, respectively.
  + *
  + * DEFAULT_LIMIT_REQUEST_FIELDS can be modified or disabled (set = 0) by
  + * the server config directive LimitRequestFields.
    */
  -#ifndef AP_LIMIT_REQUEST_LINE
  -#define AP_LIMIT_REQUEST_LINE 8190
  +#ifndef DEFAULT_LIMIT_REQUEST_LINE
  +#define DEFAULT_LIMIT_REQUEST_LINE 8190
   #endif /* default limit on bytes in Request-Line (Method+URI+HTTP-version) */
  -#ifndef AP_LIMIT_REQUEST_FIELDS
  -#define AP_LIMIT_REQUEST_FIELDS 100
  -#endif /* default limit on number of request header fields */
  -#ifndef AP_LIMIT_REQUEST_FIELDSIZE
  -#define AP_LIMIT_REQUEST_FIELDSIZE 8190
  +#ifndef DEFAULT_LIMIT_REQUEST_FIELDSIZE
  +#define DEFAULT_LIMIT_REQUEST_FIELDSIZE 8190
   #endif /* default limit on bytes in any one header field  */
  +#ifndef DEFAULT_LIMIT_REQUEST_FIELDS
  +#define DEFAULT_LIMIT_REQUEST_FIELDS 100
  +#endif /* default limit on number of request header fields */
   
   /*
    * The below defines the base string of the Server: header. Additional
  @@ -845,6 +850,10 @@
   
       uid_t server_uid;        /* effective user id when calling exec wrapper 
*/
       gid_t server_gid;        /* effective group id when calling exec wrapper 
*/
  +
  +    int limit_req_line;      /* limit on size of the HTTP request line    */
  +    int limit_req_fieldsize; /* limit on size of any request header field */
  +    int limit_req_fields;    /* limit on number of request header fields  */
   };
   
   /* These are more like real hosts than virtual hosts */
  
  
  
  1.123     +3 -0      apache-1.3/src/main/http_config.c
  
  Index: http_config.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/main/http_config.c,v
  retrieving revision 1.122
  retrieving revision 1.123
  diff -u -r1.122 -r1.123
  --- http_config.c     1998/08/11 00:09:44     1.122
  +++ http_config.c     1998/08/11 09:26:23     1.123
  @@ -1410,6 +1410,9 @@
       s->loglevel = DEFAULT_LOGLEVEL;
       s->srm_confname = RESOURCE_CONFIG_FILE;
       s->access_confname = ACCESS_CONFIG_FILE;
  +    s->limit_req_line = DEFAULT_LIMIT_REQUEST_LINE;
  +    s->limit_req_fieldsize = DEFAULT_LIMIT_REQUEST_FIELDSIZE;
  +    s->limit_req_fields = DEFAULT_LIMIT_REQUEST_FIELDS;
       s->timeout = DEFAULT_TIMEOUT;
       s->keep_alive_timeout = DEFAULT_KEEPALIVE_TIMEOUT;
       s->keep_alive_max = DEFAULT_KEEPALIVE;
  
  
  
  1.223     +73 -0     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.222
  retrieving revision 1.223
  diff -u -r1.222 -r1.223
  --- http_core.c       1998/08/11 02:50:53     1.222
  +++ http_core.c       1998/08/11 09:26:23     1.223
  @@ -2333,6 +2333,73 @@
       return NULL;
   }
   
  +static const char *set_limit_req_line(cmd_parms *cmd, void *dummy, char *arg)
  +{
  +    const char *err = ap_check_cmd_context(cmd,
  +                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  +    int lim;
  +
  +    if (err != NULL) {
  +        return err;
  +    }
  +    lim = atoi(arg);
  +    if (lim < 0) {
  +        return ap_pstrcat(cmd->temp_pool, "LimitRequestLine \"", arg, 
  +                          "\" must be a non-negative integer", NULL);
  +    }
  +    if (lim > DEFAULT_LIMIT_REQUEST_LINE) {
  +        return ap_psprintf(cmd->temp_pool, "LimitRequestLine \"%s\" "
  +                           "must not exceed the precompiled maximum of %d",
  +                           arg, DEFAULT_LIMIT_REQUEST_LINE);
  +    }
  +    cmd->server->limit_req_line = lim;
  +    return NULL;
  +}
  +
  +static const char *set_limit_req_fieldsize(cmd_parms *cmd, void *dummy,
  +                                           char *arg)
  +{
  +    const char *err = ap_check_cmd_context(cmd,
  +                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  +    int lim;
  +
  +    if (err != NULL) {
  +        return err;
  +    }
  +    lim = atoi(arg);
  +    if (lim < 0) {
  +        return ap_pstrcat(cmd->temp_pool, "LimitRequestFieldsize \"", arg, 
  +                          "\" must be a non-negative integer (0 = no limit)",
  +                          NULL);
  +    }
  +    if (lim > DEFAULT_LIMIT_REQUEST_FIELDSIZE) {
  +        return ap_psprintf(cmd->temp_pool, "LimitRequestFieldsize \"%s\" "
  +                          "must not exceed the precompiled maximum of %d",
  +                           arg, DEFAULT_LIMIT_REQUEST_FIELDSIZE);
  +    }
  +    cmd->server->limit_req_fieldsize = lim;
  +    return NULL;
  +}
  +
  +static const char *set_limit_req_fields(cmd_parms *cmd, void *dummy, char 
*arg)
  +{
  +    const char *err = ap_check_cmd_context(cmd,
  +                                           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
  +    int lim;
  +
  +    if (err != NULL) {
  +        return err;
  +    }
  +    lim = atoi(arg);
  +    if (lim < 0) {
  +        return ap_pstrcat(cmd->temp_pool, "LimitRequestFields \"", arg, 
  +                          "\" must be a non-negative integer (0 = no limit)",
  +                          NULL);
  +    }
  +    cmd->server->limit_req_fields = lim;
  +    return NULL;
  +}
  +
   static const char *set_limit_req_body(cmd_parms *cmd, core_dir_config *conf,
                                         char *arg) 
   {
  @@ -2553,6 +2620,12 @@
     "Determine tokens displayed in the Server: header - Min(imal), OS or Full" 
},
   { "ExtendedStatus", set_extended_status, NULL, RSRC_CONF, TAKE1,
     "\"On\" to enable extended status information, \"Off\" to disable" },
  +{ "LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF, TAKE1,
  +  "Limit on maximum size of an HTTP request line"},
  +{ "LimitRequestFieldsize", set_limit_req_fieldsize, NULL, RSRC_CONF, TAKE1,
  +  "Limit on maximum size of an HTTP request header field"},
  +{ "LimitRequestFields", set_limit_req_fields, NULL, RSRC_CONF, TAKE1,
  +  "Limit (0 = unlimited) on max number of header fields in a request 
message"},
   { "LimitRequestBody", set_limit_req_body,
     (void*)XtOffsetOf(core_dir_config, limit_req_body),
     RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1,
  
  
  
  1.237     +8 -6      apache-1.3/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
  retrieving revision 1.236
  retrieving revision 1.237
  diff -u -r1.236 -r1.237
  --- http_protocol.c   1998/08/10 04:16:15     1.236
  +++ http_protocol.c   1998/08/11 09:26:24     1.237
  @@ -626,7 +626,7 @@
   
   static int read_request_line(request_rec *r)
   {
  -    char l[AP_LIMIT_REQUEST_LINE + 2];  /* getline needs two extra for \n\0 
*/
  +    char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 
*/
       const char *ll = l;
       const char *uri;
       conn_rec *conn = r->connection;
  @@ -694,7 +694,7 @@
        * buffer before finding the end-of-line.  This is only going to
        * happen if it exceeds the configured limit for a request-line.
        */
  -    if (len >= sizeof(l) - 1) {
  +    if (len > r->server->limit_req_line) {
           r->status    = HTTP_REQUEST_URI_TOO_LARGE;
           r->proto_num = HTTP_VERSION(1,0);
           r->protocol  = ap_pstrdup(r->pool, "HTTP/1.0");
  @@ -738,7 +738,7 @@
   /* XXX: could use ap_overlap_tables here... which generalizes this code */
   static void get_mime_headers(request_rec *r)
   {
  -    char field[AP_LIMIT_REQUEST_FIELDSIZE + 2];  /* getline needs two extra 
*/
  +    char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* getline's two extra 
*/
       conn_rec *c = r->connection;
       char *value;
       char *copy;
  @@ -791,10 +791,12 @@
        */
       while ((len = getline(field, sizeof(field), c->client, 1)) > 0) {
   
  -        if (++fields_read > AP_LIMIT_REQUEST_FIELDS) {
  +        if (r->server->limit_req_fields &&
  +            (++fields_read > r->server->limit_req_fields)) {
               r->status = HTTP_BAD_REQUEST;
               ap_table_setn(r->notes, "error-notes",
  -                "Number of request header fields exceeds server 
limit.<P>\n");
  +                          "The number of request header fields exceeds "
  +                          "this server's limit.<P>\n");
               ap_destroy_pool(tmp);
               return;
           }
  @@ -802,7 +804,7 @@
            * buffer before finding the end-of-line.  This is only going to
            * happen if it exceeds the configured limit for a field size.
            */
  -        if (len >= sizeof(field) - 1) { 
  +        if (len > r->server->limit_req_fieldsize) {
               r->status = HTTP_BAD_REQUEST;
               ap_table_setn(r->notes, "error-notes", ap_pstrcat(r->pool,
                   "Size of a request header field exceeds server limit.<P>\n"
  
  
  

Reply via email to