X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=parsers.c;h=27ada5f76c44b1263a97f0d42c7b47c0ce50caa2;hb=8719a1048c59e4a500b0c4c31fc133a038de4c0c;hp=3a2b4fee98bb439fcbb09681b5eca37fe12b511d;hpb=a68640d0f98a1f37e83c3f1d922dd3f2783d09bc;p=privoxy.git diff --git a/parsers.c b/parsers.c index 3a2b4fee..27ada5f7 100644 --- a/parsers.c +++ b/parsers.c @@ -1,4 +1,4 @@ -const char parsers_rcs[] = "$Id: parsers.c,v 1.290 2014/07/25 11:56:02 fabiankeil Exp $"; +const char parsers_rcs[] = "$Id: parsers.c,v 1.296 2014/11/03 14:41:12 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/parsers.c,v $ @@ -1662,6 +1662,8 @@ static jb_err server_keep_alive(struct client_state *csp, char **header) csp->flags |= CSP_FLAG_SERVER_KEEP_ALIVE_TIMEOUT_SET; } + freez(*header); + return JB_ERR_OK; } @@ -2195,11 +2197,12 @@ static jb_err server_content_type(struct client_state *csp, char **header) */ if ((csp->content_type & CT_TEXT) || (csp->action->flags & ACTION_FORCE_TEXT_MODE)) { + jb_err err; freez(*header); *header = strdup_or_die("Content-Type: "); - string_append(header, csp->action->string[ACTION_STRING_CONTENT_TYPE]); - if (header == NULL) + err = string_append(header, csp->action->string[ACTION_STRING_CONTENT_TYPE]); + if (JB_ERR_OK != err) { log_error(LOG_LEVEL_HEADER, "Insufficient memory to replace Content-Type!"); return JB_ERR_MEMORY; @@ -2321,8 +2324,7 @@ static jb_err server_content_encoding(struct client_state *csp, char **header) /* * Log a warning if the user expects the content to be filtered. */ - if ((csp->rlist != NULL) && - (!list_is_empty(csp->action->multi[ACTION_MULTI_FILTER]))) + if (content_filters_enabled(csp->action)) { log_error(LOG_LEVEL_INFO, "SDCH-compressed content detected, content filtering disabled. " @@ -3837,6 +3839,7 @@ static jb_err client_connection_header_adder(struct client_state *csp) * is a partial range (HTTP status 206) * - Rewrite HTTP/1.1 answers to HTTP/1.0 if +downgrade * action applies. + * - Normalize the HTTP-version. * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) @@ -3846,36 +3849,84 @@ static jb_err client_connection_header_adder(struct client_state *csp) * original string if necessary. * * Returns : JB_ERR_OK on success, or - * JB_ERR_MEMORY on out-of-memory error. + * JB_ERR_PARSE on fatal parse errors. * *********************************************************************/ static jb_err server_http(struct client_state *csp, char **header) { - sscanf(*header, "HTTP/%*d.%*d %d", &(csp->http->status)); + char *reason_phrase = NULL; + char *new_response_line; + char *p; + size_t length; + unsigned int major_version; + unsigned int minor_version; + + /* Get the reason phrase which start after the second whitespace */ + p = strchr(*header, ' '); + if (NULL != p) + { + p++; + reason_phrase = strchr(p, ' '); + } + + if (reason_phrase != NULL) + { + reason_phrase++; + } + else + { + log_error(LOG_LEVEL_ERROR, + "Response line lacks reason phrase: %s", *header); + reason_phrase=""; + } + + if (3 != sscanf(*header, "HTTP/%u.%u %d", &major_version, + &minor_version, &(csp->http->status))) + { + log_error(LOG_LEVEL_ERROR, + "Failed to parse the response line: %s", *header); + return JB_ERR_PARSE; + } + if (csp->http->status == 206) { csp->content_type = CT_TABOO; } - if ((csp->action->flags & ACTION_DOWNGRADE) != 0) + if (major_version != 1 || (minor_version != 0 && minor_version != 1)) { - /* XXX: Should we do a real validity check here? */ - if (strlen(*header) > 8) - { - (*header)[7] = '0'; - log_error(LOG_LEVEL_HEADER, "Downgraded answer to HTTP/1.0"); - } - else - { - /* - * XXX: Should we block the request or - * enlist a valid status code line here? - */ - log_error(LOG_LEVEL_INFO, "Malformed server response detected. " - "Downgrading to HTTP/1.0 impossible."); - } + /* + * According to RFC 7230 2.6 intermediaries MUST send + * their own HTTP-version in forwarded messages. + */ + log_error(LOG_LEVEL_ERROR, + "Unsupported HTTP version. Downgrading to 1.1."); + major_version = 1; + minor_version = 1; + } + + if (((csp->action->flags & ACTION_DOWNGRADE) != 0) && (minor_version == 1)) + { + log_error(LOG_LEVEL_HEADER, "Downgrading answer to HTTP/1.0"); + minor_version = 0; } + /* Rebuild response line. */ + length = sizeof("HTTP/1.1 200 ") + strlen(reason_phrase) + 1; + new_response_line = malloc_or_die(length); + + snprintf(new_response_line, length, "HTTP/%u.%u %d %s", + major_version, minor_version, csp->http->status, reason_phrase); + + if (0 != strcmp(*header, new_response_line)) + { + log_error(LOG_LEVEL_HEADER, "Response line '%s' changed to '%s'", + *header, new_response_line); + } + + freez(*header); + *header = new_response_line; + return JB_ERR_OK; }