Purpose : Used with other docs and files only.
- $Id: p-config.sgml,v 2.80 2012/03/19 12:56:26 fabiankeil Exp $
+ $Id: p-config.sgml,v 2.81 2012/03/19 12:56:41 fabiankeil Exp $
Copyright (C) 2001-2011 Privoxy Developers http://www.privoxy.org/
See LICENSE.
Sample Configuration File for Privoxy v&p-version;
</title>
<para>
- $Id: p-config.sgml,v 2.80 2012/03/19 12:56:26 fabiankeil Exp $
+ $Id: p-config.sgml,v 2.81 2012/03/19 12:56:41 fabiankeil Exp $
</para>
<para>
Copyright (C) 2001-2011 Privoxy Developers http://www.privoxy.org/
</sect3>
+<sect3 renderas="sect4" id="client-header-order"><title>client-header-order</title>
+<variablelist>
+ <varlistentry>
+ <term>Specifies:</term>
+ <listitem>
+ <para>
+ The order in which client headers are sorted before forwarding them.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Type of value:</term>
+ <listitem>
+ <para>
+ <replaceable>Client header names delimited by spaces or tabs</replaceable>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Default value:</term>
+ <listitem>
+ <para>None</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Notes:</term>
+ <listitem>
+ <para>
+ By default &my-app; leaves the client headers in the order they
+ were sent by the client. Headers are modified in-place, new headers
+ are added at the end of the already existing headers.
+ </para>
+ <para>
+ The header order can be used to fingerprint client requests
+ independently of other headers like the User-Agent.
+ </para>
+ <para>
+ This directive allows to sort the headers differently to better
+ mimic a different User-Agent. Client headers will be emitted
+ in the order given, headers whose name isn't explicitly specified
+ are added at the end.
+ </para>
+ <para>
+ Note that sorting headers in an uncommon way will make fingerprinting
+ actually easier. Encrypted headers are not affected by this directive.
+ </para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+<![%config-file;[<literallayout>@@#client-header-order Host \
+# User-Agent \
+# Accept \
+# Accept-Language \
+# Accept-Encoding \
+# Proxy-Connection,\
+# Referer,Cookie \
+# If-Modified-Since \
+# Cache-Control \
+# Content-Length \
+# Content-Type
+</literallayout>]]>
+</sect3>
+
+
</sect2>
<!-- ~ End section ~ -->
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.128 2012/05/24 14:58:16 fabiankeil Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.129 2012/06/08 15:15:11 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
#define hash_admin_address 4112573064U /* "admin-address" */
#define hash_allow_cgi_request_crunching 258915987U /* "allow-cgi-request-crunching" */
#define hash_buffer_limit 1881726070U /* "buffer-limit */
+#define hash_client_header_order 2701453514U /* "client-header-order" */
#define hash_compression_level 2464423563U /* "compression-level" */
#define hash_confdir 1978389U /* "confdir" */
#define hash_connection_sharing 1348841265U /* "connection-sharing" */
freez(config->re_filterfile[i]);
}
+ list_remove_all(config->ordered_client_headers);
+
freez(config->admin_address);
freez(config->proxy_info_url);
freez(config->proxy_args);
}
+/*********************************************************************
+ *
+ * Function : parse_client_header_order
+ *
+ * Description : Parse the value of the header-order directive
+ *
+ * Parameters :
+ * 1 : ordered_header_list: List to insert the ordered
+ * headers into.
+ * 2 : ordered_headers: The ordered header names separated
+ * by spaces or tabs.
+ *
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void parse_client_header_order(struct list *ordered_header_list, const char *ordered_headers)
+{
+ char *original_headers_copy;
+ char **vector;
+ int number_of_headers;
+ int i;
+
+ assert(ordered_header_list != NULL);
+ assert(ordered_headers != NULL);
+
+ if (ordered_headers == NULL)
+ {
+ log_error(LOG_LEVEL_FATAL, "header-order used without argument");
+ }
+
+ /*
+ * XXX: This estimate is guaranteed to be high enough as we
+ * let ssplit() ignore empty fields, but also a bit wasteful.
+ * The same hack is used in get_last_url() so it looks like
+ * a real solution is needed.
+ */
+ size_t max_segments = strlen(ordered_headers) / 2;
+ if (max_segments == 0)
+ {
+ max_segments = 1;
+ }
+ vector = malloc_or_die(max_segments * sizeof(char *));
+
+ original_headers_copy = strdup_or_die(ordered_headers);
+
+ number_of_headers = ssplit(original_headers_copy, "\t ", vector, max_segments);
+ if (number_of_headers == -1)
+ {
+ log_error(LOG_LEVEL_FATAL, "Failed to split ordered headers");
+ }
+
+ for (i = 0; i < number_of_headers; i++)
+ {
+ if (JB_ERR_OK != enlist(ordered_header_list, vector[i]))
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Failed to enlist ordered header: %s", vector[i]);
+ }
+ }
+
+ freez(vector);
+ freez(original_headers_copy);
+
+ return;
+
+}
+
+
/*********************************************************************
*
* Function : load_config
config->buffer_limit = (size_t)(1024 * atoi(arg));
break;
+/* *************************************************************************
+ * client-header-order header-1 header-2 ... header-n
+ * *************************************************************************/
+ case hash_client_header_order:
+ list_remove_all(config->ordered_client_headers);
+ parse_client_header_order(config->ordered_client_headers, arg);
+ break;
+
/* *************************************************************************
* confdir directory-name
* *************************************************************************/
-const char parsers_rcs[] = "$Id: parsers.c,v 1.245 2012/04/06 15:17:10 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.246 2012/07/23 12:40:30 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
}
+/*********************************************************************
+ *
+ * Function : enforce_header_order
+ *
+ * Description : Enforces a given header order.
+ *
+ * Parameters :
+ * 1 : headers = List of headers to order.
+ * 2 : ordered_headers = List of ordered header names.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+static void enforce_header_order(struct list *headers, const struct list *ordered_headers)
+{
+ struct list_entry *sorted_header;
+ struct list new_headers[1];
+ struct list_entry *header;
+
+ init_list(new_headers);
+
+ /* The request line is always the first "header" */
+
+ assert(NULL != headers->first->str);
+ enlist(new_headers, headers->first->str);
+ freez(headers->first->str)
+
+ /* Enlist the specified headers in the given order */
+
+ for (sorted_header = ordered_headers->first; sorted_header != NULL;
+ sorted_header = sorted_header->next)
+ {
+ const size_t sorted_header_length = strlen(sorted_header->str);
+ for (header = headers->first; header != NULL; header = header->next)
+ {
+ /* Header enlisted in previous run? -> ignore */
+ if (header->str == NULL) continue;
+
+ if (0 == strncmpic(sorted_header->str, header->str, sorted_header_length)
+ && (header->str[sorted_header_length] == ':'))
+ {
+ log_error(LOG_LEVEL_HEADER, "Enlisting sorted header %s", header->str);
+ if (JB_ERR_OK != enlist(new_headers, header->str))
+ {
+ log_error(LOG_LEVEL_HEADER, "Failed to enlist %s", header->str);
+ }
+ freez(header->str);
+ }
+ }
+ }
+
+ /* Enlist the rest of the headers behind the ordered ones */
+ for (header = headers->first; header != NULL; header = header->next)
+ {
+ /* Header enlisted in previous run? -> ignore */
+ if (header->str == NULL) continue;
+
+ log_error(LOG_LEVEL_HEADER,
+ "Enlisting left-over header %s", header->str);
+ if (JB_ERR_OK != enlist(new_headers, header->str))
+ {
+ log_error(LOG_LEVEL_HEADER, "Failed to enlist %s", header->str);
+ }
+ freez(header->str);
+ }
+
+ list_remove_all(headers);
+ list_duplicate(headers, new_headers);
+ list_remove_all(new_headers);
+
+ return;
+}
+
/*********************************************************************
*
* Function : sed
f++;
}
+ if (!filter_server_headers && !list_is_empty(csp->config->ordered_client_headers))
+ {
+ enforce_header_order(csp->headers, csp->config->ordered_client_headers);
+ }
+
return err;
}
#ifndef PROJECT_H_INCLUDED
#define PROJECT_H_INCLUDED
/** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.176 2012/06/19 12:50:22 fabiankeil Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.177 2012/07/23 12:43:42 fabiankeil Exp $"
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/project.h,v $
/** The short names of the pcre filter files. */
const char *re_filterfile_short[MAX_AF_FILES];
+ /**< List of ordered client header names. */
+ struct list ordered_client_headers[1];
+
/** The hostname to show on CGI pages, or NULL to use the real one. */
const char *hostname;