]> granicus.if.org Git - apache/commitdiff
Correct request header handling of whitespace with the new possible config of
authorWilliam A. Rowe Jr <wrowe@apache.org>
Thu, 18 Aug 2016 20:26:53 +0000 (20:26 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Thu, 18 Aug 2016 20:26:53 +0000 (20:26 +0000)
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

server/protocol.c

index ed1ff100a636d8fd3da0201afd31053230ae682f..094dc88a40c4c815e8a9f448d3d07721b74dddee 100644 (file)
@@ -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 */