You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by li...@apache.org on 2023/02/10 02:07:19 UTC
[tomcat] branch 8.5.x updated: Fix BZ 66471 - JSessionId secure attribute missing with RemoteIpFilter and X-Forwarded-Proto set to https
This is an automated email from the ASF dual-hosted git repository.
lihan pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push:
new 5b72c94e8b Fix BZ 66471 - JSessionId secure attribute missing with RemoteIpFilter and X-Forwarded-Proto set to https
5b72c94e8b is described below
commit 5b72c94e8b2c4ada63a1d91dc527bf4d8fd1f510
Author: lihan <li...@apache.org>
AuthorDate: Fri Feb 10 10:01:27 2023 +0800
Fix BZ 66471 - JSessionId secure attribute missing with RemoteIpFilter and X-Forwarded-Proto set to https
https://bz.apache.org/bugzilla/show_bug.cgi?id=66471
---
java/org/apache/catalina/Globals.java | 7 ++
java/org/apache/catalina/connector/Request.java | 14 ++++
.../apache/catalina/filters/RemoteIpFilter.java | 7 +-
.../catalina/filters/TestRemoteIpFilter.java | 96 ++++++++++++++++------
webapps/docs/changelog.xml | 5 ++
5 files changed, 100 insertions(+), 29 deletions(-)
diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java
index 07213317d6..e21e6e202d 100644
--- a/java/org/apache/catalina/Globals.java
+++ b/java/org/apache/catalina/Globals.java
@@ -111,6 +111,13 @@ public final class Globals {
public static final String SENDFILE_SUPPORTED_ATTR = org.apache.coyote.Constants.SENDFILE_SUPPORTED_ATTR;
+ /**
+ * The request attribute that is set to the value of {@code Boolean.TRUE}
+ * if {@link org.apache.catalina.filters.RemoteIpFilter} determines
+ * that this request was submitted via a secure channel.
+ */
+ public static final String REMOTE_IP_FILTER_SECURE = "org.apache.catalina.filters.RemoteIpFilter.secure";
+
/**
* The request attribute that can be used by a servlet to pass
* to the connector the name of the file that is to be served
diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
index 1a1644c053..53e562ff52 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -3655,6 +3655,20 @@ public class Request implements HttpServletRequest {
// NO-OP
}
});
+ specialAttributes.put(Globals.REMOTE_IP_FILTER_SECURE,
+ new SpecialAttributeAdapter() {
+ @Override
+ public Object get(Request request, String name) {
+ return Boolean.valueOf(request.isSecure());
+ }
+
+ @Override
+ public void set(Request request, String name, Object value) {
+ if (value instanceof Boolean) {
+ request.setSecure(((Boolean) value).booleanValue());
+ }
+ }
+ });
specialAttributes.put(Globals.STREAM_ID,
new SpecialAttributeAdapter() {
@Override
diff --git a/java/org/apache/catalina/filters/RemoteIpFilter.java b/java/org/apache/catalina/filters/RemoteIpFilter.java
index 8bf562dcf8..534d214d46 100644
--- a/java/org/apache/catalina/filters/RemoteIpFilter.java
+++ b/java/org/apache/catalina/filters/RemoteIpFilter.java
@@ -579,11 +579,6 @@ public class RemoteIpFilter implements Filter {
return serverPort;
}
- @Override
- public boolean isSecure() {
- return secure;
- }
-
public void removeHeader(String name) {
Map.Entry<String, List<String>> header = getHeaderEntry(name);
if (header != null) {
@@ -623,7 +618,7 @@ public class RemoteIpFilter implements Filter {
}
public void setSecure(boolean secure) {
- this.secure = secure;
+ super.getRequest().setAttribute(Globals.REMOTE_IP_FILTER_SECURE, Boolean.valueOf(secure));
}
public void setServerName(String serverName) {
diff --git a/test/org/apache/catalina/filters/TestRemoteIpFilter.java b/test/org/apache/catalina/filters/TestRemoteIpFilter.java
index cd7869a553..bf51a5aef8 100644
--- a/test/org/apache/catalina/filters/TestRemoteIpFilter.java
+++ b/test/org/apache/catalina/filters/TestRemoteIpFilter.java
@@ -82,15 +82,21 @@ public class TestRemoteIpFilter extends TomcatBaseTest {
private static final long serialVersionUID = 1L;
- private transient HttpServletRequest request;
-
- public HttpServletRequest getRequest() {
- return request;
- }
+ public String remoteAddr;
+ public String remoteHost;
+ public String scheme;
+ public String serverName;
+ public int serverPort;
+ public boolean isSecure;
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- this.request = request;
+ this.isSecure = request.isSecure();
+ this.remoteAddr = request.getRemoteAddr();
+ this.remoteHost = request.getRemoteHost();
+ this.scheme = request.getScheme();
+ this.serverName = request.getServerName();
+ this.serverPort = request.getServerPort();
PrintWriter writer = response.getWriter();
writer.println("request.remoteAddr=" + request.getRemoteAddr());
@@ -130,16 +136,6 @@ public class TestRemoteIpFilter extends TomcatBaseTest {
getCoyoteRequest().scheme().setString(scheme);
}
- @Override
- public void setAttribute(String name, Object value) {
- getCoyoteRequest().getAttributes().put(name, value);
- }
-
- @Override
- public Object getAttribute(String name) {
- return getCoyoteRequest().getAttributes().get(name);
- }
-
@Override
public String getServerName() {
return "localhost";
@@ -771,16 +767,70 @@ public class TestRemoteIpFilter extends TomcatBaseTest {
// VALIDATE
Assert.assertEquals(HttpURLConnection.HTTP_OK, httpURLConnection.getResponseCode());
- HttpServletRequest request = mockServlet.getRequest();
- Assert.assertNotNull(request);
// VALIDATE X-FORWARDED-FOR
- Assert.assertEquals(expectedRemoteAddr, request.getRemoteAddr());
- Assert.assertEquals(expectedRemoteAddr, request.getRemoteHost());
+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteAddr);
+ Assert.assertEquals(expectedRemoteAddr, mockServlet.remoteHost);
// VALIDATE X-FORWARDED-PROTO
- Assert.assertTrue(request.isSecure());
- Assert.assertEquals("https", request.getScheme());
- Assert.assertEquals(443, request.getServerPort());
+ Assert.assertTrue(mockServlet.isSecure);
+ Assert.assertEquals("https", mockServlet.scheme);
+ Assert.assertEquals(443, mockServlet.serverPort);
+ }
+
+ @Test
+ public void testJSessionIdSecureAttributeMissing() throws Exception {
+
+ // mostly default configuration : enable "x-forwarded-proto"
+ Map<String, String> remoteIpFilterParameter = new HashMap<>();
+ remoteIpFilterParameter.put("protocolHeader", "x-forwarded-proto");
+
+ // SETUP
+ Tomcat tomcat = getTomcatInstance();
+ Context root = tomcat.addContext("", TEMP_DIR);
+
+ FilterDef filterDef = new FilterDef();
+ filterDef.getParameterMap().putAll(remoteIpFilterParameter);
+ filterDef.setFilterClass(RemoteIpFilter.class.getName());
+ filterDef.setFilterName(RemoteIpFilter.class.getName());
+
+ root.addFilterDef(filterDef);
+
+ FilterMap filterMap = new FilterMap();
+ filterMap.setFilterName(RemoteIpFilter.class.getName());
+ filterMap.addURLPatternDecoded("*");
+ root.addFilterMap(filterMap);
+
+ Bug66471Servlet bug66471Servlet = new Bug66471Servlet();
+
+ Tomcat.addServlet(root, bug66471Servlet.getClass().getName(), bug66471Servlet);
+ root.addServletMappingDecoded("/test", bug66471Servlet.getClass().getName());
+
+ getTomcatInstance().start();
+
+ Map<String, List<String>> resHeaders = new HashMap<>();
+ Map<String, List<String>> reqHeaders = new HashMap<>();
+ String expectedRemoteAddr = "my-remote-addr";
+ List<String> forwardedFor = new ArrayList<>(1);
+ forwardedFor.add(expectedRemoteAddr);
+ List<String> forwardedProto = new ArrayList<>(1);
+ forwardedProto.add("https");
+ reqHeaders.put("x-forwarded-for", forwardedFor);
+ reqHeaders.put("x-forwarded-proto", forwardedProto);
+
+ getUrl("http://localhost:" + tomcat.getConnector().getLocalPort() +
+ "/test", null, reqHeaders, resHeaders);
+ String setCookie = resHeaders.get("Set-Cookie").get(0);
+ Assert.assertTrue(setCookie.contains("Secure"));
+ Assert.assertTrue(bug66471Servlet.isSecure.booleanValue());
+ }
+ public static class Bug66471Servlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+ public Boolean isSecure;
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ req.getSession();
+ isSecure = (Boolean) req.getAttribute(Globals.REMOTE_IP_FILTER_SECURE);
+ }
}
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 8bb1f17c46..47e1242485 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -121,6 +121,11 @@
external web server. Based on code and ideas from pull request
<pr>506</pr> provided by Max Fortun. (remm)
</add>
+ <fix>
+ <bug>66471</bug>: Fix JSessionId secure attribute missing When
+ <code>RemoteIpFilter</code> determines that this request was submitted
+ via a secure channel. (lihan)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org