You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2024/04/16 11:11:09 UTC
(tomcat) branch 9.0.x updated: Update Basic authentication to RFC 7617
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new edaf5efd93 Update Basic authentication to RFC 7617
edaf5efd93 is described below
commit edaf5efd93f9ff409630bc2338f21e1a60abbf73
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Apr 16 12:10:52 2024 +0100
Update Basic authentication to RFC 7617
---
.../catalina/authenticator/BasicAuthenticator.java | 45 ++++--
.../authenticator/TestBasicAuthParser.java | 173 ++++++++++-----------
webapps/docs/changelog.xml | 7 +
webapps/docs/config/valve.xml | 4 +-
4 files changed, 121 insertions(+), 108 deletions(-)
diff --git a/java/org/apache/catalina/authenticator/BasicAuthenticator.java b/java/org/apache/catalina/authenticator/BasicAuthenticator.java
index acdf084051..63ac050f69 100644
--- a/java/org/apache/catalina/authenticator/BasicAuthenticator.java
+++ b/java/org/apache/catalina/authenticator/BasicAuthenticator.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
+import java.util.Base64;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -29,7 +30,6 @@ import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.codec.binary.Base64;
/**
* An <b>Authenticator</b> and <b>Valve</b> implementation of HTTP BASIC Authentication, as outlined in RFC 7617: "The
@@ -43,7 +43,7 @@ public class BasicAuthenticator extends AuthenticatorBase {
private Charset charset = StandardCharsets.ISO_8859_1;
private String charsetString = null;
- private boolean trimCredentials = true;
+ private boolean trimCredentials = false;
public String getCharset() {
@@ -64,11 +64,27 @@ public class BasicAuthenticator extends AuthenticatorBase {
}
+ /**
+ * Obtain the current setting for the removal of whitespace around the decoded user name and password.
+ *
+ * @return {@code true} if white space will be removed around the decoded user name and password
+ *
+ * @deprecated Will be removed in Tomcat 11 onwards.
+ */
+ @Deprecated
public boolean getTrimCredentials() {
return trimCredentials;
}
+ /**
+ * Configures trimming of whitespace around the decoded user name and password.
+ *
+ * @param trimCredentials {@code true} to remove white space around the decoded user name and password
+ *
+ * @deprecated Will be removed in Tomcat 11 onwards.
+ */
+ @Deprecated
public void setTrimCredentials(boolean trimCredentials) {
this.trimCredentials = trimCredentials;
}
@@ -155,31 +171,29 @@ public class BasicAuthenticator extends AuthenticatorBase {
private String password = null;
/**
- * Parse the HTTP Authorization header for BASIC authentication as per RFC 2617 section 2, and the Base64
- * encoded credentials as per RFC 2045 section 6.8.
+ * Parse the HTTP Authorization header for BASIC authentication as per RFC 7617.
*
* @param input The header value to parse in-place
* @param charset The character set to use to convert the bytes to a string
*
- * @throws IllegalArgumentException If the header does not conform to RFC 2617
- *
- * @deprecated Unused. Will be removed in Tomcat 10. Use 3-arg constructor
+ * @throws IllegalArgumentException If the header does not conform to RFC 7617
*/
- @Deprecated
public BasicCredentials(ByteChunk input, Charset charset) throws IllegalArgumentException {
- this(input, charset, true);
+ this(input, charset, false);
}
/**
- * Parse the HTTP Authorization header for BASIC authentication as per RFC 2617 section 2, and the Base64
- * encoded credentials as per RFC 2045 section 6.8.
+ * Parse the HTTP Authorization header for BASIC authentication as per RFC 7617.
*
* @param input The header value to parse in-place
* @param charset The character set to use to convert the bytes to a string
* @param trimCredentials Should leading and trailing whitespace be removed from the parsed credentials
*
- * @throws IllegalArgumentException If the header does not conform to RFC 2617
+ * @throws IllegalArgumentException If the header does not conform to RFC 7617
+ *
+ * @deprecated Will be removed in Tomcat 11 onwards
*/
+ @Deprecated
public BasicCredentials(ByteChunk input, Charset charset, boolean trimCredentials)
throws IllegalArgumentException {
authorization = input;
@@ -212,7 +226,8 @@ public class BasicAuthenticator extends AuthenticatorBase {
}
/*
- * The authorization method string is case-insensitive and must hae at least one space character as a delimiter.
+ * The authorization method string is case-insensitive and must have at exactly one space character as a
+ * delimiter.
*/
private void parseMethod() throws IllegalArgumentException {
if (authorization.startsWithIgnoreCase(METHOD, 0)) {
@@ -231,7 +246,9 @@ public class BasicAuthenticator extends AuthenticatorBase {
* surrounding white space.
*/
private byte[] parseBase64() throws IllegalArgumentException {
- byte[] decoded = Base64.decodeBase64(authorization.getBuffer(), base64blobOffset, base64blobLength);
+ byte[] encoded = new byte[base64blobLength];
+ System.arraycopy(authorization.getBuffer(), base64blobOffset, encoded, 0, base64blobLength);
+ byte[] decoded = Base64.getDecoder().decode(encoded);
// restore original offset
authorization.setOffset(initialOffset);
if (decoded == null) {
diff --git a/test/org/apache/catalina/authenticator/TestBasicAuthParser.java b/test/org/apache/catalina/authenticator/TestBasicAuthParser.java
index d1dfe31f0b..03d91ba250 100644
--- a/test/org/apache/catalina/authenticator/TestBasicAuthParser.java
+++ b/test/org/apache/catalina/authenticator/TestBasicAuthParser.java
@@ -18,12 +18,12 @@ package org.apache.catalina.authenticator;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.Base64;
import org.junit.Assert;
import org.junit.Test;
import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.codec.binary.Base64;
/**
* Test the BasicAuthenticator's BasicCredentials inner class and the
@@ -45,7 +45,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -56,7 +56,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, null);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertNull(credentials.getPassword());
}
@@ -68,7 +68,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -80,7 +80,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertNull(credentials.getPassword());
}
@@ -93,34 +93,24 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD1, credentials.getPassword());
}
/*
- * RFC 2045 says the Base64 encoded string should be represented
- * as lines of no more than 76 characters. However, RFC 2617
- * says a base64-user-pass token is not limited to 76 char/line.
- * It also says all line breaks, including mandatory ones,
- * should be ignored during decoding.
- * This test case has a line break in the Base64 string.
- * (See also testGoodCribBase64Big below).
+ * Line breaks are not permitted inside the base64 encoded value.
*/
- @Test
- public void testGoodCribLineWrap() throws Exception {
- final String USER_LONG = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- + "abcdefghijklmnopqrstuvwxyz0123456789+/AAAABBBBCCCC"
- + "DDDD"; // 80 characters
+ @Test(expected=IllegalArgumentException.class)
+ public void testLineWrap() throws Exception {
final String BASE64_CRIB = "QUJDREVGR0hJSktMTU5PUFFSU1RVVldY"
+ "WVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0"
+ "\n" + "NTY3ODkrL0FBQUFCQkJCQ0NDQ0REREQ=";
- final BasicAuthHeader AUTH_HEADER =
- new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
+ final BasicAuthHeader AUTH_HEADER = new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
+ @SuppressWarnings("unused")
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
- Assert.assertEquals(USER_LONG, credentials.getUsername());
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
}
/*
@@ -141,7 +131,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_LONG, credentials.getUsername());
}
@@ -157,7 +147,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(METHOD, USER_NAME, PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -172,26 +162,19 @@ public class TestBasicAuthParser {
new BasicAuthHeader(METHOD, USER_NAME, PASSWORD);
@SuppressWarnings("unused")
BasicAuthenticator.BasicCredentials credentials =
- new BasicAuthenticator.BasicCredentials(AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ new BasicAuthenticator.BasicCredentials(AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
}
/*
- * Confirm the Basic parser tolerates excess white space after
- * the authentication method.
- *
- * RFC2617 does not define the separation syntax between the auth-scheme
- * and basic-credentials tokens. Tomcat tolerates any amount of white
- * (within the limits of HTTP header sizes).
+ * Confirm the Basic parser allows exactly one space after the authentication method.
*/
- @Test
+ @Test(expected=IllegalArgumentException.class)
public void testAuthMethodExtraLeadingSpace() throws Exception {
final BasicAuthHeader AUTH_HEADER =
new BasicAuthHeader(NICE_METHOD + " ", USER_NAME, PASSWORD);
+ @SuppressWarnings("unused")
final BasicAuthenticator.BasicCredentials credentials =
- new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
- Assert.assertEquals(USER_NAME, credentials.getUsername());
- Assert.assertEquals(PASSWORD, credentials.getPassword());
+ new BasicAuthenticator.BasicCredentials(AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
}
@@ -205,7 +188,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PWD_WRONG);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertNotSame(PASSWORD, credentials.getPassword());
}
@@ -217,7 +200,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, EMPTY_USER_NAME, PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(EMPTY_USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -229,7 +212,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, SHORT_USER_NAME, PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(SHORT_USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -241,7 +224,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, SHORT_PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(SHORT_PASSWORD, credentials.getPassword());
}
@@ -253,7 +236,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_SPACE);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_SPACE, credentials.getPassword());
}
@@ -265,7 +248,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_COLON);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_COLON, credentials.getPassword());
}
@@ -277,7 +260,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_COLON);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_COLON, credentials.getPassword());
}
@@ -289,41 +272,46 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_COLON);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_COLON, credentials.getPassword());
}
/*
- * Confirm the Basic parser tolerates excess white space after
- * the base64 blob.
- *
- * RFC2617 does not define this case, but asks servers to be
- * tolerant of this kind of client deviation.
+ * Confirm the Basic parser does not tolerate excess white space after the base64 blob.
*/
- @Test
+ @Test(expected=IllegalArgumentException.class)
public void testAuthMethodExtraTrailingSpace() throws Exception {
+ final BasicAuthHeader AUTH_HEADER = new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD, " ");
+ @SuppressWarnings("unused")
+ BasicAuthenticator.BasicCredentials credentials =
+ new BasicAuthenticator.BasicCredentials(AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ }
+
+ /*
+ * Confirm the Basic parser does not tolerate excess white space around the username inside the base64 blob.
+ */
+ @Test
+ public void testUserExtraSpace() throws Exception {
final BasicAuthHeader AUTH_HEADER =
- new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD, " ");
+ new BasicAuthHeader(NICE_METHOD, " " + USER_NAME + " ", PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
- Assert.assertEquals(USER_NAME, credentials.getUsername());
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ Assert.assertNotEquals(USER_NAME, credentials.getUsername());
+ Assert.assertEquals(USER_NAME, credentials.getUsername().trim());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
/*
- * Confirm the Basic parser tolerates excess white space around
- * the username inside the base64 blob.
- *
- * RFC2617 does not define the separation syntax between the auth-scheme
- * and basic-credentials tokens. Tomcat should tolerate any reasonable
- * amount of white space.
+ * Confirm the Basic parser tolerates excess white space around the user name inside the base64 blob when
+ * trimCredentials is enabled.
*/
@Test
- public void testUserExtraSpace() throws Exception {
+ public void testUserExtraSpaceWithTrimCredentials() throws Exception {
final BasicAuthHeader AUTH_HEADER =
new BasicAuthHeader(NICE_METHOD, " " + USER_NAME + " ", PASSWORD);
+ @SuppressWarnings("deprecation")
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
@@ -332,17 +320,29 @@ public class TestBasicAuthParser {
}
/*
- * Confirm the Basic parser tolerates excess white space around
- * the username within the base64 blob.
- *
- * RFC2617 does not define the separation syntax between the auth-scheme
- * and basic-credentials tokens. Tomcat should tolerate any reasonable
- * amount of white space.
+ * Confirm the Basic parser does not tolerate excess white space around the password within the base64 blob.
*/
@Test
public void testPasswordExtraSpace() throws Exception {
final BasicAuthHeader AUTH_HEADER =
new BasicAuthHeader(NICE_METHOD, USER_NAME, " " + PASSWORD + " ");
+ BasicAuthenticator.BasicCredentials credentials =
+ new BasicAuthenticator.BasicCredentials(
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ Assert.assertEquals(USER_NAME, credentials.getUsername());
+ Assert.assertNotEquals(PASSWORD, credentials.getPassword());
+ Assert.assertEquals(PASSWORD, credentials.getPassword().trim());
+ }
+
+ /*
+ * Confirm the Basic parser tolerates excess white space around the password inside the base64 blob when
+ * trimCredentials is enabled.
+ */
+ @Test
+ public void testPasswordExtraSpaceWithTrimCredentials() throws Exception {
+ final BasicAuthHeader AUTH_HEADER =
+ new BasicAuthHeader(NICE_METHOD, USER_NAME, " " + PASSWORD + " ");
+ @SuppressWarnings("deprecation")
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
@@ -370,7 +370,7 @@ public class TestBasicAuthParser {
@SuppressWarnings("unused") // Exception will be thrown.
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
}
/*
@@ -386,44 +386,31 @@ public class TestBasicAuthParser {
@SuppressWarnings("unused")
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
}
/*
- * "-" is not a legal base64 character. The RFC says it must be
- * ignored by the decoder. This is a very strange case because the
- * next character is a pad, which terminates the string normally.
- * It is likely (but not certain) the decoded password will be
- * damaged and subsequent authentication will fail.
+ * "-" is not a legal base64 character.
*/
- @Test
+ @Test(expected=IllegalArgumentException.class)
public void testBadBase64LastChar() throws Exception {
final String BASE64_CRIB = "dXNlcmlkOnNlY3JldA-=";
- final String POSSIBLY_DAMAGED_PWD = "secret";
- final BasicAuthHeader AUTH_HEADER =
- new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
+ final BasicAuthHeader AUTH_HEADER = new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
+ @SuppressWarnings("unused")
BasicAuthenticator.BasicCredentials credentials =
- new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
- Assert.assertEquals(USER_NAME, credentials.getUsername());
- Assert.assertEquals(POSSIBLY_DAMAGED_PWD, credentials.getPassword());
+ new BasicAuthenticator.BasicCredentials(AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
}
/*
- * The trailing third "=" is illegal. However, the RFC says the decoder
- * must terminate as soon as the first pad is detected, so no error
- * will be detected unless the payload has been damaged in some way.
+ * The trailing third "=" is illegal.
*/
- @Test
+ @Test(expected=IllegalArgumentException.class)
public void testBadBase64TooManyEquals() throws Exception {
final String BASE64_CRIB = "dXNlcmlkOnNlY3JldA===";
- final BasicAuthHeader AUTH_HEADER =
- new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
+ final BasicAuthHeader AUTH_HEADER = new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
+ @SuppressWarnings("unused")
BasicAuthenticator.BasicCredentials credentials =
- new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
- Assert.assertEquals(USER_NAME, credentials.getUsername());
- Assert.assertEquals(PASSWORD, credentials.getPassword());
+ new BasicAuthenticator.BasicCredentials(AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
}
/*
@@ -440,7 +427,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -479,7 +466,7 @@ public class TestBasicAuthParser {
: username + ":" + password;
byte[] credentialsBytes =
userCredentials.getBytes(StandardCharsets.ISO_8859_1);
- String base64auth = Base64.encodeBase64String(credentialsBytes);
+ String base64auth = Base64.getEncoder().encodeToString(credentialsBytes);
byte[] base64Bytes =
base64auth.getBytes(StandardCharsets.ISO_8859_1);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index bb92070fa2..4ec65bc19f 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -160,6 +160,13 @@
<bug>68862</bug>: Handle possible response commit when processing read
errors. (remm)
</fix>
+ <fix>
+ Update Basic authentication to implement the requirements of RFC 7617
+ including the changing of the <code>trimCredentials</code> setting which
+ is now defaults to <code>false</code>. Note that the
+ <code>trimCredentials</code> setting will be removed in Tomcat 11.
+ (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
diff --git a/webapps/docs/config/valve.xml b/webapps/docs/config/valve.xml
index f4a862ba1a..c679f3c827 100644
--- a/webapps/docs/config/valve.xml
+++ b/webapps/docs/config/valve.xml
@@ -1563,7 +1563,9 @@
<attribute name="trimCredentials" required="false">
<p>Controls whether leading and/or trailing whitespace is removed from
the parsed credentials. If not specified, the default value is
- <code>true</code>.</p>
+ <code>false</code>.
+ </p>
+ <p>Note: This attribute will be removed from Tomcat 11 onwards.</p>
</attribute>
</attributes>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org