On 11/04/2016 03:20 PM, wr...@apache.org wrote:
> Author: wrowe
> Date: Fri Nov 4 14:20:16 2016
> New Revision: 1768036
>
> URL: http://svn.apache.org/viewvc?rev=1768036=rev
> Log:
> Add an option to enforce stricter HTTP conformance
>
> This is a first stab, the checks will likely have to be revised.
> For now, we check
>
> * if the request line contains control characters
> * if the request uri has fragment or username/password
> * that the request method is standard or registered with RegisterHttpMethod
> * that the request protocol is of the form HTTP/[1-9]+.[0-9]+,
>or missing for 0.9
> * if there is garbage in the request line after the protocol
> * if any request header contains control characters
> * if any request header has an empty name
> * for the host name in the URL or Host header:
>- if an IPv4 dotted decimal address: Reject octal or hex values, require
> exactly four parts
>- if a DNS host name: Reject non-alphanumeric characters besides '.' and
> '-'. As a side effect, this rejects multiple Host headers.
> * if any response header contains control characters
> * if any response header has an empty name
> * that the Location response header (if present) has a valid scheme and is
>absolute
>
> If we have a host name both from the URL and the Host header, we replace the
> Host header with the value from the URL to enforce RFC conformance.
>
> There is a log-only mode, but the loglevels of the logged messages need some
> thought/work. Currently, the checks for incoming data log for 'core' and the
> checks for outgoing data log for 'http'. Maybe we need a way to configure the
> loglevels separately from the core/http loglevels.
>
> change protocol number parsing in strict mode according to HTTPbis draft
> - only accept single digit version components
> - don't accept white-space after protocol specification
>
> Clean up comment, fix log tags.
> Submitted by: sf
> Backports: r1426877, r1426879, r1426988, r1426992
>
>
> Modified: httpd/httpd/branches/2.4.x-merge-http-strict/server/vhost.c
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x-merge-http-strict/server/vhost.c?rev=1768036=1768035=1768036=diff
> ==
> --- httpd/httpd/branches/2.4.x-merge-http-strict/server/vhost.c (original)
> +++ httpd/httpd/branches/2.4.x-merge-http-strict/server/vhost.c Fri Nov 4
> 14:20:16 2016
> @@ -1040,23 +1108,79 @@ static void check_serverpath(request_rec
> }
> }
>
> +static APR_INLINE const char *construct_host_header(request_rec *r,
> +int is_v6literal)
> +{
> +struct iovec iov[5];
> +apr_size_t nvec = 0;
> +/*
> + * We cannot use ap_get_server_name/port here, because we must
> + * ignore UseCanonicalName/Port.
> + */
> +if (is_v6literal) {
> +iov[nvec].iov_base = "[";
> +iov[nvec].iov_len = 1;
> +nvec++;
> +}
> +iov[nvec].iov_base = (void *)r->hostname;
> +iov[nvec].iov_len = strlen(r->hostname);
> +nvec++;
> +if (is_v6literal) {
> +iov[nvec].iov_base = "]";
> +iov[nvec].iov_len = 1;
> +nvec++;
> +}
> +if (r->parsed_uri.port_str) {
> +iov[nvec].iov_base = ":";
> +iov[nvec].iov_len = 1;
> +nvec++;
> +iov[nvec].iov_base = r->parsed_uri.port_str;
> +iov[nvec].iov_len = strlen(r->parsed_uri.port_str);
> +nvec++;
> +}
> +return apr_pstrcatv(r->pool, iov, nvec, NULL);
> +}
>
> AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r)
> {
> -const char *host_header;
> +core_server_config *conf =
> ap_get_core_module_config(r->server->module_config);
> +const char *host_header = apr_table_get(r->headers_in, "Host");
> +int is_v6literal, have_hostname_from_url = 0;
>
> if (r->hostname) {
> /*
> * If there was a host part in the Request-URI, ignore the 'Host'
> * header.
> */
> -fix_hostname(r, NULL);
> +have_hostname_from_url = 1;
> +is_v6literal = fix_hostname(r, NULL, conf->http_conformance);
> }
> -else if ((host_header = apr_table_get(r->headers_in, "Host")) != NULL ) {
> -fix_hostname(r, host_header);
> +else if (host_header != NULL) {
> +is_v6literal = fix_hostname(r, host_header, conf->http_conformance);
> }
> if (r->status != HTTP_OK)
> return;
> +
> +if (conf->http_conformance & AP_HTTP_CONFORMANCE_STRICT) {
> +/*
> + * If we have both hostname from an absoluteURI and a Host header,
> + * we must ignore the Host header (RFC 2616 5.2).
> + * To enforce this, we reset the Host header to the value from the
> + * request line.
> + */
> +if (have_hostname_from_url && host_header != NULL) {
> +const char *info = "Would replace";
> +