[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-cvs
Subject:    svn commit: r1869223 - in /httpd/httpd/trunk: include/http_protocol.h modules/proxy/mod_proxy_http.c
From:       ylavic () apache ! org
Date:       2019-10-31 16:10:08
Message-ID: 20191031161008.A4D2C17A0FA () svn01-us-east ! apache ! org
[Download RAW message or body]

Author: ylavic
Date: Thu Oct 31 16:10:08 2019
New Revision: 1869223

URL: http://svn.apache.org/viewvc?rev=1869223&view=rev
Log:
Revert r1869222, wrong files committed.

Modified:
    httpd/httpd/trunk/include/http_protocol.h
    httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c
    httpd/httpd/trunk/server/protocol.c

Modified: httpd/httpd/trunk/include/http_protocol.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/http_protocol.h?rev=1869223&r1=1869222&r2=1869223&view=diff
 ==============================================================================
--- httpd/httpd/trunk/include/http_protocol.h (original)
+++ httpd/httpd/trunk/include/http_protocol.h Thu Oct 31 16:10:08 2019
@@ -82,30 +82,6 @@ AP_DECLARE(void) ap_get_mime_headers(req
 AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r,
                                           apr_bucket_brigade *bb);
 
-/**
- * @struct ap_mime_headers_ctx
- * @brief  Context for ap_get_mime_headers_ex()
- */
-typedef struct ap_mime_headers_ctx ap_mime_headers_ctx_t;
-struct ap_mime_headers_ctx {
-    int limit_req_fields;
-    int limit_req_fieldsize;
-    apr_table_t *headers;
-    apr_table_t *notes;
-    apr_bucket_brigade *bb;
-    unsigned int strict:1,
-                 compress:1;
-};
-
-/**
- * Generic version of ap_get_mime_headers_core() that takes a filter as
- * parameter and options regarding limits to apply.
- * @param f The filter to read from
- * @param ctx The context/options (@see ap_mime_headers_ctx)
- */
-AP_DECLARE(int) ap_get_mime_headers_ex(request_rec *r, ap_filter_t *f,
-                                       ap_mime_headers_ctx_t *ctx);
-
 /* Finish up stuff after a request */
 
 /**

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_http.c?rev=1869223&r1=1869222&r2=1869223&view=diff
 ==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_http.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_http.c Thu Oct 31 16:10:08 2019
@@ -303,18 +303,16 @@ static int stream_reqbody_read(proxy_htt
     return OK;
 }
 
-static int stream_reqbody(proxy_http_req_t *req)
+static int stream_reqbody(proxy_http_req_t *req, rb_methods rb_method)
 {
     request_rec *r = req->r;
     int seen_eos = 0, rv = OK;
     apr_size_t hdr_len;
     char chunk_hdr[20];  /* must be here due to transient bucket. */
-    conn_rec *origin = req->origin;
     proxy_conn_rec *p_conn = req->backend;
     apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
     apr_bucket_brigade *header_brigade = req->header_brigade;
     apr_bucket_brigade *input_brigade = req->input_brigade;
-    rb_methods rb_method = req->rb_method;
     apr_off_t bytes, bytes_streamed = 0;
     apr_bucket *e;
 
@@ -328,7 +326,7 @@ static int stream_reqbody(proxy_http_req
         }
 
         if (!APR_BRIGADE_EMPTY(input_brigade)) {
-            /* If this brigade contains EOS, remove it and be done. */
+            /* If this brigade contains EOS, either stop or remove it. */
             if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
                 seen_eos = 1;
 
@@ -370,8 +368,7 @@ static int stream_reqbody(proxy_http_req
                     APR_BRIGADE_INSERT_TAIL(input_brigade, e);
                 }
             }
-            else if (rb_method == RB_STREAM_CL
-                     && bytes_streamed > req->cl_val) {
+            else if (bytes_streamed > req->cl_val) {
                 /* C-L < bytes streamed?!?
                  * We will error out after the body is completely
                  * consumed, but we can't stream more bytes at the
@@ -403,7 +400,7 @@ static int stream_reqbody(proxy_http_req
         APR_BRIGADE_PREPEND(input_brigade, header_brigade);
 
         /* Flush here on EOS because we won't stream_reqbody_read() again */
-        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin,
+        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, req->origin,
                                    input_brigade, seen_eos);
         if (rv != OK) {
             return rv;
@@ -465,6 +462,10 @@ static int spool_reqbody_cl(proxy_http_r
         /* If this brigade contains EOS, either stop or remove it. */
         if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
             seen_eos = 1;
+
+            /* We can't pass this EOS to the output_filters. */
+            e = APR_BRIGADE_LAST(input_brigade);
+            apr_bucket_delete(e);
         }
 
         apr_brigade_length(input_brigade, 1, &bytes);
@@ -858,19 +859,33 @@ static int ap_proxy_http_request(proxy_h
 {
     int rv;
     request_rec *r = req->r;
+    apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
+    apr_bucket_brigade *header_brigade = req->header_brigade;
+    apr_bucket_brigade *input_brigade = req->input_brigade;
 
     /* send the request header/body, if any. */
     switch (req->rb_method) {
-    case RB_SPOOL_CL:
     case RB_STREAM_CL:
     case RB_STREAM_CHUNKED:
         if (req->do_100_continue) {
-            rv = ap_proxy_pass_brigade(req->bucket_alloc, r, req->backend,
-                                       req->origin, req->header_brigade, 1);
+            rv = ap_proxy_pass_brigade(bucket_alloc, r, req->backend,
+                                       req->origin, header_brigade, 1);
         }
         else {
-            rv = stream_reqbody(req);
+            rv = stream_reqbody(req, req->rb_method);
+        }
+        break;
+
+    case RB_SPOOL_CL:
+        /* Prefetch has built the header and spooled the whole body;
+         * if we don't expect 100-continue we can flush both all at once,
+         * otherwise flush the header only.
+         */
+        if (!req->do_100_continue) {
+            APR_BRIGADE_CONCAT(header_brigade, input_brigade);
         }
+        rv = ap_proxy_pass_brigade(bucket_alloc, r, req->backend,
+                                   req->origin, header_brigade, 1);
         break;
 
     default:
@@ -1575,10 +1590,15 @@ int ap_proxy_http_process_response(proxy
 
                 /* Send the request body (fully). */
                 switch(req->rb_method) {
-                case RB_SPOOL_CL:
                 case RB_STREAM_CL:
                 case RB_STREAM_CHUNKED:
-                    status = stream_reqbody(req);
+                    status = stream_reqbody(req, req->rb_method);
+                    break;
+                case RB_SPOOL_CL:
+                    /* Prefetch has spooled the whole body, flush it. */
+                    status = ap_proxy_pass_brigade(req->bucket_alloc, r,
+                                                   backend, origin,
+                                                   req->input_brigade, 1);
                     break;
                 default:
                     /* Shouldn't happen */

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c?rev=1869223&r1=1869222&r2=1869223&view=diff
 ==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c Thu Oct 31 16:10:08 2019
@@ -294,223 +294,6 @@ static int proxy_wstunnel_canon(request_
     return OK;
 }
 
-static request_rec *make_resp(conn_rec *c, request_rec *r)
-{
-    apr_pool_t *pool;
-    request_rec *rp;
-
-    apr_pool_create(&pool, c->pool);
-
-    rp = apr_pcalloc(pool, sizeof(*r));
-
-    rp->pool            = pool;
-    rp->status          = HTTP_OK;
-
-    rp->headers_in      = apr_table_make(pool, 50);
-    rp->trailers_in     = apr_table_make(pool, 5);
-
-    rp->subprocess_env  = apr_table_make(pool, 50);
-    rp->headers_out     = apr_table_make(pool, 12);
-    rp->trailers_out    = apr_table_make(pool, 5);
-    rp->err_headers_out = apr_table_make(pool, 5);
-    rp->notes           = apr_table_make(pool, 5);
-
-    rp->server = r->server;
-    rp->log = r->log;
-    rp->proxyreq = r->proxyreq;
-    rp->request_time = r->request_time;
-    rp->connection      = c;
-    rp->output_filters  = c->output_filters;
-    rp->input_filters   = c->input_filters;
-    rp->proto_output_filters  = c->output_filters;
-    rp->proto_input_filters   = c->input_filters;
-    rp->useragent_ip = c->client_ip;
-    rp->useragent_addr = c->client_addr;
-
-    rp->request_config  = ap_create_request_config(pool);
-
-    return rp;
-}
-
-static int proxy_wstunnel_handle_http_response(request_rec *r,
-                                               proxy_conn_rec *backend,
-                                               proxy_server_conf *sconf,
-                                               apr_bucket_brigade *bb)
-{
-    conn_rec *origin = backend->connection;
-    proxy_worker *worker = backend->worker;
-    char fixed_buffer[HUGE_STRING_LEN];
-    char *buffer = fixed_buffer;
-    int size = HUGE_STRING_LEN;
-    ap_mime_headers_ctx_t ctx;
-    request_rec *resp;
-    apr_status_t rv;
-    apr_size_t len;
-    int rc;
-
-    /* Only use dynamically sized buffer if user specifies ResponseFieldSize */
-    if (worker->s->response_field_size_set) {
-        size = worker->s->response_field_size;
-        if (size > HUGE_STRING_LEN) {
-            buffer = apr_palloc(r->pool, size);
-        }
-    }
-
-    resp = make_resp(origin, r);
-
-    rv = ap_rgetline(&buffer, size, &len, resp, 0, bb);
-    apr_brigade_cleanup(bb);
-
-    if (rv != APR_SUCCESS || !apr_date_checkmask(buffer, "HTTP/#.# ### *")) {
-        return HTTP_BAD_GATEWAY;
-    }
-
-    r->status = atoi(&buffer[9]);
-    if (!ap_is_HTTP_VALID_RESPONSE(r->status)) {
-        return HTTP_BAD_GATEWAY;
-    }
-    r->status_line = apr_pstrdup(r->pool, &buffer[9]);
-
-    memset(&ctx, 0, sizeof(ctx));
-    ctx.bb = bb;
-    ctx.headers = r->headers_out;
-    ctx.limit_req_fieldsize = size;
-    rc = ap_get_mime_headers_ex(r, origin->input_filters, &ctx);
-    apr_brigade_cleanup(bb);
-    if (rc != OK) {
-        r->status = HTTP_OK;
-        r->status_line = NULL;
-        apr_table_clear(r->headers_out);
-        return rc;
-    }
-
-#if 0
-    if (r->status != HTTP_SWITCHING_PROTOCOLS) {
-        conn_rec *c = r->connection;
-        apr_read_type_e block = APR_NONBLOCK_READ;
-        apr_bucket_brigade *pass_bb = apr_brigade_create(r->pool,
-                                                         c->bucket_alloc);
-        int finish = 0;
-
-        r->sent_bodyct = 1;
-        do {
-            apr_bucket *e;
-            apr_off_t readbytes = 0;
-
-            rv = ap_get_brigade(origin->input_filters, bb,
-                                AP_MODE_READBYTES, block,
-                                sconf->io_buffer_size);
-
-            /* ap_get_brigade will return success with an empty brigade
-             * for a non-blocking read which would block: */
-            if (block == APR_NONBLOCK_READ
-                    && (APR_STATUS_IS_EAGAIN(rv)
-                        || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)))) {
-                /* flush to the client and switch to blocking mode */
-                e = apr_bucket_flush_create(c->bucket_alloc);
-                APR_BRIGADE_INSERT_TAIL(bb, e);
-                if (ap_pass_brigade(r->output_filters, bb)
-                        || c->aborted) {
-                    finish = 1;
-                    rc = DONE;
-                }
-                apr_brigade_cleanup(bb);
-                block = APR_BLOCK_READ;
-                continue;
-            }
-            if (rv == APR_EOF) {
-                break;
-            }
-            if (rv != APR_SUCCESS) {
-                if (rv == APR_ENOSPC) {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02475)
-                                  "Response chunk/line was too large to parse");
-                }
-                else if (rv == APR_ENOTIMPL) {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02476)
-                                  "Response Transfer-Encoding was not recognised");
-                }
-                else {
-                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01110)
-                                  "Network error reading response");
-                }
-
-                /* In this case, we are in real trouble because
-                 * our backend bailed on us. Given we're half way
-                 * through a response, our only option is to
-                 * disconnect the client too.
-                 */
-                e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL,
-                                           r->pool, c->bucket_alloc);
-                APR_BRIGADE_INSERT_TAIL(bb, e);
-                e = ap_bucket_eoc_create(c->bucket_alloc);
-                APR_BRIGADE_INSERT_TAIL(bb, e);
-                ap_pass_brigade(r->output_filters, bb);
-                apr_brigade_cleanup(bb);
-                rc = DONE;
-                break;
-            }
-
-            /* next time try a non-blocking read */
-            block = APR_NONBLOCK_READ;
-
-            if (!apr_is_empty_table(resp->trailers_in)) {
-                apr_table_do(add_trailers, r->trailers_out,
-                             resp->trailers_in, NULL);
-                apr_table_clear(resp->trailers_in);
-            }
-
-            apr_brigade_length(bb, 0, &readbytes);
-            backend->worker->s->read += readbytes;
-
-            /* sanity check */
-            if (APR_BRIGADE_EMPTY(bb)) {
-                break;
-            }
-
-            /* Switch the allocator lifetime of the buckets */
-            ap_proxy_buckets_lifetime_transform(r, bb, pass_bb);
-
-            /* found the last brigade? */
-            if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pass_bb))) {
-                /* the brigade may contain transient buckets that contain
-                 * data that lives only as long as the backend connection.
-                 * Force a setaside so these transient buckets become heap
-                 * buckets that live as long as the request.
-                 */
-                for (e = APR_BRIGADE_FIRST(pass_bb);
-                        e != APR_BRIGADE_SENTINEL(pass_bb);
-                        e = APR_BUCKET_NEXT(e)) {
-                    apr_bucket_setaside(e, r->pool);
-                }
-                /* finally it is safe to clean up the brigade from the
-                 * connection pool, as we have forced a setaside on all
-                 * buckets.
-                 */
-                apr_brigade_cleanup(bb);
-                finish = 1;
-            }
-
-            /* try send what we read */
-            if (ap_pass_brigade(r->output_filters, pass_bb) != APR_SUCCESS
-                    || c->aborted) {
-                /* Ack! Phbtt! Die! User aborted! */
-                finish = 1;
-                rc = DONE;
-            }
-
-            /* make sure we always clean up after ourselves */
-            apr_brigade_cleanup(pass_bb);
-            apr_brigade_cleanup(bb);
-        } while (!finish);
-
-        return rc;
-    }
-#endif
-
-    return DECLINED;
-}
-
 /*
  * process the request and write the response.
  */
@@ -535,13 +318,14 @@ static int proxy_wstunnel_request(apr_po
     apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);
     apr_socket_t *client_socket = ap_get_conn_socket(c);
     ws_baton_t *baton = apr_pcalloc(r->pool, sizeof(ws_baton_t));
+    int status;
     proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config, \
                &proxy_wstunnel_module);
     const char *upgrade_method = *worker->s->upgrade ? worker->s->upgrade : \
                "WebSocket";
-    int status;
+
+    header_brigade = apr_brigade_create(p, backconn->bucket_alloc);
 
     ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "sending request");
 
-    header_brigade = apr_brigade_create(p, backconn->bucket_alloc);
     rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, conn,
                                  worker, conf, uri, url, server_portstr,
                                  &old_cl_val, &old_te_val);
@@ -550,19 +334,13 @@ static int proxy_wstunnel_request(apr_po
     }
 
     if (ap_cstr_casecmp(upgrade_method, "NONE") == 0) {
-        buf = apr_pstrdup(p, "Upgrade: WebSocket" CRLF
-                             "Connection: Upgrade" CRLF
-                             CRLF);
+        buf = apr_pstrdup(p, "Upgrade: WebSocket" CRLF "Connection: Upgrade" CRLF \
CRLF);  } else if (ap_cstr_casecmp(upgrade_method, "ANY") == 0) {
         const char *upgrade;
         upgrade = apr_table_get(r->headers_in, "Upgrade");
-        buf = apr_pstrcat(p, "Upgrade: ", upgrade, CRLF
-                             "Connection: Upgrade" CRLF
-                             CRLF, NULL);
+        buf = apr_pstrcat(p, "Upgrade: ", upgrade, CRLF "Connection: Upgrade" CRLF \
CRLF, NULL);  } else {
-        buf = apr_pstrcat(p, "Upgrade: ", upgrade_method, CRLF
-                             "Connection: Upgrade" CRLF
-                             CRLF, NULL);
+        buf = apr_pstrcat(p, "Upgrade: ", upgrade_method, CRLF "Connection: Upgrade" \
CRLF CRLF, NULL);  }
     ap_xlate_proto_to_ascii(buf, strlen(buf));
     e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
@@ -572,9 +350,7 @@ static int proxy_wstunnel_request(apr_po
                                     header_brigade, 1)) != OK)
         return rv;
 
-    if ((rv = proxy_wstunnel_handle_http_response(r, conn, conf,
-                                                  header_brigade)) != DECLINED)
-        return rv;
+    apr_brigade_cleanup(header_brigade);
 
     ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "setting up poll()");
 
@@ -690,7 +466,7 @@ static int proxy_wstunnel_handler(reques
     char *locurl = url;
     apr_uri_t *uri;
     int is_ssl = 0;
-    const char *upgrade_method;
+    const char *upgrade_method = *worker->s->upgrade ? worker->s->upgrade : \
"WebSocket";  
     if (ap_cstr_casecmpn(url, "wss:", 4) == 0) {
         scheme = "WSS";
@@ -704,7 +480,6 @@ static int proxy_wstunnel_handler(reques
         return DECLINED;
     }
 
-    upgrade_method = *worker->s->upgrade ? worker->s->upgrade : "WebSocket";
     if (ap_cstr_casecmp(upgrade_method, "NONE") != 0) {
         const char *upgrade;
         upgrade = apr_table_get(r->headers_in, "Upgrade");

Modified: httpd/httpd/trunk/server/protocol.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/protocol.c?rev=1869223&r1=1869222&r2=1869223&view=diff
 ==============================================================================
--- httpd/httpd/trunk/server/protocol.c (original)
+++ httpd/httpd/trunk/server/protocol.c Thu Oct 31 16:10:08 2019
@@ -554,7 +554,22 @@ AP_DECLARE(apr_status_t) ap_rgetline(cha
                                      apr_size_t *read, request_rec *r,
                                      int flags, apr_bucket_brigade *bb)
 {
-    return ap_fgetline(s, n, read, r->proto_input_filters, flags, bb, r->pool);
+    apr_status_t rv;
+
+    rv = ap_fgetline_core(s, n, read, r->proto_input_filters, flags,
+                          bb, r->pool);
+#if APR_CHARSET_EBCDIC
+    /* On EBCDIC boxes, each complete http protocol input line needs to be
+     * translated into the code page used by the compiler.  Since
+     * ap_fgetline_core uses recursion, we do the translation in a wrapper
+     * function to ensure that each input character gets translated only once.
+     */
+    if (*read) {
+        ap_xlate_proto_from_ascii(*s, *read);
+    }
+#endif
+
+    return rv;
 }
 
 AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int flags)
@@ -989,30 +1004,23 @@ rrl_failed:
     return 0;
 }
 
-struct table_do_fn_check_lengths_baton {
-    request_rec *r;
-    ap_mime_headers_ctx_t *ctx;
-};
-static int table_do_fn_check_lengths(void *arg, const char *key,
+static int table_do_fn_check_lengths(void *r_, const char *key,
                                      const char *value)
 {
-    struct table_do_fn_check_lengths_baton *baton = arg;
-
-    if (value == NULL || baton->ctx->limit_req_fieldsize >= strlen(value))
+    request_rec *r = r_;
+    if (value == NULL || r->server->limit_req_fieldsize >= strlen(value) )
         return 1;
 
-    if (baton->ctx->notes) {
-        apr_table_setn(baton->ctx->notes, "error-notes",
-                       "Size of a header field exceeds limit.");
-    }
-    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, baton->r, APLOGNO(00560)
-                  "Header exceeds size limit after merging: %.*s",
+    r->status = HTTP_BAD_REQUEST;
+    apr_table_setn(r->notes, "error-notes",
+                   "Size of a request header field exceeds server limit.");
+    ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00560) "Request "
+                  "header exceeds LimitRequestFieldSize after merging: %.*s",
                   field_name_len(key), key);
     return 0;
 }
 
-AP_DECLARE(int) ap_get_mime_headers_ex(request_rec *r, ap_filter_t *f,
-                                       ap_mime_headers_ctx_t *ctx)
+AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb)
 {
     char *last_field = NULL;
     apr_size_t last_len = 0;
@@ -1022,53 +1030,44 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
     apr_size_t len;
     int fields_read = 0;
     char *tmp_field;
-    apr_bucket_brigade *bb = ctx->bb;
-    int rc = OK;
-
-    if (bb == NULL) {
-        bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
-    }
-    if (ctx->headers == NULL) {
-        ctx->headers = apr_table_make(r->pool, 25);
-    }
-    if (ctx->limit_req_fieldsize <= 0) {
-        ctx->limit_req_fieldsize = HUGE_STRING_LEN;
-    }
+    core_server_config *conf = ap_get_core_module_config(r->server->module_config);
+    int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
 
     /*
      * Read header lines until we get the empty separator line, a read error,
-     * the connection closes (EOF), reach the size limit(s), or we timeout.
+     * the connection closes (EOF), reach the server limit, or we timeout.
      */
     while(1) {
         apr_status_t rv;
 
         field = NULL;
-        rv = ap_fgetline(&field, ctx->limit_req_fieldsize + 2, &len, f,
-                         ctx->strict ? AP_GETLINE_CRLF : 0, bb, r->pool);
+        rv = ap_rgetline(&field, r->server->limit_req_fieldsize + 2,
+                         &len, r, strict ? AP_GETLINE_CRLF : 0, bb);
 
         if (rv != APR_SUCCESS) {
+            if (APR_STATUS_IS_TIMEUP(rv)) {
+                r->status = HTTP_REQUEST_TIME_OUT;
+            }
+            else {
+                r->status = HTTP_BAD_REQUEST;
+            }
+
             /* ap_rgetline returns APR_ENOSPC if it fills up the buffer before
              * finding the end-of-line.  This is only going to happen if it
              * exceeds the configured limit for a field size.
              */
             if (rv == APR_ENOSPC) {
-                if (ctx->notes) {
-                    apr_table_setn(ctx->notes, "error-notes",
-                                   "Size of a header field exceeds limit.");
-                }
+                apr_table_setn(r->notes, "error-notes",
+                               "Size of a request header field "
+                               "exceeds server limit.");
                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00561)
-                              "Header exceeds size limit%s%.*s",
+                              "Request header exceeds LimitRequestFieldSize%s"
+                              "%.*s",
                               (field && *field) ? ": " : "",
                               (field) ? field_name_len(field) : 0,
                               (field) ? field : "");
             }
-            if (APR_STATUS_IS_TIMEUP(rv)) {
-                rc = HTTP_REQUEST_TIME_OUT;
-            }
-            else {
-                rc = HTTP_BAD_REQUEST;
-            }
-            goto cleanup;
+            return;
         }
 
         /* For all header values, and all obs-fold lines, the presence of
@@ -1088,18 +1087,18 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
             apr_size_t fold_len;
 
             if (last_field == NULL) {
+                r->status = HTTP_BAD_REQUEST;
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03442)
                               "Line folding encountered before first"
                               " header line");
-                rc = HTTP_BAD_REQUEST;
-                goto cleanup;
+                return;
             }
 
             if (field[1] == '\0') {
+                r->status = HTTP_BAD_REQUEST;
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03443)
                               "Empty folded line encountered");
-                rc = HTTP_BAD_REQUEST;
-                goto cleanup;
+                return;
             }
 
             /* Leading whitespace on an obs-fold line can be
@@ -1116,19 +1115,19 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
              */
             fold_len = last_len + len + 1; /* trailing null */
 
-            if (fold_len >= (apr_size_t)ctx->limit_req_fieldsize) {
-                if (ctx->notes) {
-                    /* report what we have accumulated so far before the
-                     * overflow (last_field) as the field with the problem
-                     */
-                    apr_table_setn(ctx->notes, "error-notes",
-                                   "Size of a header field exceeds limit.");
-                }
+            if (fold_len >= (apr_size_t)(r->server->limit_req_fieldsize)) {
+                r->status = HTTP_BAD_REQUEST;
+                /* report what we have accumulated so far before the
+                 * overflow (last_field) as the field with the problem
+                 */
+                apr_table_setn(r->notes, "error-notes",
+                               "Size of a request header field "
+                               "exceeds server limit.");
                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00562)
-                              "Header exceeds size limit after folding: %.*s",
+                              "Request header exceeds LimitRequestFieldSize "
+                              "after folding: %.*s",
                               field_name_len(last_field), last_field);
-                rc = HTTP_BAD_REQUEST;
-                goto cleanup;
+                return;
             }
 
             if (fold_len > alloc_len) {
@@ -1158,47 +1157,46 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
              * most recently read input line).
              */
 
-            if (ctx->limit_req_fields
-                    && (++fields_read > ctx->limit_req_fields)) {
-                if (ctx->notes) {
-                    apr_table_setn(ctx->notes, "error-notes",
-                                   "The number of header fields "
-                                   "exceeds the limit.");
-                }
+            if (r->server->limit_req_fields
+                    && (++fields_read > r->server->limit_req_fields)) {
+                r->status = HTTP_BAD_REQUEST;
+                apr_table_setn(r->notes, "error-notes",
+                               "The number of request header fields "
+                               "exceeds this server's limit.");
                 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00563)
-                              "Number of headers exceeds the limit");
-                rc = HTTP_BAD_REQUEST;
-                goto cleanup;
+                              "Number of request headers exceeds "
+                              "LimitRequestFields");
+                return;
             }
 
-            if (!ctx->strict)
+            if (!strict)
             {
                 /* Not Strict ('Unsafe' mode), using the legacy parser */
 
                 if (!(value = strchr(last_field, ':'))) { /* Find ':' or */
+                    r->status = HTTP_BAD_REQUEST;   /* abort bad request */
                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00564)
-                                  "Header field is missing ':' "
+                                  "Request header field is missing ':' "
                                   "separator: %.*s", (int)LOG_NAME_MAX_LEN,
                                   last_field);
-                    rc = HTTP_BAD_REQUEST;
-                    goto cleanup;
+                    return;
                 }
 
                 if (value == last_field) {
+                    r->status = HTTP_BAD_REQUEST;
                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03453)
-                                  "Header field name was empty");
-                    rc = HTTP_BAD_REQUEST;
-                    goto cleanup;
+                                  "Request header field name was empty");
+                    return;
                 }
 
                 *value++ = '\0'; /* NUL-terminate at colon */
 
                 if (strpbrk(last_field, "\t\n\v\f\r ")) {
+                    r->status = HTTP_BAD_REQUEST;
                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03452)
-                                  "Header field name presented"
+                                  "Request header field name presented"
                                   " invalid whitespace");
-                    rc = HTTP_BAD_REQUEST;
-                    goto cleanup;
+                    return;
                 }
 
                 while (*value == ' ' || *value == '\t') {
@@ -1206,11 +1204,11 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
                 }
 
                 if (strpbrk(value, "\n\v\f\r")) {
+                    r->status = HTTP_BAD_REQUEST;
                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(03451)
-                                  "Header field value presented"
+                                  "Request header field value presented"
                                   " bad whitespace");
-                    rc = HTTP_BAD_REQUEST;
-                    goto cleanup;
+                    return;
                 }
             }
             else /* Using strict RFC7230 parsing */
@@ -1218,11 +1216,11 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
                 /* Ensure valid token chars before ':' per RFC 7230 3.2.4 */
                 value = (char *)ap_scan_http_token(last_field);
                 if ((value == last_field) || *value != ':') {
+                    r->status = HTTP_BAD_REQUEST;
                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02426)
                                   "Request header field name is malformed: "
                                   "%.*s", (int)LOG_NAME_MAX_LEN, last_field);
-                    rc = HTTP_BAD_REQUEST;
-                    goto cleanup;
+                    return;
                 }
 
                 *value++ = '\0'; /* NUL-terminate last_field name at ':' */
@@ -1240,15 +1238,15 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
                  * for specific header handler logic later in the cycle
                  */
                 if (*tmp_field != '\0') {
+                    r->status = HTTP_BAD_REQUEST;
                     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02427)
                                   "Request header value is malformed: "
                                   "%.*s", (int)LOG_NAME_MAX_LEN, value);
-                    rc = HTTP_BAD_REQUEST;
-                    goto cleanup;
+                    return;
                 }
             }
 
-            apr_table_addn(ctx->headers, last_field, value);
+            apr_table_addn(r->headers_in, last_field, value);
 
             /* This last_field header is now stored in headers_in,
              * resume processing of the current input line.
@@ -1262,7 +1260,7 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
 
         /* Keep track of this new header line so that we can extend it across
          * any obs-fold or parse it on the next loop iteration. We referenced
-         * our previously allocated buffer in ctx->headers,
+         * our previously allocated buffer in r->headers_in,
          * so allocate a fresh buffer if required.
          */
         alloc_len = 0;
@@ -1273,51 +1271,18 @@ AP_DECLARE(int) ap_get_mime_headers_ex(r
     /* Combine multiple message-header fields with the same
      * field-name, following RFC 2616, 4.2.
      */
-    if (ctx->compress) {
-        apr_table_compress(ctx->headers, APR_OVERLAP_TABLES_MERGE);
-    }
-
-    /* Enforce limit for merged headers */
-    {
-        struct table_do_fn_check_lengths_baton baton = { r, ctx };
-        if (!apr_table_do(table_do_fn_check_lengths, &baton,
-                          ctx->headers, NULL)) {
-            rc = HTTP_BAD_REQUEST;
-            goto cleanup;
-        }
-    }
-
-cleanup:
-    if (bb != ctx->bb) {
-        apr_brigade_destroy(bb);
-    }
-    return rc;
-}
+    apr_table_compress(r->headers_in, APR_OVERLAP_TABLES_MERGE);
 
-AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb)
-{
-    core_server_config *conf = ap_get_core_module_config(r->server->module_config);
-    ap_mime_headers_ctx_t ctx;
-    int status;
-    
-    memset(&ctx, 0, sizeof(ctx));
-    ctx.strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
-    ctx.limit_req_fields = r->server->limit_req_fields;
-    ctx.limit_req_fieldsize = r->server->limit_req_fieldsize;
-    ctx.headers = r->headers_in;
-    ctx.notes = r->notes;
-    ctx.compress = 1;
-    ctx.bb = bb;
-
-    status = ap_get_mime_headers_ex(r, r->proto_input_filters, &ctx);
-    if (status != OK) {
-        r->status = status;
-    }
+    /* enforce LimitRequestFieldSize for merged headers */
+    apr_table_do(table_do_fn_check_lengths, r, r->headers_in, NULL);
 }
 
 AP_DECLARE(void) ap_get_mime_headers(request_rec *r)
 {
-    ap_get_mime_headers_core(r, NULL);
+    apr_bucket_brigade *tmp_bb;
+    tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+    ap_get_mime_headers_core(r, tmp_bb);
+    apr_brigade_destroy(tmp_bb);
 }
 
 AP_DECLARE(request_rec *) ap_create_request(conn_rec *conn)


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic