-const char parsers_rcs[] = "$Id: parsers.c,v 1.270 2012/12/07 12:43:55 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.274 2013/01/04 12:20:31 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
static jb_err server_proxy_connection_adder(struct client_state *csp);
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+static jb_err proxy_authentication(struct client_state *csp, char **header);
static jb_err create_forged_referrer(char **header, const char *hostport);
static jb_err create_fake_referrer(char **header, const char *fake_referrer);
{ "Request-Range:", 14, client_range },
{ "If-Range:", 9, client_range },
{ "X-Filter:", 9, client_x_filter },
+ { "Proxy-Authorization:", 20, proxy_authentication },
#if 0
{ "Transfer-Encoding:", 18, client_transfer_encoding },
#endif
{ "Transfer-Encoding:", 18, server_transfer_coding },
{ "content-disposition:", 20, server_content_disposition },
{ "Last-Modified:", 14, server_last_modified },
+ { "Proxy-Authenticate:", 19, proxy_authentication },
{ "*", 0, crunch_server_header },
{ "*", 0, filter_header },
{ NULL, 0, NULL }
}
+/*********************************************************************
+ *
+ * Function : proxy_authentication
+ *
+ * Description : Removes headers that are relevant for proxy
+ * authentication unless forwarding them has
+ * been explicitly requested.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : header = On input, pointer to header to modify.
+ * On output, pointer to the modified header, or NULL
+ * to remove the header. This function frees the
+ * original string if necessary.
+ *
+ * Returns : JB_ERR_OK.
+ *
+ *********************************************************************/
+static jb_err proxy_authentication(struct client_state *csp, char **header)
+{
+ if ((csp->config->feature_flags &
+ RUNTIME_FEATURE_FORWARD_PROXY_AUTHENTICATION_HEADERS) == 0) {
+ log_error(LOG_LEVEL_HEADER,
+ "Forwarding proxy authentication headers is disabled. Crunching: %s", *header);
+ freez(*header);
+ }
+ return JB_ERR_OK;
+}
+
+
/*********************************************************************
*
* Function : client_keep_alive
/* Remove header if it isn't the first Content-Type header */
if ((csp->content_type & CT_DECLARED))
{
- /*
- * Another, slightly slower, way to see if
- * we already parsed another Content-Type header.
- */
- assert(NULL != get_header_value(csp->headers, "Content-Type:"));
-
- log_error(LOG_LEVEL_ERROR,
- "Multiple Content-Type headers. Removing and ignoring: \'%s\'",
- *header);
- freez(*header);
-
+ if (content_filters_enabled(csp->action))
+ {
+ /*
+ * Making sure the client interprets the content the same way
+ * Privoxy did is only relevant if Privoxy modified it.
+ *
+ * Checking for this is "hard" as it's not yet known when
+ * this function is called, thus go shopping and and just
+ * check if Privoxy could filter it.
+ *
+ * The main thing is that we don't mess with the headers
+ * unless the user signalled that it's acceptable.
+ */
+ log_error(LOG_LEVEL_HEADER,
+ "Multiple Content-Type headers detected. "
+ "Removing and ignoring: %s",
+ *header);
+ freez(*header);
+ }
return JB_ERR_OK;
}
continue;
}
*result = timegm(&gmt);
+
+#ifdef FEATURE_STRPTIME_SANITY_CHECKS
+ /*
+ * Verify that parsing the date recreated from the first
+ * parse operation gets the previous result. If it doesn't,
+ * either strptime() or strftime() are malfunctioning.
+ *
+ * We could string-compare the recreated date with the original
+ * header date, but this leads to false positives as strptime()
+ * may let %a accept all day formats while strftime() will only
+ * create one.
+ */
+ {
+ char recreated_date[100];
+ struct tm *tm;
+ time_t result2;
+
+ tm = gmtime(result);
+ strftime(recreated_date, sizeof(recreated_date), time_formats[i], tm);
+ memset(&gmt, 0, sizeof(gmt));
+ if (NULL == strptime(recreated_date, time_formats[i], &gmt))
+ {
+ log_error(LOG_LEVEL_ERROR,
+ "Failed to parse '%s' generated with '%s' to recreate '%s'.",
+ recreated_date, time_formats[i], header_time);
+ continue;
+ }
+ result2 = timegm(&gmt);
+ if (*result != result2)
+ {
+ log_error(LOG_LEVEL_ERROR, "strftime() and strptime() disagree. "
+ "Format: '%s'. In: '%s', out: '%s'. %d != %d. Rejecting.",
+ time_formats[i], header_time, recreated_date, *result, result2);
+ continue;
+ }
+ }
+#endif
+
return JB_ERR_OK;
}
}