Package: libapache-mod-rpaf
Version: 0.5-2
Severity: wishlist

mod_rpaf always uses the last value from the X-Forwarded-For header as
the client IP, breaking when you have several chained proxies (i.e.
Pound in front of Squid in front of Apache).

The attached patch makes it use the last address in the header which is
not in RPAFproxy_ips, falling back to the first one if they are all
known proxies.

diff -ur mod_rpaf-0.5/mod_rpaf-2.0.c libapache-mod-rpaf-0.5/mod_rpaf-2.0.c
--- mod_rpaf-0.5/mod_rpaf-2.0.c	2004-03-17 15:47:30.000000000 +0000
+++ libapache-mod-rpaf-0.5/mod_rpaf-2.0.c	2006-06-16 18:04:05.000000000 +0100
@@ -130,6 +130,16 @@
     return 0;
 }
 
+static char* last_not_in_array(apr_array_header_t *forwarded_for,
+			       apr_array_header_t *proxy_ips) {
+    int i;
+    for (i = (forwarded_for->nelts)-1; i > 0; i--) {
+	if (!is_in_array(((char **)forwarded_for->elts)[i], proxy_ips))
+	    break;
+    }
+    return ((char **)forwarded_for->elts)[i];
+}
+
 static int change_remote_ip(request_rec *r) {
     const char *fwdvalue;
     char *val;
@@ -147,7 +157,7 @@
                 if (*fwdvalue != '\0')
                     ++fwdvalue;
             }
-            r->connection->remote_ip = apr_pstrdup(r->connection->pool, ((char **)arr->elts)[((arr->nelts)-1)]);
+            r->connection->remote_ip = apr_pstrdup(r->connection->pool, last_not_in_array(arr, cfg->proxy_ips));
             r->connection->remote_addr->sa.sin.sin_addr.s_addr = inet_addr(r->connection->remote_ip);
             if (cfg->sethostname) {
                 const char *hostvalue;
diff -ur mod_rpaf-0.5/mod_rpaf.c libapache-mod-rpaf-0.5/mod_rpaf.c
--- mod_rpaf-0.5/mod_rpaf.c	2004-03-17 15:47:30.000000000 +0000
+++ libapache-mod-rpaf-0.5/mod_rpaf.c	2006-06-16 18:04:38.000000000 +0100
@@ -130,6 +130,16 @@
     return 0;
 }
 
+static char* last_not_in_array(array_header *forwarded_for,
+			       array_header *proxy_ips) {
+    int i;
+    for (i = (forwarded_for->nelts)-1; i > 0; i--) {
+	if (!is_in_array(((char **)forwarded_for->elts)[i], proxy_ips))
+	    break;
+    }
+    return ((char **)forwarded_for->elts)[i];
+}
+
 static int change_remote_ip(request_rec *r) {
     const char *fwdvalue;
     char *val;
@@ -147,7 +157,7 @@
                 if (*fwdvalue != '\0')
                     ++fwdvalue;
             }
-            r->connection->remote_ip = ap_pstrdup(r->connection->pool, ((char **)arr->elts)[((arr->nelts)-1)]);
+            r->connection->remote_ip = ap_pstrdup(r->connection->pool, last_not_in_array(arr, cfg->proxy_ips));
             r->connection->remote_addr.sin_addr.s_addr = inet_addr(r->connection->remote_ip);
             if (cfg->sethostname) {
                 const char *hostvalue;
-- 
ilmari
"A disappointingly low fraction of the human race is,
 at any given time, on fire." - Stig Sandbeck Mathisen

Reply via email to