[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