-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 $
*
* 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,
#include "list.h"
#include "deanimate.h"
#include "urlmatch.h"
+#include "loaders.h"
#ifdef _WIN32
#include "win32.h"
}
+/*********************************************************************
+ *
+ * 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...)
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;
-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 $
*
* 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
* 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;
/*
* 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);
}
}
}
- /* 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 */
*
*/
- /*
- * 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.
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);
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 */
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)
{
/*
/* 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 */
*
* 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);