X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=jcc.c;h=a4e430ef8d3c70ba1b02ecebcc8c262523fdbd50;hb=a0d27be015948b09b3903108377a4b1b6d0924c8;hp=c726713e443f990db9e5ecb62aff1c22aa77e0bf;hpb=74a1e3a8a7da3082faf2f7c4cfe22e0dc1a73f2f;p=privoxy.git diff --git a/jcc.c b/jcc.c index c726713e..a4e430ef 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.142 2007/08/05 13:50:26 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.147 2007/08/25 14:42:40 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,26 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.142 2007/08/05 13:50:26 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.147 2007/08/25 14:42:40 fabiankeil + * Don't crash if a broken header filter wiped out the request line. + * + * Revision 1.146 2007/08/20 17:09:32 fabiankeil + * Fix byte_count calculation in case of flushes + * and don't parse the server headers a second time. + * + * Revision 1.145 2007/08/19 13:13:31 fabiankeil + * - If there's a connection problem after we already forwarded + * parts of the original content, just hang up. Fixes BR#1776724. + * - Fix warnings about unused code on mingw32. + * - In case of flushes, calculate the byte count + * less incorrectly (I think). + * + * Revision 1.144 2007/08/11 14:43:22 fabiankeil + * Add some more prototypes for static functions. + * + * Revision 1.143 2007/08/05 13:58:19 fabiankeil + * Comment out request_contains_null_bytes() until it's used again. + * * Revision 1.142 2007/08/05 13:50:26 fabiankeil * #1763173 from Stefan Huehner: s@const static@static const@ * and declare some more functions static. @@ -961,8 +981,28 @@ int urls_rejected = 0; /* total nr of urls rejected */ int g_terminate = 0; #endif -static void listen_loop(void); +#if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA) +static void sig_handler(int the_signal); +#endif +static int client_protocol_is_unsupported(const struct client_state *csp, char *req); +static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers); +static jb_err get_server_headers(struct client_state *csp); +static const char *crunch_reason(const struct http_response *rsp); +static void send_crunch_response(struct client_state *csp, struct http_response *rsp); +/* + * static int request_contains_null_bytes(const struct client_state *csp, char *buf, int len); + */ +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 chat(struct client_state *csp); +static void serve(struct client_state *csp); +#if defined(unix) +static void usage(const char *myname); +#endif +static void initialize_mutexes(void); +static jb_socket bind_port_helper(struct configuration_spec *config); +static void listen_loop(void); + #ifdef AMIGA void serve(struct client_state *csp); #else /* ifndef AMIGA */ @@ -1101,6 +1141,9 @@ struct cruncher const int flags; }; +static int crunch_response_triggered(struct client_state *csp, const struct cruncher crunchers[]); +static filter_function_ptr get_filter_function(struct client_state *csp); + /* Complete list of cruncher functions */ static const struct cruncher crunchers_all[] = { { direct_response, CF_COUNT_AS_REJECT|CF_IGNORE_FORCE}, @@ -2105,22 +2148,21 @@ static void chat(struct client_state *csp) } csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE; - if (strcmp(http->cmd, csp->headers->first->str)) + /* Check request line for rewrites. */ + if ((NULL == csp->headers->first->str) + || (strcmp(http->cmd, csp->headers->first->str) && + (JB_ERR_OK != change_request_destination(csp)))) { /* - * A header filter rewrote the request line, - * modify the http request accordingly. + * A header filter broke the request line - bail out. */ - if (JB_ERR_OK != change_request_destination(csp)) - { - write_socket(csp->cfd, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE)); - /* XXX: Use correct size */ - log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request generated\" 500 0", csp->ip_addr_str); - log_error(LOG_LEVEL_ERROR, "Invalid request line after applying header filters."); + write_socket(csp->cfd, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE)); + /* XXX: Use correct size */ + log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request generated\" 500 0", csp->ip_addr_str); + log_error(LOG_LEVEL_ERROR, "Invalid request line after applying header filters."); - free_http_request(http); - return; - } + free_http_request(http); + return; } /* decide how to route the HTTP request */ @@ -2421,10 +2463,23 @@ static void chat(struct client_state *csp) "CONNECT already confirmed. Unable to tell the client about the problem."); return; } + else if (byte_count) + { + /* + * Just hang up. We already transmitted the original headers + * and parts of the original content and therefore missed the + * chance to send an error message (without risking data corruption). + * + * XXX: we could retry with a fancy range request here. + */ + log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. " + "Unable to tell the client about the problem."); + return; + } rsp = error_response(csp, "connect-failed", errno); - if(rsp) + if (rsp) { send_crunch_response(csp, rsp); } @@ -2555,10 +2610,7 @@ static void chat(struct client_state *csp) int flushed; log_error(LOG_LEVEL_ERROR, "Flushing header and buffers. Stepping back from filtering."); - if (JB_ERR_OK != sed(server_patterns, add_server_headers, csp)) - { - log_error(LOG_LEVEL_FATAL, "Failed to parse server headers."); - } + hdr = list_to_text(csp->headers); if (hdr == NULL) { @@ -2572,19 +2624,6 @@ static void chat(struct client_state *csp) return; } - - if (crunch_response_triggered(csp, crunchers_light)) - { - /* - * One of the tags created by a server-header - * tagger triggered a crunch. We already - * delivered the crunch response to the client - * and are done here after cleaning up. - */ - freez(hdr); - return; - } - hdrlen = strlen(hdr); if (write_socket(csp->cfd, hdr, hdrlen) @@ -2597,11 +2636,15 @@ static void chat(struct client_state *csp) return; } - byte_count += hdrlen + (size_t)flushed + (size_t)len; + /* + * 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. + */ + byte_count = (size_t)flushed; freez(hdr); content_filter = NULL; server_body = 1; - } } else @@ -2831,6 +2874,7 @@ static int32 server_thread(void *data) #endif +#if defined(unix) /********************************************************************* * * Function : usage @@ -2851,7 +2895,7 @@ static void usage(const char *myname) #endif /* defined(unix) */ "[--help] " #if defined(unix) - "[--no-daemon] [--pidfile pidfile] [--user user[.group]] " + "[--no-daemon] [--pidfile pidfile] [--pre-chroot-nslookup hostname] [--user user[.group]] " #endif /* defined(unix) */ "[--version] [configfile]\n" "Aborting\n", myname); @@ -2859,6 +2903,7 @@ static void usage(const char *myname) exit(2); } +#endif /* defined(unix) */ /********************************************************************* @@ -2963,6 +3008,7 @@ int main(int argc, const char *argv[]) struct group *grp = NULL; char *p; int do_chroot = 0; + char *pre_chroot_nslookup_to_load_resolver = NULL; #endif Argc = argc; @@ -3057,6 +3103,12 @@ int main(int argc, const char *argv[]) if (p != NULL) *--p = '\0'; } + else if (strcmp(argv[argc_pos], "--pre-chroot-nslookup" ) == 0) + { + if (++argc_pos == argc) usage(argv[0]); + pre_chroot_nslookup_to_load_resolver = strdup(argv[argc_pos]); + } + else if (strcmp(argv[argc_pos], "--chroot" ) == 0) { do_chroot = 1; @@ -3265,6 +3317,14 @@ int main(int argc, const char *argv[]) { log_error(LOG_LEVEL_FATAL, "Home directory for %s undefined", pw->pw_name); } + /* Read the time zone file from /etc before doing chroot. */ + tzset(); + if (NULL != pre_chroot_nslookup_to_load_resolver + && '\0' != pre_chroot_nslookup_to_load_resolver[0]) + { + /* Initialize resolver library. */ + (void) resolve_hostname_to_ip(pre_chroot_nslookup_to_load_resolver); + } if (chroot(pw->pw_dir) < 0) { log_error(LOG_LEVEL_FATAL, "Cannot chroot to %s", pw->pw_dir);