httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Randy Terbush <ra...@zyzzyva.com>
Subject Re: [PATCH] PR#378 part 1: Fix handling of request body in core
Date Mon, 21 Jul 1997 01:08:42 GMT
+1


> This is a protocol bug fix.  The patch is for 1.3 and I'll commit that,
> but I'd also like to see it in any 1.2.2.  Basically, we always need to
> check for a request body, even for GET, OPTIONS, and TRACE.  The latter
> is required by HTTP/1.1 to not have a body, but we still must check for it.
> 
> I haven't fixed the problem with special-casing the "*" Request-URI
> (we currently return 403), but this is all I have time for at the moment.
> 
> .....Roy
> 
> Index: http_core.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/http_core.c,v
> retrieving revision 1.97
> diff -c -r1.97 http_core.c
> *** http_core.c	1997/07/17 22:27:29	1.97
> --- http_core.c	1997/07/19 16:09:55
> ***************
> *** 1368,1376 ****
>         (core_dir_config *)get_module_config(r->per_dir_config, &core_module);
>       int rangestatus, errstatus;
>       FILE *f;
> !     
>       r->allowed |= (1 << M_GET);
> -     r->allowed |= (1 << M_TRACE);
>       r->allowed |= (1 << M_OPTIONS);
>   
>       if (r->method_number == M_INVALID) {
> --- 1368,1381 ----
>         (core_dir_config *)get_module_config(r->per_dir_config, &core_module);
>       int rangestatus, errstatus;
>       FILE *f;
> ! 
> !     /* This handler has no use for a request body (yet), but we still
> !      * need to read and discard it if the client sent one.
> !      */
> !     if ((errstatus = discard_request_body(r)) != OK)
> !         return errstatus;
> ! 
>       r->allowed |= (1 << M_GET);
>       r->allowed |= (1 << M_OPTIONS);
>   
>       if (r->method_number == M_INVALID) {
> Index: http_protocol.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/http_protocol.c,v
> retrieving revision 1.142
> diff -c -r1.142 http_protocol.c
> *** http_protocol.c	1997/07/19 10:20:50	1.142
> --- http_protocol.c	1997/07/19 16:09:56
> ***************
> *** 1094,1127 ****
>       bputs("\015\012", client);    /* Send the terminating empty line */
>   }
>   
>   static char *make_allow(request_rec *r)
>   {
> !     int allowed = r->allowed;
> ! 
> !     if( allowed == 0 ) {
> ! 	/* RFC2068 #14.7, Allow must contain at least one method.  So rather
> ! 	 * than deal with the possibility of trying not to emit an Allow:
> ! 	 * header, i.e. #10.4.6 says 405 Method Not Allowed MUST include
> ! 	 * an Allow header, we'll just say TRACE is valid.
> ! 	 */
> ! 	return( "TRACE" );
> !     }
> ! 
> !     return 2 + pstrcat(r->pool, (allowed & (1 << M_GET)) ? ", GET, HEAD"
: "",
> ! 		       (allowed & (1 << M_POST)) ? ", POST" : "",
> ! 		       (allowed & (1 << M_PUT)) ? ", PUT" : "",
> ! 		       (allowed & (1 << M_DELETE)) ? ", DELETE" : "",
> ! 		       (allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
> ! 		       (allowed & (1 << M_TRACE)) ? ", TRACE" : "",
> ! 		       NULL);
> -     
>   }
>   
>   int send_http_trace (request_rec *r)
>   {
>       /* Get the original request */
>       while (r->prev) r = r->prev;
>   
>       hard_timeout("send TRACE", r);
>   
>       r->content_type = "message/http";
> --- 1094,1124 ----
>       bputs("\015\012", client);    /* Send the terminating empty line */
>   }
>   
> + /* Build the Allow field-value from the request handler method mask.
> +  * Note that we always allow TRACE, since it is handled below.
> +  */
>   static char *make_allow(request_rec *r)
>   {
> !     return 2 + pstrcat(r->pool,
> !                        (r->allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
> !                        (r->allowed & (1 << M_POST)) ? ", POST" : "",
> !                        (r->allowed & (1 << M_PUT)) ? ", PUT" : "",
> !                        (r->allowed & (1 << M_DELETE)) ? ", DELETE" : "",
> !                        (r->allowed & (1 << M_OPTIONS)) ? ", OPTIONS" :
"",
> !                        ", TRACE",
> !                        NULL);
>   }
>   
>   int send_http_trace (request_rec *r)
>   {
> +     int rv;
> + 
>       /* Get the original request */
>       while (r->prev) r = r->prev;
>   
> +     if ((rv = setup_client_block(r, REQUEST_NO_BODY)))
> +         return rv;
> + 
>       hard_timeout("send TRACE", r);
>   
>       r->content_type = "message/http";
> ***************
> *** 1533,1538 ****
> --- 1530,1572 ----
>       return (chunk_start + len_read);
>   }
>   
> + /* In HTTP/1.1, any method can have a body.  However, most GET handlers
> +  * wouldn't know what to do with a request body if they received one.
> +  * This helper routine tests for and reads any message body in the request,
> +  * simply discarding whatever it receives.  We need to do this because
> +  * failing to read the request body would cause it to be interpreted
> +  * as the next request on a persistent connection.  
> +  *
> +  * Since we return an error status if the request is malformed, this
> +  * routine should be called at the beginning of a no-body handler, e.g.,
> +  *
> +  *    if ((retval = discard_request_body(r)) != OK)
> +  *        return retval;
> +  */
> + API_EXPORT(int) discard_request_body(request_rec *r)
> + {
> +     int rv;
> + 
> +     if ((rv = setup_client_block(r, REQUEST_CHUNKED_PASS)))
> +         return rv;
> + 
> +     if (should_client_block(r)) {
> +         char dumpbuf[HUGE_STRING_LEN];
> + 
> +         hard_timeout("reading request body", r);
> +         while ((rv = get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
> +             continue;
> +         kill_timeout(r);
> + 
> +         if (rv < 0)
> +             return HTTP_BAD_REQUEST;
> +     }
> +     return OK;
> + }
> + 
> + /*
> +  * Send the body of a response to the client.
> +  */
>   API_EXPORT(long) send_fd(FILE *f, request_rec *r) {
>       return send_fd_length(f, r, -1);
>   }
> Index: http_protocol.h
> ===================================================================
> RCS file: /export/home/cvs/apache/src/http_protocol.h,v
> retrieving revision 1.23
> diff -c -r1.23 http_protocol.h
> *** http_protocol.h	1997/07/15 21:39:56	1.23
> --- http_protocol.h	1997/07/19 16:09:56
> ***************
> *** 134,139 ****
> --- 134,140 ----
>   API_EXPORT(int) setup_client_block (request_rec *r, int read_policy);
>   API_EXPORT(int) should_client_block (request_rec *r);
>   API_EXPORT(long) get_client_block (request_rec *r, char *buffer, int bufsiz);
> + API_EXPORT(int) discard_request_body (request_rec *r);
>   
>   /* Sending a byterange */
>   
> Index: http_request.c
> ===================================================================
> RCS file: /export/home/cvs/apache/src/http_request.c,v
> retrieving revision 1.64
> diff -c -r1.64 http_request.c
> *** http_request.c	1997/07/19 08:03:53	1.64
> --- http_request.c	1997/07/19 16:09:56
> ***************
> *** 930,937 ****
>            * we handle it specially.
>            */
>           if (r->method_number == M_TRACE) {
> !             send_http_trace(r);
> !             finalize_request_protocol(r);
>               return;
>           }
>   
> --- 930,939 ----
>            * we handle it specially.
>            */
>           if (r->method_number == M_TRACE) {
> !             if ((access_status = send_http_trace(r)))
> ! 	        die(access_status, r);
> !             else
> !                 finalize_request_protocol(r);
>               return;
>           }
>   



Mime
View raw message