]> granicus.if.org Git - apache/commitdiff
Merge r1729929 from trunk:
authorJim Jagielski <jim@apache.org>
Wed, 2 Mar 2016 13:20:24 +0000 (13:20 +0000)
committerJim Jagielski <jim@apache.org>
Wed, 2 Mar 2016 13:20:24 +0000 (13:20 +0000)
Introduce an ap_get_useragent_host() accessor to replace the old
ap_get_remote_host() in most applications, but preserve the original
behavior for all ap_get_remote_host() consumers (mostly, because we
don't have the request_rec in the first place, and also to avoid any
unintended consequences).

This accessor continues to store the remote_host of connection based
uesr agents within the conn_rec for optimization.  Only where some
other module modifies the useragent_addr will we perform a per-request
query of the remote_host.

(Fixed compilation issues noted by Ranier, applies to 2.4.x trunk,
modulo CHANGES and ap_mmn.h)

Submitted by: wrowe
Reviewed/backported by: jim

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1733281 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
include/ap_mmn.h
include/http_core.h
include/httpd.h
server/core.c

diff --git a/CHANGES b/CHANGES
index 91bad9827324476bd6147b98ba780b6c43af725d..49f74c70a2096265d240df74e00105f56f76fdc3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,11 @@
 
 Changes with Apache 2.4.19
 
+  *) core: Track the useragent_host per-request when mod_remoteip or similar
+     modules track a per-request useragent_ip.  Modules should be updated
+     to inquire for ap_get_useragent_host() in place of ap_get_remote_host().
+     [William Rowe]
+
   *) core: fix a bug in <UnDefine ...> directive processing. When used, the last
      <Define...>'ed variable was also withdrawn. PR 59019
      [Christophe Jaillet]
diff --git a/STATUS b/STATUS
index 6cccc2624f77ff26e013cae768fffadb8aa35412..2dfe74ca2e54e15d1826f72343aaf7a258eecdb0 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -112,15 +112,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) core: Track the useragent_host per-request when mod_remoteip or similar
-     modules track a per-request useragent_ip.  Modules should be updated
-     to inquire for ap_get_useragent_host() in place of ap_get_remote_host().
-     Trunk version of patch:
-         http://svn.apache.org/r1729929
-     Trunk patch to core.c/http_core.h applies, modulo CHANGES & ap_mmn.h
-     Note: httpd.h comment r.e. realiging bit fields must be omitted.
-     +1: wrowe, ylavic, icing
-
   *) hostname: Test and log useragent_host per-request across various modules,
      including the scoreboard, expression and rewrite engines, setenvif,
      authz_host, access_compat, custom logging, ssl and REMOTE_HOST variables.
index 368830c038fb09d9aaeac31c505bc41634084662..c017f2700cd80dc680076eb7428a390d93876f8d 100644 (file)
  *                          add protocol to worker_score in scoreboard.h,
  *                          Add pre_close connection hook and 
  *                          ap_prep_lingering_close().
+ * 20120211.56 (2.4.19-dev) Split useragent_host from the conn_rec into
+ *                          the request_rec, with ap_get_useragent_host()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 55                   /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 56                   /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 97cb864072cb559f4b0a0866250070f252e73d52..d39546f7334e8f62ccd185e97c7edf9bd81b6f0c 100644 (file)
@@ -158,6 +158,32 @@ AP_DECLARE(int) ap_allow_overrides(request_rec *r);
  */
 AP_DECLARE(const char *) ap_document_root(request_rec *r);
 
+/**
+ * Lookup the remote user agent's DNS name or IP address
+ * @ingroup get_remote_hostname
+ * @param req The current request
+ * @param type The type of lookup to perform.  One of:
+ * <pre>
+ *     REMOTE_HOST returns the hostname, or NULL if the hostname
+ *                 lookup fails.  It will force a DNS lookup according to the
+ *                 HostnameLookups setting.
+ *     REMOTE_NAME returns the hostname, or the dotted quad if the
+ *                 hostname lookup fails.  It will force a DNS lookup according
+ *                 to the HostnameLookups setting.
+ *     REMOTE_NOLOOKUP is like REMOTE_NAME except that a DNS lookup is
+ *                     never forced.
+ *     REMOTE_DOUBLE_REV will always force a DNS lookup, and also force
+ *                   a double reverse lookup, regardless of the HostnameLookups
+ *                   setting.  The result is the (double reverse checked)
+ *                   hostname, or NULL if any of the lookups fail.
+ * </pre>
+ * @param str_is_ip unless NULL is passed, this will be set to non-zero on
+ *        output when an IP address string is returned
+ * @return The remote hostname (based on the request useragent_ip)
+ */
+AP_DECLARE(const char *) ap_get_useragent_host(request_rec *req, int type,
+                                               int *str_is_ip);
+
 /**
  * Lookup the remote client's DNS name or IP address
  * @ingroup get_remote_host
@@ -180,7 +206,7 @@ AP_DECLARE(const char *) ap_document_root(request_rec *r);
  * </pre>
  * @param str_is_ip unless NULL is passed, this will be set to non-zero on output when an IP address
  *        string is returned
- * @return The remote hostname
+ * @return The remote hostname (based on the connection client_ip)
  */
 AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config, int type, int *str_is_ip);
 
index e61b6d99e65270fa335d029deff774609b123028..69e6e3a2e670c0c0d2e643097f5f3fabda4e8945 100644 (file)
@@ -1046,6 +1046,15 @@ struct request_rec {
     apr_table_t *trailers_in;
     /** MIME trailer environment from the response */
     apr_table_t *trailers_out;
+
+    /** Originator's DNS name, if known.  NULL if DNS hasn't been checked,
+     *  "" if it has and no address was found.  N.B. Only access this though
+     *  ap_get_useragent_host() */
+    char *useragent_host;
+    /** have we done double-reverse DNS? -1 yes/failure, 0 not yet,
+     *  1 yes/success
+     */
+    int double_reverse;
 };
 
 /**
index 7ace95a5e8562ca87b14e42d83e8fa636987035d..99c91a0ec7a5987d6f25a6fa5572199149dbaef9 100644 (file)
@@ -848,35 +848,36 @@ char *ap_response_code_string(request_rec *r, int error_index)
 
 
 /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
-static APR_INLINE void do_double_reverse (conn_rec *conn)
+static APR_INLINE int do_double_reverse (int double_reverse,
+                                         const char *remote_host,
+                                         apr_sockaddr_t *client_addr,
+                                         apr_pool_t *pool)
 {
     apr_sockaddr_t *sa;
     apr_status_t rv;
 
-    if (conn->double_reverse) {
+    if (double_reverse) {
         /* already done */
-        return;
+        return double_reverse;
     }
 
-    if (conn->remote_host == NULL || conn->remote_host[0] == '\0') {
+    if (remote_host == NULL || remote_host[0] == '\0') {
         /* single reverse failed, so don't bother */
-        conn->double_reverse = -1;
-        return;
+        return -1;
     }
 
-    rv = apr_sockaddr_info_get(&sa, conn->remote_host, APR_UNSPEC, 0, 0, conn->pool);
+    rv = apr_sockaddr_info_get(&sa, remote_host, APR_UNSPEC, 0, 0, pool);
     if (rv == APR_SUCCESS) {
         while (sa) {
-            if (apr_sockaddr_equal(sa, conn->client_addr)) {
-                conn->double_reverse = 1;
-                return;
+            if (apr_sockaddr_equal(sa, client_addr)) {
+                return 1;
             }
 
             sa = sa->next;
         }
     }
 
-    conn->double_reverse = -1;
+    return -1;
 }
 
 AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
@@ -914,7 +915,10 @@ AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
             ap_str_tolower(conn->remote_host);
 
             if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
-                do_double_reverse(conn);
+                conn->double_reverse = do_double_reverse(conn->double_reverse,
+                                                         conn->remote_host,
+                                                         conn->client_addr,
+                                                         conn->pool);
                 if (conn->double_reverse != 1) {
                     conn->remote_host = NULL;
                 }
@@ -928,7 +932,9 @@ AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
     }
 
     if (type == REMOTE_DOUBLE_REV) {
-        do_double_reverse(conn);
+        conn->double_reverse = do_double_reverse(conn->double_reverse,
+                                                 conn->remote_host,
+                                                 conn->client_addr, conn->pool);
         if (conn->double_reverse == -1) {
             return NULL;
         }
@@ -953,6 +959,83 @@ AP_DECLARE(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
     }
 }
 
+AP_DECLARE(const char *) ap_get_useragent_host(request_rec *r,
+                                               int type, int *str_is_ip)
+{
+    conn_rec *conn = r->connection;
+    int hostname_lookups;
+    int ignored_str_is_ip;
+
+    if (r->useragent_addr == conn->client_addr) {
+        return ap_get_remote_host(conn, r->per_dir_config, type, str_is_ip);
+    }
+
+    if (!str_is_ip) { /* caller doesn't want to know */
+        str_is_ip = &ignored_str_is_ip;
+    }
+    *str_is_ip = 0;
+
+    hostname_lookups = ((core_dir_config *)
+                        ap_get_core_module_config(r->per_dir_config))
+                            ->hostname_lookups;
+    if (hostname_lookups == HOSTNAME_LOOKUP_UNSET) {
+        hostname_lookups = HOSTNAME_LOOKUP_OFF;
+    }
+
+    if (type != REMOTE_NOLOOKUP
+        && r->useragent_host == NULL
+        && (type == REMOTE_DOUBLE_REV
+        || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
+
+        if (apr_getnameinfo(&r->useragent_host, r->useragent_addr, 0)
+            == APR_SUCCESS) {
+            ap_str_tolower(r->useragent_host);
+
+            if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
+                r->double_reverse = do_double_reverse(r->double_reverse,
+                                                      r->useragent_host,
+                                                      r->useragent_addr,
+                                                      r->pool);
+                if (r->double_reverse != 1) {
+                    r->useragent_host = NULL;
+                }
+            }
+        }
+
+        /* if failed, set it to the NULL string to indicate error */
+        if (r->useragent_host == NULL) {
+            r->useragent_host = "";
+        }
+    }
+
+    if (type == REMOTE_DOUBLE_REV) {
+        r->double_reverse = do_double_reverse(r->double_reverse,
+                                              r->useragent_host,
+                                              r->useragent_addr, r->pool);
+        if (r->double_reverse == -1) {
+            return NULL;
+        }
+    }
+
+    /*
+     * Return the desired information; either the remote DNS name, if found,
+     * or either NULL (if the hostname was requested) or the IP address
+     * (if any identifier was requested).
+     */
+    if (r->useragent_host != NULL && r->useragent_host[0] != '\0') {
+        return r->useragent_host;
+    }
+    else {
+        if (type == REMOTE_HOST || type == REMOTE_DOUBLE_REV) {
+            return NULL;
+        }
+        else {
+            *str_is_ip = 1;
+            return r->useragent_ip;
+        }
+    }
+}
+
 /*
  * Optional function coming from mod_ident, used for looking up ident user
  */