From 55fe1fbbdc7d4b66cdd1178df9a3e29f48b51b06 Mon Sep 17 00:00:00 2001
From: Mario Fetka <mario@localhost.localdomain>
Date: Wed, 1 Apr 2020 17:27:16 +0200
Subject: [PATCH] Bump

---
 Makefile                 |   4 +-
 README.md                |   4 ++
 debian/changelog         |   3 --
 debian/control           |   2 +-
 debian/docs              |   1 -
 debian/lintian-overrides |   2 +
 debian/rules             |   2 +-
 mod_proxy_protocol.c     | 110 +++++++++++++++++++++++++++------------
 8 files changed, 86 insertions(+), 42 deletions(-)
 create mode 100644 debian/lintian-overrides

diff --git a/Makefile b/Makefile
index 0627d7a..c0ff43b 100644
--- a/Makefile
+++ b/Makefile
@@ -12,11 +12,11 @@ all: .libs/mod_proxy_protocol.so
 
 # build the so in the current directory
 .libs/mod_proxy_protocol.so: mod_proxy_protocol.c
-	$(APXS) -c mod_proxy_protocol.c
+	$(APXS) -c -Wc,-Wall mod_proxy_protocol.c
 
 # install the so - usually needs root access
 install: .libs/mod_proxy_protocol.so
-	$(APXS) -i mod_proxy_protocol.c
+	$(APXS) -i mod_proxy_protocol.la
 
 # generate the html doc
 docs: mod_proxy_protocol.html
diff --git a/README.md b/README.md
index cbc25bc..eebeb68 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,10 @@ This is an [Apache](http://httpd.apache.org/) module that implements the
 server side of HAProxy's
 [Proxy Protocol](http://blog.haproxy.com/haproxy/proxy-protocol/).
 
+Note: as of Apache 2.4.30 this code has been merged into
+[mod_remoteip](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html),
+with the `ProxyProtocol` directive renamed to `RemoteIPProxyProtocol`.
+
 ## Build and Install
 
 You'll need the apache development packages installed (typically something
diff --git a/debian/changelog b/debian/changelog
index aa4c74f..d732ac3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
 mod-proxy-protocol (0.2-2) UNRELEASED; urgency=medium
 
   * Add patch for CVE-2019-10097
@@ -11,8 +10,6 @@ mod-proxy-protocol (0.2-1) xenial; urgency=low
 
  -- Roadrunner2 <roadrunner2@github.com>  Tue, 20 Mar 2018 02:11:49 -0700
 
-=======
->>>>>>> upstream/0.1
 mod-proxy-protocol (0.1-1) trusty; urgency=low
 
   * Initial release
diff --git a/debian/control b/debian/control
index a0cdc0a..596d88b 100644
--- a/debian/control
+++ b/debian/control
@@ -8,7 +8,7 @@ Homepage: https://github.com/roadrunner2/mod-proxy-protocol
 
 Package: libapache2-mod-proxy-protocol
 Architecture: amd64
-Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211, apache2 (>= 2.4.0)
+Depends: ${shlibs:Depends}, ${misc:Depends}, apache2-api-20120211
 Description: Apache module for proxy protocol
  The proxy protocol is a way for upstream proxies and load-balancers to
  for the ip-address of the client to the server. This package contains
diff --git a/debian/docs b/debian/docs
index 931c46d..e980146 100644
--- a/debian/docs
+++ b/debian/docs
@@ -1,5 +1,4 @@
 README.md
 mod_proxy_protocol.xml
 mod_proxy_protocol.xml.meta
-mod_proxy_protocol.html
 debian/README.Debian
diff --git a/debian/lintian-overrides b/debian/lintian-overrides
new file mode 100644
index 0000000..48369ea
--- /dev/null
+++ b/debian/lintian-overrides
@@ -0,0 +1,2 @@
+libapache2-mod-proxy-protocol: apache2-module-depends-on-real-apache2-package
+libapache2-mod-proxy-protocol: copyright-should-refer-to-common-license-file-for-apache-2
diff --git a/debian/rules b/debian/rules
index db2bc2a..f311f7d 100755
--- a/debian/rules
+++ b/debian/rules
@@ -4,7 +4,7 @@
 
 build:
 	dh_testdir
-	make all docs
+	make all # docs
 
 clean:
 	dh_testdir
diff --git a/mod_proxy_protocol.c b/mod_proxy_protocol.c
index 5766b80..e74fdf4 100644
--- a/mod_proxy_protocol.c
+++ b/mod_proxy_protocol.c
@@ -80,6 +80,37 @@ static int pp_hook_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
     return OK;
 }
 
+#if !(APR_VERSION_AT_LEAST(1,5,0))
+static APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr)
+{
+    static const char inaddr_any[
+#if APR_HAVE_IPV6
+        sizeof(struct in6_addr)
+#else
+        sizeof(struct in_addr)
+#endif
+    ] = {0};
+
+    if (addr->ipaddr_ptr /* IP address initialized */
+        && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
+        if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) {
+            return 1;
+        }
+#if APR_HAVE_IPV6
+    if (addr->family == AF_INET6
+        && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) {
+        struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
+
+        if (!memcmp(inaddr_any, v4, sizeof *v4)) {
+            return 1;
+        }
+    }
+#endif
+    }
+    return 0;
+}
+#endif
+
 /* Similar apr_sockaddr_equal, except that it compares ports too. */
 static int pp_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
 {
@@ -92,37 +123,19 @@ static int pp_sockaddr_equal(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
 static int pp_sockaddr_compat(apr_sockaddr_t *addr1, apr_sockaddr_t *addr2)
 {
     /* test exact address equality */
-#if !(APR_VERSION_AT_LEAST(1,5,0))
-    apr_sockaddr_t addr0;
-    static const char inaddr_any[ sizeof(struct in_addr) ] = {0};
-#endif
-
     if (apr_sockaddr_equal(addr1, addr2) &&
         (addr1->port == addr2->port || addr1->port == 0 || addr2->port == 0)) {
         return 1;
     }
 
-#if APR_VERSION_AT_LEAST(1,5,0)
     /* test address wildcards */
     if (apr_sockaddr_is_wildcard(addr1) &&
         (addr1->port == 0 || addr1->port == addr2->port)) {
-#else
-    addr0.ipaddr_ptr = &inaddr_any;
-    addr0.ipaddr_len = addr1->ipaddr_len;
-    if (apr_sockaddr_equal(&addr0, addr1) &&
-        (addr1->port == 0 || addr1->port == addr2->port)) {
-#endif
         return 1;
     }
 
-#if APR_VERSION_AT_LEAST (1,5,0)
     if (apr_sockaddr_is_wildcard(addr2) &&
         (addr2->port == 0 || addr2->port == addr1->port)) {
-#else
-    addr0.ipaddr_len = addr2->ipaddr_len;
-    if (apr_sockaddr_equal(&addr0, addr2) &&
-        (addr2->port == 0 || addr2->port == addr1->port)) {
-#endif
         return 1;
     }
 
@@ -320,6 +333,18 @@ static int pp_hook_pre_connection(conn_rec *c, void *csd)
     pp_config *conf;
     pp_conn_config *conn_conf;
 
+    /* Establish master config in slave connections, so that request
+     * processing finds it. */
+    if (c->master != NULL) {
+        conn_conf = ap_get_module_config(c->master->conn_config,
+                                         &proxy_protocol_module);
+        if (conn_conf) {
+            ap_set_module_config(c->conn_config, &proxy_protocol_module,
+                                 conn_conf);
+        }
+        return DECLINED;
+    }
+
     /* check if we're enabled for this connection */
     conf = ap_get_module_config(ap_server_conf->module_config,
                                 &proxy_protocol_module);
@@ -379,7 +404,7 @@ static pp_parse_status_t pp_process_v1_header(conn_rec *c,
                                               proxy_header *hdr, apr_size_t len,
                                               apr_size_t *hdr_len)
 {
-    char *end, *next, *word, *host, *valid_addr_chars, *saveptr;
+    char *end, *word, *host, *valid_addr_chars, *saveptr;
     char buf[sizeof(hdr->v1.line)];
     apr_port_t port;
     apr_status_t ret;
@@ -488,8 +513,6 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c,
                                               proxy_header *hdr)
 {
     apr_status_t ret;
-    struct in_addr *in_addr;
-    struct in6_addr *in6_addr;
 
     switch (hdr->v2.ver_cmd & 0xF) {
         case 0x01: /* PROXY command */
@@ -527,18 +550,17 @@ static pp_parse_status_t pp_process_v2_header(conn_rec *c,
                     break;
 
                 default:
-                    /* unsupported protocol, keep local connection address */
-                    return HDR_DONE;
+                    /* unsupported protocol */
+                    ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(10183)
+                          "RemoteIPProxyProtocol: unsupported protocol %.2hx",
+                           (unsigned short)hdr->v2.fam);
+                    return HDR_ERROR;
             }
             break;  /* we got a sockaddr now */
 
-        case 0x00: /* LOCAL command */
-            /* keep local connection address for LOCAL */
-            return HDR_DONE;
-
         default:
             /* not a supported command */
-            ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, c, 
+            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, 
                           "ProxyProtocol: unsupported command %.2hx",
                           hdr->v2.ver_cmd);
             return HDR_ERROR;
@@ -623,12 +645,25 @@ static apr_status_t pp_input_filter(ap_filter_t *f,
     /* try to read a header's worth of data */
     while (!ctx->done) {
         if (APR_BRIGADE_EMPTY(ctx->bb)) {
-            ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block,
-                                 ctx->need - ctx->rcvd);
+            apr_off_t got, want = ctx->need - ctx->rcvd;
+            ret = ap_get_brigade(f->next, ctx->bb, ctx->mode, block, want);
             if (ret != APR_SUCCESS) {
+                ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10184)
+                       "failed reading input");
                 return ret;
             }
+
+            ret = apr_brigade_length(ctx->bb, 1, &got);
+            if (ret || got > want) {
+              ap_log_cerror(APLOG_MARK, APLOG_ERR, ret, f->c, APLOGNO(10185)
+                     "RemoteIPProxyProtocol header too long, "
+                     "got %" APR_OFF_T_FMT " expected %" APR_OFF_T_FMT,
+                     got, want);
+              f->c->aborted = 1;
+              return APR_ECONNABORTED;
+            }
         }
+
         if (APR_BRIGADE_EMPTY(ctx->bb)) {
             return APR_EOF;
         }
@@ -672,13 +707,20 @@ static apr_status_t pp_input_filter(ap_filter_t *f,
                                             ctx->rcvd, &ctx->need);
             }
             else if (ctx->version == 2) {
+                proxy_header *hdr = (proxy_header *) ctx->header;
+
                 if (ctx->rcvd >= MIN_V2_HDR_LEN) {
-                    ctx->need = MIN_V2_HDR_LEN +
-                                ntohs(((proxy_header *) ctx->header)->v2.len);
+                    ctx->need = MIN_V2_HDR_LEN + ntohs(hdr->v2.len);
+                    if (ctx->need > sizeof(proxy_v2)) {
+                      ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, f->c, APLOGNO(10186)
+                             "RemoteIPProxyProtocol protocol header length too long");
+                      f->c->aborted = 1;
+                      apr_brigade_destroy(ctx->bb);
+                      return APR_ECONNABORTED;
+                    }
                 }
                 if (ctx->rcvd >= ctx->need) {
-                    psts = pp_process_v2_header(f->c, conn_conf,
-                                                (proxy_header *) ctx->header);
+                    psts = pp_process_v2_header(f->c, conn_conf, hdr);
                 }
             }
             else {