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 2e3e6ed Correct Javadoc and refactor code for clarity 2e3e6ed is described below commit 2e3e6edfa286f14f011079fd1a5144aec5013e28 Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Aug 19 15:56:09 2020 +0100 Correct Javadoc and refactor code for clarity Based on a PR by Milo van der Zee --- .../realm/MessageDigestCredentialHandler.java | 57 ++++++++++------------ webapps/docs/changelog.xml | 6 +++ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java b/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java index d16bd85..616e0e5 100644 --- a/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java +++ b/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java @@ -38,8 +38,9 @@ import org.apache.tomcat.util.security.ConcurrentMessageDigest; * password</li> * <li><b>{SHA}encodedCredential</b> - a Base64 encoded SHA1 digest of the * password</li> - * <li><b>{SSHA}encodedCredential</b> - 20 character salt followed by the salted - * SHA1 digest Base64 encoded</li> + * <li><b>{SSHA}encodedCredential</b> - 20 byte Base64 encoded SHA1 digest + * followed by variable length salt. + * <pre>{SSHA}<sha-1 digest:20><salt:n></pre></li> * <li><b>salt$iterationCount$encodedCredential</b> - a hex encoded salt, * iteration code and a hex encoded credential, each separated by $</li> * </ul> @@ -72,8 +73,7 @@ public class MessageDigestCredentialHandler extends DigestCredentialHandlerBase try { this.encoding = B2CConverter.getCharset(encodingName); } catch (UnsupportedEncodingException e) { - log.error(sm.getString("mdCredentialHandler.unknownEncoding", - encodingName, encoding.name())); + log.error(sm.getString("mdCredentialHandler.unknownEncoding", encodingName, encoding.name())); } } } @@ -94,7 +94,6 @@ public class MessageDigestCredentialHandler extends DigestCredentialHandlerBase @Override public boolean matches(String inputCredentials, String storedCredentials) { - if (inputCredentials == null || storedCredentials == null) { return false; } @@ -106,33 +105,30 @@ public class MessageDigestCredentialHandler extends DigestCredentialHandlerBase // Some directories and databases prefix the password with the hash // type. The string is in a format compatible with Base64.encode not // the normal hex encoding of the digest - if (storedCredentials.startsWith("{MD5}") || - storedCredentials.startsWith("{SHA}")) { + if (storedCredentials.startsWith("{MD5}") || storedCredentials.startsWith("{SHA}")) { // Server is storing digested passwords with a prefix indicating // the digest type - String serverDigest = storedCredentials.substring(5); - String userDigest = Base64.encodeBase64String(ConcurrentMessageDigest.digest( - getAlgorithm(), inputCredentials.getBytes(StandardCharsets.ISO_8859_1))); - return userDigest.equals(serverDigest); - + String base64ServerDigest = storedCredentials.substring(5); + byte[] userDigest = ConcurrentMessageDigest.digest( + getAlgorithm(), inputCredentials.getBytes(StandardCharsets.ISO_8859_1)); + String base64UserDigest = Base64.encodeBase64String(userDigest); + return base64UserDigest.equals(base64ServerDigest); } else if (storedCredentials.startsWith("{SSHA}")) { - // Server is storing digested passwords with a prefix indicating - // the digest type and the salt used when creating that digest - - String serverDigestPlusSalt = storedCredentials.substring(6); - + // "{SSHA}<sha-1 digest:20><salt:n>" // Need to convert the salt to bytes to apply it to the user's // digested password. - byte[] serverDigestPlusSaltBytes = - Base64.decodeBase64(serverDigestPlusSalt); - final int saltPos = 20; - byte[] serverDigestBytes = new byte[saltPos]; - System.arraycopy(serverDigestPlusSaltBytes, 0, - serverDigestBytes, 0, saltPos); - final int saltLength = serverDigestPlusSaltBytes.length - saltPos; + String serverDigestPlusSalt = storedCredentials.substring(6); + byte[] serverDigestPlusSaltBytes = Base64.decodeBase64(serverDigestPlusSalt); + + // Extract the first 20 bytes containing the SHA-1 digest + final int digestLength = 20; + byte[] serverDigestBytes = new byte[digestLength]; + System.arraycopy(serverDigestPlusSaltBytes, 0, serverDigestBytes, 0, digestLength); + + // the remaining bytes are the salt + final int saltLength = serverDigestPlusSaltBytes.length - digestLength; byte[] serverSaltBytes = new byte[saltLength]; - System.arraycopy(serverDigestPlusSaltBytes, saltPos, - serverSaltBytes, 0, saltLength); + System.arraycopy(serverDigestPlusSaltBytes, digestLength, serverSaltBytes, 0, saltLength); // Generate the digested form of the user provided password // using the salt @@ -141,10 +137,8 @@ public class MessageDigestCredentialHandler extends DigestCredentialHandlerBase serverSaltBytes); return Arrays.equals(userDigestBytes, serverDigestBytes); - } else if (storedCredentials.indexOf('$') > -1) { return matchesSaltIterationsEncoded(inputCredentials, storedCredentials); - } else { // Hex hashes should be compared case-insensitively String userDigest = mutate(inputCredentials, null, 1); @@ -164,13 +158,12 @@ public class MessageDigestCredentialHandler extends DigestCredentialHandlerBase if (algorithm == null) { return inputCredentials; } else { + byte[] inputCredentialbytes = inputCredentials.getBytes(encoding); byte[] userDigest; if (salt == null) { - userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, - inputCredentials.getBytes(encoding)); + userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, inputCredentialbytes); } else { - userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, - salt, inputCredentials.getBytes(encoding)); + userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, salt, inputCredentialbytes); } return HexUtils.toHexString(userDigest); } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index af4dfee..1f09bd7 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -82,6 +82,12 @@ the requested resource. Based on a pull request by Sergey Ponomarev. (markt) </fix> + <fix> + Correct the description of the storage format for salted hashes in the + Javadoc for <code>MessageDigestCredentialHandler</code> and refactor the + associated code for clarity. + Based on a patch provided by Milo van der Zee. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org