SEC-1031: LdapShaPasswordEncoder.isPasswordValid startOfHash off by one
http://jira.springframework.org/browse/SEC-1031. Fixed startOfHash value and added tests to check full length of password is used.
This commit is contained in:
parent
0ba690fb0e
commit
0bbab88504
|
@ -86,9 +86,9 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
|
||||||
sha.update(rawPass.getBytes("UTF-8"));
|
sha.update(rawPass.getBytes("UTF-8"));
|
||||||
} catch (java.security.NoSuchAlgorithmException e) {
|
} catch (java.security.NoSuchAlgorithmException e) {
|
||||||
throw new IllegalStateException("No SHA implementation available!");
|
throw new IllegalStateException("No SHA implementation available!");
|
||||||
} catch (UnsupportedEncodingException ue) {
|
} catch (UnsupportedEncodingException ue) {
|
||||||
throw new IllegalStateException("UTF-8 not supported!");
|
throw new IllegalStateException("UTF-8 not supported!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (salt != null) {
|
if (salt != null) {
|
||||||
Assert.isInstanceOf(byte[].class, salt, "Salt value must be a byte array");
|
Assert.isInstanceOf(byte[].class, salt, "Salt value must be a byte array");
|
||||||
|
@ -131,7 +131,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
|
||||||
*/
|
*/
|
||||||
public boolean isPasswordValid(final String encPass, final String rawPass, Object salt) {
|
public boolean isPasswordValid(final String encPass, final String rawPass, Object salt) {
|
||||||
String prefix = extractPrefix(encPass);
|
String prefix = extractPrefix(encPass);
|
||||||
|
|
||||||
if (prefix == null) {
|
if (prefix == null) {
|
||||||
return encPass.equals(rawPass);
|
return encPass.equals(rawPass);
|
||||||
}
|
}
|
||||||
|
@ -141,32 +141,32 @@ public class LdapShaPasswordEncoder implements PasswordEncoder {
|
||||||
} else if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) {
|
} else if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) {
|
||||||
throw new IllegalArgumentException("Unsupported password prefix '" + prefix + "'");
|
throw new IllegalArgumentException("Unsupported password prefix '" + prefix + "'");
|
||||||
} else {
|
} else {
|
||||||
// Standard SHA
|
// Standard SHA
|
||||||
salt = null;
|
salt = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int startOfHash = prefix.length() + 1;
|
int startOfHash = prefix.length();
|
||||||
|
|
||||||
String encodedRawPass = encodePassword(rawPass, salt).substring(startOfHash);
|
String encodedRawPass = encodePassword(rawPass, salt).substring(startOfHash);
|
||||||
|
|
||||||
return encodedRawPass.equals(encPass.substring(startOfHash));
|
return encodedRawPass.equals(encPass.substring(startOfHash));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hash prefix or null if there isn't one.
|
* Returns the hash prefix or null if there isn't one.
|
||||||
*/
|
*/
|
||||||
private String extractPrefix(String encPass) {
|
private String extractPrefix(String encPass) {
|
||||||
if (!encPass.startsWith("{")) {
|
if (!encPass.startsWith("{")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int secondBrace = encPass.lastIndexOf('}');
|
int secondBrace = encPass.lastIndexOf('}');
|
||||||
|
|
||||||
if (secondBrace < 0) {
|
if (secondBrace < 0) {
|
||||||
throw new IllegalArgumentException("Couldn't find closing brace for SHA prefix");
|
throw new IllegalArgumentException("Couldn't find closing brace for SHA prefix");
|
||||||
}
|
}
|
||||||
|
|
||||||
return encPass.substring(0, secondBrace + 1);
|
return encPass.substring(0, secondBrace + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) {
|
public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class LdapShaPasswordEncoderTests {
|
||||||
assertFalse(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", "wrongpassword", null));
|
assertFalse(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", "wrongpassword", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidSaltedPasswordFails() {
|
public void invalidSaltedPasswordFails() {
|
||||||
assertFalse(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "wrongpassword", null));
|
assertFalse(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "wrongpassword", null));
|
||||||
assertFalse(sha.isPasswordValid("{SSHA}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", "wrongpassword", null));
|
assertFalse(sha.isPasswordValid("{SSHA}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", "wrongpassword", null));
|
||||||
|
@ -81,6 +81,15 @@ public class LdapShaPasswordEncoderTests {
|
||||||
assertTrue(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", "boabspasswurd", null));
|
assertTrue(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", "boabspasswurd", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// SEC-1031
|
||||||
|
public void fullLengthOfHashIsUsedInComparison() throws Exception {
|
||||||
|
// Change the first hash character from '2' to '3'
|
||||||
|
assertFalse(sha.isPasswordValid("{SSHA}35ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "boabspasswurd", null));
|
||||||
|
// Change the last hash character from 'X' to 'Y'
|
||||||
|
assertFalse(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgY", "boabspasswurd", null));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void correctPrefixCaseIsUsed() {
|
public void correctPrefixCaseIsUsed() {
|
||||||
sha.setForceLowerCasePrefix(false);
|
sha.setForceLowerCasePrefix(false);
|
||||||
|
@ -95,12 +104,12 @@ public class LdapShaPasswordEncoderTests {
|
||||||
|
|
||||||
@Test(expected=IllegalArgumentException.class)
|
@Test(expected=IllegalArgumentException.class)
|
||||||
public void invalidPrefixIsRejected() {
|
public void invalidPrefixIsRejected() {
|
||||||
sha.isPasswordValid("{MD9}xxxxxxxxxx" , "somepassword", null);
|
sha.isPasswordValid("{MD9}xxxxxxxxxx" , "somepassword", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected=IllegalArgumentException.class)
|
@Test(expected=IllegalArgumentException.class)
|
||||||
public void malformedPrefixIsRejected() {
|
public void malformedPrefixIsRejected() {
|
||||||
// No right brace
|
// No right brace
|
||||||
sha.isPasswordValid("{SSHA25ro4PKC8jhQZ26jVsozhX/xaP0suHgX" , "somepassword", null);
|
sha.isPasswordValid("{SSHA25ro4PKC8jhQZ26jVsozhX/xaP0suHgX" , "somepassword", null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue