This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 0d746c58fe17e43f8fbc5b1e58e37cc376141093 Author: opencode <[email protected]> AuthorDate: Mon Oct 12 14:36:34 2026 +0200 Do not resolve REMOTE_IDENT to the authenticated user in rewrite valve REMOTE_IDENT is the RFC 931 ident protocol user name, a variable Tomcat never supported since there is no ident client. ResolverImpl resolved it as request.getRemoteUser(), silently turning any rule filtering on %{REMOTE_IDENT} into an authentication check, and vice versa turning access control intent on ident into an unintended authentication test. Drop the case so REMOTE_IDENT resolves to undefined, which the substitution machinery expands to an empty string, matching mod_rewrite with ident disabled and the empty REMOTE_IDENT CGI environment value that CGIServlet already produces. List REMOTE_IDENT among the not implemented variables, add a regression test that authenticates a request before the rewrite valve and asserts REMOTE_USER still resolves while REMOTE_IDENT is empty, and add a changelog entry for this change in rule semantics. --- .../catalina/valves/rewrite/ResolverImpl.java | 3 +- .../catalina/valves/rewrite/TestRewriteValve.java | 47 ++++++++++++++++++++++ webapps/docs/changelog.xml | 7 ++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java index 15c43e7e2e..71f50c4baf 100644 --- a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java +++ b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java @@ -92,6 +92,7 @@ public class ResolverImpl extends Resolver { * <li>SERVER_ADMIN</li> * <li>API_VERSION</li> * <li>IS_SUBREQ</li> + * <li>REMOTE_IDENT (no RFC 931 ident protocol support)</li> * </ul> */ @Override @@ -122,8 +123,6 @@ public class ResolverImpl extends Resolver { return String.valueOf(request.getRemotePort()); } else if (key.equals("REMOTE_USER")) { return request.getRemoteUser(); - } else if (key.equals("REMOTE_IDENT")) { - return request.getRemoteUser(); } else if (key.equals("REQUEST_METHOD")) { return request.getMethod(); } else if (key.equals("SCRIPT_FILENAME")) { diff --git a/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java b/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java index 2917308c6b..1213cc3eac 100644 --- a/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java +++ b/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java @@ -22,6 +22,7 @@ import java.io.PrintWriter; import java.net.HttpURLConnection; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.security.Principal; import java.time.LocalDate; import java.util.Arrays; import java.util.HashMap; @@ -359,6 +360,52 @@ public class TestRewriteValve extends TomcatBaseTest { "/c/x", "/c/x", null, expected + "TUE" + expected); } + @Test + public void testRemoteIdentIsNotTheRemoteUser() throws Exception { + // REMOTE_IDENT is the RFC 931 ident protocol user name, which Tomcat + // does not support. It must resolve to undefined (expanding to an + // empty string), not to the authenticated user name that REMOTE_USER + // returns. + String config = "RewriteRule ^/c/x$ - " + + "[E=X-Test:user=%{REMOTE_USER}+ident=%{REMOTE_IDENT}]\n"; + + Tomcat tomcat = getTomcatInstance(); + Context ctx = getProgrammaticRootContext(); + + // Authenticate the request before the rewrite valve runs + ctx.getPipeline().addValve(new ValveBase() { + @Override + public void invoke(Request request, Response response) + throws IOException, ServletException { + request.setUserPrincipal(new Principal() { + @Override + public String getName() { + return "testuser"; + } + }); + getNext().invoke(request, response); + } + }); + + RewriteValve rewriteValve = new RewriteValve(); + ctx.getPipeline().addValve(rewriteValve); + rewriteValve.setConfiguration(config); + + Tomcat.addServlet(ctx, "snoop", new SnoopServlet()); + ctx.addServletMapping("/c/*", "snoop"); + + tomcat.start(); + + ByteChunk res = new ByteChunk(); + int rc = methodUrl("http://localhost:" + getPort() + "/c/x", res, + DEFAULT_CLIENT_TIMEOUT_MS, null, null, Method.GET, true); + Assert.assertEquals(200, rc); + res.setCharset(StandardCharsets.UTF_8); + RequestDescriptor requestDesc = SnoopResult.parse(res.toString()); + Assert.assertEquals("user=testuser+ident=", + requestDesc.getAttribute("X-Test")); + } + @Test public void testRewriteMissingCurlyBraceOnVar() throws Exception { try { diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 60b0b7c536..3efef96e68 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -144,6 +144,13 @@ mod_rewrite values (month 1-12, day of week 0-6 with Sunday being 0). (remm) </fix> + <fix> + Stop resolving the <code>REMOTE_IDENT</code> server variable of the + rewrite valve to the authenticated user name. <code>REMOTE_IDENT</code> + is the RFC 931 ident protocol user name, which Tomcat does not support. + It now resolves to undefined, expanding to an empty string, instead of + silently turning ident-based rules into authentication checks. (remm) + </fix> </changelog> </subsection> <subsection name="Web applications"> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
