Author: markt
Date: Wed Jan 23 13:57:50 2019
New Revision: 1851916
URL: http://svn.apache.org/viewvc?rev=1851916&view=rev
Log:
Make the removal of leading and trailing whitespace from credentials passed to
BASIC authentication configurable via a new attribute, trimCredentials on the
BasicAuthenticator.
Modified:
tomcat/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java
tomcat/trunk/java/org/apache/catalina/authenticator/mbeans-descriptors.xml
tomcat/trunk/test/org/apache/catalina/authenticator/TestBasicAuthParser.java
tomcat/trunk/webapps/docs/changelog.xml
tomcat/trunk/webapps/docs/config/valve.xml
Modified:
tomcat/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java?rev=1851916&r1=1851915&r2=1851916&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/authenticator/BasicAuthenticator.java
Wed Jan 23 13:57:50 2019
@@ -49,6 +49,7 @@ public class BasicAuthenticator extends
private Charset charset = StandardCharsets.ISO_8859_1;
private String charsetString = null;
+ private boolean trimCredentials = true;
public String getCharset() {
@@ -69,6 +70,17 @@ public class BasicAuthenticator extends
}
+
+ public boolean getTrimCredentials() {
+ return trimCredentials;
+ }
+
+
+ public void setTrimCredentials(boolean trimCredentials) {
+ this.trimCredentials = trimCredentials;
+ }
+
+
@Override
protected boolean doAuthenticate(Request request, HttpServletResponse
response)
throws IOException {
@@ -87,7 +99,7 @@ public class BasicAuthenticator extends
ByteChunk authorizationBC = authorization.getByteChunk();
BasicCredentials credentials = null;
try {
- credentials = new BasicCredentials(authorizationBC, charset);
+ credentials = new BasicCredentials(authorizationBC, charset,
trimCredentials);
String username = credentials.getUsername();
String password = credentials.getPassword();
@@ -138,6 +150,7 @@ public class BasicAuthenticator extends
private static final String METHOD = "basic ";
private final Charset charset;
+ private final boolean trimCredentials;
private final ByteChunk authorization;
private final int initialOffset;
private int base64blobOffset;
@@ -145,6 +158,7 @@ public class BasicAuthenticator extends
private String username = null;
private String password = null;
+
/**
* Parse the HTTP Authorization header for BASIC authentication
* as per RFC 2617 section 2, and the Base64 encoded credentials
@@ -156,11 +170,35 @@ public class BasicAuthenticator extends
*
* @throws IllegalArgumentException If the header does not conform
* to RFC 2617
+ * @deprecated Unused. Will be removed in Tomcat 10. Use {@link
+ * BasicCredentials#BasicCredentials(ByteChunk, Charset,
+ * boolean)}
*/
+ @Deprecated
public BasicCredentials(ByteChunk input, Charset charset) throws
IllegalArgumentException {
+ this(input, charset, true);
+ }
+
+ /**
+ * 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.
+ *
+ * @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
+ */
+ public BasicCredentials(ByteChunk input, Charset charset, boolean
trimCredentials)
+ throws IllegalArgumentException {
authorization = input;
initialOffset = input.getOffset();
this.charset = charset;
+ this.trimCredentials = trimCredentials;
parseMethod();
byte[] decoded = parseBase64();
@@ -245,12 +283,12 @@ public class BasicAuthenticator extends
username = new String(decoded, 0, colon, charset);
password = new String(decoded, colon + 1, decoded.length -
colon - 1, charset);
// tolerate surplus white space around credentials
- if (password.length() > 1) {
+ if (password.length() > 1 && trimCredentials) {
password = password.trim();
}
}
// tolerate surplus white space around credentials
- if (username.length() > 1) {
+ if (username.length() > 1 && trimCredentials) {
username = username.trim();
}
}
Modified:
tomcat/trunk/java/org/apache/catalina/authenticator/mbeans-descriptors.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/mbeans-descriptors.xml?rev=1851916&r1=1851915&r2=1851916&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/authenticator/mbeans-descriptors.xml
(original)
+++ tomcat/trunk/java/org/apache/catalina/authenticator/mbeans-descriptors.xml
Wed Jan 23 13:57:50 2019
@@ -64,6 +64,10 @@
description="The name of the LifecycleState that this component
is currently in"
type="java.lang.String"
writeable="false"/>
+
+ <attribute name="trimCredentials"
+ description="Controls whether leading and/or trailing
whitespace is removed from the parsed credentials"
+ type="boolean"/>
</mbean>
Modified:
tomcat/trunk/test/org/apache/catalina/authenticator/TestBasicAuthParser.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/authenticator/TestBasicAuthParser.java?rev=1851916&r1=1851915&r2=1851916&view=diff
==============================================================================
---
tomcat/trunk/test/org/apache/catalina/authenticator/TestBasicAuthParser.java
(original)
+++
tomcat/trunk/test/org/apache/catalina/authenticator/TestBasicAuthParser.java
Wed Jan 23 13:57:50 2019
@@ -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);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
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);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
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);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
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);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertNull(credentials.getPassword());
}
@@ -93,7 +93,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD1, credentials.getPassword());
}
@@ -119,7 +119,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_LONG, credentials.getUsername());
}
@@ -141,7 +141,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_LONG, credentials.getUsername());
}
@@ -157,7 +157,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(METHOD, USER_NAME, PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -174,7 +174,7 @@ public class TestBasicAuthParser {
BasicAuthenticator.BasicCredentials credentials = null;
try {
credentials = new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.fail("IllegalArgumentException expected");
}
catch (Exception e) {
@@ -197,7 +197,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD + " ", USER_NAME, PASSWORD);
final BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -213,7 +213,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PWD_WRONG);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertNotSame(PASSWORD, credentials.getPassword());
}
@@ -225,7 +225,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, EMPTY_USER_NAME, PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(EMPTY_USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -237,7 +237,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, SHORT_USER_NAME, PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(SHORT_USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -249,7 +249,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, SHORT_PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(SHORT_PASSWORD, credentials.getPassword());
}
@@ -261,7 +261,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_SPACE);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_SPACE, credentials.getPassword());
}
@@ -273,7 +273,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_COLON);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_COLON, credentials.getPassword());
}
@@ -285,7 +285,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_COLON);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_COLON, credentials.getPassword());
}
@@ -297,7 +297,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD_COLON);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD_COLON, credentials.getPassword());
}
@@ -315,7 +315,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, PASSWORD, " ");
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -334,7 +334,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, " " + USER_NAME + " ",
PASSWORD);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -353,7 +353,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, USER_NAME, " " + PASSWORD + "
");
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -378,7 +378,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertNotSame(PASSWORD, credentials.getPassword());
Assert.assertEquals(TRUNCATED_PWD, credentials.getPassword());
@@ -396,7 +396,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertNotSame(PASSWORD, credentials.getPassword());
}
@@ -416,7 +416,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(POSSIBLY_DAMAGED_PWD, credentials.getPassword());
}
@@ -433,7 +433,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
@@ -452,7 +452,7 @@ public class TestBasicAuthParser {
new BasicAuthHeader(NICE_METHOD, BASE64_CRIB);
BasicAuthenticator.BasicCredentials credentials =
new BasicAuthenticator.BasicCredentials(
- AUTH_HEADER.getHeader(), StandardCharsets.UTF_8);
+ AUTH_HEADER.getHeader(), StandardCharsets.UTF_8, true);
Assert.assertEquals(USER_NAME, credentials.getUsername());
Assert.assertEquals(PASSWORD, credentials.getPassword());
}
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1851916&r1=1851915&r2=1851916&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Wed Jan 23 13:57:50 2019
@@ -107,6 +107,12 @@
<bug>63078</bug>: Ensure the utility thread pool is at least two, as
the
deployer uses a blocking pattern. (remm, markt)
</fix>
+ <add>
+ Make the removal of leading and trailing whitespace from credentials
+ passed to BASIC authentication configurable via a new attribute,
+ <code>trimCredentials</code> on the <code>BasicAuthenticator</code>.
+ (markt)
+ </add>
</changelog>
</subsection>
<subsection name="Coyote">
Modified: tomcat/trunk/webapps/docs/config/valve.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=1851916&r1=1851915&r2=1851916&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/valve.xml (original)
+++ tomcat/trunk/webapps/docs/config/valve.xml Wed Jan 23 13:57:50 2019
@@ -1271,6 +1271,12 @@
specified, the platform default provider will be used.</p>
</attribute>
+ <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>
+ </attribute>
+
<attribute name="jaspicCallbackHandlerClass" required="false">
<p>Name of the Java class of the
<code>javax.security.auth.callback.CallbackHandler</code>
implementation
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]