https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #7 from Grzegorz Grzybek <[email protected]> --- Oh - I love digging in history - I had to reason about code from early 2000s to understand the consequences in 2020s... True - I was thinking about {SHA}xxx format for LDAP passwords. I didn't find exact RFC, but there's https://datatracker.ietf.org/doc/html/draft-stroeder-hashed-userpassword-values specifying prefixes like {SHA} or even {SSHA512}. This draft introduces this scheme: {<digest-alg>}<base64(password-hash salt)> RFC 3112 LDAP Authentication Password Schema has different syntax - '$' separated values. Tomcat's https://tomcat.apache.org/tomcat-11.0-doc/config/credentialhandler.html#MessageDigestCredentialHandler defines/documents SSHA as: 20 character salt followed by the salted SHA1 digest Base64 encoded However in the code https://github.com/apache/tomcat/blob/51fd0788b401d589acb9bede8cbd6a495a9ca943/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java#L117 we have // "{SSHA}<sha-1 digest:20><salt:n>" ... // Extract the first 20 bytes containing the SHA-1 digest final int digestLength = 20; ... System.arraycopy(serverDigestPlusSaltBytes, 0, serverDigestBytes, 0, digestLength); ... System.arraycopy(serverDigestPlusSaltBytes, digestLength, serverSaltBytes, 0, saltLength); so the documentation is wrong and should be: 20 bytes of SHA1 digest of password and the salt, followed by the salt bytes ,Base64 encoded Apache Directory Server also uses password+salt digest (in this order): https://github.com/apache/directory-ldap-api/blob/master/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java#L446-L478 And base64 encodes the hash+salt (in this order): https://github.com/apache/directory-ldap-api/blob/be233029e53c7914d3e2588ec151c325cf54b771/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java#L258 So here, Tomcat code, ApacheDS code and this IETF drafts are consistent, but Tomcat documentation is not. While I agree that using: <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="SHA-384" /> means that the user knows what's being done, when you're NOT configuring this handler we can assume that tomcat-users.xml like this: <tomcat-users> <user username="tomcat" password="tomcat=" roles="..."/> <user username="tomcat2" password="{MD5}GzWdh1OFi1W++gRBBnqu0w==" roles="..."/> <user username="tomcat3" password="{SSHA}iVkga68v3vXOzrB7OuNiD5gzaaeOMrVbUjPdZxTGurtfZ/bpHRTvEZAFmvEvhtlFeTV0vhZZg3ZrEQ==" roles="..."/> </tomcat-users> should be fine. But it's not - passwords for tomcat2 and tomcat3 users are compared directly because of: if (getAlgorithm() == null) { // No digests, compare directly return DigestCredentialHandlerBase.equals(inputCredentials, storedCredentials, false); Let's not discuss the strength of MD5 or using Memory/UserDatabaseRealm for serious use. I'm just trying to clear the confusion ;) Oh and I just tried to check `{SSHA}iVkga68v3vXOzrB7OuNiD5gzaaeOMrVbUjPdZxTGurtfZ/bpHRTvEZAFmvEvhtlFeTV0vhZZg3ZrEQ==` ('tomcat' password with 38 bytes salt and SHA-1) and when checking the incoming password, first the password is digested then the salt: // Generate the digested form of the user provided password // using the salt byte[] userDigestBytes = ConcurrentMessageDigest.digest(getAlgorithm(), inputCredentials.getBytes(StandardCharsets.ISO_8859_1), serverSaltBytes); While when checking $-separated password (salt $ ic $ digest), org.apache.catalina.realm.MessageDigestCredentialHandler#mutate first digests the salt and then the password... -- You are receiving this mail because: You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
