Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues/2659: Fix password comparison. #2660

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/main/java/fr/xephi/authme/security/PasswordSecurity.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,8 @@ public boolean comparePassword(String password, String playerName) {
* @return True if the password matches, false otherwise
*/
public boolean comparePassword(String password, HashedPassword hashedPassword, String playerName) {
String playerLowerCase = playerName.toLowerCase(Locale.ROOT);
return methodMatches(encryptionMethod, password, hashedPassword, playerLowerCase)
|| compareWithLegacyHashes(password, hashedPassword, playerLowerCase);
return methodMatches(encryptionMethod, password, hashedPassword, playerName)
|| compareWithLegacyHashes(password, hashedPassword, playerName);
}

/**
Expand Down
22 changes: 9 additions & 13 deletions src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertThat;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
Expand Down Expand Up @@ -118,12 +118,10 @@ public void shouldReturnPasswordMatch() {
// given
HashedPassword password = new HashedPassword("$TEST$10$SOME_HASH", null);
String playerName = "Tester";
// Calls to EncryptionMethod are always with the lower-case version of the name
String playerLowerCase = playerName.toLowerCase(Locale.ROOT);
String clearTextPass = "myPassTest";

given(dataSource.getPassword(playerName)).willReturn(password);
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(true);
given(method.comparePassword(clearTextPass, password, playerName)).willReturn(true);

// when
boolean result = passwordSecurity.comparePassword(clearTextPass, playerName);
Expand All @@ -132,19 +130,18 @@ public void shouldReturnPasswordMatch() {
assertThat(result, equalTo(true));
verify(dataSource).getPassword(playerName);
verify(pluginManager).callEvent(any(PasswordEncryptionEvent.class));
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
verify(method).comparePassword(clearTextPass, password, playerName);
}

@Test
public void shouldReturnPasswordMismatch() {
// given
HashedPassword password = new HashedPassword("$TEST$10$SOME_HASH", null);
String playerName = "My_PLayer";
String playerLowerCase = playerName.toLowerCase(Locale.ROOT);
String clearTextPass = "passw0Rd1";

given(dataSource.getPassword(playerName)).willReturn(password);
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false);
given(method.comparePassword(clearTextPass, password, playerName)).willReturn(false);

// when
boolean result = passwordSecurity.comparePassword(clearTextPass, playerName);
Expand All @@ -153,7 +150,7 @@ public void shouldReturnPasswordMismatch() {
assertThat(result, equalTo(false));
verify(dataSource).getPassword(playerName);
verify(pluginManager).callEvent(any(PasswordEncryptionEvent.class));
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
verify(method).comparePassword(clearTextPass, password, playerName);
}

@Test
Expand All @@ -179,14 +176,13 @@ public void shouldTryOtherMethodsForFailedPassword() {
HashedPassword password =
new HashedPassword("$2y$10$2e6d2193f43501c926e25elvWlPmWczmrfrnbZV0dUZGITjYjnkkW");
String playerName = "somePlayer";
String playerLowerCase = playerName.toLowerCase(Locale.ROOT);
String clearTextPass = "Test";
// MD5 hash for "Test"
HashedPassword newPassword = new HashedPassword("0cbc6611f5540bd0809a388dc95a615b");

given(dataSource.getPassword(argThat(equalToIgnoringCase(playerName)))).willReturn(password);
given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false);
given(method.computeHash(clearTextPass, playerLowerCase)).willReturn(newPassword);
given(method.comparePassword(clearTextPass, password, playerName)).willReturn(false);
given(method.computeHash(clearTextPass, playerName)).willReturn(newPassword);
given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.MD5);
given(settings.getProperty(SecuritySettings.LEGACY_HASHES)).willReturn(newHashSet(HashAlgorithm.BCRYPT));
passwordSecurity.reload();
Expand All @@ -201,8 +197,8 @@ public void shouldTryOtherMethodsForFailedPassword() {
// should only be invoked with all lower-case names. Data source is case-insensitive itself, so this is fine.
verify(dataSource).getPassword(argThat(equalToIgnoringCase(playerName)));
verify(pluginManager, times(2)).callEvent(any(PasswordEncryptionEvent.class));
verify(method).comparePassword(clearTextPass, password, playerLowerCase);
verify(dataSource).updatePassword(playerLowerCase, newPassword);
verify(method).comparePassword(clearTextPass, password, playerName);
verify(dataSource).updatePassword(playerName, newPassword);
}

@Test
Expand Down