From: Fabian Keil Date: Tue, 22 Dec 2020 17:24:17 +0000 (+0100) Subject: Allow to rewrite the request destination for https-intercepted requests X-Git-Tag: v_3_0_30~169 X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=commitdiff_plain;h=093ce0d6a6ba53bc4f89d3c12287fb7e9dcb8a46;ds=sidebyside Allow to rewrite the request destination for https-intercepted requests ... behind the client's back. The documentation already sort of claimed that it was supported by not especially mentioning that it didn't work for https-inspected requests. Fixes SF bug #923 reported by withoutname. --- diff --git a/jcc.c b/jcc.c index 44e75610..e7ad4e25 100644 --- a/jcc.c +++ b/jcc.c @@ -968,8 +968,8 @@ static int crunch_response_triggered(struct client_state *csp, const struct crun * * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) - * 2 : fwd = The forwarding spec used for the request - * XXX: Should use http->fwd instead. + * 2 : fwd = The forwarding spec used for the request. + * Can be NULL. * 3 : request_line = The old request line which will be replaced. * * Returns : Nothing. Terminates in case of memory problems. @@ -997,7 +997,7 @@ static void build_request_line(struct client_state *csp, const struct forward_sp *request_line = strdup(http->gpc); string_append(request_line, " "); - if (fwd->forward_host && fwd->type != FORWARD_WEBSERVER) + if (fwd != NULL && fwd->forward_host && fwd->type != FORWARD_WEBSERVER) { string_append(request_line, http->url); } @@ -2528,6 +2528,95 @@ static jb_err receive_encrypted_request(struct client_state *csp) } +/********************************************************************* + * + * Function : change_encrypted_request_destination + * + * Description : Parse a (rewritten) request line from an encrypted + * request and regenerate the http request data. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Forwards the parse_http_request() return code. + * Terminates in case of memory problems. + * + *********************************************************************/ +static jb_err change_encrypted_request_destination(struct client_state *csp) +{ + jb_err err; + char *original_host = csp->http->host; + + log_error(LOG_LEVEL_REDIRECTS, "Rewrite detected: %s", + csp->https_headers->first->str); + csp->http->host = NULL; + free_http_request(csp->http); + err = parse_http_request(csp->https_headers->first->str, csp->http); + if (JB_ERR_OK != err) + { + log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.", + jb_err_to_string(err)); + return err; + } + + if (csp->http->host == NULL) + { + /* + * The rewritten request line did not specify a host + * which means we can use the original host specified + * by the client. + */ + csp->http->host = original_host; + log_error(LOG_LEVEL_REDIRECTS, "Keeping the original host: %s", + csp->http->host); + /* + * If the rewritten request line didn't contain a host + * it also didn't contain a port so we can reuse the host + * and set the port to 443. + */ + freez(csp->http->hostport); + csp->http->hostport = strdup_or_die(csp->http->host); + csp->http->port = 443; + /* + * While the request line didn't mention it, + * we're https-inspecting and want to speak TLS + * with the server. + */ + csp->http->server_ssl = 1; + csp->http->ssl = 1; + } + else + { + /* The rewrite filter added a host so we can ditch the original */ + freez(original_host); + csp->http->server_ssl = csp->http->ssl; + } + + csp->http->client_ssl = 1; + + freez(csp->https_headers->first->str); + build_request_line(csp, NULL, &csp->https_headers->first->str); + + if (!server_use_ssl(csp)) + { + log_error(LOG_LEVEL_REDIRECTS, + "Rewritten request line results in downgrade to http"); + /* + * Replace the unencryptd headers received with the + * CONNECT request with the ones we received securely. + */ + destroy_list(csp->headers); + csp->headers->first = csp->https_headers->first; + csp->headers->last = csp->https_headers->last; + csp->https_headers->first = NULL; + csp->https_headers->last = NULL; + } + + return JB_ERR_OK; + +} + + /********************************************************************* * * Function : process_encrypted_request @@ -2709,6 +2798,17 @@ static jb_err process_encrypted_request(struct client_state *csp) return JB_ERR_PARSE; } + if ((NULL == csp->https_headers->first->str) + || (strcmp(csp->http->cmd, csp->https_headers->first->str) && + (JB_ERR_OK != change_encrypted_request_destination(csp)))) + { + log_error(LOG_LEVEL_ERROR, + "Failed to get the request destination in the rewritten headers"); + ssl_send_data_delayed(&(csp->ssl_client_attr), + (const unsigned char *)CHEADER, strlen(CHEADER), get_write_delay(csp)); + return JB_ERR_PARSE; + } + log_error(LOG_LEVEL_HEADER, "Encrypted request processed"); log_applied_actions(csp->action); log_error(LOG_LEVEL_REQUEST, "https://%s%s", csp->http->hostport,