X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jcc.c;h=e872a39c9af8a8cbcd0a26df5a7211d46a18e500;hp=93af90148b5f077df29a41e1b17dcfe71cd112cf;hb=1caad5412cf064ef018ce94f1bb3827f366b9210;hpb=f9b953ed3f2bc2de510352e56dfbf91efd19ac7e diff --git a/jcc.c b/jcc.c index 93af9014..e872a39c 100644 --- a/jcc.c +++ b/jcc.c @@ -62,10 +62,8 @@ #else /* ifndef _WIN32 */ -# if !defined (__OS2__) # include # include -# endif /* ndef __OS2__ */ # include # include # include @@ -86,14 +84,6 @@ # include /* declarations for threads and stuff. */ # endif -# if defined(__EMX__) || defined(__OS2__) -# include /* OS/2/EMX needs a little help with select */ -# endif -# ifdef __OS2__ -#define INCL_DOS -# include -# endif - #ifdef HAVE_POLL #ifdef __GLIBC__ #include @@ -143,7 +133,7 @@ int urls_rejected = 0; /* total nr of urls rejected */ int g_terminate = 0; #endif -#if !defined(_WIN32) && !defined(__OS2__) +#if !defined(_WIN32) static void sig_handler(int the_signal); #endif static int client_protocol_is_unsupported(struct client_state *csp, char *req); @@ -156,6 +146,7 @@ static jb_err receive_client_request(struct client_state *csp); static jb_err parse_client_request(struct client_state *csp); static void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line); static jb_err change_request_destination(struct client_state *csp); +static void handle_established_connection(struct client_state *csp); static void chat(struct client_state *csp); static void serve(struct client_state *csp); #if !defined(_WIN32) || defined(_WIN_CONSOLE) @@ -176,10 +167,6 @@ static int32 server_thread(void *data); #define sleep(N) Sleep(((N) * 1000)) #endif -#ifdef __OS2__ -#define sleep(N) DosSleep(((N) * 100)) -#endif - #ifdef FUZZ int process_fuzzed_input(char *fuzz_input_type, char *fuzz_input_file); void show_fuzz_usage(const char *name); @@ -346,7 +333,7 @@ static const struct cruncher crunchers_light[] = { * * here? */ -#if !defined(_WIN32) && !defined(__OS2__) +#if !defined(_WIN32) /********************************************************************* * * Function : sig_handler @@ -880,8 +867,8 @@ static void send_crunch_response(struct client_state *csp, struct http_response { /* There is nothing we can do about it. */ log_error(LOG_LEVEL_CONNECT, "Couldn't deliver the error message " - "for %s through client socket %d using TLS/SSL", - http->url, csp->cfd); + "for https://%s%s through client socket %d using TLS/SSL", + http->hostport, http->url, csp->cfd); } } else @@ -1200,6 +1187,7 @@ void save_connection_destination(jb_socket sfd, } server_connection->forward_port = fwd->forward_port; } +#endif /* FEATURE_CONNECTION_KEEP_ALIVE */ /********************************************************************* @@ -1300,7 +1288,6 @@ static void verify_request_length(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "Complete client request received."); } } -#endif /* FEATURE_CONNECTION_KEEP_ALIVE */ /********************************************************************* @@ -1921,6 +1908,7 @@ static jb_err parse_client_request(struct client_state *csp) /* Assume persistence until further notice */ csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ if (csp->http->ssl == 0) { @@ -1941,11 +1929,12 @@ static jb_err parse_client_request(struct client_state *csp) } verify_request_length(csp); } +#ifndef FEATURE_HTTPS_INSPECTION else { csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; } -#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ +#endif err = sed(csp, FILTER_CLIENT_HEADERS); if (JB_ERR_OK != err) @@ -2231,6 +2220,12 @@ static jb_err receive_encrypted_request(struct client_state *csp) } len = ssl_recv_data(&(csp->ssl_client_attr), (unsigned char *)buf, sizeof(buf)); + if (len == 0) + { + log_error(LOG_LEVEL_CONNECT, + "Socket %d closed while waiting for client headers", csp->cfd); + return JB_ERR_PARSE; + } if (len == -1) { return JB_ERR_PARSE; @@ -2270,9 +2265,25 @@ static jb_err process_encrypted_request(struct client_state *csp) struct list header_list; struct list *headers = &header_list; + assert(csp->ssl_with_client_is_opened); + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) + { + csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; + } +#endif err = receive_encrypted_request(csp); if (err != JB_ERR_OK) { + if (csp->client_iob->cur == NULL) + { + /* + * We did not receive any data, most likely because the + * client is done. Don't log this as a parse failure. + */ + return JB_ERR_PARSE; + } /* XXX: Also used for JB_ERR_MEMORY */ log_error(LOG_LEVEL_ERROR, "Failed to receive encrypted request: %s", jb_err_to_string(err)); @@ -2362,11 +2373,24 @@ static jb_err process_encrypted_request(struct client_state *csp) /* Split the domain we just got for pattern matching */ init_domain_components(csp->http); +#ifdef FEATURE_CLIENT_TAGS + /* XXX: If the headers were enlisted sooner, passing csp would do. */ + if (csp->client_address == NULL) + { + set_client_address(csp, headers); + get_tag_list_for_client(csp->client_tags, csp->client_address); + } +#endif + #ifdef FEATURE_TOGGLE if ((csp->flags & CSP_FLAG_TOGGLED_ON) != 0) #endif { - /* Determine the actions for this URL */ + /* + * Determine the actions for this request after + * clearing the ones from the previous one. + */ + free_current_action(csp->action); get_url_actions(csp, csp->http); } @@ -2434,6 +2458,100 @@ static int cgi_page_requested(const char *host) } + +#ifdef FEATURE_CONNECTION_KEEP_ALIVE +/********************************************************************* + * + * Function : continue_https_chat + * + * Description : Behaves similar to chat() but only deals with + * https-inspected requests that arrive on an already + * established connection. The first request is always + * served by chat() which is a lot more complex as it + * has to deal with forwarding settings and connection + * failures etc. + * + * If a connection to the server has already been + * opened it is reused unless the request is blocked + * or the forwarder changed. + * + * If a connection to the server has not yet been + * opened (because the previous request was crunched), + * or the forwarder changed, the connection is dropped + * so that the client retries on a fresh one. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Nothing. + * + *********************************************************************/ +static void continue_https_chat(struct client_state *csp) +{ + const struct forward_spec *fwd; + + if (JB_ERR_OK != process_encrypted_request(csp)) + { + return; + } + + csp->requests_received_total++; + + /* + * We have an encrypted request. Check if one of the crunchers wants it. + */ + if (crunch_response_triggered(csp, crunchers_all)) + { + /* + * Yes. The client got the crunch response and we're done here. + */ + return; + } + if (csp->ssl_with_server_is_opened == 0) + { + log_error(LOG_LEVEL_CONNECT, + "Dropping the client connection on socket %d. " + "The server connection has not been established yet.", + csp->cfd); + csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; + return; + } + assert(csp->server_connection.sfd != JB_INVALID_SOCKET); + + fwd = forward_url(csp, csp->http); + if (!connection_destination_matches(&csp->server_connection, csp->http, fwd)) + { + log_error(LOG_LEVEL_CONNECT, + "Dropping the client connection on socket %d with " + "server socket %d connected to %s. The forwarder has changed.", + csp->cfd, csp->server_connection.sfd, csp->server_connection.host); + csp->flags &= ~CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; + return; + } + + log_error(LOG_LEVEL_CONNECT, + "Reusing server socket %d connected to %s. Requests already sent: %u.", + csp->server_connection.sfd, csp->server_connection.host, + csp->server_connection.requests_sent_total); + + if (send_https_request(csp)) + { + /* + * Most likely the server connection timed out. We can't easily + * create a new one so simply drop the client connection without a + * error response to let the client retry. + */ + log_error(LOG_LEVEL_CONNECT, + "Dropping client connection on socket %d. " + "Forwarding the encrypted client request failed.", + csp->cfd); + return; + } + csp->server_connection.requests_sent_total++; + handle_established_connection(csp); + freez(csp->receive_buffer); +} +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ #endif @@ -2519,15 +2637,7 @@ static void handle_established_connection(struct client_state *csp) for (;;) { #ifndef HAVE_POLL -#ifdef __OS2__ - /* - * FD_ZERO here seems to point to an errant macro which crashes. - * So do this by hand for now... - */ - memset(&rfds,0x00,sizeof(fd_set)); -#else FD_ZERO(&rfds); -#endif #ifdef FEATURE_CONNECTION_KEEP_ALIVE if (!watch_client_socket) { @@ -3470,9 +3580,7 @@ static void handle_established_connection(struct client_state *csp) #endif return; /* huh? we should never get here */ } -#ifdef FEATURE_HTTPS_INSPECTION - close_client_and_server_ssl_connections(csp); -#endif + if (csp->content_length == 0) { /* @@ -3716,7 +3824,11 @@ static void chat(struct client_state *csp) if (csp->server_connection.sfd != JB_INVALID_SOCKET) { #ifdef FEATURE_CONNECTION_SHARING - if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) + if (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING +#ifdef FEATURE_HTTPS_INSPECTION + && !server_use_ssl(csp) +#endif + ) { remember_connection(&csp->server_connection); } @@ -3760,7 +3872,6 @@ static void chat(struct client_state *csp) } if (JB_ERR_OK != process_encrypted_request(csp)) { - log_error(LOG_LEVEL_ERROR, "Failed to parse encrypted request."); close_client_ssl_connection(csp); return; } @@ -3774,7 +3885,6 @@ static void chat(struct client_state *csp) /* * Yes. The client got the crunch response and we're done here. */ - close_client_ssl_connection(csp); return; } } @@ -4053,7 +4163,7 @@ extern int fuzz_server_response(struct client_state *csp, char *fuzz_input_file) if (strcmp(fuzz_input_file, "-") == 0) { - /* XXX: Doesn'T work yet. */ + /* XXX: Doesn't work yet. */ csp->server_connection.sfd = 0; } else @@ -4118,6 +4228,9 @@ static void prepare_csp_for_next_request(struct client_state *csp) freez(csp->error_message); free_http_request(csp->http); destroy_list(csp->headers); +#ifdef FEATURE_HTTPS_INSPECTION + destroy_list(csp->https_headers); +#endif destroy_list(csp->tags); #ifdef FEATURE_CLIENT_TAGS destroy_list(csp->client_tags); @@ -4202,7 +4315,16 @@ static void serve(struct client_state *csp) { unsigned int latency; - chat(csp); +#ifdef FEATURE_HTTPS_INSPECTION + if (continue_chatting && client_use_ssl(csp)) + { + continue_https_chat(csp); + } + else +#endif + { + chat(csp); + } /* * If the request has been crunched, @@ -4254,6 +4376,9 @@ static void serve(struct client_state *csp) forget_connection(csp->server_connection.sfd); } #endif /* def FEATURE_CONNECTION_SHARING */ +#ifdef FEATURE_HTTPS_INSPECTION + close_server_ssl_connection(csp); +#endif close_socket(csp->server_connection.sfd); mark_connection_closed(&csp->server_connection); } @@ -4264,6 +4389,15 @@ static void serve(struct client_state *csp) continue_chatting = 0; config_file_change_detected = 1; } +#ifdef FEATURE_HTTPS_INSPECTION + if (continue_chatting && client_use_ssl(csp) && + csp->ssl_with_client_is_opened == 0) + { + continue_chatting = 0; + log_error(LOG_LEVEL_CONNECT, "Client socket %d is no longer usable. " + "The TLS session has been terminated.", csp->cfd); + } +#endif if (continue_chatting) { @@ -4299,8 +4433,8 @@ static void serve(struct client_state *csp) && socket_is_still_alive(csp->cfd)) { log_error(LOG_LEVEL_CONNECT, - "Client request %u arrived in time on socket %d.", - csp->requests_received_total+1, csp->cfd); + "Data arrived in time on client socket %d. Requests so far: %u", + csp->cfd, csp->requests_received_total); prepare_csp_for_next_request(csp); } else @@ -4308,7 +4442,11 @@ static void serve(struct client_state *csp) #ifdef FEATURE_CONNECTION_SHARING if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) && (csp->server_connection.sfd != JB_INVALID_SOCKET) - && (socket_is_still_alive(csp->server_connection.sfd))) + && (socket_is_still_alive(csp->server_connection.sfd)) +#ifdef FEATURE_HTTPS_INSPECTION + && !server_use_ssl(csp) +#endif + ) { time_t time_open = time(NULL) - csp->server_connection.timestamp; @@ -4363,6 +4501,11 @@ static void serve(struct client_state *csp) forget_connection(csp->server_connection.sfd); } #endif /* def FEATURE_CONNECTION_SHARING */ + +#ifdef FEATURE_HTTPS_INSPECTION + close_server_ssl_connection(csp); +#endif /* def FEATURE_HTTPS_INSPECTION */ + close_socket(csp->server_connection.sfd); } @@ -4378,6 +4521,9 @@ static void serve(struct client_state *csp) csp->cfd, 0 != (csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE), socket_is_still_alive(csp->cfd), data_is_available(csp->cfd, 0), config_file_change_detected, csp->requests_received_total); +#ifdef FEATURE_HTTPS_INSPECTION + close_client_ssl_connection(csp); +#endif drain_and_close_socket(csp->cfd); } @@ -4864,7 +5010,7 @@ int main(int argc, char **argv) * are handled when and where they occur without relying * on a signal. */ -#if !defined(_WIN32) && !defined(__OS2__) +#if !defined(_WIN32) { int idx; const int catched_signals[] = { SIGTERM, SIGINT, SIGHUP }; @@ -5326,7 +5472,7 @@ static void listen_loop(void) for (;;) #endif { -#if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) && !defined(__OS2__) +#if !defined(FEATURE_PTHREAD) && !defined(_WIN32) && !defined(__BEOS__) while (waitpid(-1, NULL, WNOHANG) > 0) { /* zombie children */ @@ -5455,10 +5601,11 @@ static void listen_loop(void) #define SELECTED_ONE_OPTION { pthread_t the_thread; + int ret; - errno = pthread_create(&the_thread, &attrs, + ret = pthread_create(&the_thread, &attrs, (void * (*)(void *))serve, csp); - child_id = errno ? -1 : 0; + child_id = ret ? -1 : 0; } #endif @@ -5470,15 +5617,6 @@ static void listen_loop(void) csp); #endif -#if defined(__OS2__) && !defined(SELECTED_ONE_OPTION) -#define SELECTED_ONE_OPTION - child_id = _beginthread( - (void(* _Optlink)(void*))serve, - NULL, - 64 * 1024, - csp); -#endif - #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION) #define SELECTED_ONE_OPTION { @@ -5608,7 +5746,7 @@ static void listen_loop(void) #ifdef FEATURE_GRACEFUL_TERMINATION - log_error(LOG_LEVEL_ERROR, "Graceful termination requested"); + log_error(LOG_LEVEL_INFO, "Graceful termination requested"); unload_current_config_file(); unload_current_actions_file();