X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jcc.c;h=02f6f25ede39f5122d70122e4eb99d9a30995033;hp=5b83d17c503e49a47f4fc0aa1a4860814526c513;hb=HEAD;hpb=caacb81062e2e3152231c09c9da62a31e4efc170 diff --git a/jcc.c b/jcc.c index 5b83d17c..0e110a3c 100644 --- a/jcc.c +++ b/jcc.c @@ -5,7 +5,7 @@ * Purpose : Main file. Contains main() method, main loop, and * the main connection-handling function. * - * Copyright : Written by and Copyright (C) 2001-2022 the + * Copyright : Written by and Copyright (C) 2001-2023 the * Privoxy team. https://www.privoxy.org/ * * Based on the Internet Junkbuster originally written @@ -2122,12 +2122,12 @@ static int read_http_request_body(struct client_state *csp) if (to_read != 0) { log_error(LOG_LEVEL_CONNECT, - "Not enough request body has been read: expected %lu more bytes", + "Not enough request body has been read: expected %lu more bytes.", to_read); return 1; } log_error(LOG_LEVEL_CONNECT, - "The last %d bytes of the request body have been read", len); + "The last %d bytes of the request body have been read.", len); return 0; } @@ -2302,7 +2302,7 @@ static int read_https_request_body(struct client_state *csp) if (len <= 0) { log_error(LOG_LEVEL_CONNECT, - "Did not receive the whole encrypted request body from %s", + "Did not receive the whole encrypted request body from %s.", csp->ip_addr_str); return 1; } @@ -2316,13 +2316,13 @@ static int read_https_request_body(struct client_state *csp) if (to_read != 0) { log_error(LOG_LEVEL_CONNECT, - "Not enough encrypted request body has been read: expected %lu more bytes", + "Not enough encrypted request body has been read: expected %lu more bytes.", to_read); return 1; } log_error(LOG_LEVEL_CONNECT, - "The last %llu bytes of the encrypted request body have been read", + "The last %llu bytes of the encrypted request body have been read.", csp->expected_client_content_length); return 0; } @@ -2345,9 +2345,8 @@ static int receive_and_send_encrypted_post_data(struct client_state *csp) { int content_length_known = csp->expected_client_content_length != 0; - while ((content_length_known && csp->expected_client_content_length != 0) || - (is_ssl_pending(&(csp->ssl_client_attr)) || - data_is_available(csp->cfd, csp->config->socket_timeout))) + while (is_ssl_pending(&(csp->ssl_client_attr)) + || (content_length_known && csp->expected_client_content_length != 0)) { unsigned char buf[BUFFER_SIZE]; int len; @@ -2371,7 +2370,7 @@ static int receive_and_send_encrypted_post_data(struct client_state *csp) /* XXX: Does this actually happen? */ break; } - log_error(LOG_LEVEL_CONNECT, "Forwarding %d bytes of encrypted request body", + log_error(LOG_LEVEL_CONNECT, "Forwarding %d bytes of encrypted request body.", len); len = ssl_send_data(&(csp->ssl_server_attr), buf, (size_t)len); if (len == -1) @@ -2386,13 +2385,13 @@ static int receive_and_send_encrypted_post_data(struct client_state *csp) } if (csp->expected_client_content_length == 0) { - log_error(LOG_LEVEL_CONNECT, "Forwarded the last %d bytes", len); + log_error(LOG_LEVEL_CONNECT, "Forwarded the last %d bytes.", len); break; } } } - log_error(LOG_LEVEL_CONNECT, "Done forwarding encrypted request body"); + log_error(LOG_LEVEL_CONNECT, "Done forwarding encrypted request body."); return 0; @@ -2422,7 +2421,7 @@ static int send_https_request(struct client_state *csp) if (hdr == NULL) { /* FIXME Should handle error properly */ - log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header"); + log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header."); } list_remove_all(csp->https_headers); @@ -2459,14 +2458,14 @@ static int send_https_request(struct client_state *csp) if (csp->expected_client_content_length < flushed) { log_error(LOG_LEVEL_ERROR, - "Flushed %ld bytes of request body while only expecting %llu", + "Flushed %ld bytes of request body while only expecting %llu.", flushed, csp->expected_client_content_length); csp->expected_client_content_length = 0; } else { log_error(LOG_LEVEL_CONNECT, - "Flushed %ld bytes of request body while expecting %llu", + "Flushed %ld bytes of request body while expecting %llu.", flushed, csp->expected_client_content_length); csp->expected_client_content_length -= (unsigned)flushed; if (receive_and_send_encrypted_post_data(csp)) @@ -2478,11 +2477,11 @@ static int send_https_request(struct client_state *csp) else { log_error(LOG_LEVEL_CONNECT, - "Flushed %ld bytes of request body", flushed); + "Flushed %ld bytes of request body.", flushed); } } - log_error(LOG_LEVEL_CONNECT, "Encrypted request sent"); + log_error(LOG_LEVEL_CONNECT, "Encrypted request sent."); return 0; @@ -2511,12 +2510,12 @@ static jb_err receive_encrypted_request_headers(struct client_state *csp) do { - log_error(LOG_LEVEL_HEADER, "Waiting for encrypted client headers"); + log_error(LOG_LEVEL_HEADER, "Waiting for encrypted client headers."); if (!is_ssl_pending(&(csp->ssl_client_attr)) && !data_is_available(csp->cfd, csp->config->socket_timeout)) { log_error(LOG_LEVEL_CONNECT, - "Socket %d timed out while waiting for client headers", csp->cfd); + "Socket %d timed out while waiting for client headers.", csp->cfd); return JB_ERR_PARSE; } len = ssl_recv_data(&(csp->ssl_client_attr), @@ -2524,7 +2523,7 @@ static jb_err receive_encrypted_request_headers(struct client_state *csp) if (len == 0) { log_error(LOG_LEVEL_CONNECT, - "Socket %d closed while waiting for client headers", csp->cfd); + "Socket %d closed while waiting for client headers.", csp->cfd); return JB_ERR_PARSE; } if (len == -1) @@ -2538,7 +2537,7 @@ static jb_err receive_encrypted_request_headers(struct client_state *csp) p = strstr(csp->client_iob->cur, "\r\n\r\n"); } while (p == NULL); - log_error(LOG_LEVEL_HEADER, "Encrypted headers received completely"); + log_error(LOG_LEVEL_HEADER, "Encrypted headers received completely."); return JB_ERR_OK; } @@ -3026,6 +3025,67 @@ static void continue_https_chat(struct client_state *csp) #endif +/********************************************************************* + * + * Function : send_server_headers + * + * Description : Sends the server headers to the client. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : 0 on succes, -1 on error. + * + *********************************************************************/ +static int send_server_headers(struct client_state *csp) +{ + char *server_headers; + int ret; + + server_headers = list_to_text(csp->headers); + if (server_headers == NULL) + { + /* + * Memory is too tight to even generate the header. + * Send our static "Out-of-memory" page. + */ + log_error(LOG_LEVEL_ERROR, + "Out of memory while trying to send server headers."); + send_crunch_response(csp, cgi_error_memory()); + mark_server_socket_tainted(csp); +#ifdef FEATURE_HTTPS_INSPECTION + close_client_and_server_ssl_connections(csp); +#endif + return -1; + } +#ifdef FEATURE_HTTPS_INSPECTION + if (client_use_ssl(csp)) + { + ret = ssl_send_data_delayed(&(csp->ssl_client_attr), + (const unsigned char *)server_headers, strlen(server_headers), + get_write_delay(csp)); + } + else +#endif + { + ret = write_socket_delayed(csp->cfd, server_headers, strlen(server_headers), + get_write_delay(csp)); + } + freez(server_headers); + if (ret < 0) + { + log_error(LOG_LEVEL_ERROR, "Failed to send server headers to the client."); + mark_server_socket_tainted(csp); +#ifdef FEATURE_HTTPS_INSPECTION + close_client_and_server_ssl_connections(csp); +#endif + return -1; + } + + return 0; + +} + /********************************************************************* * * Function : handle_established_connection @@ -3042,7 +3102,6 @@ static void continue_https_chat(struct client_state *csp) *********************************************************************/ static void handle_established_connection(struct client_state *csp) { - char *hdr; char *p; int n; #ifdef HAVE_POLL @@ -3384,8 +3443,6 @@ static void handle_established_connection(struct client_state *csp) /* * The server wants to talk. It could be the header or the body. - * If `hdr' is null, then it's the header otherwise it's the body. - * FIXME: Does `hdr' really mean `host'? No. */ #ifdef HAVE_POLL if (poll_fds[1].revents != 0) @@ -3568,11 +3625,9 @@ static void handle_established_connection(struct client_state *csp) "Failed to update server headers. after filtering."); } - hdr = list_to_text(csp->headers); - if (hdr == NULL) + if (send_server_headers(csp)) { - /* FIXME Should handle error properly */ - log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); + return; } #ifdef FEATURE_HTTPS_INSPECTION @@ -3581,16 +3636,12 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - if ((ssl_send_data_delayed(&(csp->ssl_client_attr), - (const unsigned char *)hdr, strlen(hdr), - get_write_delay(csp)) < 0) - || (ssl_send_data_delayed(&(csp->ssl_client_attr), + if (ssl_send_data_delayed(&(csp->ssl_client_attr), (const unsigned char *) ((p != NULL) ? p : csp->iob->cur), - csp->content_length, get_write_delay(csp)) < 0)) + csp->content_length, get_write_delay(csp)) < 0) { log_error(LOG_LEVEL_ERROR, "Failed to send the modified content to the client over TLS"); - freez(hdr); freez(p); mark_server_socket_tainted(csp); close_client_and_server_ssl_connections(csp); @@ -3600,19 +3651,16 @@ static void handle_established_connection(struct client_state *csp) else #endif /* def FEATURE_HTTPS_INSPECTION */ { - if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) - || write_socket_delayed(csp->cfd, ((p != NULL) ? p : csp->iob->cur), + if (write_socket_delayed(csp->cfd, ((p != NULL) ? p : csp->iob->cur), (size_t)csp->content_length, write_delay)) { log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E"); - freez(hdr); freez(p); mark_server_socket_tainted(csp); return; } } - freez(hdr); freez(p); } @@ -3654,29 +3702,15 @@ static void handle_established_connection(struct client_state *csp) */ if (add_to_iob(csp->iob, csp->config->buffer_limit, csp->receive_buffer, len)) { - size_t hdrlen; long flushed; log_error(LOG_LEVEL_INFO, "Flushing header and buffers. Stepping back from filtering."); - hdr = list_to_text(csp->headers); - if (hdr == NULL) + if (send_server_headers(csp)) { - /* - * Memory is too tight to even generate the header. - * Send our static "Out-of-memory" page. - */ - log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush."); - rsp = cgi_error_memory(); - send_crunch_response(csp, rsp); - mark_server_socket_tainted(csp); -#ifdef FEATURE_HTTPS_INSPECTION - close_client_and_server_ssl_connections(csp); -#endif return; } - hdrlen = strlen(hdr); #ifdef FEATURE_HTTPS_INSPECTION /* @@ -3684,9 +3718,7 @@ static void handle_established_connection(struct client_state *csp) */ if (client_use_ssl(csp)) { - if ((ssl_send_data_delayed(&(csp->ssl_client_attr), - (const unsigned char *)hdr, hdrlen, get_write_delay(csp)) < 0) - || ((flushed = ssl_flush_socket(&(csp->ssl_client_attr), + if (((flushed = ssl_flush_socket(&(csp->ssl_client_attr), csp->iob)) < 0) || (ssl_send_data_delayed(&(csp->ssl_client_attr), (const unsigned char *)csp->receive_buffer, (size_t)len, @@ -3694,7 +3726,6 @@ static void handle_established_connection(struct client_state *csp) { log_error(LOG_LEVEL_CONNECT, "Flush header and buffers to client failed"); - freez(hdr); mark_server_socket_tainted(csp); close_client_and_server_ssl_connections(csp); return; @@ -3703,26 +3734,22 @@ static void handle_established_connection(struct client_state *csp) else #endif /* def FEATURE_HTTPS_INSPECTION */ { - if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay) - || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0) + if (((flushed = flush_iob(csp->cfd, csp->iob, write_delay)) < 0) || write_socket_delayed(csp->cfd, csp->receive_buffer, (size_t)len, write_delay)) { log_error(LOG_LEVEL_CONNECT, "Flush header and buffers to client failed: %E"); - freez(hdr); mark_server_socket_tainted(csp); return; } } /* - * Reset the byte_count to the amount of bytes - * we just flushed. len will be added a few lines below, - * hdrlen doesn't matter for LOG_LEVEL_CLF. + * Reset the byte_count to the amount of bytes we just + * flushed. len will be added a few lines below. */ byte_count = (unsigned long long)flushed; - freez(hdr); if ((csp->flags & CSP_FLAG_CHUNKED) && (chunk_offset != 0)) { log_error(LOG_LEVEL_CONNECT, @@ -4037,12 +4064,6 @@ static void handle_established_connection(struct client_state *csp) #endif return; } - hdr = list_to_text(csp->headers); - if (hdr == NULL) - { - /* FIXME Should handle error properly */ - log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); - } if ((csp->flags & CSP_FLAG_CHUNKED) && !(csp->flags & CSP_FLAG_CONTENT_LENGTH_SET)) @@ -4079,7 +4100,6 @@ static void handle_established_connection(struct client_state *csp) * delivered the crunch response to the client * and are done here after cleaning up. */ - freez(hdr); mark_server_socket_tainted(csp); #ifdef FEATURE_HTTPS_INSPECTION close_client_and_server_ssl_connections(csp); @@ -4098,22 +4118,23 @@ static void handle_established_connection(struct client_state *csp) * may be in the buffer). Use standard or secured * connection. */ + if (send_server_headers(csp)) + { + return; + } #ifdef FEATURE_HTTPS_INSPECTION if (client_use_ssl(csp)) { - if ((ssl_send_data_delayed(&(csp->ssl_client_attr), - (const unsigned char *)hdr, strlen(hdr), - get_write_delay(csp)) < 0) - || ((len = ssl_flush_socket(&(csp->ssl_client_attr), - csp->iob)) < 0)) + if ((len = ssl_flush_socket(&(csp->ssl_client_attr), + csp->iob)) < 0) { - log_error(LOG_LEVEL_CONNECT, "Write header to client failed"); + log_error(LOG_LEVEL_CONNECT, + "Sending buffered bytes to the client failed"); /* * The write failed, so don't bother mentioning it * to the client... it probably can't hear us anyway. */ - freez(hdr); mark_server_socket_tainted(csp); #ifdef FEATURE_HTTPS_INSPECTION close_client_and_server_ssl_connections(csp); @@ -4124,16 +4145,14 @@ static void handle_established_connection(struct client_state *csp) else #endif /* def FEATURE_HTTPS_INSPECTION */ { - if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay) - || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0)) + if ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0) { log_error(LOG_LEVEL_ERROR, - "write header to client failed"); + "Sending buffered bytes to the client failed."); /* * The write failed, so don't bother mentioning it * to the client... it probably can't hear us anyway. */ - freez(hdr); mark_server_socket_tainted(csp); return; } @@ -4147,15 +4166,15 @@ static void handle_established_connection(struct client_state *csp) */ if (chunk_offset >= len) { - log_error(LOG_LEVEL_CONNECT, - "Reducing chunk offset from %lu to %lu after flushing %ld bytes", + log_error(LOG_LEVEL_CONNECT, "Reducing the chunk offset " + "from %lu to %lu after flushing %ld bytes.", chunk_offset, (chunk_offset - (unsigned)len), len); chunk_offset = chunk_offset - (unsigned)len; } else { log_error(LOG_LEVEL_CONNECT, - "Keeping chunk offset at %lu despite flushing %ld bytes", + "Keeping chunk offset at %lu despite flushing %ld bytes.", chunk_offset, len); /* * If we can't parse the chunk-encoded data we should @@ -4168,7 +4187,6 @@ static void handle_established_connection(struct client_state *csp) /* we're finished with the server's header */ - freez(hdr); server_body = 1; /* @@ -6251,7 +6269,8 @@ static void listen_loop(void) if (!accept_connection(csp, bfds)) { - log_error(LOG_LEVEL_CONNECT, "accept failed: %E"); + log_error(LOG_LEVEL_CONNECT, + "Failed to accept() incoming connection: %E"); freez(csp_list); continue; }