diff options
author | William A. Rowe Jr <wrowe@apache.org> | 2016-08-18 22:26:53 +0200 |
---|---|---|
committer | William A. Rowe Jr <wrowe@apache.org> | 2016-08-18 22:26:53 +0200 |
commit | dc0d9fa11e66dc80ead856b6902db8d9c1e40dc7 (patch) | |
tree | 78ab4af6742bc3328680909d726085aeaca2967d | |
parent | Remove unused typedef uthn_dbd_conf (diff) | |
download | apache2-dc0d9fa11e66dc80ead856b6902db8d9c1e40dc7.tar.xz apache2-dc0d9fa11e66dc80ead856b6902db8d9c1e40dc7.zip |
Correct request header handling of whitespace with the new possible config of
HttpProtocolOptions Unsafe StrictWhitespace
I have elected not to preserve any significance to excess whitespace in the
now-deprecated obs-fold code path, that's certainly open for discussion.
This can be reviewed by tweaking t/conf/extra.conf to switch Strict to Unsafe.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1756847 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | server/protocol.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/server/protocol.c b/server/protocol.c index ed1ff100a6..094dc88a40 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -878,6 +878,7 @@ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb char *tmp_field; core_server_config *conf = ap_get_core_module_config(r->server->module_config); int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE); + int strictspaces = (conf->http_whitespace == AP_HTTP_WHITESPACE_STRICT); /* * Read header lines until we get the empty separator line, a read error, @@ -988,7 +989,7 @@ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb } memcpy(last_field + last_len, field, len +1); /* +1 for nul */ /* Replace obs-fold w/ SP per RFC 7230 3.2.4 */ - if (strict) { + if (strict || strictspaces) { last_field[last_len] = ' '; } last_len += len; @@ -1017,9 +1018,23 @@ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb return; } - if (!strict) { + if (!strict) + { /* Not Strict ('Unsafe' mode), using the legacy parser */ + if (strictspaces && strpbrk(last_field, "\n\v\f\r")) { + r->status = HTTP_BAD_REQUEST; + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03451) + "Request header presented bad whitespace " + "(disallowed by StrictWhitespace)"); + return; + } + else { + char *ll = last_field; + while ((ll = strpbrk(ll, "\n\v\f\r"))) + *(ll++) = ' '; + } + if (!(value = strchr(last_field, ':'))) { /* Find ':' or */ r->status = HTTP_BAD_REQUEST; /* abort bad request */ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00564) @@ -1029,10 +1044,19 @@ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb return; } - tmp_field = value - 1; /* last character of field-name */ + /* last character of field-name */ + tmp_field = value - (value > last_field ? 1 : 0); *value++ = '\0'; /* NUL-terminate at colon */ + if (strictspaces && strpbrk(last_field, " \t")) { + r->status = HTTP_BAD_REQUEST; + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03452) + "Request header field name with whitespace " + "(disallowed by StrictWhitespace)"); + return; + } + while (*value == ' ' || *value == '\t') { ++value; /* Skip to start of value */ } @@ -1040,7 +1064,14 @@ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb /* Strip LWS after field-name: */ while (tmp_field > last_field && (*tmp_field == ' ' || *tmp_field == '\t')) { - *tmp_field-- = '\0'; + *(tmp_field--) = '\0'; + } + + if (tmp_field == last_field) { + r->status = HTTP_BAD_REQUEST; + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(03453) + "Request header field name was empty"); + return; } } else /* Using strict RFC7230 parsing */ |