Optionally use the X-Forwarded-For header for client tags
authorFabian Keil <fk@fabiankeil.de>
Sun, 22 May 2016 12:43:07 +0000 (12:43 +0000)
committerFabian Keil <fk@fabiankeil.de>
Sun, 22 May 2016 12:43:07 +0000 (12:43 +0000)
... if it exists.

Sponsored by: Robert Klemme

cgisimple.c
client-tags.c
client-tags.h
jcc.c
loadcfg.c
loaders.c
project.h

index a47ef79..8acfc1e 100644 (file)
@@ -1,4 +1,4 @@
-const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.140 2016/05/08 10:46:18 fabiankeil Exp $";
+const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.141 2016/05/08 10:46:29 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/cgisimple.c,v $
@@ -358,7 +358,7 @@ jb_err cgi_show_client_tags(struct client_state *csp,
    {
       return JB_ERR_MEMORY;
    }
-
+   assert(csp->client_address != NULL);
    toggled_tag = lookup(parameters, "tag");
    if (*toggled_tag != '\0')
    {
@@ -396,7 +396,7 @@ jb_err cgi_show_client_tags(struct client_state *csp,
          int tag_state;
 
          privoxy_mutex_lock(&client_tags_mutex);
-         tag_state = client_has_requested_tag(csp->ip_addr_str, this_tag->name);
+         tag_state = client_has_requested_tag(csp->client_address, this_tag->name);
          privoxy_mutex_unlock(&client_tags_mutex);
          if (!err) err = string_append(&client_tag_status, "<tr><td>");
          if (!err) err = string_append(&client_tag_status, this_tag->name);
@@ -429,7 +429,7 @@ jb_err cgi_show_client_tags(struct client_state *csp,
       return JB_ERR_MEMORY;
    }
 
-   if (map(exports, "client-ip-addr", 1, csp->ip_addr_str, 1))
+   if (map(exports, "client-ip-addr", 1, csp->client_address, 1))
    {
       free_map(exports);
       return JB_ERR_MEMORY;
index 0bcbf35..fda1f88 100644 (file)
@@ -42,6 +42,7 @@
 #include "jcc.h"
 #include "miscutil.h"
 #include "errlog.h"
+#include "parsers.h"
 
 struct client_specific_tag
 {
@@ -491,17 +492,17 @@ jb_err enable_client_specific_tag(struct client_state *csp,
       return JB_ERR_PARSE;
    }
 
-   if (client_has_requested_tag(csp->ip_addr_str, tag_name))
+   if (client_has_requested_tag(csp->client_address, tag_name))
    {
       log_error(LOG_LEVEL_ERROR,
-         "Tag '%s' already enabled for client '%s'", tag->name, csp->ip_addr_str);
+         "Tag '%s' already enabled for client '%s'", tag->name, csp->client_address);
    }
    else
    {
-      add_tag_for_client(csp->ip_addr_str, tag_name, time_to_live);
+      add_tag_for_client(csp->client_address, tag_name, time_to_live);
       log_error(LOG_LEVEL_INFO,
          "Tag '%s' enabled for client '%s'. TTL: %d.",
-         tag->name, csp->ip_addr_str, time_to_live);
+         tag->name, csp->client_address, time_to_live);
    }
 
    privoxy_mutex_unlock(&client_tags_mutex);
@@ -536,17 +537,17 @@ jb_err disable_client_specific_tag(struct client_state *csp, const char *tag_nam
       return JB_ERR_PARSE;
    }
 
-   if (client_has_requested_tag(csp->ip_addr_str, tag_name))
+   if (client_has_requested_tag(csp->client_address, tag_name))
    {
-      remove_tag_for_client(csp->ip_addr_str, tag_name);
+      remove_tag_for_client(csp->client_address, tag_name);
       log_error(LOG_LEVEL_INFO,
-         "Tag '%s' disabled for client '%s'", tag->name, csp->ip_addr_str);
+         "Tag '%s' disabled for client '%s'", tag->name, csp->client_address);
    }
    else
    {
       log_error(LOG_LEVEL_ERROR,
          "Tag '%s' currently not set for client '%s'",
-         tag->name, csp->ip_addr_str);
+         tag->name, csp->client_address);
    }
 
    privoxy_mutex_unlock(&client_tags_mutex);
@@ -595,6 +596,44 @@ int client_tag_match(const struct pattern_spec *pattern,
    return 0;
 
 }
+
+
+/*********************************************************************
+ *
+ * Function    :  set_client_address
+ *
+ * Description :  Sets the client address that will be used to enable,
+ *                disable, or apply client tags.
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *          2  :  headers = Client headers
+ *
+ * Returns     :  void.
+ *
+ *********************************************************************/
+void set_client_address(struct client_state *csp, const struct list *headers)
+{
+   if (csp->config->trust_x_forwarded_for)
+   {
+      const char *client_address;
+
+      client_address = get_header_value(headers, "X-Forwarded-For:");
+      if (client_address != NULL)
+      {
+         csp->client_address = strdup_or_die(client_address);
+         log_error(LOG_LEVEL_HEADER,
+            "Got client address %s from X-Forwarded-For header",
+            csp->client_address);
+      }
+   }
+
+   if (csp->client_address == NULL)
+   {
+      csp->client_address = strdup_or_die(csp->ip_addr_str);
+   }
+}
+
 #else
 #error Compiling client-tags.c without FEATURE_CLIENT_TAGS
 #endif /* def FEATURE_CLIENT_TAGS */
index 328346e..6f8398c 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef CLIENT_TAGS_H_INCLUDED
 #define CLIENT_TAGS_H_INCLUDED
-#define CLIENT_TAGS_H_VERSION "$Id: client-tags.h,v 1.1 2016/03/17 10:42:27 fabiankeil Exp $"
+#define CLIENT_TAGS_H_VERSION "$Id: client-tags.h,v 1.2 2016/05/03 13:21:42 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/client-tags.h,v $
@@ -40,6 +40,8 @@ extern jb_err enable_client_specific_tag(struct client_state *csp,
                                          const time_t time_to_live);
 extern int client_has_requested_tag(const char *client_address,
                                     const char *tag);
+extern void set_client_address(struct client_state *csp,
+                               const struct list *headers);
 
 #define CLIENT_TAG_LENGTH_MAX 50
 #endif
diff --git a/jcc.c b/jcc.c
index 8ab7f87..ad210ab 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,4 +1,4 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.441 2016/02/26 12:29:38 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.442 2016/03/17 10:40:53 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
@@ -1678,6 +1678,12 @@ static jb_err receive_client_request(struct client_state *csp)
       }
    }
 
+#ifdef FEATURE_CLIENT_TAGS
+   /* XXX: If the headers were enlisted sooner, passing csp would do. */
+   set_client_address(csp, headers);
+   get_tag_list_for_client(csp->client_tags, csp->client_address);
+#endif
+
    /*
     * Determine the actions for this URL
     */
@@ -1848,9 +1854,6 @@ static void chat(struct client_state *csp)
 
    http = csp->http;
 
-#if FEATURE_CLIENT_TAGS
-   get_tag_list_for_client(csp->client_tags, csp->ip_addr_str);
-#endif
    if (receive_client_request(csp) != JB_ERR_OK)
    {
       return;
@@ -2824,6 +2827,7 @@ static void prepare_csp_for_next_request(struct client_state *csp)
    destroy_list(csp->tags);
 #ifdef FEATURE_CLIENT_TAGS
    destroy_list(csp->client_tags);
+   freez(csp->client_address);
 #endif
    free_current_action(csp->action);
    if (NULL != csp->fwd)
index 879091e..7cf5801 100644 (file)
--- a/loadcfg.c
+++ b/loadcfg.c
@@ -1,4 +1,4 @@
-const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.151 2016/05/03 13:21:42 fabiankeil Exp $";
+const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.152 2016/05/08 10:46:55 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
@@ -166,6 +166,7 @@ static struct file_list *current_configfile = NULL;
 #define hash_tolerate_pipelining         1360286620U /* "tolerate-pipelining" */
 #define hash_toggle                          447966U /* "toggle" */
 #define hash_trust_info_url               430331967U /* "trust-info-url" */
+#define hash_trust_x_forwarded_for       2971537414U /* "trust-x-forwarded-for" */
 #define hash_trustfile                     56494766U /* "trustfile" */
 #define hash_usermanual                  1416668518U /* "user-manual" */
 #define hash_activity_animation          1817904738U /* "activity-animation" */
@@ -599,6 +600,7 @@ struct configuration_spec * load_config(void)
 #ifdef FEATURE_CLIENT_TAGS
    config->client_tag_lifetime       = 60;
 #endif
+   config->trust_x_forwarded_for     = 0;
    /*
     * 128 client sockets ought to be enough for everybody who can't
     * be bothered to read the documentation to figure out how to
@@ -1587,6 +1589,13 @@ struct configuration_spec * load_config(void)
             break;
 #endif /* def FEATURE_TRUST */
 
+/* *************************************************************************
+ * trust-x-forwarded-for (0|1)
+ * *************************************************************************/
+         case hash_trust_x_forwarded_for :
+            config->trust_x_forwarded_for = parse_toggle_state(cmd, arg);
+            break;
+
 /* *************************************************************************
  * trustfile filename
  * (In confdir by default.)
index 2c84b32..92e0353 100644 (file)
--- a/loaders.c
+++ b/loaders.c
@@ -1,4 +1,4 @@
-const char loaders_rcs[] = "$Id: loaders.c,v 1.102 2016/02/26 12:30:46 fabiankeil Exp $";
+const char loaders_rcs[] = "$Id: loaders.c,v 1.103 2016/05/08 10:45:32 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/loaders.c,v $
@@ -182,6 +182,9 @@ unsigned int sweep(void)
          last_active->next = client_list->next;
 
          freez(csp->ip_addr_str);
+#ifdef FEATURE_CLIENT_TAGS
+         freez(csp->client_address);
+#endif
          freez(csp->client_iob->buf);
          freez(csp->iob->buf);
          freez(csp->error_message);
index a53aa87..32a63d5 100644 (file)
--- a/project.h
+++ b/project.h
@@ -1,7 +1,7 @@
 #ifndef PROJECT_H_INCLUDED
 #define PROJECT_H_INCLUDED
 /** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.213 2016/03/17 10:40:53 fabiankeil Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.214 2016/03/30 11:13:25 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/project.h,v $
@@ -953,6 +953,12 @@ struct client_state
 #ifdef FEATURE_CLIENT_TAGS
    /** List of all tags that apply to this client (assigned based on address) */
    struct list client_tags[1];
+   /** The address of the client the request (presumably) came from.
+    *  Either the address returned by accept(), or the address provided
+    *  with the X-Forwarded-For header, provided Privoxy has been configured
+    *  to use it.
+    */
+   char *client_address;
 #endif
 
    /** MIME-Type key, see CT_* above */
@@ -1347,6 +1353,7 @@ struct configuration_spec
    /* Maximum number of seconds a temporarily enabled tag stays enabled. */
    unsigned int client_tag_lifetime;
 #endif /* def FEATURE_CLIENT_TAGS */
+   int trust_x_forwarded_for;
 
 #ifdef FEATURE_ACL