X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jcc.c;h=8f408e8cf51a376a4fe059a5d14f83e042b0ca97;hp=7266e1aad7c655e5a16072dfaa75e448410c77e4;hb=5d6f5f5cec8002999594c3276fc034e23809e604;hpb=8728cdead13a06cddc650bedd58e299d8cc78314 diff --git a/jcc.c b/jcc.c index 7266e1aa..8f408e8c 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.150 2007/09/28 16:39:29 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.171 2008/03/27 18:27:25 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -6,7 +6,7 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.150 2007/09/28 16:39:29 fabiankeil Exp $" * Purpose : Main file. Contains main() method, main loop, and * the main connection-handling function. * - * Copyright : Written by and Copyright (C) 2001-2007 the SourceForge + * Copyright : Written by and Copyright (C) 2001-2008 the SourceForge * Privoxy team. http://www.privoxy.org/ * * Based on the Internet Junkbuster originally written @@ -33,6 +33,90 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.150 2007/09/28 16:39:29 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.171 2008/03/27 18:27:25 fabiankeil + * Remove kill-popups action. + * + * Revision 1.170 2008/03/06 16:33:46 fabiankeil + * If limit-connect isn't used, don't limit CONNECT requests to port 443. + * + * Revision 1.169 2008/03/04 18:30:39 fabiankeil + * Remove the treat-forbidden-connects-like-blocks action. We now + * use the "blocked" page for forbidden CONNECT requests by default. + * + * Revision 1.168 2008/03/02 12:25:25 fabiankeil + * Also use shiny new connect_port_is_forbidden() in jcc.c. + * + * Revision 1.167 2008/02/23 16:57:12 fabiankeil + * Rename url_actions() to get_url_actions() and let it + * use the standard parameter ordering. + * + * Revision 1.166 2008/02/23 16:33:43 fabiankeil + * Let forward_url() use the standard parameter ordering + * and mark its second parameter immutable. + * + * Revision 1.165 2008/02/02 19:36:56 fabiankeil + * Remove the "Listening ... for local connections only" log message. + * Whether or not remote connections are able to reach Privoxy is up + * to the operating system. + * + * Revision 1.164 2007/12/16 18:32:46 fabiankeil + * Prevent the log messages for CONNECT requests to unacceptable + * ports from printing the limit-connect argument as [null] if + * limit-connect hasn't been explicitly enabled. + * + * Revision 1.163 2007/12/13 01:47:11 david__schmidt + * Make sure all console-mode apps get a usage() instance + * + * Revision 1.162 2007/12/06 17:54:57 fabiankeil + * Reword NO_SERVER_DATA_RESPONSE to make it harder + * to misunderstand what the message is all about. + * + * Revision 1.161 2007/12/04 19:44:22 fabiankeil + * Unbreak trustfile which previously didn't work without + * FEATURE_TOGGLE. Fixes BR#1843585, reported by Lee. + * + * Revision 1.160 2007/11/29 18:00:29 fabiankeil + * Plug memory leak. Spotted by Valgrind, triggered by + * Privoxy-Regression-Test feeding proxyfuzz.py. + * + * Revision 1.159 2007/11/24 14:34:09 fabiankeil + * In the HTTP snipplets, refer to the client as client. + * + * Revision 1.158 2007/11/11 16:44:17 fabiankeil + * Emit a log message when activating the MS IIS5 hack. + * + * Revision 1.157 2007/11/03 17:34:49 fabiankeil + * Log the "weak randomization factor" warning only + * once for mingw32 and provide some more details. + * + * Revision 1.156 2007/11/01 18:20:58 fabiankeil + * Initialize log module after initializing mutexes, future + * deadlocks in that code should now work cross-platform. + * + * Revision 1.155 2007/10/23 20:12:45 fabiankeil + * Fix first CSUCCEED line to end in \r\n as required by RFC1945. + * Reported by Bert van Leeuwen in BR#1818808. + * + * Revision 1.154 2007/10/19 17:00:08 fabiankeil + * Downgrade "Flushing header and buffers" message to LOG_LEVEL_INFO. + * + * Revision 1.153 2007/10/14 14:12:41 fabiankeil + * When in daemon mode, close stderr after the configuration file has been + * parsed the first time. If logfile isn't set, stop logging. Fixes BR#897436. + * + * Revision 1.152 2007/10/04 18:03:34 fabiankeil + * - Fix a crash when parsing invalid requests whose first header + * is rejected by get_header(). Regression (re?)introduced + * in r1.143 by yours truly. + * - Move ACTION_VANILLA_WAFER handling into parsers.c's + * client_cookie_adder() to make sure send-vanilla-wafer can be + * controlled through tags (and thus regression-tested). + * + * Revision 1.151 2007/09/29 10:21:16 fabiankeil + * - Move get_filter_function() from jcc.c to filters.c + * so the filter functions can be static. + * - Don't bother filtering body-less responses. + * * Revision 1.150 2007/09/28 16:39:29 fabiankeil * Execute content filters through execute_content_filter(). * @@ -966,7 +1050,6 @@ http://www.fabiankeil.de/sourcecode/privoxy/ #include "filters.h" #include "loaders.h" #include "parsers.h" -#include "killpopup.h" #include "miscutil.h" #include "errlog.h" #include "jbsockets.h" @@ -1007,7 +1090,7 @@ static void build_request_line(struct client_state *csp, const struct forward_sp static jb_err change_request_destination(struct client_state *csp); static void chat(struct client_state *csp); static void serve(struct client_state *csp); -#if defined(unix) +#if !defined(_WIN32) || defined(_WIN_CONSOLE) static void usage(const char *myname); #endif static void initialize_mutexes(void); @@ -1060,49 +1143,33 @@ const char *pidfile = NULL; int received_hup_signal = 0; #endif /* defined unix */ -/* The vanilla wafer. */ -static const char VANILLA_WAFER[] = - "NOTICE=TO_WHOM_IT_MAY_CONCERN_" - "Do_not_send_me_any_copyrighted_information_other_than_the_" - "document_that_I_am_requesting_or_any_of_its_necessary_components._" - "In_particular_do_not_send_me_any_cookies_that_" - "are_subject_to_a_claim_of_copyright_by_anybody._" - "Take_notice_that_I_refuse_to_be_bound_by_any_license_condition_" - "(copyright_or_otherwise)_applying_to_any_cookie._"; - /* HTTP snipplets. */ static const char CSUCCEED[] = - "HTTP/1.0 200 Connection established\n" + "HTTP/1.0 200 Connection established\r\n" "Proxy-Agent: Privoxy/" VERSION "\r\n\r\n"; static const char CHEADER[] = - "HTTP/1.0 400 Invalid header received from browser\r\n" + "HTTP/1.0 400 Invalid header received from client\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" - "Invalid header received from browser.\r\n"; - -static const char CFORBIDDEN[] = - "HTTP/1.0 403 Connection not allowable\r\n" - "Proxy-Agent: Privoxy " VERSION "\r\n" - "X-Hint: If you read this message interactively, then you know why this happens ,-)\r\n" - "Connection: close\r\n\r\n"; + "Invalid header received from client.\r\n"; static const char FTP_RESPONSE[] = - "HTTP/1.0 400 Invalid request received from browser\r\n" + "HTTP/1.0 400 Invalid request received from client\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Invalid request. Privoxy doesn't support FTP.\r\n"; static const char GOPHER_RESPONSE[] = - "HTTP/1.0 400 Invalid request received from browser\r\n" + "HTTP/1.0 400 Invalid request received from client\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Invalid request. Privoxy doesn't support gopher.\r\n"; /* XXX: should be a template */ static const char MISSING_DESTINATION_RESPONSE[] = - "HTTP/1.0 400 Bad request received from browser\r\n" + "HTTP/1.0 400 Bad request received from client\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" @@ -1115,12 +1182,12 @@ static const char NO_SERVER_DATA_RESPONSE[] = "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" "Empty server or forwarder response.\r\n" - "The connection was closed without sending any data.\r\n"; + "The connection has been closed but Privoxy didn't receive any data.\r\n"; #if 0 /* XXX: should be a template */ static const char NULL_BYTE_RESPONSE[] = - "HTTP/1.0 400 Bad request received from browser\r\n" + "HTTP/1.0 400 Bad request received from client\r\n" "Proxy-Agent: Privoxy " VERSION "\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n" @@ -1854,9 +1921,6 @@ static void chat(struct client_state *csp) struct http_request *http; int len; /* for buffer sizes (and negative error codes) */ jb_err err; -#ifdef FEATURE_KILL_POPUPS - int block_popups_now = 0; /* bool, 1==currently blocking popups */ -#endif /* def FEATURE_KILL_POPUPS */ /* Function that does the content filtering for the current request */ filter_function_ptr content_filter = NULL; @@ -1896,7 +1960,7 @@ static void chat(struct client_state *csp) } while ((NULL != req) && ('\0' == *req)); - if (NULL != req) + if ((NULL != req) && ('\0' != *req)) { /* Request received. Validate and parse it. */ @@ -1986,6 +2050,7 @@ static void chat(struct client_state *csp) if (len <= 0) { log_error(LOG_LEVEL_ERROR, "read from client failed: %E"); + destroy_list(headers); return; } @@ -1995,6 +2060,7 @@ static void chat(struct client_state *csp) */ if (add_to_iob(csp, buf, len)) { + destroy_list(headers); return; } continue; @@ -2024,7 +2090,7 @@ static void chat(struct client_state *csp) * An error response has already been send * and we're done here. */ - return; + return; } } @@ -2040,7 +2106,7 @@ static void chat(struct client_state *csp) else #endif /* ndef FEATURE_TOGGLE */ { - url_actions(http, csp); + get_url_actions(csp, http); } /* @@ -2059,16 +2125,6 @@ static void chat(struct client_state *csp) list_append_list_unique(csp->headers, headers); destroy_list(headers); - /* - * If the user has not supplied any wafers, and the user has not - * told us to suppress the vanilla wafer, then send the vanilla wafer. - */ - if (list_is_empty(csp->action->multi[ACTION_MULTI_WAFER]) - && ((csp->action->flags & ACTION_VANILLA_WAFER) != 0)) - { - enlist(csp->action->multi[ACTION_MULTI_WAFER], VANILLA_WAFER); - } - err = sed(client_patterns, add_client_headers, csp); if (JB_ERR_OK != err) { @@ -2095,7 +2151,8 @@ static void chat(struct client_state *csp) } /* decide how to route the HTTP request */ - if (NULL == (fwd = forward_url(http, csp))) + fwd = forward_url(csp, http); + if (NULL == fwd) { log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!"); /* Never get here - LOG_LEVEL_FATAL causes program exit */ @@ -2138,50 +2195,16 @@ static void chat(struct client_state *csp) * */ - /* - * Check if a CONNECT request is allowable: - * In the absence of a +limit-connect action, allow only port 443. - * If there is an action, allow whatever matches the specificaton. - */ - if(http->ssl) + if (http->ssl && connect_port_is_forbidden(csp)) { - if( ( !(csp->action->flags & ACTION_LIMIT_CONNECT) && csp->http->port != 443) - || (csp->action->flags & ACTION_LIMIT_CONNECT - && !match_portlist(csp->action->string[ACTION_STRING_LIMIT_CONNECT], csp->http->port)) ) - { - if (csp->action->flags & ACTION_TREAT_FORBIDDEN_CONNECTS_LIKE_BLOCKS) - { - /* - * The response may confuse some clients, - * but makes unblocking easier. - * - * XXX: It seems to work with all major browsers, - * so we should consider returning a body by default someday ... - */ - log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. " - "limit-connect{%s} doesn't allow CONNECT requests to port %d.", - csp->ip_addr_str, csp->action->string[ACTION_STRING_LIMIT_CONNECT], - csp->http->port); - csp->action->flags |= ACTION_BLOCK; - http->ssl = 0; - } - else - { - write_socket(csp->cfd, CFORBIDDEN, strlen(CFORBIDDEN)); - log_error(LOG_LEVEL_INFO, "Request from %s denied. " - "limit-connect{%s} doesn't allow CONNECT requests to port %d.", - csp->ip_addr_str, csp->action->string[ACTION_STRING_LIMIT_CONNECT], - csp->http->port); - assert(NULL != csp->http->ocmd); - log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 403 0", csp->ip_addr_str, csp->http->ocmd); - - list_remove_all(csp->headers); - /* - * XXX: For consistency we might want to log a crunch message here. - */ - return; - } - } + const char *acceptable_connect_ports = + csp->action->string[ACTION_STRING_LIMIT_CONNECT]; + assert(NULL != acceptable_connect_ports); + log_error(LOG_LEVEL_INFO, "Request from %s marked for blocking. " + "limit-connect{%s} doesn't allow CONNECT requests to port %d.", + csp->ip_addr_str, acceptable_connect_ports, csp->http->port); + csp->action->flags |= ACTION_BLOCK; + http->ssl = 0; } if (http->ssl == 0) @@ -2279,7 +2302,7 @@ static void chat(struct client_state *csp) */ if (write_socket(csp->sfd, hdr, strlen(hdr)) - || (flush_socket(csp->sfd, csp) < 0)) + || (flush_socket(csp->sfd, csp->iob) < 0)) { log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E", http->hostport); @@ -2422,14 +2445,6 @@ static void chat(struct client_state *csp) */ buf[len] = '\0'; -#ifdef FEATURE_KILL_POPUPS - /* Filter the popups on this read. */ - if (block_popups_now) - { - filter_popups(buf, csp); - } -#endif /* def FEATURE_KILL_POPUPS */ - /* Normally, this would indicate that we've read * as much as the server has sent us and we can * close the client connection. However, Microsoft @@ -2509,6 +2524,9 @@ static void chat(struct client_state *csp) * This is NOT the body, so * Let's pretend the server just sent us a blank line. */ + log_error(LOG_LEVEL_INFO, + "Malformerd HTTP headers detected and MS IIS5 hack enabled. " + "Expect an invalid response or even no response at all."); snprintf(buf, sizeof(buf), "\r\n"); len = (int)strlen(buf); @@ -2540,7 +2558,7 @@ static void chat(struct client_state *csp) size_t hdrlen; int flushed; - log_error(LOG_LEVEL_ERROR, "Flushing header and buffers. Stepping back from filtering."); + log_error(LOG_LEVEL_INFO, "Flushing header and buffers. Stepping back from filtering."); hdr = list_to_text(csp->headers); if (hdr == NULL) @@ -2558,7 +2576,7 @@ static void chat(struct client_state *csp) hdrlen = strlen(hdr); if (write_socket(csp->cfd, hdr, hdrlen) - || ((flushed = flush_socket(csp->cfd, csp)) < 0) + || ((flushed = flush_socket(csp->cfd, csp->iob)) < 0) || (write_socket(csp->cfd, buf, (size_t)len))) { log_error(LOG_LEVEL_CONNECT, "Flush header and buffers to client failed: %E"); @@ -2673,20 +2691,6 @@ static void chat(struct client_state *csp) if (!http->ssl) /* We talk plaintext */ { - -#ifdef FEATURE_KILL_POPUPS - /* Start blocking popups if appropriate. */ - if ((csp->content_type & CT_TEXT) && /* It's a text / * MIME-Type */ - (csp->action->flags & ACTION_NO_POPUPS) != 0) /* Policy allows */ - { - block_popups_now = 1; - /* - * Filter the part of the body that came in the same read - * as the last headers: - */ - filter_popups(csp->iob->cur, csp); - } -#endif /* def FEATURE_KILL_POPUPS */ content_filter = get_filter_function(csp); } /* @@ -2700,7 +2704,7 @@ static void chat(struct client_state *csp) */ if (write_socket(csp->cfd, hdr, strlen(hdr)) - || ((len = flush_socket(csp->cfd, csp)) < 0)) + || ((len = flush_socket(csp->cfd, csp->iob)) < 0)) { log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); @@ -2805,7 +2809,7 @@ static int32 server_thread(void *data) #endif -#if defined(unix) +#if !defined(_WIN32) || defined(_WIN_CONSOLE) /********************************************************************* * * Function : usage @@ -2834,7 +2838,7 @@ static void usage(const char *myname) exit(2); } -#endif /* defined(unix) */ +#endif /* #if !defined(_WIN32) || defined(_WIN_CONSOLE) */ /********************************************************************* @@ -3099,6 +3103,7 @@ int main(int argc, const char *argv[]) files->next = NULL; clients->next = NULL; + /* XXX: factor out initialising after the next stable release. */ #ifdef AMIGA InitAmiga(); #elif defined(_WIN32) @@ -3108,9 +3113,21 @@ int main(int argc, const char *argv[]) /* Prepare mutexes if supported and necessary. */ initialize_mutexes(); + /* Enable logging until further notice. */ + init_log_module(Argv[0]); + random_seed = (unsigned int)time(NULL); #ifdef HAVE_RANDOM srandom(random_seed); +#elif defined (_WIN32) + /* + * See pick_from_range() in miscutil.c for details. + */ + log_error(LOG_LEVEL_INFO, + "No thread-safe PRNG implemented for your platform. " + "Using weak \'randomization\' factor which will " + "limit the already questionable usefulness of " + "header-time-randomizing actions (disabled by default)."); #else srand(random_seed); #endif /* ifdef HAVE_RANDOM */ @@ -3218,10 +3235,9 @@ int main(int argc, const char *argv[]) close ( fd ); } #endif /* 1 */ - /* FIXME: should close stderr (fd 2) here too, but the test - * for existence - * and load config file is done in listen_loop() and puts - * some messages on stderr there. + /* + * stderr (fd 2) will be closed later on, when the + * log file has been parsed. */ close( 0 ); @@ -3351,16 +3367,7 @@ static jb_socket bind_port_helper(struct configuration_spec * config) int result; jb_socket bfd; - if ( (config->haddr != NULL) - && (config->haddr[0] == '1') - && (config->haddr[1] == '2') - && (config->haddr[2] == '7') - && (config->haddr[3] == '.') ) - { - log_error(LOG_LEVEL_INFO, "Listening on port %d for local connections only", - config->hport); - } - else if (config->haddr == NULL) + if (config->haddr == NULL) { log_error(LOG_LEVEL_INFO, "Listening on port %d on all IP addresses", config->hport); @@ -3460,7 +3467,7 @@ static void listen_loop(void) */ if (received_hup_signal) { - init_error_log(Argv[0], config->logfile, config->debug); + init_error_log(Argv[0], config->logfile); received_hup_signal = 0; } #endif @@ -3535,10 +3542,10 @@ static void listen_loop(void) #ifdef FEATURE_TOGGLE if (global_toggle_state) +#endif /* def FEATURE_TOGGLE */ { csp->flags |= CSP_FLAG_TOGGLED_ON; } -#endif /* def FEATURE_TOGGLE */ if (run_loader(csp)) {