From: Fabian Keil Date: Fri, 1 Jun 2007 16:41:11 +0000 (+0000) Subject: Add forward-override{} to change the forwarding settings through X-Git-Tag: v_3_0_7~228 X-Git-Url: http://www.privoxy.org/gitweb/%40user-manual%40%40actions-help-prefix%40SERVER-HEADER-FILTER?a=commitdiff_plain;h=0faa75b156fa3f5c0e09a620a9a16db5996c3e7a;p=privoxy.git Add forward-override{} to change the forwarding settings through action sections. This is mainly interesting to forward different clients differently (for example based on User-Agent or request origin). --- diff --git a/filters.c b/filters.c index f6665bf0..deeb7d8f 100644 --- a/filters.c +++ b/filters.c @@ -1,4 +1,4 @@ -const char filters_rcs[] = "$Id: filters.c,v 1.86 2007/04/30 15:03:28 fabiankeil Exp $"; +const char filters_rcs[] = "$Id: filters.c,v 1.87 2007/04/30 15:53:10 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/filters.c,v $ @@ -40,6 +40,9 @@ const char filters_rcs[] = "$Id: filters.c,v 1.86 2007/04/30 15:03:28 fabiankeil * * Revisions : * $Log: filters.c,v $ + * Revision 1.87 2007/04/30 15:53:10 fabiankeil + * Make sure filters with dynamic jobs actually use them. + * * Revision 1.86 2007/04/30 15:03:28 fabiankeil * - Introduce dynamic pcrs jobs that can resolve variables. * - Don't run redirect functions more than once, @@ -586,6 +589,7 @@ const char filters_rcs[] = "$Id: filters.c,v 1.86 2007/04/30 15:03:28 fabiankeil #include "list.h" #include "deanimate.h" #include "urlmatch.h" +#include "loaders.h" #ifdef _WIN32 #include "win32.h" @@ -2314,12 +2318,155 @@ void apply_url_actions(struct current_action_spec *action, } +/********************************************************************* + * + * Function : get_forward_override_settings + * + * Description : Returns forward settings as specified with the + * forward-override{} action. forward-override accepts + * forward lines similar to the one used in the + * configuration file, but without the URL pattern. + * + * For example: + * + * forward / . + * + * in the configuration file can be replaced with + * the action section: + * + * {+forward-override{forward .}} + * / + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : Pointer to forwarding structure in case of success. + * Invalid syntax is fatal. + * + *********************************************************************/ +const struct forward_spec *get_forward_override_settings(struct client_state *csp) +{ + const char *forward_override_line = csp->action->string[ACTION_STRING_FORWARD_OVERRIDE]; + char forward_settings[BUFFER_SIZE]; + char *http_parent = NULL; + /* variable names were chosen for consistency reasons. */ + struct forward_spec *fwd = NULL; + int vec_count; + char *vec[3]; + + assert(csp->action->flags & ACTION_FORWARD_OVERRIDE); + /* Should be enforced by load_one_actions_file() */ + assert(strlen(forward_override_line) < sizeof(forward_settings) - 1); + + /* Create a copy ssplit can modify */ + strlcpy(forward_settings, forward_override_line, sizeof(forward_settings)); + + if (NULL != csp->fwd) + { + /* + * XXX: Currently necessary to prevent memory + * leaks when the show-url-info cgi page is visited. + */ + unload_forward_spec(csp->fwd); + } + + /* + * allocate a new forward node, valid only for + * the lifetime of this request. Save its location + * in csp as well, so sweep() can free it later on. + */ + fwd = csp->fwd = zalloc(sizeof(*fwd)); + if (NULL == fwd) + { + log_error(LOG_LEVEL_FATAL, + "can't allocate memory for forward-override{%s}", forward_override_line); + /* Never get here - LOG_LEVEL_FATAL causes program exit */ + } + + vec_count = ssplit(forward_settings, " \t", vec, SZ(vec), 1, 1); + if ((vec_count == 2) && !strcasecmp(vec[0], "forward")) + { + fwd->type = SOCKS_NONE; + + /* Parse the parent HTTP proxy host:port */ + http_parent = vec[1]; + + } + else if (vec_count == 3) + { + char *socks_proxy = NULL; + + if (!strcasecmp(vec[0], "forward-socks4")) + { + fwd->type = SOCKS_4; + socks_proxy = vec[1]; + } + else if (!strcasecmp(vec[0], "forward-socks4a")) + { + fwd->type = SOCKS_4A; + socks_proxy = vec[1]; + } + + if (NULL != socks_proxy) + { + /* Parse the SOCKS proxy host[:port] */ + fwd->gateway_host = strdup(socks_proxy); + + if (NULL != (socks_proxy = strchr(fwd->gateway_host, ':'))) + { + *socks_proxy++ = '\0'; + fwd->gateway_port = strtol(socks_proxy, NULL, 0); + } + + if (fwd->gateway_port <= 0) + { + fwd->gateway_port = 1080; + } + + http_parent = vec[2]; + } + } + + if (NULL == http_parent) + { + log_error(LOG_LEVEL_FATAL, + "Invalid forward-override syntax in: %s", forward_override_line); + /* Never get here - LOG_LEVEL_FATAL causes program exit */ + } + + /* Parse http forwarding settings */ + if (strcmp(http_parent, ".") != 0) + { + fwd->forward_host = strdup(http_parent); + + if (NULL != (http_parent = strchr(fwd->forward_host, ':'))) + { + *http_parent++ = '\0'; + fwd->forward_port = strtol(http_parent, NULL, 0); + } + + if (fwd->forward_port <= 0) + { + fwd->forward_port = 8000; + } + } + + assert (NULL != fwd); + + log_error(LOG_LEVEL_CONNECT, + "Overriding forwarding settings based on \'%s\'", forward_override_line); + + return fwd; +} + /********************************************************************* * * Function : forward_url * * Description : Should we forward this to another proxy? * + * XXX: Should be changed to make use of csp->fwd. + * * Parameters : * 1 : http = http_request request for current URL * 2 : csp = Current client state (buffers, headers, etc...) @@ -2333,6 +2480,11 @@ const struct forward_spec * forward_url(struct http_request *http, static const struct forward_spec fwd_default[1] = { FORWARD_SPEC_INITIALIZER }; struct forward_spec *fwd = csp->config->forward; + if (csp->action->flags & ACTION_FORWARD_OVERRIDE) + { + return get_forward_override_settings(csp); + } + if (fwd == NULL) { return fwd_default; diff --git a/jcc.c b/jcc.c index 62f54ad9..0e83a68f 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.134 2007/05/16 14:59:46 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.135 2007/05/24 17:03:50 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,12 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.134 2007/05/16 14:59:46 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.135 2007/05/24 17:03:50 fabiankeil + * - Let usage() mention the --chroot parameter. + * - Use read_socket() consistently and always leave + * the last buffer byte alone, even in cases where + * null termination (currently) doesn't matter. + * * Revision 1.134 2007/05/16 14:59:46 fabiankeil * - Fix config file loading on Unix if no config file is specified. * Since r1.97 Privoxy would always interpret the last argument as @@ -1604,11 +1610,13 @@ int crunch_response_triggered(struct client_state *csp, const struct cruncher cr * Parameters : * 1 : csp = Current client state (buffers, headers, etc...) * 2 : fwd = The forwarding spec used for the request + * XXX: Should use http->fwd instead. + * 3 : request_line = The old request line which will be replaced. * * Returns : Nothing. Terminates in case of memory problems. * *********************************************************************/ -void build_request_line(struct client_state *csp, const struct forward_spec *fwd) +void build_request_line(struct client_state *csp, const struct forward_spec *fwd, char **request_line) { struct http_request *http = csp->http; @@ -1632,30 +1640,27 @@ void build_request_line(struct client_state *csp, const struct forward_spec *fwd /* * Rebuild the request line. - * XXX: If a http forwarder is used and the HTTP version - * wasn't downgraded, we don't have to rebuild anything. */ - freez(http->cmd); - - http->cmd = strdup(http->gpc); - string_append(&http->cmd, " "); + freez(*request_line); + *request_line = strdup(http->gpc); + string_append(request_line, " "); if (fwd->forward_host) { - string_append(&http->cmd, http->url); + string_append(request_line, http->url); } else { - string_append(&http->cmd, http->path); + string_append(request_line, http->path); } - string_append(&http->cmd, " "); - string_append(&http->cmd, http->ver); + string_append(request_line, " "); + string_append(request_line, http->ver); - if (http->cmd == NULL) + if (*request_line == NULL) { log_error(LOG_LEVEL_FATAL, "Out of memory writing HTTP command"); } - log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", http->cmd); + log_error(LOG_LEVEL_HEADER, "New HTTP Request-Line: %s", *request_line); } @@ -1866,9 +1871,55 @@ static void chat(struct client_state *csp) } } - /* decide how to route the HTTP request */ + /* + * Determine the actions for this URL + */ +#ifdef FEATURE_TOGGLE + if (!(csp->flags & CSP_FLAG_TOGGLED_ON)) + { + /* Most compatible set of actions (i.e. none) */ + init_current_action(csp->action); + } + else +#endif /* ndef FEATURE_TOGGLE */ + { + url_actions(http, csp); + } + + /* + * Save a copy of the original request for logging + */ + http->ocmd = strdup(http->cmd); + + if (http->ocmd == NULL) + { + log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line"); + } + + enlist(csp->headers, http->cmd); + + /* Append the previously read headers */ + 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); + } - if ((fwd = forward_url(http, csp)) == NULL) + if (JB_ERR_OK != sed(client_patterns, add_client_headers, csp)) + { + log_error(LOG_LEVEL_FATAL, "Failed to parse client headers"); + } + csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE; + + /* decide how to route the HTTP request */ + if (NULL == (fwd = forward_url(http, csp))) { log_error(LOG_LEVEL_FATAL, "gateway spec is NULL!?!? This can't happen!"); /* Never get here - LOG_LEVEL_FATAL causes program exit */ @@ -1910,22 +1961,6 @@ static void chat(struct client_state *csp) * */ - /* - * Determine the actions for this URL - */ -#ifdef FEATURE_TOGGLE - if (!(csp->flags & CSP_FLAG_TOGGLED_ON)) - { - /* Most compatible set of actions (i.e. none) */ - init_current_action(csp->action); - } - else -#endif /* ndef FEATURE_TOGGLE */ - { - url_actions(http, csp); - } - - /* * Check if a CONNECT request is allowable: * In the absence of a +limit-connect action, allow only port 443. @@ -1953,52 +1988,26 @@ static void chat(struct client_state *csp) write_socket(csp->cfd, CFORBIDDEN, strlen(CFORBIDDEN)); 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); + + list_remove_all(csp->headers); + return; } } } - - /* - * Save a copy of the original request for logging - */ - http->ocmd = strdup(http->cmd); - - if (http->ocmd == NULL) - { - log_error(LOG_LEVEL_FATAL, "Out of memory copying HTTP request line"); - } - - /* - * (Re)build the HTTP request for non-SSL requests. - */ if (http->ssl == 0) { - build_request_line(csp, fwd); - } - enlist(csp->headers, http->cmd); - - /* Append the previously read headers */ - 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); + freez(csp->headers->first->str); + build_request_line(csp, fwd, &csp->headers->first->str); } - hdr = sed(client_patterns, add_client_headers, csp); + hdr = list_to_text(csp->headers); if (hdr == NULL) { /* FIXME Should handle error properly */ log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header"); } - csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE; #ifdef FEATURE_KILL_POPUPS block_popups = ((csp->action->flags & ACTION_NO_POPUPS) != 0); @@ -2271,8 +2280,12 @@ static void chat(struct client_state *csp) csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur); } - hdr = sed(server_patterns_light, NULL, csp); + if (JB_ERR_OK != sed(server_patterns_light, NULL, csp)) + { + log_error(LOG_LEVEL_FATAL, "Failed to parse server headers."); + } + hdr = list_to_text(csp->headers); if (hdr == NULL) { /* FIXME Should handle error properly */ @@ -2337,8 +2350,11 @@ static void chat(struct client_state *csp) int flushed; log_error(LOG_LEVEL_ERROR, "Flushing header and buffers. Stepping back from filtering."); - - hdr = sed(server_patterns, add_server_headers, csp); + 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) { /* @@ -2452,8 +2468,11 @@ static void chat(struct client_state *csp) /* we have now received the entire header. * filter it and send the result to the client */ - - hdr = sed(server_patterns, add_server_headers, csp); + 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) { /* FIXME Should handle error properly */ @@ -2690,7 +2709,7 @@ void initialize_mutexes() * * For example older FreeBSD versions (< 6.x?) * have no gethostbyname_r, but gethostbyname is - * thead safe. + * thread safe. */ #ifndef HAVE_GMTIME_R if (!err) err = pthread_mutex_init(&gmtime_mutex, 0);