You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2005/07/01 22:00:01 UTC

svn commit: r208787 - in /httpd/httpd/trunk/modules: http/http_filters.c http/http_protocol.c proxy/mod_proxy.c

Author: wrowe
Date: Fri Jul  1 12:59:59 2005
New Revision: 208787

URL: http://svn.apache.org/viewcvs?rev=208787&view=rev
Log:

  Plug AllowTrace extended|on|off into proxy and http core.

  It still is not 'correct' until REQUEST_CHUNKED_PASS is reimplemented
  and passes some chunk headers, since we aren't echoing the entire
  request.  But it gets me further on testing 1.3 -> 2.0 -> 2.1 -> 2.0 -> 1.3
  proxy behaviors.

Modified:
    httpd/httpd/trunk/modules/http/http_filters.c
    httpd/httpd/trunk/modules/http/http_protocol.c
    httpd/httpd/trunk/modules/proxy/mod_proxy.c

Modified: httpd/httpd/trunk/modules/http/http_filters.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_filters.c?rev=208787&r1=208786&r2=208787&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http/http_filters.c (original)
+++ httpd/httpd/trunk/modules/http/http_filters.c Fri Jul  1 12:59:59 2005
@@ -759,9 +759,16 @@
 
 AP_DECLARE_NONSTD(int) ap_send_http_trace(request_rec *r)
 {
+    core_server_config *conf;
     int rv;
-    apr_bucket_brigade *b;
+    apr_bucket_brigade *bb;
     header_struct h;
+    apr_bucket *b;
+    int body;
+    char *bodyread, *bodyoff;
+    apr_size_t bodylen = 0;
+    apr_size_t bodybuf;
+    long res;
 
     if (r->method_number != M_TRACE) {
         return DECLINED;
@@ -771,23 +778,87 @@
     while (r->prev) {
         r = r->prev;
     }
+    conf = (core_server_config *)ap_get_module_config(r->server->module_config,
+                                                      &core_module);
 
-    if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY))) {
+    if (conf->trace_enable == AP_TRACE_DISABLE) {
+	apr_table_setn(r->notes, "error-notes",
+                      "TRACE denied by server configuration");
+        return HTTP_FORBIDDEN;
+    }
+
+    if (conf->trace_enable == AP_TRACE_EXTENDED)
+        /* XX should be = REQUEST_CHUNKED_PASS */
+        body = REQUEST_CHUNKED_DECHUNK;
+    else
+        body = REQUEST_NO_BODY;
+
+    if ((rv = ap_setup_client_block(r, body))) {
+        if (rv == HTTP_REQUEST_ENTITY_TOO_LARGE)
+    	    apr_table_setn(r->notes, "error-notes",
+                          "TRACE with a request body is not allowed");
         return rv;
     }
 
+    if (ap_should_client_block(r)) {
+
+        if (r->remaining > 0) {
+            if (r->remaining > 65536) {
+	        apr_table_setn(r->notes, "error-notes",
+                       "Extended TRACE request bodies cannot exceed 64k\n");
+                return HTTP_REQUEST_ENTITY_TOO_LARGE;
+            }
+            /* always 32 extra bytes to catch chunk header exceptions */
+            bodybuf = (apr_size_t)r->remaining + 32;
+        }
+        else {
+            /* Add an extra 8192 for chunk headers */
+            bodybuf = 73730;
+        }
+
+        bodyoff = bodyread = apr_palloc(r->pool, bodybuf);
+
+        /* only while we have enough for a chunked header */
+        while ((!bodylen || bodybuf >= 32) &&
+               (res = ap_get_client_block(r, bodyoff, bodybuf)) > 0) {
+            bodylen += res;
+            bodybuf -= res;
+            bodyoff += res;
+        }
+        if (res > 0 && bodybuf < 32) {
+            /* discard_rest_of_request_body into our buffer */
+            while (ap_get_client_block(r, bodyread, bodylen) > 0)
+                ;
+	    apr_table_setn(r->notes, "error-notes",
+                   "Extended TRACE request bodies cannot exceed 64k\n");
+            return HTTP_REQUEST_ENTITY_TOO_LARGE;
+        }
+
+        if (res < 0) {
+            return HTTP_BAD_REQUEST;
+        }
+    }
+
     ap_set_content_type(r, "message/http");
 
     /* Now we recreate the request, and echo it back */
 
-    b = apr_brigade_create(r->pool, r->connection->bucket_alloc);
-    apr_brigade_putstrs(b, NULL, NULL, r->the_request, CRLF, NULL);
+    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+    apr_brigade_putstrs(bb, NULL, NULL, r->the_request, CRLF, NULL);
     h.pool = r->pool;
-    h.bb = b;
+    h.bb = bb;
     apr_table_do((int (*) (void *, const char *, const char *))
                  form_header_field, (void *) &h, r->headers_in, NULL);
-    apr_brigade_puts(b, NULL, NULL, CRLF);
-    ap_pass_brigade(r->output_filters, b);
+    apr_brigade_puts(bb, NULL, NULL, CRLF);
+
+    /* If configured to accept a body, echo the body */
+    if (bodylen) {
+        b = apr_bucket_pool_create(bodyread, bodylen, 
+                                   r->pool, bb->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(bb, b);
+    }
+    
+    ap_pass_brigade(r->output_filters,  bb);
 
     return DONE;
 }
@@ -1089,6 +1160,7 @@
  *    REQUEST_NO_BODY          Send 413 error if message has any body
  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
+ *    REQUEST_CHUNKED_PASS     If chunked, pass the chunk headers with body.
  *
  *    In order to use the last two options, the caller MUST provide a buffer
  *    large enough to hold a chunk-size line, including any extensions.

Modified: httpd/httpd/trunk/modules/http/http_protocol.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_protocol.c?rev=208787&r1=208786&r2=208787&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http/http_protocol.c (original)
+++ httpd/httpd/trunk/modules/http/http_protocol.c Fri Jul  1 12:59:59 2005
@@ -754,6 +754,9 @@
     apr_int64_t mask;
     apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
     apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry);
+    /* For TRACE below */
+    core_server_config *conf =
+        ap_get_module_config(r->server->module_config, &core_module);
 
     mask = r->allowed_methods->method_mask;
 
@@ -771,8 +774,9 @@
         }
     }
 
-    /* TRACE is always allowed */
-    *(const char **)apr_array_push(allow) = "TRACE";
+    /* TRACE is tested on a per-server basis */
+    if (conf->trace_enable != AP_TRACE_DISABLE)
+        *(const char **)apr_array_push(allow) = "TRACE";
 
     list = apr_array_pstrcat(r->pool, allow, ',');
 

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/proxy/mod_proxy.c?rev=208787&r1=208786&r2=208787&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy.c Fri Jul  1 12:59:59 2005
@@ -541,7 +541,23 @@
         if (maxfwd < 1) {
             switch (r->method_number) {
             case M_TRACE: {
+                core_server_config *coreconf = (core_server_config *)
+                                    ap_get_module_config(sconf, &core_module);
                 int access_status;
+
+                if (coreconf->trace_enable == AP_TRACE_DISABLE)
+                    return ap_proxyerror(r, HTTP_NOT_IMPLEMENTED,
+                                         "TRACE denied by server configuration");
+
+                /* Can't test ap_should_client_block, we aren't ready to send
+                 * the client a 100 Continue response till the connection has
+                 * been established
+                 */
+                if (coreconf->trace_enable != AP_TRACE_EXTENDED 
+                    && (r->read_length || (!r->read_chunked && (r->remaining <= 0))))
+                    return ap_proxyerror(r, HTTP_REQUEST_ENTITY_TOO_LARGE,
+                                         "TRACE with request body is not allowed");
+
                 r->proxyreq = PROXYREQ_NONE;
                 if ((access_status = ap_send_http_trace(r)))
                     ap_die(access_status, r);



Re: svn commit: r208787 - in /httpd/httpd/trunk/modules: http/http_filters.c http/http_protocol.c proxy/mod_proxy.c

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On July 6, 2005 4:30:49 PM -0700 Paul Querna <ch...@force-elite.com> wrote:

> Then we should remove them from trunk today.  Why leave a 'flat-out
> wrong' API available?

If no one has removed them from trunk by the hackathon next weekend, I will 
remove them then.  -- justin



Re: svn commit: r208787 - in /httpd/httpd/trunk/modules: http/http_filters.c http/http_protocol.c proxy/mod_proxy.c

Posted by Paul Querna <ch...@force-elite.com>.
Justin Erenkrantz wrote:

> --On July 4, 2005 11:08:18 PM -0500 "William A. Rowe, Jr." 
> <wr...@rowe-clan.net> wrote:
>
>>>  It still is not 'correct' until REQUEST_CHUNKED_PASS is reimplemented
>>>  and passes some chunk headers, since we aren't echoing the entire
>>>  request.  But it gets me further on testing 1.3 -> 2.0 -> 2.1 -> 
>>> 2.0 ->
>>>  1.3 proxy behaviors.
>>
>
> As I've said before, REQUEST_CHUNKED_PASS needs to go away in 2.x.  
> The correct 'fix' is to remove the CHUNK input filter and then call 
> ap_get_brigade().  But, calling ap_should_client_block, 
> ap_get_client_block(), etc. is just flat-out wrong for 2.x.  -- justin


Then we should remove them from trunk today.  Why leave a 'flat-out 
wrong' API available?



Re: svn commit: r208787 - in /httpd/httpd/trunk/modules: http/http_filters.c http/http_protocol.c proxy/mod_proxy.c

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 06:21 PM 7/6/2005, Justin Erenkrantz wrote:
>--On July 4, 2005 11:08:18 PM -0500 "William A. Rowe, Jr." <wr...@rowe-clan.net> wrote:
>>> It still is not 'correct' until REQUEST_CHUNKED_PASS is reimplemented
>>> and passes some chunk headers, since we aren't echoing the entire
>>> request.  But it gets me further on testing 1.3 -> 2.0 -> 2.1 -> 2.0 ->
>>> 1.3 proxy behaviors.
>
>As I've said before, REQUEST_CHUNKED_PASS needs to go away in 2.x.  The correct 'fix' is to remove the CHUNK input filter and then call ap_get_brigade().  But, calling ap_should_client_block, ap_get_client_block(), etc. is just flat-out wrong for 2.x.  -- justin

Actually, in this odd case you are wrong.  There is no CHUNKED_PASS
in 2.x today, what you desire was already accomplished.

And I agree that a ap_get_brigade structure would be better.  I just
haven't had time to recode to 2.x.

And I agree that in httpd 3.x we eliminate ap_XXX_client_block.

But CHUNKED_PASS is *exactly* the behavior we want if we are
trying to backtrace how a back-end server observed a request
body.  We don't want the pretty output, we want the raw gorey
details, literally.  Roy has previously complained that we do
too much massaging before spitting back out the TRACE result.



Re: svn commit: r208787 - in /httpd/httpd/trunk/modules: http/http_filters.c http/http_protocol.c proxy/mod_proxy.c

Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
--On July 4, 2005 11:08:18 PM -0500 "William A. Rowe, Jr." 
<wr...@rowe-clan.net> wrote:
>>  It still is not 'correct' until REQUEST_CHUNKED_PASS is reimplemented
>>  and passes some chunk headers, since we aren't echoing the entire
>>  request.  But it gets me further on testing 1.3 -> 2.0 -> 2.1 -> 2.0 ->
>>  1.3 proxy behaviors.

As I've said before, REQUEST_CHUNKED_PASS needs to go away in 2.x.  The 
correct 'fix' is to remove the CHUNK input filter and then call 
ap_get_brigade().  But, calling ap_should_client_block, 
ap_get_client_block(), etc. is just flat-out wrong for 2.x.  -- justin

Re: svn commit: r208787 - in /httpd/httpd/trunk/modules: http/http_filters.c http/http_protocol.c proxy/mod_proxy.c

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
Before I left for holiday, this was queued against the wrong
sender account :(  Anyways I'll fix early tomorrow.

----------------

This is a bit off in http_proxy, and I'm out of time to fix
right now.  It's nestled in the hop count elimination, but if
we had no hard max hops, then we miss this code.  It needs
to move a bit further south.

At 03:00 PM 7/1/2005, wrowe@apache.org wrote:
>Author: wrowe
>Date: Fri Jul  1 12:59:59 2005
>New Revision: 208787
>
>URL: http://svn.apache.org/viewcvs?rev=208787&view=rev
>Log:
>
>  Plug AllowTrace extended|on|off into proxy and http core.
>
>  It still is not 'correct' until REQUEST_CHUNKED_PASS is reimplemented
>  and passes some chunk headers, since we aren't echoing the entire
>  request.  But it gets me further on testing 1.3 -> 2.0 -> 2.1 -> 2.0 -> 1.3
>  proxy behaviors.
>
>Modified:
>    httpd/httpd/trunk/modules/http/http_filters.c
>    httpd/httpd/trunk/modules/http/http_protocol.c
>    httpd/httpd/trunk/modules/proxy/mod_proxy.c
>
>Modified: httpd/httpd/trunk/modules/http/http_filters.c
>URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_filters.c?rev=208787&r1=208786&r2=208787&view=diff
>==============================================================================
>--- httpd/httpd/trunk/modules/http/http_filters.c (original)
>+++ httpd/httpd/trunk/modules/http/http_filters.c Fri Jul  1 12:59:59 2005
>@@ -759,9 +759,16 @@
> 
> AP_DECLARE_NONSTD(int) ap_send_http_trace(request_rec *r)
> {
>+    core_server_config *conf;
>     int rv;
>-    apr_bucket_brigade *b;
>+    apr_bucket_brigade *bb;
>     header_struct h;
>+    apr_bucket *b;
>+    int body;
>+    char *bodyread, *bodyoff;
>+    apr_size_t bodylen = 0;
>+    apr_size_t bodybuf;
>+    long res;
> 
>     if (r->method_number != M_TRACE) {
>         return DECLINED;
>@@ -771,23 +778,87 @@
>     while (r->prev) {
>         r = r->prev;
>     }
>+    conf = (core_server_config *)ap_get_module_config(r->server->module_config,
>+                                                      &core_module);
> 
>-    if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY))) {
>+    if (conf->trace_enable == AP_TRACE_DISABLE) {
>+       apr_table_setn(r->notes, "error-notes",
>+                      "TRACE denied by server configuration");
>+        return HTTP_FORBIDDEN;
>+    }
>+
>+    if (conf->trace_enable == AP_TRACE_EXTENDED)
>+        /* XX should be = REQUEST_CHUNKED_PASS */
>+        body = REQUEST_CHUNKED_DECHUNK;
>+    else
>+        body = REQUEST_NO_BODY;
>+
>+    if ((rv = ap_setup_client_block(r, body))) {
>+        if (rv == HTTP_REQUEST_ENTITY_TOO_LARGE)
>+           apr_table_setn(r->notes, "error-notes",
>+                          "TRACE with a request body is not allowed");
>         return rv;
>     }
> 
>+    if (ap_should_client_block(r)) {
>+
>+        if (r->remaining > 0) {
>+            if (r->remaining > 65536) {
>+               apr_table_setn(r->notes, "error-notes",
>+                       "Extended TRACE request bodies cannot exceed 64k\n");
>+                return HTTP_REQUEST_ENTITY_TOO_LARGE;
>+            }
>+            /* always 32 extra bytes to catch chunk header exceptions */
>+            bodybuf = (apr_size_t)r->remaining + 32;
>+        }
>+        else {
>+            /* Add an extra 8192 for chunk headers */
>+            bodybuf = 73730;
>+        }
>+
>+        bodyoff = bodyread = apr_palloc(r->pool, bodybuf);
>+
>+        /* only while we have enough for a chunked header */
>+        while ((!bodylen || bodybuf >= 32) &&
>+               (res = ap_get_client_block(r, bodyoff, bodybuf)) > 0) {
>+            bodylen += res;
>+            bodybuf -= res;
>+            bodyoff += res;
>+        }
>+        if (res > 0 && bodybuf < 32) {
>+            /* discard_rest_of_request_body into our buffer */
>+            while (ap_get_client_block(r, bodyread, bodylen) > 0)
>+                ;
>+           apr_table_setn(r->notes, "error-notes",
>+                   "Extended TRACE request bodies cannot exceed 64k\n");
>+            return HTTP_REQUEST_ENTITY_TOO_LARGE;
>+        }
>+
>+        if (res < 0) {
>+            return HTTP_BAD_REQUEST;
>+        }
>+    }
>+
>     ap_set_content_type(r, "message/http");
> 
>     /* Now we recreate the request, and echo it back */
> 
>-    b = apr_brigade_create(r->pool, r->connection->bucket_alloc);
>-    apr_brigade_putstrs(b, NULL, NULL, r->the_request, CRLF, NULL);
>+    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
>+    apr_brigade_putstrs(bb, NULL, NULL, r->the_request, CRLF, NULL);
>     h.pool = r->pool;
>-    h.bb = b;
>+    h.bb = bb;
>     apr_table_do((int (*) (void *, const char *, const char *))
>                  form_header_field, (void *) &h, r->headers_in, NULL);
>-    apr_brigade_puts(b, NULL, NULL, CRLF);
>-    ap_pass_brigade(r->output_filters, b);
>+    apr_brigade_puts(bb, NULL, NULL, CRLF);
>+
>+    /* If configured to accept a body, echo the body */
>+    if (bodylen) {
>+        b = apr_bucket_pool_create(bodyread, bodylen, 
>+                                   r->pool, bb->bucket_alloc);
>+        APR_BRIGADE_INSERT_TAIL(bb, b);
>+    }
>+    
>+    ap_pass_brigade(r->output_filters,  bb);
> 
>     return DONE;
> }
>@@ -1089,6 +1160,7 @@
>  *    REQUEST_NO_BODY          Send 413 error if message has any body
>  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
>  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
>+ *    REQUEST_CHUNKED_PASS     If chunked, pass the chunk headers with body.
>  *
>  *    In order to use the last two options, the caller MUST provide a buffer
>  *    large enough to hold a chunk-size line, including any extensions.
>
>Modified: httpd/httpd/trunk/modules/http/http_protocol.c
>URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_protocol.c?rev=208787&r1=208786&r2=208787&view=diff
>==============================================================================
>--- httpd/httpd/trunk/modules/http/http_protocol.c (original)
>+++ httpd/httpd/trunk/modules/http/http_protocol.c Fri Jul  1 12:59:59 2005
>@@ -754,6 +754,9 @@
>     apr_int64_t mask;
>     apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
>     apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry);
>+    /* For TRACE below */
>+    core_server_config *conf =
>+        ap_get_module_config(r->server->module_config, &core_module);
> 
>     mask = r->allowed_methods->method_mask;
> 
>@@ -771,8 +774,9 @@
>         }
>     }
> 
>-    /* TRACE is always allowed */
>-    *(const char **)apr_array_push(allow) = "TRACE";
>+    /* TRACE is tested on a per-server basis */
>+    if (conf->trace_enable != AP_TRACE_DISABLE)
>+        *(const char **)apr_array_push(allow) = "TRACE";
> 
>     list = apr_array_pstrcat(r->pool, allow, ',');
> 
>
>Modified: httpd/httpd/trunk/modules/proxy/mod_proxy.c
>URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/proxy/mod_proxy.c?rev=208787&r1=208786&r2=208787&view=diff
>==============================================================================
>--- httpd/httpd/trunk/modules/proxy/mod_proxy.c (original)
>+++ httpd/httpd/trunk/modules/proxy/mod_proxy.c Fri Jul  1 12:59:59 2005
>@@ -541,7 +541,23 @@
>         if (maxfwd < 1) {
>             switch (r->method_number) {
>             case M_TRACE: {
>+                core_server_config *coreconf = (core_server_config *)
>+                                    ap_get_module_config(sconf, &core_module);
>                 int access_status;
>+
>+                if (coreconf->trace_enable == AP_TRACE_DISABLE)
>+                    return ap_proxyerror(r, HTTP_NOT_IMPLEMENTED,
>+                                         "TRACE denied by server configuration");
>+
>+                /* Can't test ap_should_client_block, we aren't ready to send
>+                 * the client a 100 Continue response till the connection has
>+                 * been established
>+                 */
>+                if (coreconf->trace_enable != AP_TRACE_EXTENDED 
>+                    && (r->read_length || (!r->read_chunked && (r->remaining <= 0))))
>+                    return ap_proxyerror(r, HTTP_REQUEST_ENTITY_TOO_LARGE,
>+                                         "TRACE with request body is not allowed");
>+
>                 r->proxyreq = PROXYREQ_NONE;
>                 if ((access_status = ap_send_http_trace(r)))
>                     ap_die(access_status, r);



Re: svn commit: r208787 - in /httpd/httpd/trunk/modules: http/http_filters.c http/http_protocol.c proxy/mod_proxy.c

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
Before I left for holiday, this was queued against the wrong
sender account :(  Anyways I'll fix early tomorrow.

----------------

This is a bit off in http_proxy, and I'm out of time to fix
right now.  It's nestled in the hop count elimination, but if
we had no hard max hops, then we miss this code.  It needs
to move a bit further south.

At 03:00 PM 7/1/2005, wrowe@apache.org wrote:
>Author: wrowe
>Date: Fri Jul  1 12:59:59 2005
>New Revision: 208787
>
>URL: http://svn.apache.org/viewcvs?rev=208787&view=rev
>Log:
>
>  Plug AllowTrace extended|on|off into proxy and http core.
>
>  It still is not 'correct' until REQUEST_CHUNKED_PASS is reimplemented
>  and passes some chunk headers, since we aren't echoing the entire
>  request.  But it gets me further on testing 1.3 -> 2.0 -> 2.1 -> 2.0 -> 1.3
>  proxy behaviors.
>
>Modified:
>    httpd/httpd/trunk/modules/http/http_filters.c
>    httpd/httpd/trunk/modules/http/http_protocol.c
>    httpd/httpd/trunk/modules/proxy/mod_proxy.c
>
>Modified: httpd/httpd/trunk/modules/http/http_filters.c
>URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_filters.c?rev=208787&r1=208786&r2=208787&view=diff
>==============================================================================
>--- httpd/httpd/trunk/modules/http/http_filters.c (original)
>+++ httpd/httpd/trunk/modules/http/http_filters.c Fri Jul  1 12:59:59 2005
>@@ -759,9 +759,16 @@
> 
> AP_DECLARE_NONSTD(int) ap_send_http_trace(request_rec *r)
> {
>+    core_server_config *conf;
>     int rv;
>-    apr_bucket_brigade *b;
>+    apr_bucket_brigade *bb;
>     header_struct h;
>+    apr_bucket *b;
>+    int body;
>+    char *bodyread, *bodyoff;
>+    apr_size_t bodylen = 0;
>+    apr_size_t bodybuf;
>+    long res;
> 
>     if (r->method_number != M_TRACE) {
>         return DECLINED;
>@@ -771,23 +778,87 @@
>     while (r->prev) {
>         r = r->prev;
>     }
>+    conf = (core_server_config *)ap_get_module_config(r->server->module_config,
>+                                                      &core_module);
> 
>-    if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY))) {
>+    if (conf->trace_enable == AP_TRACE_DISABLE) {
>+       apr_table_setn(r->notes, "error-notes",
>+                      "TRACE denied by server configuration");
>+        return HTTP_FORBIDDEN;
>+    }
>+
>+    if (conf->trace_enable == AP_TRACE_EXTENDED)
>+        /* XX should be = REQUEST_CHUNKED_PASS */
>+        body = REQUEST_CHUNKED_DECHUNK;
>+    else
>+        body = REQUEST_NO_BODY;
>+
>+    if ((rv = ap_setup_client_block(r, body))) {
>+        if (rv == HTTP_REQUEST_ENTITY_TOO_LARGE)
>+           apr_table_setn(r->notes, "error-notes",
>+                          "TRACE with a request body is not allowed");
>         return rv;
>     }
> 
>+    if (ap_should_client_block(r)) {
>+
>+        if (r->remaining > 0) {
>+            if (r->remaining > 65536) {
>+               apr_table_setn(r->notes, "error-notes",
>+                       "Extended TRACE request bodies cannot exceed 64k\n");
>+                return HTTP_REQUEST_ENTITY_TOO_LARGE;
>+            }
>+            /* always 32 extra bytes to catch chunk header exceptions */
>+            bodybuf = (apr_size_t)r->remaining + 32;
>+        }
>+        else {
>+            /* Add an extra 8192 for chunk headers */
>+            bodybuf = 73730;
>+        }
>+
>+        bodyoff = bodyread = apr_palloc(r->pool, bodybuf);
>+
>+        /* only while we have enough for a chunked header */
>+        while ((!bodylen || bodybuf >= 32) &&
>+               (res = ap_get_client_block(r, bodyoff, bodybuf)) > 0) {
>+            bodylen += res;
>+            bodybuf -= res;
>+            bodyoff += res;
>+        }
>+        if (res > 0 && bodybuf < 32) {
>+            /* discard_rest_of_request_body into our buffer */
>+            while (ap_get_client_block(r, bodyread, bodylen) > 0)
>+                ;
>+           apr_table_setn(r->notes, "error-notes",
>+                   "Extended TRACE request bodies cannot exceed 64k\n");
>+            return HTTP_REQUEST_ENTITY_TOO_LARGE;
>+        }
>+
>+        if (res < 0) {
>+            return HTTP_BAD_REQUEST;
>+        }
>+    }
>+
>     ap_set_content_type(r, "message/http");
> 
>     /* Now we recreate the request, and echo it back */
> 
>-    b = apr_brigade_create(r->pool, r->connection->bucket_alloc);
>-    apr_brigade_putstrs(b, NULL, NULL, r->the_request, CRLF, NULL);
>+    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
>+    apr_brigade_putstrs(bb, NULL, NULL, r->the_request, CRLF, NULL);
>     h.pool = r->pool;
>-    h.bb = b;
>+    h.bb = bb;
>     apr_table_do((int (*) (void *, const char *, const char *))
>                  form_header_field, (void *) &h, r->headers_in, NULL);
>-    apr_brigade_puts(b, NULL, NULL, CRLF);
>-    ap_pass_brigade(r->output_filters, b);
>+    apr_brigade_puts(bb, NULL, NULL, CRLF);
>+
>+    /* If configured to accept a body, echo the body */
>+    if (bodylen) {
>+        b = apr_bucket_pool_create(bodyread, bodylen, 
>+                                   r->pool, bb->bucket_alloc);
>+        APR_BRIGADE_INSERT_TAIL(bb, b);
>+    }
>+    
>+    ap_pass_brigade(r->output_filters,  bb);
> 
>     return DONE;
> }
>@@ -1089,6 +1160,7 @@
>  *    REQUEST_NO_BODY          Send 413 error if message has any body
>  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
>  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
>+ *    REQUEST_CHUNKED_PASS     If chunked, pass the chunk headers with body.
>  *
>  *    In order to use the last two options, the caller MUST provide a buffer
>  *    large enough to hold a chunk-size line, including any extensions.
>
>Modified: httpd/httpd/trunk/modules/http/http_protocol.c
>URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/http/http_protocol.c?rev=208787&r1=208786&r2=208787&view=diff
>==============================================================================
>--- httpd/httpd/trunk/modules/http/http_protocol.c (original)
>+++ httpd/httpd/trunk/modules/http/http_protocol.c Fri Jul  1 12:59:59 2005
>@@ -754,6 +754,9 @@
>     apr_int64_t mask;
>     apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
>     apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry);
>+    /* For TRACE below */
>+    core_server_config *conf =
>+        ap_get_module_config(r->server->module_config, &core_module);
> 
>     mask = r->allowed_methods->method_mask;
> 
>@@ -771,8 +774,9 @@
>         }
>     }
> 
>-    /* TRACE is always allowed */
>-    *(const char **)apr_array_push(allow) = "TRACE";
>+    /* TRACE is tested on a per-server basis */
>+    if (conf->trace_enable != AP_TRACE_DISABLE)
>+        *(const char **)apr_array_push(allow) = "TRACE";
> 
>     list = apr_array_pstrcat(r->pool, allow, ',');
> 
>
>Modified: httpd/httpd/trunk/modules/proxy/mod_proxy.c
>URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/proxy/mod_proxy.c?rev=208787&r1=208786&r2=208787&view=diff
>==============================================================================
>--- httpd/httpd/trunk/modules/proxy/mod_proxy.c (original)
>+++ httpd/httpd/trunk/modules/proxy/mod_proxy.c Fri Jul  1 12:59:59 2005
>@@ -541,7 +541,23 @@
>         if (maxfwd < 1) {
>             switch (r->method_number) {
>             case M_TRACE: {
>+                core_server_config *coreconf = (core_server_config *)
>+                                    ap_get_module_config(sconf, &core_module);
>                 int access_status;
>+
>+                if (coreconf->trace_enable == AP_TRACE_DISABLE)
>+                    return ap_proxyerror(r, HTTP_NOT_IMPLEMENTED,
>+                                         "TRACE denied by server configuration");
>+
>+                /* Can't test ap_should_client_block, we aren't ready to send
>+                 * the client a 100 Continue response till the connection has
>+                 * been established
>+                 */
>+                if (coreconf->trace_enable != AP_TRACE_EXTENDED 
>+                    && (r->read_length || (!r->read_chunked && (r->remaining <= 0))))
>+                    return ap_proxyerror(r, HTTP_REQUEST_ENTITY_TOO_LARGE,
>+                                         "TRACE with request body is not allowed");
>+
>                 r->proxyreq = PROXYREQ_NONE;
>                 if ((access_status = ap_send_http_trace(r)))
>                     ap_die(access_status, r);