X-Git-Url: http://www.privoxy.org/gitweb/?p=privoxy.git;a=blobdiff_plain;f=jcc.c;h=7c09830b8cf92311c3c3ffbdcbec3248e247a576;hp=b3509e46add12dcc71c61dd791ef4260ef42816e;hb=8d59f7cc685e7b83a3634a329f7f8eabe583653a;hpb=69206227e248b4845fe7e6ff9fe04ce3edcf2bd6 diff --git a/jcc.c b/jcc.c index b3509e46..7c09830b 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.37 2001/09/10 11:12:24 oes Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.47 2001/10/10 16:44:36 oes Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,52 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.37 2001/09/10 11:12:24 oes Exp $"; * * Revisions : * $Log: jcc.c,v $ + * Revision 1.47 2001/10/10 16:44:36 oes + * Added CONNECT destination port limitation check + * + * Revision 1.46 2001/10/08 15:17:41 oes + * Re-enabled SSL forwarding + * + * Revision 1.45 2001/10/07 15:42:11 oes + * Replaced 6 boolean members of csp with one bitmap (csp->flags) + * + * Moved downgrading of the HTTP version from parse_http_request to + * chat(), since we can't decide if it is necessary before we have + * determined the actions for the URL. The HTTP command is now + * *always* re-built so the repairs need no longer be special-cased. + * + * filter_popups now gets a csp pointer so it can raise the new + * CSP_FLAG_MODIFIED flag. + * + * Bugfix + * + * Added configurable size limit for the IOB. If the IOB grows so + * large that the next read would exceed the limit, the header + * is generated, and the header & unfiltered buffer are flushed + * to the client. Chat then continues in non-buffering, + * non-filtering body mode. + * + * Revision 1.44 2001/10/02 18:13:57 oes + * Ooops + * + * Revision 1.43 2001/10/02 15:32:13 oes + * Moved generation of hdr + * + * Revision 1.42 2001/09/21 23:02:02 david__schmidt + * Cleaning up 2 compiler warnings on OS/2. + * + * Revision 1.41 2001/09/16 17:05:14 jongfoster + * Removing unused #include showarg.h + * + * Revision 1.40 2001/09/16 15:41:45 jongfoster + * Fixing signed/unsigned comparison warning. + * + * Revision 1.39 2001/09/16 13:21:27 jongfoster + * Changes to use new list functions. + * + * Revision 1.38 2001/09/16 13:01:46 jongfoster + * Removing redundant function call that zeroed zalloc()'d memory. + * * Revision 1.37 2001/09/10 11:12:24 oes * Deleted unused variable * @@ -321,6 +367,10 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.37 2001/09/10 11:12:24 oes Exp $"; # include /* declarations for threads and stuff. */ # endif +# ifdef __EMX__ +# include /* OS/2/EMX needs a little help with select */ +# endif + # ifndef FD_ZERO # include # endif @@ -332,7 +382,6 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.37 2001/09/10 11:12:24 oes Exp $"; #include "jcc.h" #include "filters.h" #include "loaders.h" -#include "showargs.h" #include "parsers.h" #include "killpopup.h" #include "miscutil.h" @@ -408,17 +457,17 @@ static void chat(struct client_state *csp) { /* * This next lines are a little ugly, but they simplifies the if statements - * below. Basically if TOGGLE, then we want the if to test "csp->toggled_on", - * else we don't. And if FEATURE_FORCE_LOAD, then we want the if to test - * "csp->toggled_on", else we don't + * below. Basically if TOGGLE, then we want the if to test if the + * CSP_FLAG_TOGGLED_ON flag ist set, else we don't. And if FEATURE_FORCE_LOAD, + * then we want the if to test for CSP_FLAG_FORCED , else we don't */ #ifdef FEATURE_TOGGLE -# define IS_TOGGLED_ON_AND (csp->toggled_on) && +# define IS_TOGGLED_ON_AND (csp->flags & CSP_FLAG_TOGGLED_ON) && #else /* ifndef FEATURE_TOGGLE */ # define IS_TOGGLED_ON_AND #endif /* ndef FEATURE_TOGGLE */ #ifdef FEATURE_FORCE_LOAD -# define IS_NOT_FORCED_AND (!csp->force) && +# define IS_NOT_FORCED_AND !(csp->flags & CSP_FLAG_FORCED) && #else /* ifndef FEATURE_FORCE_LOAD */ # define IS_NOT_FORCED_AND #endif /* def FEATURE_FORCE_LOAD */ @@ -483,14 +532,11 @@ static void chat(struct client_state *csp) { strclean(req, FORCE_PREFIX); log_error(LOG_LEVEL_FORCE, "Enforcing request \"%s\".\n", req); - csp->force = 1; + csp->flags |= CSP_FLAG_FORCED; } - else - { - csp->force = 0; - } + #endif /* def FEATURE_FORCE_LOAD */ - + parse_http_request(req, http, csp); freez(req); break; @@ -518,61 +564,112 @@ static void chat(struct client_state *csp) * we have to do one of the following: * * create = use the original HTTP request to create a new - * HTTP request that has only the path component - * without the http://domainspec - * pass = pass the original HTTP request unchanged + * HTTP request that has either the path component + * without the http://domainspec (w/path) or the + * full orininal URL (w/url) + * Note that the path and/or the HTTP version may + * have been altered by now. + * + * connect = Open a socket to the host:port of the server + * and short-circuit server and client socket. * - * drop = drop the HTTP request + * pass = Pass the request unchanged if forwarding a CONNECT + * request to a parent proxy. Note that we'll be sending + * the CFAIL message ourselves if connecting to the parent + * fails, but we won't send a CSUCCEED message if it works, + * since that would result in a double message (ours and the + * parent's). After sending the request to the parent, we simply + * tunnel. * - * here's the matrix: + * here's the matrix: * SSL * 0 1 * +--------+--------+ * | | | - * 0 | create | drop | - * | | | + * 0 | create | connect| + * | w/path | | * Forwarding +--------+--------+ * | | | - * 1 | pass | pass | - * | | | + * 1 | create | pass | + * | w/url | | * +--------+--------+ * */ - if (fwd->forward_host) + /* + * Determine the actions for this URL + */ +#ifdef FEATURE_TOGGLE + if (!(csp->flags & CSP_FLAG_TOGGLED_ON)) { - /* if forwarding, just pass the request as is */ - enlist(csp->headers, http->cmd); + /* Most compatible set of actions (i.e. none) */ + init_current_action(csp->action); } else +#endif /* ndef FEATURE_TOGGLE */ { - if (http->ssl == 0) - { - /* otherwise elide the host information from the url */ - p = NULL; - p = strsav(p, http->gpc); - p = strsav(p, " "); - p = strsav(p, http->path); - p = strsav(p, " "); - p = strsav(p, http->ver); - enlist(csp->headers, p); - freez(p); - } + url_actions(http, csp); } - /* decide what we're to do with cookies */ -#ifdef FEATURE_TOGGLE - if (!csp->toggled_on) + /* + * 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) { - /* Most compatible set of actions (i.e. none) */ - init_current_action(csp->action); + 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)) ) + { + strcpy(buf, CFORBIDDEN); + write_socket(csp->cfd, buf, strlen(buf)); + + log_error(LOG_LEVEL_CONNECT, "Denying suspicious CONNECT request from %s", csp->ip_addr_str); + log_error(LOG_LEVEL_CLF, "%s - - [%T] \" \" 403 0", csp->ip_addr_str); + + return; + } } - else -#endif /* ndef FEATURE_TOGGLE */ + + + /* + * Downgrade http version from 1.1 to 1.0 if +downgrade + * action applies + */ + if (!strcmpic(http->ver, "HTTP/1.1") && csp->action->flags & ACTION_DOWNGRADE) { - url_actions(http, csp); + freez(http->ver); + http->ver = strdup("HTTP/1.0"); + } + + /* + * (Re)build the HTTP request for non-SSL requests. + * If forwarding, use the whole URL, else, use only the path. + */ + if (http->ssl == 0) + { + freez(http->cmd); + + http->cmd = strsav(http->cmd, http->gpc); + http->cmd = strsav(http->cmd, " "); + + if (fwd->forward_host) + { + http->cmd = strsav(http->cmd, http->url); + } + else + { + http->cmd = strsav(http->cmd, http->path); + } + + http->cmd = strsav(http->cmd, " "); + http->cmd = strsav(http->cmd, http->ver); + } + enlist(csp->headers, http->cmd); + #ifdef FEATURE_COOKIE_JAR /* @@ -581,13 +678,14 @@ static void chat(struct client_state *csp) * vanilla wafer, then send the vanilla wafer. */ if ((csp->config->jarfile != NULL) - && (csp->action->multi[ACTION_MULTI_WAFER]->next == NULL) + && 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); } #endif /* def FEATURE_COOKIE_JAR */ + #ifdef FEATURE_KILL_POPUPS block_popups = ((csp->action->flags & ACTION_NO_POPUPS) != 0); #endif /* def FEATURE_KILL_POPUPS */ @@ -621,9 +719,6 @@ static void chat(struct client_state *csp) /* We have a request. */ - hdr = sed(client_patterns, add_client_headers, csp); - destroy_list(csp->headers); - /* * Now, check to see if we need to intercept it, i.e. * If @@ -661,7 +756,7 @@ static void chat(struct client_state *csp) #ifdef FEATURE_STATISTICS /* Count as a rejected request */ - csp->rejected = 1; + csp->flags |= CSP_FLAG_REJECTED; #endif /* def FEATURE_STATISTICS */ /* Log (FIXME: All intercept reasons apprear as "crunch" with Status 200) */ @@ -670,7 +765,6 @@ static void chat(struct client_state *csp) /* Clean up and return */ free_http_response(rsp); - freez(hdr); return; } @@ -721,12 +815,14 @@ static void chat(struct client_state *csp) } free_http_response(rsp); - freez(hdr); return; } log_error(LOG_LEVEL_CONNECT, "OK"); + hdr = sed(client_patterns, add_client_headers, csp); + list_remove_all(csp->headers); + if (fwd->forward_host || (http->ssl == 0)) { /* write the client's (modified) header to the server @@ -868,7 +964,7 @@ static void chat(struct client_state *csp) /* Filter the popups on this read. */ if (block_popups_now) { - filter_popups(buf); + filter_popups(buf, csp); } #endif /* def FEATURE_KILL_POPUPS */ @@ -916,14 +1012,16 @@ static void chat(struct client_state *csp) n = strlen(hdr); if ((write_socket(csp->cfd, hdr, n) != n) - || (write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length) != csp->content_length)) + || (write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length) != (int)csp->content_length)) { - log_error(LOG_LEVEL_CONNECT, "write modified content to client failed: %E"); + log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E"); return; } freez(hdr); - freez(p); + if (NULL != p) { + freez(p); + } } break; /* "game over, man" */ @@ -954,6 +1052,36 @@ static void chat(struct client_state *csp) if (content_filter) { add_to_iob(csp, buf, n); + + /* + * If the buffer limit will be reached on the next read, + * switch to non-filtering mode, i.e. make & write the + * header, flush the socket and get out of the way. + */ + if (csp->iob->eod - csp->iob->buf + BUFFER_SIZE > csp->config->buffer_limit) + { + log_error(LOG_LEVEL_ERROR, "Buffer size limit reached! Flushing and stepping back."); + + hdr = sed(server_patterns, add_server_headers, csp); + n = strlen(hdr); + byte_count += n; + + if (((write_socket(csp->cfd, hdr, n) != n) + || (n = flush_socket(csp->cfd, csp) < 0))) + { + log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E"); + + freez(hdr); + return; + } + + freez(hdr); + byte_count += n; + + content_filter = NULL; + server_body = 1; + + } } else { @@ -1042,7 +1170,7 @@ static void chat(struct client_state *csp) * Filter the part of the body that came in the same read * as the last headers: */ - filter_popups(csp->iob->cur); + filter_popups(csp->iob->cur, csp); } #endif /* def FEATURE_KILL_POPUPS */ @@ -1137,7 +1265,7 @@ static void serve(struct client_state *csp) close_socket(csp->sfd); } - csp->active = 0; + csp->flags &= ~CSP_FLAG_ACTIVE; } @@ -1315,7 +1443,7 @@ static void listen_loop(void) continue; } - csp->active = 1; + csp->flags |= CSP_FLAG_ACTIVE; csp->sfd = -1; csp->config = config = load_config(); @@ -1377,8 +1505,10 @@ static void listen_loop(void) } #ifdef FEATURE_TOGGLE - /* by haroon - most of credit to srt19170 */ - csp->toggled_on = g_bToggleIJB; + if (g_bToggleIJB) + { + csp->flags |= CSP_FLAG_TOGGLED_ON; + } #endif /* def FEATURE_TOGGLE */ if (run_loader(csp)) @@ -1490,7 +1620,7 @@ static void listen_loop(void) wait( NULL ); #endif /* !defined(_WIN32) && defined(__CYGWIN__) */ close_socket(csp->cfd); - csp->active = 0; + csp->flags &= ~CSP_FLAG_ACTIVE; } #endif @@ -1507,7 +1637,7 @@ static void listen_loop(void) write_socket(csp->cfd, buf, strlen(buf)); close_socket(csp->cfd); - csp->active = 0; + csp->flags &= ~CSP_FLAG_ACTIVE; sleep(5); continue; }