From c8db6199d973c89f06a159770618eb63d0b0d873 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Sat, 6 Mar 2021 17:34:39 +0100 Subject: [PATCH] Establish the TLS connection with the client earlier ... and decide how to route the request afterwards. This allows to change the forwarding settings based on information from the https-inspected request, for example the path. Adjust build_request_line() to create a CONNECT request line when https-inspecting and forwarding to a HTTP proxy. Fixes SF bug #925 reported by Wen Yue. --- jcc.c | 132 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 54 deletions(-) diff --git a/jcc.c b/jcc.c index 7805291c..3f42be1b 100644 --- a/jcc.c +++ b/jcc.c @@ -995,12 +995,35 @@ static void build_request_line(struct client_state *csp, const struct forward_sp * Rebuild the request line. */ freez(*request_line); - *request_line = strdup(http->gpc); - string_append(request_line, " "); +#ifdef FEATURE_HTTPS_INSPECTION + if (fwd != NULL && fwd->forward_host && + fwd->type != FORWARD_WEBSERVER && client_use_ssl(csp)) + { + *request_line = strdup("CONNECT "); + } + else +#endif + { + *request_line = strdup(http->gpc); + string_append(request_line, " "); + } if (fwd != NULL && fwd->forward_host && fwd->type != FORWARD_WEBSERVER) { - string_append(request_line, http->url); +#ifdef FEATURE_HTTPS_INSPECTION + if (client_use_ssl(csp)) + { + char port_string[10]; + + string_append(request_line, http->host); + snprintf(port_string, sizeof(port_string), ":%d", http->port); + string_append(request_line, port_string); + } + else +#endif + { + string_append(request_line, http->url); + } } else { @@ -4132,9 +4155,6 @@ static void chat(struct client_state *csp) return; } - /* decide how to route the HTTP request */ - fwd = forward_url(csp, http); - #ifdef FEATURE_HTTPS_INSPECTION /* * Setting flags to use old solution with SSL tunnel and to disable @@ -4237,10 +4257,6 @@ static void chat(struct client_state *csp) #endif } - - freez(csp->headers->first->str); - build_request_line(csp, fwd, &csp->headers->first->str); - /* * We have a request. Check if one of the crunchers wants it * unless the client wants to use TLS/SSL in which case we @@ -4259,6 +4275,58 @@ static void chat(struct client_state *csp) return; } +#ifdef FEATURE_HTTPS_INSPECTION + if (client_use_ssl(csp) && !use_ssl_tunnel) + { + int ret; + /* + * Creating a SSL proxy. + * + * By sending the CSUCCEED message we're lying to the client as + * the connection hasn't actually been established yet. We don't + * establish the connection until we have seen and parsed the + * encrypted client headers. + */ + if (write_socket_delayed(csp->cfd, CSUCCEED, + strlen(CSUCCEED), get_write_delay(csp)) != 0) + { + log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); + return; + } + + ret = create_client_ssl_connection(csp); + if (ret != 0) + { + log_error(LOG_LEVEL_ERROR, + "Failed to open a secure connection with the client"); + return; + } + if (JB_ERR_OK != process_encrypted_request(csp)) + { + close_client_ssl_connection(csp); + return; + } + /* + * We have an encrypted request. Check if one of the crunchers now + * wants it (for example because the previously invisible path was + * required to match). + */ + if (crunch_response_triggered(csp, crunchers_all)) + { + /* + * Yes. The client got the crunch response and we're done here. + */ + return; + } + } +#endif + + /* decide how to route the HTTP request */ + fwd = forward_url(csp, http); + + freez(csp->headers->first->str); + build_request_line(csp, fwd, &csp->headers->first->str); + log_applied_actions(csp->action); if (fwd->forward_host) { @@ -4307,51 +4375,7 @@ static void chat(struct client_state *csp) mark_connection_closed(&csp->server_connection); } #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ -#ifdef FEATURE_HTTPS_INSPECTION - if (client_use_ssl(csp) && !use_ssl_tunnel) - { - int ret; - /* - * Creating a SSL proxy. - * - * By sending the CSUCCEED message we're lying to the client as - * the connection hasn't actually been established yet. We don't - * establish the connection until we have seen and parsed the - * encrypted client headers. - */ - if (write_socket_delayed(csp->cfd, CSUCCEED, - strlen(CSUCCEED), get_write_delay(csp)) != 0) - { - log_error(LOG_LEVEL_ERROR, "Sending SUCCEED to client failed"); - return; - } - ret = create_client_ssl_connection(csp); - if (ret != 0) - { - log_error(LOG_LEVEL_ERROR, - "Failed to open a secure connection with the client"); - return; - } - if (JB_ERR_OK != process_encrypted_request(csp)) - { - close_client_ssl_connection(csp); - return; - } - /* - * We have an encrypted request. Check if one of the crunchers now - * wants it (for example because the previously invisible path was - * required to match). - */ - if (crunch_response_triggered(csp, crunchers_all)) - { - /* - * Yes. The client got the crunch response and we're done here. - */ - return; - } - } -#endif /* * Connecting to destination server */ -- 2.39.2