This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 161a46b442c2c04c856581fdfbe35051d1a430fe 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 0cbdafc617..7dafcf54f5 100644 --- a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java +++ b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java @@ -93,6 +93,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 @@ -123,8 +124,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 a61186d6b7..ddccd4e1ad 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 8ea24c3111..b2d6e530d4 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -2027,6 +2027,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="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
