This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/master by this push:
     new 479a6a9  Fix BZ 56181 - return correct remoteHost with 
RemoteIP[Valve|Filter]
479a6a9 is described below

commit 479a6a932181ee76d316dfec3bfeeaf39c0a2a6d
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Nov 26 18:57:25 2020 +0000

    Fix BZ 56181 - return correct remoteHost with RemoteIP[Valve|Filter]
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=56181
---
 .../catalina/filters/LocalStrings.properties       |  1 +
 .../apache/catalina/filters/RemoteIpFilter.java    | 41 +++++++++++++++++++++-
 .../apache/catalina/valves/LocalStrings.properties |  1 +
 java/org/apache/catalina/valves/RemoteIpValve.java | 19 +++++++++-
 webapps/docs/changelog.xml                         |  6 ++++
 webapps/docs/config/filter.xml                     |  6 ++++
 6 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/catalina/filters/LocalStrings.properties 
b/java/org/apache/catalina/filters/LocalStrings.properties
index 2e9f564..5877b76 100644
--- a/java/org/apache/catalina/filters/LocalStrings.properties
+++ b/java/org/apache/catalina/filters/LocalStrings.properties
@@ -58,6 +58,7 @@ remoteCidrFilter.noRemoteIp=Client does not have an IP 
address. Request denied.
 remoteIpFilter.invalidHostHeader=Invalid value [{0}] found for Host in HTTP 
header [{1}]
 remoteIpFilter.invalidHostWithPort=Host value [{0}] in HTTP header [{1}] 
included a port number which will be ignored
 remoteIpFilter.invalidNumber=Illegal number for parameter [{0}]: [{1}]
+remoteIpFilter.invalidRemoteAddress=Unable to determine the remote host 
because the reported remote address [{0}] is not valid
 
 requestFilter.deny=Denied request for [{0}] based on property [{1}]
 
diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java 
b/java/org/apache/catalina/filters/RemoteIpFilter.java
index e37859b..e20faee 100644
--- a/java/org/apache/catalina/filters/RemoteIpFilter.java
+++ b/java/org/apache/catalina/filters/RemoteIpFilter.java
@@ -18,6 +18,8 @@ package org.apache.catalina.filters;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -166,6 +168,13 @@ import org.apache.tomcat.util.res.StringManager;
  * <td>integer</td>
  * <td>443</td>
  * </tr>
+ * <tr>
+ * <td>enableLookups</td>
+ * <td>Should a DNS lookup be performed to provide a host name when calling 
{@link ServletRequest#getRemoteHost()}</td>
+ * <td>N/A</td>
+ * <td>boolean</td>
+ * <td>false</td>
+ * </tr>
  * </table>
  * <p>
  * <strong>Regular expression vs. IP address blocks:</strong> 
<code>mod_remoteip</code> allows to use address blocks (e.g.
@@ -681,6 +690,8 @@ public class RemoteIpFilter extends GenericFilter {
 
     protected static final String TRUSTED_PROXIES_PARAMETER = "trustedProxies";
 
+    protected static final String ENABLE_LOOKUPS_PARAMETER = "enableLookups";
+
     /**
      * Convert a given comma delimited list of regular expressions into an 
array of String
      *
@@ -773,6 +784,8 @@ public class RemoteIpFilter extends GenericFilter {
      */
     private Pattern trustedProxies = null;
 
+    private boolean enableLookups;
+
     public void doFilter(HttpServletRequest request, HttpServletResponse 
response, FilterChain chain) throws IOException, ServletException {
 
         boolean isInternal = internalProxies != null &&
@@ -823,7 +836,22 @@ public class RemoteIpFilter extends GenericFilter {
             if (remoteIp != null) {
 
                 xRequest.setRemoteAddr(remoteIp);
-                xRequest.setRemoteHost(remoteIp);
+                if (getEnableLookups()) {
+                    // This isn't a lazy lookup but that would be a little more
+                    // invasive - mainly in XForwardedRequest - and if
+                    // enableLookups is true is seems reasonable that the
+                    // hostname will be required so look it up here.
+                    try {
+                        InetAddress inetAddress = 
InetAddress.getByName(remoteIp);
+                        // We know we need a DNS look up so use 
getCanonicalHostName()
+                        
xRequest.setRemoteHost(inetAddress.getCanonicalHostName());
+                    } catch (UnknownHostException e) {
+                        
log.debug(sm.getString("remoteIpFilter.invalidRemoteAddress", remoteIp), e);
+                        xRequest.setRemoteHost(remoteIp);
+                    }
+                } else {
+                    xRequest.setRemoteHost(remoteIp);
+                }
 
                 if (proxiesHeaderValue.size() == 0) {
                     xRequest.removeHeader(proxiesHeader);
@@ -1013,6 +1041,10 @@ public class RemoteIpFilter extends GenericFilter {
         return trustedProxies;
     }
 
+    public boolean getEnableLookups() {
+        return enableLookups;
+    }
+
     @Override
     public void init() throws ServletException {
         if (getInitParameter(INTERNAL_PROXIES_PARAMETER) != null) {
@@ -1070,6 +1102,10 @@ public class RemoteIpFilter extends GenericFilter {
                 throw new 
NumberFormatException(sm.getString("remoteIpFilter.invalidNumber", 
HTTPS_SERVER_PORT_PARAMETER, e.getLocalizedMessage()));
             }
         }
+
+        if (getInitParameter(ENABLE_LOOKUPS_PARAMETER) != null) {
+            
setEnableLookups(Boolean.parseBoolean(getInitParameter(ENABLE_LOOKUPS_PARAMETER)));
+        }
     }
 
     /**
@@ -1282,6 +1318,9 @@ public class RemoteIpFilter extends GenericFilter {
         }
     }
 
+    public void setEnableLookups(boolean enableLookups) {
+        this.enableLookups = enableLookups;
+    }
 
     /*
      * Log objects are not Serializable but this Filter is because it extends
diff --git a/java/org/apache/catalina/valves/LocalStrings.properties 
b/java/org/apache/catalina/valves/LocalStrings.properties
index 3379786..25f8332 100644
--- a/java/org/apache/catalina/valves/LocalStrings.properties
+++ b/java/org/apache/catalina/valves/LocalStrings.properties
@@ -135,6 +135,7 @@ remoteCidrValve.noRemoteIp=Client does not have an IP 
address. Request denied.
 remoteIpValve.invalidHostHeader=Invalid value [{0}] found for Host in HTTP 
header [{1}]
 remoteIpValve.invalidHostWithPort=Host value [{0}] in HTTP header [{1}] 
included a port number which will be ignored
 remoteIpValve.invalidPortHeader=Invalid value [{0}] found for port in HTTP 
header [{1}]
+remoteIpValve.invalidRemoteAddress=Unable to determine the remote host because 
the reported remote address [{0}] is not valid
 
 requestFilterValve.configInvalid=One or more invalid configuration settings 
were provided for the Remote[Addr|Host]Valve which prevented the Valve and its 
parent containers from starting
 requestFilterValve.deny=Denied request for [{0}] based on property [{1}]
diff --git a/java/org/apache/catalina/valves/RemoteIpValve.java 
b/java/org/apache/catalina/valves/RemoteIpValve.java
index 53191e5..d9a52b1 100644
--- a/java/org/apache/catalina/valves/RemoteIpValve.java
+++ b/java/org/apache/catalina/valves/RemoteIpValve.java
@@ -17,6 +17,8 @@
 package org.apache.catalina.valves;
 
 import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -658,7 +660,22 @@ public class RemoteIpValve extends ValveBase {
             if (remoteIp != null) {
 
                 request.setRemoteAddr(remoteIp);
-                request.setRemoteHost(remoteIp);
+                if (request.getConnector().getEnableLookups()) {
+                    // This isn't a lazy lookup but that would be a little more
+                    // invasive - mainly in Request.getRemoteHost() - and if
+                    // enableLookups is true it seems reasonable that the
+                    // hotsname will be required so look it up here.
+                    try {
+                        InetAddress inetAddress = 
InetAddress.getByName(remoteIp);
+                        // We know we need a DNS look up so use 
getCanonicalHostName()
+                        
request.setRemoteHost(inetAddress.getCanonicalHostName());
+                    } catch (UnknownHostException e) {
+                        
log.debug(sm.getString("remoteIpValve.invalidRemoteAddress", remoteIp), e);
+                        request.setRemoteHost(remoteIp);
+                    }
+                } else {
+                    request.setRemoteHost(remoteIp);
+                }
 
                 if (proxiesHeaderValue.size() == 0) {
                     
request.getCoyoteRequest().getMimeHeaders().removeHeader(proxiesHeader);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 3743633..d675f2c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -106,6 +106,12 @@
 <section name="Tomcat 10.0.0-M11 (markt)" rtext="in development">
   <subsection name="Catalina">
     <changelog>
+      <fix>
+        <bug>56181</bug>: Update the RemoteIpValve and RemoteIpFilter so that
+        calls to <code>ServletRequest.getRemoteHost()</code> are consistent 
with
+        the return value of <code>ServletRequest.getRemoteAddr()</code> rather
+        than always returning a value for the proxy. (markt)
+      </fix>
       <add>
         <bug>64080</bug>: Enhance the graceful shutdown feature. Includes a new
         option for <code>StandardService</code>,
diff --git a/webapps/docs/config/filter.xml b/webapps/docs/config/filter.xml
index e8ae1c7..da25ecb 100644
--- a/webapps/docs/config/filter.xml
+++ b/webapps/docs/config/filter.xml
@@ -1551,6 +1551,12 @@ FINE: Request "/docs/config/manager.html" with response 
status "200"
 
     <attributes>
 
+      <attribute name="enableLookups" required="false">
+        <p>Should a DNS lookup be performed to provide a host name when calling
+        <code>ServletRequest#getRemoteHost()</code>. If not specified, the
+        default of <code>false</code> is used.</p>
+      </attribute>
+
       <attribute name="remoteIpHeader" required="false">
         <p>Name of the HTTP Header read by this valve that holds the list of
         traversed IP addresses starting from the requesting client. If not


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to