You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2026/10/17 15:56:00 UTC
(tomcat) 03/16: Reject digest challenges without a realm in WebSocket client
This is an automated email from the ASF dual-hosted git repository.
rmaucher pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit a23c816abba4a6fe7a244c762679f5b3024ddef8
Author: opencode <re...@apache.org>
AuthorDate: Fri Oct 16 23:06:23 2026 +0200
Reject digest challenges without a realm in WebSocket client
The mandatory realm parameter of the server Digest challenge (RFC 7616
section 3.3) was not validated. If a non-compliant server omitted the
realm and the user had not configured one, the client sent an
authorization header containing the literal text realm="null" and
computed the digest using the string "null" in A1, resulting in a
malformed header and a silent authentication failure.
Throw an explicit AuthenticationException when the challenge omits the
realm, matching the existing handling of a missing qop value. Add a unit
test for the case.
Found by code review.
---
java/org/apache/tomcat/websocket/DigestAuthenticator.java | 3 +++
java/org/apache/tomcat/websocket/LocalStrings.properties | 1 +
test/org/apache/tomcat/websocket/TestDigestAuthenticator.java | 9 +++++++++
3 files changed, 13 insertions(+)
diff --git a/java/org/apache/tomcat/websocket/DigestAuthenticator.java b/java/org/apache/tomcat/websocket/DigestAuthenticator.java
index f885b55607..0cb58aeb7a 100644
--- a/java/org/apache/tomcat/websocket/DigestAuthenticator.java
+++ b/java/org/apache/tomcat/websocket/DigestAuthenticator.java
@@ -58,6 +58,9 @@ public class DigestAuthenticator extends Authenticator {
Map<String,String> parameterMap = parseAuthenticateHeader(authenticateHeader);
String realm = parameterMap.get("realm");
+ if (realm == null || realm.isEmpty()) {
+ throw new AuthenticationException(sm.getString("digestAuthenticator.noRealm"));
+ }
validateRealm(userRealm, realm);
diff --git a/java/org/apache/tomcat/websocket/LocalStrings.properties b/java/org/apache/tomcat/websocket/LocalStrings.properties
index d474670394..185bc2f7fc 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings.properties
@@ -45,6 +45,7 @@ clientEndpointHolder.instanceRegistrationFailed=Failed to register Endpoint inst
digestAuthenticator.algorithm=Unable to generate request digest [{0}]
digestAuthenticator.noQop=The server challenge did not include a qop value
+digestAuthenticator.noRealm=The server challenge did not include a realm value
futureToSendHandler.timeout=Operation timed out after waiting [{0}] [{1}] to complete
diff --git a/test/org/apache/tomcat/websocket/TestDigestAuthenticator.java b/test/org/apache/tomcat/websocket/TestDigestAuthenticator.java
index 682c1973f4..de790d458b 100644
--- a/test/org/apache/tomcat/websocket/TestDigestAuthenticator.java
+++ b/test/org/apache/tomcat/websocket/TestDigestAuthenticator.java
@@ -42,6 +42,15 @@ public class TestDigestAuthenticator {
doTestAuthorization("auth-int");
}
+ @Test(expected = AuthenticationException.class)
+ public void testAuthorizationMissingRealm() throws Exception {
+ String authenticateHeader =
+ "Digest qop=\"auth\", nonce=\"0000f844a605d5c0cb0270f1e2f10ca0\", algorithm=MD5";
+
+ DigestAuthenticator authenticator = new DigestAuthenticator();
+ authenticator.getAuthorization("GET", "/ws/echo", authenticateHeader, "user", "password", null);
+ }
+
private void doTestAuthorization(String qop) throws Exception {
String method = "GET";
String requestUri = "/ws/echo";
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org