Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Dec 2012 12:42:56 +0000 (UTC)
From:      Jun Kuriyama <kuriyama@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r309457 - in head/www/mod_extract_forwarded: . files
Message-ID:  <201212241242.qBOCgukI006267@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kuriyama
Date: Mon Dec 24 12:42:56 2012
New Revision: 309457
URL: http://svnweb.freebsd.org/changeset/ports/309457

Log:
  Add option to patch for IPv6 address support.

Added:
  head/www/mod_extract_forwarded/files/extra-patch-mod_extract_forwarded.c
     - copied unchanged from r307268, head/www/mod_extract_forwarded/files/patch-mod_extract_forwarded.c
  head/www/mod_extract_forwarded/files/extra-patch-yoshfuji   (contents, props changed)
Deleted:
  head/www/mod_extract_forwarded/files/patch-mod_extract_forwarded.c
Modified:
  head/www/mod_extract_forwarded/Makefile

Modified: head/www/mod_extract_forwarded/Makefile
==============================================================================
--- head/www/mod_extract_forwarded/Makefile	Mon Dec 24 12:41:36 2012	(r309456)
+++ head/www/mod_extract_forwarded/Makefile	Mon Dec 24 12:42:56 2012	(r309457)
@@ -3,7 +3,7 @@
 
 PORTNAME=	mod_extract_forwarded
 PORTVERSION=	2.0.2
-PORTREVISION=	3
+PORTREVISION=	4
 CATEGORIES=	www
 MASTER_SITES=	http://www.openinfo.co.uk/apache/
 DISTNAME=	extract_forwarded-${DISTVERSION}
@@ -11,15 +11,31 @@ DISTNAME=	extract_forwarded-${DISTVERSIO
 MAINTAINER=	kuriyama@FreeBSD.org
 COMMENT=	An Apache module that can make proxied requests appear with client IP
 
+OPTIONS_DEFINE=	YOSHFUJI
+YOSHFUJI_DESC=	yoshfuji patch (support IPv6 addr in config, etc)
+#OPTIONS_DEFAULT=	YOSHFUJI
+
 USE_APACHE=	22
 WRKSRC=		${WRKDIR}/extract_forwarded
 PORTDOCS=	INSTALL README
 MAKE_JOBS_SAFE=	yes
-CONFLICTS=	mod_extract_forwarded-1.*
+PATCH_STRIP=	-p1
 
 AP_FAST_BUILD=	yes
 AP_GENPLIST=	yes
 
+# Workaround for UNIQUENAME v.s. OptionsNG problem.
+#   http://lists.freebsd.org/pipermail/freebsd-ports/2012-June/075466.html
+UNIQUENAME=	ap22-${PORTNAME}
+
+.include <bsd.port.options.mk>
+
+.if ${PORT_OPTIONS:MYOSHFUJI}
+EXTRA_PATCHES=	${FILESDIR}/extra-patch-yoshfuji
+.else
+EXTRA_PATCHES=	${FILESDIR}/extra-patch-mod_extract_forwarded.c
+.endif
+
 post-install:
 .if !defined(NOPORTDOCS)
 	${MKDIR} ${DOCSDIR}/

Copied: head/www/mod_extract_forwarded/files/extra-patch-mod_extract_forwarded.c (from r307268, head/www/mod_extract_forwarded/files/patch-mod_extract_forwarded.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/mod_extract_forwarded/files/extra-patch-mod_extract_forwarded.c	Mon Dec 24 12:42:56 2012	(r309457, copy of r307268, head/www/mod_extract_forwarded/files/patch-mod_extract_forwarded.c)
@@ -0,0 +1,11 @@
+--- mod_extract_forwarded.c.orig	2010-05-24 13:43:06.446992453 +0900
++++ mod_extract_forwarded.c	2010-06-12 17:46:16.673689346 +0900
+@@ -423,7 +423,7 @@
+     {
+         result = &(conn->remote_addr->sa.sin.sin_addr.s_addr);
+     }
+-#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED)
++#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED) && APR_HAVE_IPV6 == 1
+     if (conn->remote_addr->family == AF_INET6 &&
+         IN6_IS_ADDR_V4MAPPED(&conn->remote_addr->sa.sin6.sin6_addr)) 
+     {

Added: head/www/mod_extract_forwarded/files/extra-patch-yoshfuji
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/mod_extract_forwarded/files/extra-patch-yoshfuji	Mon Dec 24 12:42:56 2012	(r309457)
@@ -0,0 +1,918 @@
+# $FreeBSD$
+diff --git a/INSTALL b/INSTALL
+index fa06d8a..d1f6d56 100644
+--- a/INSTALL
++++ b/INSTALL
+@@ -13,11 +13,12 @@ to build and install a DSO version of the module:
+ 
+ /usr/local/apache2/bin/apxs -c -i -a mod_extract_forwarded.c
+ 
+-If the Apache instance you are adding mod_extract_forwarded to will not
+-have mod_proxy and proxy_http loaded then you will get an error when
+-mod_extract_forwarded is loaded. In that case edit
+-mod_extract_forwarded.c and comment out the #define for
+-USING_proxy_http_module or change it to an an #undef. If you
+-subsequently run Apache with proxy_http do not forget to reinstate the
+-#define; failure to do so will mean that any X-Fowarded-For header
+-inserted by proxy_http will use the spoofed IP number in error.
++If the Apache instance you are adding mod_extract_forwarded to will
++have mod_proxy and proxy_http loaded then you need to build and
++install a DSO version of the module:
++
++/usr/local/apache2/bin/apxs -c -i -a mod_extract_forwarded_proxy.c
++
++Without this module, any X-Fowarded-For header inserted by proxy_http
++will use the spoofed IP number.
++
+diff --git a/mod_extract_forwarded.c b/mod_extract_forwarded.c
+index afecbcf..fa94493 100644
+--- a/mod_extract_forwarded.c
++++ b/mod_extract_forwarded.c
+@@ -84,6 +84,9 @@
+  *    of what is done by the module as an aid to understanding fixing problems
+  *    with this code; this is NOT for production use because of the volume of
+  *    output it will generate and the way it flushes stderr
++ * 8. Support IPv6: If real connection is served by IPv6 socket, both IPv4 and
++ *    IPv6 clients are supported.  If real connection is served by IPv4 socket,
++ *    only IPv4 clients are supported.  [yoshfuji]
+  * 
+  * History of Apache 2 compatible mod_extract_forwarded
+  * ----------------------------------------------------
+@@ -98,7 +101,8 @@
+  *                              Cleaned up interpretation of per_der_config 
+  *                              for internal redirect and subrequests and 
+  *                              other logic tidying
+- *
++ *             12 Apr 2009      Apache 2.2 support. [yoshfuji]
++ *             16 Apr 2009      IPv6 support. [yoshfuji]
+  */
+ 
+ #include "httpd.h"
+@@ -110,22 +114,13 @@
+ #include "http_request.h"
+ #include "util_script.h"
+ #include "http_connection.h"
+-#include "mod_proxy.h"
+ #include "apr_strings.h"
+ 
+ #include <netdb.h>
+ #include <arpa/inet.h>
+ #include <netinet/in.h>
+ 
+-/* 
+- * #define USING_proxy_http_module if proxy_http.c module is either 
+- * compiled into Apache 2 or it is being loaded as a DSO. If proxy_http.c 
+- * module is not loaded then this module will generate an error when and
+- * if it is loaded as a DSO. In that case comment out the #define, recompile
+- * and reinstall this module. BUT do not forget to change things back if
+- * proxy_http.c module is reinstated
+- */
+-#define USING_proxy_http_module 1 
++#include "mod_extract_forwarded.h"
+ 
+ /*--------------------------------------------------------------------------*/
+ /*                                                                          */
+@@ -139,17 +134,6 @@
+  */
+ module AP_MODULE_DECLARE_DATA extract_forwarded_module;
+ 
+-/*
+- * Per directory configuration record.  
+- */
+-typedef struct {
+-    int order;  /* order in which the accept and refuse specs are applied */
+-    int debug;                      /* debug output to error log flag */
+-    const char *envar;              /* name of env var to add */
+-    apr_table_t *accept_proxies;    /* proxies to trust */
+-    apr_table_t *refuse_proxies;    /* proxies to distrust */
+-} mef_config;
+-
+ /* 
+  * Two possible orders in which the accept and refuse specs are applied
+  */
+@@ -279,72 +263,41 @@ static const char *mef_debug_control(cmd_parms *cparms, void *mconfig,
+ }
+ 
+ /* 
+- * Given an IP or 'all' as "arg", add it to the accept_proxies table
++ * Given an IP or 'all' as "arg", add it to the accept_proxies/refuse_proxies
++ * table
+  */
+-static const char *mef_accept_proxy(cmd_parms *cparms, void *mconfig, 
++static const char *mef_config_proxy(cmd_parms *cparms, void *mconfig, 
+                                     const char *arg) 
+ {
+     mef_config *conf = (mef_config *)mconfig;
+-    struct hostent *hptr = NULL;
+-    char** haddr;
++    apr_table_t *conf_proxies = cparms->info ?
++                                conf->accept_proxies : conf->refuse_proxies;
+     if (strcasecmp(arg, "all") == 0)
+     /* "all" keyword replaces everything with just itself */
+     {
+-        apr_table_clear(conf->accept_proxies);
+-        apr_table_set(conf->accept_proxies, arg, "t");
++        apr_table_clear(conf_proxies);
++        apr_table_set(conf_proxies, arg, "t");
+     } 
+     else 
+-    /* Add IP to list of accepted proxies */
++    /* Add IP to list of accepted/refuse proxies */
+     {
+-        hptr = gethostbyname(arg);
+-        if (hptr) 
++        apr_sockaddr_t *sa0, *sa;
++        if (apr_sockaddr_info_get(&sa0, arg, APR_UNSPEC, 0, 0,
++                                  cparms->temp_pool) == APR_SUCCESS)
+         {
+-            apr_table_unset(conf->accept_proxies, "all");
+-            for (haddr=hptr->h_addr_list; *haddr; haddr++)
++            apr_table_unset(conf_proxies, "all");
++            for (sa = sa0; sa; sa = sa->next)
+             {
+-                apr_table_set(conf->accept_proxies, 
+-                              inet_ntoa(*((struct in_addr*)(*haddr))), "t");
++                char *ipaddr;
++                if (apr_sockaddr_ip_get(&ipaddr, sa) == APR_SUCCESS)
++                {
++                    apr_table_set(conf_proxies, ipaddr, "t");
++                }
+             }
+-        } 
+-        else
+-        {
+-            return "No 'all' or valid IP identified by MEFaccept";
+         }
+-    }
+-    return NULL;
+-}
+-
+-/* 
+- * Given an IP or 'all' as "arg", add it to the refused_proxies table
+- */
+-static const char *mef_refuse_proxy(cmd_parms *cparms, void *mconfig,
+-                                    const char *arg)
+-{
+-    mef_config *conf = (mef_config *) mconfig;
+-    struct hostent *hptr = NULL;
+-    char** haddr;
+-    if (strcasecmp(arg, "all") == 0) 
+-    /* "all" keyword replaces everything with just itself */
+-    {
+-        apr_table_clear(conf->refuse_proxies);
+-        apr_table_set(conf->refuse_proxies, arg, "t");
+-    } 
+-    else 
+-    /* Add IP to list of refused proxies */
+-    {
+-        hptr = gethostbyname(arg);
+-        if (hptr) 
+-        {
+-            apr_table_unset(conf->refuse_proxies, "all");
+-            for (haddr=hptr->h_addr_list; *haddr; haddr++)
+-            {
+-                apr_table_set(conf->refuse_proxies,
+-                              inet_ntoa(*((struct in_addr*)(*haddr))), "t");
+-            }
+-        } 
+-        else 
++        else
+         {
+-            return "No 'all' or valid IP identified by MEFrefuse";
++            return "No 'all' or valid IP identified by MEFaccept / MEFrefuse";
+         }
+     }
+     return NULL;
+@@ -385,54 +338,6 @@ static int acceptable_proxy(mef_config *conf, char *proxy_ip)
+     return 0;
+ }
+ 
+-/* 
+- * The MEFsave_rec data structure is used to preserve information that
+- * this module has modified in the conn_rec associated with a request
+- * so that the conn_rec can be restored to its original state as needed.
+- * It also carries information between transaction phases and internal
+- * redirects and subrequests
+- */
+-typedef struct MEFsave_rec MEFsave_rec;
+-
+-struct MEFsave_rec {
+-    conn_rec *connection;           /* connection record being used */
+-    in_addr_t orig_in_addr;         /* original remote in_addr_t */ 
+-    in_addr_t new_in_addr;          /* modified remote in_addr_t */ 
+-    char *orig_remote_ip;           /* original remote_ip */
+-    char *new_remote_ip;            /* modified remote_ip */
+-    int conn_rec_mod_state;         /* conn_rec modification state */
+-    int debug;                      /* are we printing MEF debug */
+-    const char *envar;              /* name of env var to add */
+-    void *per_dir_config;           /* per_dir_config applicable */
+-    MEFsave_rec *other_saved;       /* any preceding req's save_rec */
+-    request_rec *other_r;           /* any preceding req's request_rec */    
+-};
+-
+-#define CONN_REC_MODIFIED 1
+-#define CONN_REC_RESTORED 0
+-
+-/*
+- * remote_in_addr returns a pointer to the in_addr_t which specifes
+- * the IP of the remote end of the connection supporting the specified
+- * request. NULL is returned if this cannot be determined.
+- */
+-static in_addr_t *get_remote_in_addr(conn_rec *conn)
+-{
+-    in_addr_t *result = NULL;
+-    if (conn->remote_addr->family == AF_INET)
+-    {
+-        result = &(conn->remote_addr->sa.sin.sin_addr.s_addr);
+-    }
+-#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED)
+-    if (conn->remote_addr->family == AF_INET6 &&
+-        IN6_IS_ADDR_V4MAPPED(&conn->remote_addr->sa.sin6.sin6_addr)) 
+-    {
+-        result = &(((uint32_t *)conn->remote_addr->ipaddr_ptr)[3]);
+-    }
+-#endif
+-    return result;
+-}
+-
+ /* Forward declared for convenience */
+ static apr_status_t cleanup_initial(void *data);
+ static apr_status_t cleanup_not_initial(void *data);
+@@ -446,22 +351,12 @@ static apr_status_t cleanup_not_initial(void *data);
+  */
+ static int spoof_initial(request_rec *r, char *spoof_ip, char *phase)
+ {
+-    in_addr_t *remote_in_addr;
+     MEFsave_rec *saved;
+     mef_config *conf = ap_get_module_config(r->per_dir_config, 
+                                             &extract_forwarded_module);
+-    /* Validate and acquire pointer to the remote in_addr_t */
+-    if ((remote_in_addr = get_remote_in_addr(r->connection)) == NULL)
+-    {
+-        /* Could not get a valid value so give up */
+-        if (conf->debug == MEF_DEBUG_ON) 
+-        {
+-            fprintf(stderr,"MEF: phase:%s, si problem acquiring remote_in_addr\n", 
+-                    phase);
+-            fflush(stderr);
+-        }
+-        return DECLINED;
+-    }
++    apr_sockaddr_t *sa;
++    apr_port_t port;
++
+     /*
+      * We can proceed to do the spoof
+      *
+@@ -470,9 +365,40 @@ static int spoof_initial(request_rec *r, char *spoof_ip, char *phase)
+     saved = apr_pcalloc(r->pool, sizeof(MEFsave_rec));
+     /* Then the saving */
+     saved->connection = r->connection;
+-    saved->orig_in_addr = *remote_in_addr;
++    saved->orig_addr = *r->connection->remote_addr;
+     saved->orig_remote_ip = r->connection->remote_ip;
+-    saved->new_in_addr = inet_addr(spoof_ip);
++
++    /* setup new address
++     * it's easy if address family is not changed.
++     */
++    port = r->connection->remote_addr->port;
++    if (apr_sockaddr_info_get(&sa, spoof_ip,
++                              r->connection->remote_addr->family, port,
++                              0, r->pool) != APR_SUCCESS)
++    {
++#if APR_HAVE_IPV6
++        /* Try inter-family conversion.
++         * If if the real connection is served via ipv4, it
++         * implies   Give up if connection is ipv4 and real client is ipv6.
++         */
++        char *buf;
++        if (r->connection->remote_addr->family != APR_INET6)
++        {
++            return DECLINED;
++        }
++        buf = apr_palloc(r->pool, strlen(spoof_ip) + sizeof("::ffff:"));
++	sprintf(buf, "::ffff:%s", spoof_ip);
++        if (apr_sockaddr_info_get(&sa, buf, APR_INET6, port,
++                                  0, r->pool) != APR_SUCCESS)
++        {
++            return DECLINED;
++        }
++#else
++        return DECLINED;
++#endif
++    }
++
++    saved->new_addr = *sa;
+     saved->new_remote_ip = spoof_ip;
+     saved->per_dir_config = r->per_dir_config;
+     saved->debug = conf->debug;
+@@ -480,7 +406,7 @@ static int spoof_initial(request_rec *r, char *spoof_ip, char *phase)
+     saved->other_saved = NULL;
+     saved->other_r = NULL;
+     /* Then the modifying of the conn_rec */
+-    *remote_in_addr = saved->new_in_addr;
++    *saved->connection->remote_addr = saved->new_addr;
+     saved->connection->remote_ip = saved->new_remote_ip;
+     saved->conn_rec_mod_state = CONN_REC_MODIFIED;
+     /* Force re-evaluation of the remote_host value */
+@@ -520,7 +446,6 @@ static int spoof_initial(request_rec *r, char *spoof_ip, char *phase)
+ static int spoof_not_initial(request_rec *this_r, request_rec *other_r,
+                              char *phase)
+ {
+-    in_addr_t *remote_in_addr;
+     MEFsave_rec *saved;
+     MEFsave_rec *other_saved;
+     /* 
+@@ -540,10 +465,9 @@ static int spoof_not_initial(request_rec *this_r, request_rec *other_r,
+     saved = apr_pcalloc(this_r->pool, sizeof(MEFsave_rec));
+     /* Then the copying */
+     saved->connection = other_saved->connection;
+-    remote_in_addr = get_remote_in_addr(saved->connection);
+-    saved->orig_in_addr = other_saved->orig_in_addr;
++    saved->orig_addr = other_saved->orig_addr;
+     saved->orig_remote_ip = other_saved->orig_remote_ip;
+-    saved->new_in_addr = other_saved->new_in_addr;
++    saved->new_addr = other_saved->new_addr;
+     saved->new_remote_ip = other_saved->new_remote_ip;
+     saved->per_dir_config = other_saved->per_dir_config;
+     saved->debug = other_saved->debug;
+@@ -552,7 +476,11 @@ static int spoof_not_initial(request_rec *this_r, request_rec *other_r,
+     saved->other_saved = other_saved;
+     saved->other_r = other_r;
+     /* Ensure the conn_rec is spoofed */
+-    *remote_in_addr = saved->new_in_addr;
++    if (saved->connection->remote_addr->family != saved->new_addr.family)
++    {
++        return DECLINED;
++    }
++    *saved->connection->remote_addr = saved->new_addr;
+     this_r->connection->remote_ip = saved->new_remote_ip;
+     saved->conn_rec_mod_state = CONN_REC_MODIFIED;
+     /* Force re-evaluation of the remote_host value */
+@@ -589,16 +517,11 @@ static int spoof_not_initial(request_rec *this_r, request_rec *other_r,
+  * The undo_spoof() function undoes the changes made to a conn_rec 
+  * by spoof_initial() or spoof_not_initial()
+  */
+-static int undo_spoof(MEFsave_rec *saved, request_rec *r, char *phase)
++int extract_forwarded_undo_spoof(MEFsave_rec *saved, request_rec *r,
++                                 char *phase)
+ {
+-    in_addr_t *remote_in_addr;
+-    if ((remote_in_addr = get_remote_in_addr(saved->connection)) == NULL)
+-    {
+-        /* Could not get a valid value so give up */
+-        return DECLINED;
+-    }
+     /* Do the restoring */
+-    *remote_in_addr = saved->orig_in_addr;
++    *saved->connection->remote_addr = saved->orig_addr;
+     saved->connection->remote_ip = saved->orig_remote_ip;
+     saved->connection->remote_host = NULL;
+     ap_get_remote_host(saved->connection, saved->per_dir_config, 
+@@ -641,16 +564,11 @@ static int undo_spoof(MEFsave_rec *saved, request_rec *r, char *phase)
+  *    subordinate, request_rec which is (should be) using the same
+  *    conn_rec as the primary request
+  */
+-static int redo_spoof(MEFsave_rec *saved, request_rec *r, char *phase)
++int extract_forwarded_redo_spoof(MEFsave_rec *saved, request_rec *r,
++                                 char *phase)
+ {
+-    in_addr_t *remote_in_addr;
+-    if ((remote_in_addr = get_remote_in_addr(saved->connection)) == NULL)
+-    {
+-        /* Could not get a valid value so give up */
+-        return DECLINED;
+-    }
+     /* Modify it all again */
+-    *remote_in_addr = saved->new_in_addr;
++    *saved->connection->remote_addr = saved->new_addr;
+     saved->connection->remote_ip = saved->new_remote_ip;
+     saved->connection->remote_host = NULL;
+     ap_get_remote_host(saved->connection, saved->per_dir_config, 
+@@ -704,7 +622,7 @@ static int redo_spoof(MEFsave_rec *saved, request_rec *r, char *phase)
+ static int cleanup_initial(void *data)
+ {
+     MEFsave_rec *saved = (MEFsave_rec *)data;
+-    return undo_spoof(saved, NULL, "cleanup initial"); 
++    return extract_forwarded_undo_spoof(saved, NULL, "cleanup initial"); 
+ }
+ 
+ static int cleanup_not_initial(void *data)
+@@ -712,13 +630,15 @@ static int cleanup_not_initial(void *data)
+     MEFsave_rec *saved = (MEFsave_rec *)data;
+     if (saved->other_saved->conn_rec_mod_state == CONN_REC_MODIFIED) 
+     {
+-        return redo_spoof(saved->other_saved, saved->other_r, 
+-                          "cleanup not initial");
++        return extract_forwarded_redo_spoof(saved->other_saved,
++                                            saved->other_r,
++                                            "cleanup not initial");
+     }
+     else
+     {
+-        return undo_spoof(saved->other_saved, saved->other_r,
+-                          "cleanup not initial");    
++        return extract_forwarded_undo_spoof(saved->other_saved,
++                                            saved->other_r,
++                                            "cleanup not initial");    
+     }
+ }
+ 
+@@ -758,7 +678,7 @@ static int primary_request(request_rec *r, char *phase)
+     {
+         if (conf->debug == MEF_DEBUG_ON) 
+         {
+-            fprintf(stderr,"MEF: phase:%s, $s not acceptabler proxy, %s\n", 
++            fprintf(stderr,"MEF: phase:%s, %s not acceptabler proxy, %s\n", 
+                     phase, conn->remote_ip, r->unparsed_uri);
+             fflush(stderr);
+         }
+@@ -917,66 +837,6 @@ static int mef_access_check(request_rec *r)
+     return mef_composite(r, "access check");
+ }
+ 
+-/*
+- * mef_before_proxy_http() is called if Apache 2's HTTP proxy_http handler
+- * is about to act and undoes the spoofing of the conn_rec associated with
+- * the incoming request if the proxy is about to add information to the
+- * request's X-Forwarded-For header. Without this the wrong IP (the
+- * spoof one) is added to the X-Forwarded-For header.
+- */
+-static int mef_before_proxy_http(request_rec *r, 
+-                                 proxy_server_conf *pconf,
+-                                 char *url, const char *proxyname, 
+-                                 apr_port_t proxyport)
+-{
+-    MEFsave_rec *saved;
+-    /*
+-     * If our post-read-request handler did something we may have to too 
+-     */
+-    if ((saved = (MEFsave_rec *)ap_get_module_config(r->request_config, 
+-                                         &extract_forwarded_module)) != NULL)
+-    {
+-        /*
+-         * If proxy_http is going to add X-Forwarded-For info then we have
+-         * have to undo the changes we made earlier so proxy_http can get 
+-         * it right
+-         */
+-        if (PROXYREQ_REVERSE == r->proxyreq) 
+-        {
+-            undo_spoof(saved,  r, "before proxy http");
+-        }
+-    }
+-    return DECLINED;
+-}
+-
+-/*
+- * mef_logging() is used to redo the spoofing of the conn_rec associated
+- * with the incoming request if was undone.
+- * Redoing the spoof is to ensure that the spoof IP is used for logging 
+- * information about the request
+- */
+-static int mef_logging(request_rec *r)
+-{
+-    MEFsave_rec *saved;
+-    /*
+-     * If our post-read-request handler did something we may have to too 
+-     */
+-    if ((saved = (MEFsave_rec *)ap_get_module_config(r->request_config, 
+-                                         &extract_forwarded_module)) != NULL)
+-    {
+-        /*
+-         * If we undid the spoof, probably because proxy_http was adding 
+-         * X-Forwarded-For info, then we want to redo the changes we
+-         * undid so the spook IP is logged
+-         */
+-        if (saved->conn_rec_mod_state == CONN_REC_RESTORED) 
+-        {
+-            redo_spoof(saved, r, "logging");
+-        }
+-    }
+-    return DECLINED;
+-}
+-
+ /*--------------------------------------------------------------------------*/
+ /*                                                                          */
+ /* Data structures pulling all the mef module's bits together               */
+@@ -996,16 +856,6 @@ static void mef_register_hooks(apr_pool_t *p)
+  *    ap_hook_header_parser(mef_header_parser, NULL, NULL, APR_HOOK_FIRST);
+  */
+     ap_hook_access_checker(mef_access_check, NULL, NULL, APR_HOOK_FIRST);   
+-#ifdef USING_proxy_http_module
+-    /* 
+-     * Only need to register the following handlers if proxy_http_module
+-     * is going to be loaded
+-     */
+-    static const char *const mef_proxy_b4[] = { "proxy_http.c", NULL };
+-    proxy_hook_scheme_handler(mef_before_proxy_http, NULL, mef_proxy_b4,
+-                              APR_HOOK_FIRST);
+-    ap_hook_log_transaction(mef_logging, NULL, NULL, APR_HOOK_FIRST);
+-#endif /* USING_proxy_http_module */
+ }
+ 
+ /* 
+@@ -1015,6 +865,8 @@ static void mef_register_hooks(apr_pool_t *p)
+  * translation and hence directory information is unavailable for the 
+  * request.
+  */
++static char its_an_accept;
++
+ static const command_rec mef_cmds[] =
+ {
+     AP_INIT_TAKE1(
+@@ -1043,15 +895,15 @@ static const command_rec mef_cmds[] =
+     ),
+     AP_INIT_ITERATE(
+         "MEFaccept",            /* directive name */
+-        mef_accept_proxy,       /* config action routine */
+-        NULL,                   /* argument to include in call */
++        mef_config_proxy,       /* config action routine */
++        &its_an_accept,         /* argument to include in call */
+         RSRC_CONF,              /* where available */
+                                 /* description  */
+         "One or more proxy names or IPs to accept, or 'all'" 
+     ),
+     AP_INIT_ITERATE(
+         "MEFrefuse",            /* directive name */
+-        mef_refuse_proxy,       /* config action routine */
++        mef_config_proxy,       /* config action routine */
+         NULL,                   /* argument to include in call */
+         RSRC_CONF,              /* where available */
+                                 /* description  */
+diff --git a/mod_extract_forwarded.conf b/mod_extract_forwarded.conf
+new file mode 100644
+index 0000000..b5606a5
+--- /dev/null
++++ b/mod_extract_forwarded.conf
+@@ -0,0 +1,52 @@
++<IfModule mod_extract_forwarded.c>
++	# MEForder:
++	#	This can have either of two value 'refuse,accept' or
++	#	'accept,refuse' and specifies the order in which the
++	#	information in two associated directives, MEFaccept
++	#	and MEFrefuse, are intepreted. The MEFaccept and
++	#	MEFrefuse directives are each used to spcifiy one or
++	#	more IP numbers.
++	MEForder refuse,accept
++
++	# MEFrefuse:
++	#	This can be 'all' OR a space separated list of IP numbers
++	#	and/or domain names of trusted proxy servers whose IP number
++	#	can be derived by DNS from the domain name. The presence of
++	#	'all' overrides any particular IP numbers and means
++	#	that no proxy servers are to be trusted. Individual IP
++	#	numbers mean that those the proxy servers having them
++	#	are not to be trusted. This defaults to 'all'.
++	MEFrefuse all
++
++	# MEFaccept:
++	#	This can be 'all' OR a space separated list of IP numbers
++	#	and/or domain names of trusted proxy servers whose IP number
++	#	can be derived by DNS from the domain name. The presence of
++	#	'all' overrides any particular IP numbers and means
++	#	that all proxy servers are to be trusted. Individual IP
++	#	numbers mean that those the proxy servers having them
++	#	are to be trusted. This defaults to an empty list of
++	#	trusted IP numbers.
++	# MEFaccept <trusted proxy servers' IP numbers>
++
++	# MEFaddenv:
++	#	This can be 'off', 'on' (the default) or a string. 'off'
++	#	means that when spoofing, do not add an environment variable
++	#	whose value is the IP number of the connecting machine.
++	#	'on' means that when spoofing, add an environment variable
++	#	called 'MEF_RPROXY_ADDR' whose value is the IP number of the
++	#	connecting machine. A string means that when spoofing, add
++	#	an environment variable named by the string supplied whose
++	#	value is the IP number of the connecting machine.
++
++	# MEFdebug:
++	#	This can be 'on' or 'off' (the default). When turned 'on'
++	#	information about how the mod_extract_forwarded module is
++	#	processing every request to your Apache 2 server, and any
++	#	associated internal redirects or subsrequests, is written
++	#	to the server's error_log. Thhe amount of output written
++	#	and the way it is generated is such that you would never
++	#	normally want to turn this feature on. This feature is
++	#	intended for debugging operation of the mod_extract_forwarded
++	#	mod_module and it is unlikely you will want to do that.
++</IfModule>
+diff --git a/mod_extract_forwarded.h b/mod_extract_forwarded.h
+new file mode 100644
+index 0000000..96b49a1
+--- /dev/null
++++ b/mod_extract_forwarded.h
+@@ -0,0 +1,131 @@
++/* ====================================================================
++ * The Apache Software License, Version 1.1
++ *
++ * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
++ * reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. The end-user documentation included with the redistribution,
++ *    if any, must include the following acknowledgment:
++ *       "This product includes software developed by the
++ *        Apache Software Foundation (http://www.apache.org/)."
++ *    Alternately, this acknowledgment may appear in the software itself,
++ *    if and wherever such third-party acknowledgments normally appear.
++ *
++ * 4. The names "Apache" and "Apache Software Foundation" must
++ *    not be used to endorse or promote products derived from this
++ *    software without prior written permission. For written
++ *    permission, please contact apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache",
++ *    nor may "Apache" appear in their name, without prior written
++ *    permission of the Apache Software Foundation.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Software Foundation.  For more
++ * information on the Apache Software Foundation, please see
++ * <http://www.apache.org/>.
++ *
++ */
++
++#ifndef MOD_EXTRACT_FORWARDED_H
++#define MOD_EXTRACT_FORWARDED_H
++
++#include "mod_proxy.h"
++#include "mod_extract_forwarded.h"
++
++extern module AP_MODULE_DECLARE_DATA extract_forwarded_module;
++
++/*
++ * Per directory configuration record.  
++ */
++typedef struct {
++    int order;  /* order in which the accept and refuse specs are applied */
++    int debug;                      /* debug output to error log flag */
++    const char *envar;              /* name of env var to add */
++    apr_table_t *accept_proxies;    /* proxies to trust */
++    apr_table_t *refuse_proxies;    /* proxies to distrust */
++} mef_config;
++
++/* 
++ * Two possible orders in which the accept and refuse specs are applied
++ */
++#define REFUSE_THEN_ACCEPT 0
++#define ACCEPT_THEN_REFUSE 1
++
++/*
++ * To output debug info to error log or not
++ */
++#define MEF_DEBUG_OFF 0
++#define MEF_DEBUG_ON 1
++
++/*
++ * Maximum number of IPs in an X-Forwarded-For header of a request before 
++ * it is treated a excessive and hence absurd
++ */
++#define MEF_ABSURD_PROXY_LIMIT 32
++/*
++ * Default environment variable name
++ */
++#define MEF_PROXY_ADDR "MEF_PROXY_ADDR"
++
++/* 
++ * The MEFsave_rec data structure is used to preserve information that
++ * this module has modified in the conn_rec associated with a request
++ * so that the conn_rec can be restored to its original state as needed.
++ * It also carries information between transaction phases and internal
++ * redirects and subrequests
++ */
++typedef struct MEFsave_rec MEFsave_rec;
++
++struct MEFsave_rec {
++    conn_rec *connection;           /* connection record being used */
++    apr_sockaddr_t orig_addr;       /* original remote address */
++    apr_sockaddr_t new_addr;        /* modified remote address */
++    char *orig_remote_ip;           /* original remote_ip */
++    char *new_remote_ip;            /* modified remote_ip */
++    int conn_rec_mod_state;         /* conn_rec modification state */
++    int debug;                      /* are we printing MEF debug */
++    const char *envar;              /* name of env var to add */
++    void *per_dir_config;           /* per_dir_config applicable */
++    MEFsave_rec *other_saved;       /* any preceding req's save_rec */
++    request_rec *other_r;           /* any preceding req's request_rec */    
++};
++
++#define CONN_REC_MODIFIED 1
++#define CONN_REC_RESTORED 0
++
++/*
++ * Functions provided by mod_extract_forwarded
++ */
++extern int extract_forwarded_undo_spoof(MEFsave_rec *saved, request_rec *r,
++                                        char *phase);
++extern int extract_forwarded_redo_spoof(MEFsave_rec *saved, request_rec *r,
++                                        char *phase);
++
++#endif
+diff --git a/mod_extract_forwarded_proxy.c b/mod_extract_forwarded_proxy.c
+new file mode 100644
+index 0000000..1b53d36
+--- /dev/null
++++ b/mod_extract_forwarded_proxy.c
+@@ -0,0 +1,175 @@
++/* ====================================================================
++ * The Apache Software License, Version 1.1
++ *
++ * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
++ * reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. The end-user documentation included with the redistribution,
++ *    if any, must include the following acknowledgment:
++ *       "This product includes software developed by the
++ *        Apache Software Foundation (http://www.apache.org/)."
++ *    Alternately, this acknowledgment may appear in the software itself,
++ *    if and wherever such third-party acknowledgments normally appear.
++ *
++ * 4. The names "Apache" and "Apache Software Foundation" must
++ *    not be used to endorse or promote products derived from this
++ *    software without prior written permission. For written
++ *    permission, please contact apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache",
++ *    nor may "Apache" appear in their name, without prior written
++ *    permission of the Apache Software Foundation.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Software Foundation.  For more
++ * information on the Apache Software Foundation, please see
++ * <http://www.apache.org/>.
++ *
++ */
++
++#include "mod_proxy.h"
++
++#include "mod_extract_forwarded.h"
++
++/* 
++ * The undo_spoof() function undoes the changes made to a conn_rec by
++ * spoof_initial() or spoof_not_initial()
++ */
++extern int extract_forwarded_undo_spoof(MEFsave_rec *saved, request_rec *r,
++                                        char *phase);
++
++/* 
++ * The redo_spoof() function reapplies the changes made to a 
++ * conn_rec by spoof_initial() or spoof_not_initial():
++ *
++ * 1. after a prior call to undo_spoof has removed them, typically
++ *    because of proxy_http reverse-proxy X-Forwarded-For issue
++ * 2. when an internal redirect or subrequest has generated a new
++ *    subordinate, request_rec which is (should be) using the same
++ *    conn_rec as the primary request
++ */
++extern int extract_forwarded_redo_spoof(MEFsave_rec *saved, request_rec *r,
++                                        char *phase);
++
++/*
++ * mef_before_proxy_http() is called if Apache 2's HTTP proxy_http handler
++ * is about to act and undoes the spoofing of the conn_rec associated with
++ * the incoming request if the proxy is about to add information to the
++ * request's X-Forwarded-For header. Without this the wrong IP (the
++ * spoof one) is added to the X-Forwarded-For header.
++ */
++static int mef_before_proxy_http(request_rec *r, 
++#if AP_SERVER_MINORVERSION_NUMBER >= 2
++                                 proxy_worker *worker,
++#endif
++                                 proxy_server_conf *pconf,
++                                 char *url, const char *proxyname, 
++                                 apr_port_t proxyport)
++{
++    MEFsave_rec *saved;
++    /*
++     * If our post-read-request handler did something we may have to too 
++     */
++    if ((saved = (MEFsave_rec *)ap_get_module_config(r->request_config, 
++                                         &extract_forwarded_module)) != NULL)
++    {
++        /*
++         * If proxy_http is going to add X-Forwarded-For info then we have
++         * have to undo the changes we made earlier so proxy_http can get 
++         * it right
++         */
++        if (PROXYREQ_REVERSE == r->proxyreq) 
++        {
++            extract_forwarded_undo_spoof(saved,  r, "before proxy http");
++        }
++    }
++    return DECLINED;
++}
++
++/*
++ * mef_logging() is used to redo the spoofing of the conn_rec associated
++ * with the incoming request if was undone.
++ * Redoing the spoof is to ensure that the spoof IP is used for logging 
++ * information about the request
++ */
++static int mef_logging(request_rec *r)
++{
++    MEFsave_rec *saved;
++    /*
++     * If our post-read-request handler did something we may have to too 
++     */
++    if ((saved = (MEFsave_rec *)ap_get_module_config(r->request_config, 
++                                         &extract_forwarded_module)) != NULL)
++    {
++        /*
++         * If we undid the spoof, probably because proxy_http was adding 
++         * X-Forwarded-For info, then we want to redo the changes we
++         * undid so the spook IP is logged
++         */
++        if (saved->conn_rec_mod_state == CONN_REC_RESTORED) 
++        {
++            redo_spoof(saved, r, "logging");
++        }
++    }
++    return DECLINED;
++}
++
++/*--------------------------------------------------------------------------*/
++/*                                                                          */
++/* Data structures pulling all the mef module's bits together               */
++/*                                                                          */
++/*--------------------------------------------------------------------------*/
++/*
++ * mef module's functions attached to request processing hooks. 
++ */
++static void mef_register_hooks(apr_pool_t *p)
++{
++    /* 
++     * Only need to register the following handlers if proxy_http_module
++     * is going to be loaded
++     */
++    static const char *const mef_proxy_b4[] = { "proxy_http.c", NULL };
++    proxy_hook_scheme_handler(mef_before_proxy_http, NULL, mef_proxy_b4,
++                              APR_HOOK_FIRST);
++    ap_hook_log_transaction(mef_logging, NULL, NULL, APR_HOOK_FIRST);
++}
++
++/* 
++ * mef module's definition for configuration. 
++ */
++module AP_MODULE_DECLARE_DATA extract_forwarded_module =
++{
++    STANDARD20_MODULE_STUFF,
++    NULL,                       /* per-directory config creator */
++    NULL,                       /* dir config merger */
++    NULL,                       /* server config creator */
++    NULL,                       /* server config merger */
++    NULL,                       /* command table */
++    mef_register_hooks,         /* set up other request processing hooks */
++};



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212241242.qBOCgukI006267>