Read registration recovery passwords exclusively by PNI

This commit is contained in:
Jon Chambers
2024-11-25 17:05:20 -05:00
committed by Jon Chambers
parent 6967e4e54b
commit 5b9f8177f2
19 changed files with 129 additions and 118 deletions

View File

@@ -86,6 +86,7 @@ import org.whispersystems.textsecuregcm.storage.AccountBadge;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.ChangeNumberManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.PhoneNumberIdentifiers;
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
import org.whispersystems.textsecuregcm.tests.util.AccountsHelper;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
@@ -105,6 +106,7 @@ class AccountControllerV2Test {
private final AccountsManager accountsManager = mock(AccountsManager.class);
private final ChangeNumberManager changeNumberManager = mock(ChangeNumberManager.class);
private final PhoneNumberIdentifiers phoneNumberIdentifiers = mock(PhoneNumberIdentifiers.class);
private final RegistrationServiceClient registrationServiceClient = mock(RegistrationServiceClient.class);
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager = mock(
RegistrationRecoveryPasswordsManager.class);
@@ -125,8 +127,8 @@ class AccountControllerV2Test {
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
.addResource(
new AccountControllerV2(accountsManager, changeNumberManager,
new PhoneVerificationTokenManager(registrationServiceClient, registrationRecoveryPasswordsManager,
registrationRecoveryChecker),
new PhoneVerificationTokenManager(phoneNumberIdentifiers, registrationServiceClient,
registrationRecoveryPasswordsManager, registrationRecoveryChecker),
registrationLockVerificationManager, rateLimiters))
.build();
@@ -401,6 +403,8 @@ class AccountControllerV2Test {
@Test
void recoveryPasswordManagerVerificationTrue() throws Exception {
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(any()))
.thenReturn(CompletableFuture.completedFuture(UUID.randomUUID()));
when(registrationRecoveryPasswordsManager.verify(any(), any()))
.thenReturn(CompletableFuture.completedFuture(true));
when(registrationRecoveryChecker.checkRegistrationRecoveryAttempt(any(), any()))
@@ -443,6 +447,8 @@ class AccountControllerV2Test {
@Test
void registrationRecoveryCheckerAllowsAttempt() {
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(any()))
.thenReturn(CompletableFuture.completedFuture(UUID.randomUUID()));
when(registrationRecoveryChecker.checkRegistrationRecoveryAttempt(any(), any())).thenReturn(true);
when(registrationRecoveryPasswordsManager.verify(any(), any()))
.thenReturn(CompletableFuture.completedFuture(true));

View File

@@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.controllers;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
@@ -77,6 +78,7 @@ import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.DeviceCapability;
import org.whispersystems.textsecuregcm.storage.DeviceSpec;
import org.whispersystems.textsecuregcm.storage.PhoneNumberIdentifiers;
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import org.whispersystems.textsecuregcm.tests.util.KeysHelper;
@@ -94,6 +96,7 @@ class RegistrationControllerTest {
private static final String PASSWORD = "password";
private final AccountsManager accountsManager = mock(AccountsManager.class);
private final PhoneNumberIdentifiers phoneNumberIdentifiers = mock(PhoneNumberIdentifiers.class);
private final RegistrationServiceClient registrationServiceClient = mock(RegistrationServiceClient.class);
private final RegistrationLockVerificationManager registrationLockVerificationManager = mock(
RegistrationLockVerificationManager.class);
@@ -113,8 +116,8 @@ class RegistrationControllerTest {
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
.addResource(
new RegistrationController(accountsManager,
new PhoneVerificationTokenManager(registrationServiceClient, registrationRecoveryPasswordsManager,
registrationRecoveryChecker),
new PhoneVerificationTokenManager(phoneNumberIdentifiers, registrationServiceClient,
registrationRecoveryPasswordsManager, registrationRecoveryChecker),
registrationLockVerificationManager, rateLimiters))
.build();
@@ -243,6 +246,8 @@ class RegistrationControllerTest {
@Test
void recoveryPasswordManagerVerificationFailureOrTimeout() {
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(any()))
.thenReturn(CompletableFuture.completedFuture(UUID.randomUUID()));
when(registrationRecoveryChecker.checkRegistrationRecoveryAttempt(any(), any())).thenReturn(true);
when(registrationRecoveryPasswordsManager.verify(any(), any()))
.thenReturn(CompletableFuture.failedFuture(new RuntimeException()));
@@ -289,6 +294,8 @@ class RegistrationControllerTest {
@Test
void recoveryPasswordManagerVerificationTrue() throws InterruptedException {
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(any()))
.thenReturn(CompletableFuture.completedFuture(UUID.randomUUID()));
when(registrationRecoveryChecker.checkRegistrationRecoveryAttempt(any(), any())).thenReturn(true);
when(registrationRecoveryPasswordsManager.verify(any(), any()))
.thenReturn(CompletableFuture.completedFuture(true));
@@ -325,6 +332,8 @@ class RegistrationControllerTest {
@Test
void registrationRecoveryCheckerAllowsAttempt() throws InterruptedException {
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(any()))
.thenReturn(CompletableFuture.completedFuture(UUID.randomUUID()));
when(registrationRecoveryChecker.checkRegistrationRecoveryAttempt(any(), any())).thenReturn(true);
when(registrationRecoveryPasswordsManager.verify(any(), any()))
.thenReturn(CompletableFuture.completedFuture(true));

View File

@@ -39,6 +39,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.stream.Stream;
@@ -77,6 +78,7 @@ import org.whispersystems.textsecuregcm.spam.RegistrationFraudChecker;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.PhoneNumberIdentifiers;
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
import org.whispersystems.textsecuregcm.storage.VerificationSessionManager;
import org.whispersystems.textsecuregcm.util.SystemMapper;
@@ -87,7 +89,11 @@ class VerificationControllerTest {
private static final long SESSION_EXPIRATION_SECONDS = Duration.ofMinutes(10).toSeconds();
private static final byte[] SESSION_ID = "session".getBytes(StandardCharsets.UTF_8);
private static final String NUMBER = "+18005551212";
private static final String NUMBER = PhoneNumberUtil.getInstance().format(
PhoneNumberUtil.getInstance().getExampleNumber("US"),
PhoneNumberUtil.PhoneNumberFormat.E164);
private static final UUID PNI = UUID.randomUUID();
private final RegistrationServiceClient registrationServiceClient = mock(RegistrationServiceClient.class);
private final VerificationSessionManager verificationSessionManager = mock(VerificationSessionManager.class);
@@ -95,6 +101,7 @@ class VerificationControllerTest {
private final RegistrationCaptchaManager registrationCaptchaManager = mock(RegistrationCaptchaManager.class);
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager = mock(
RegistrationRecoveryPasswordsManager.class);
private final PhoneNumberIdentifiers phoneNumberIdentifiers = mock(PhoneNumberIdentifiers.class);
private final RateLimiters rateLimiters = mock(RateLimiters.class);
private final AccountsManager accountsManager = mock(AccountsManager.class);
private final Clock clock = Clock.systemUTC();
@@ -115,7 +122,7 @@ class VerificationControllerTest {
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
.addResource(
new VerificationController(registrationServiceClient, verificationSessionManager, pushNotificationManager,
registrationCaptchaManager, registrationRecoveryPasswordsManager, rateLimiters, accountsManager,
registrationCaptchaManager, registrationRecoveryPasswordsManager, phoneNumberIdentifiers, rateLimiters, accountsManager,
RegistrationFraudChecker.noop(), dynamicConfigurationManager, clock))
.build();
@@ -131,6 +138,8 @@ class VerificationControllerTest {
.thenReturn(new DynamicRegistrationConfiguration(false));
when(dynamicConfigurationManager.getConfiguration())
.thenReturn(dynamicConfiguration);
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(NUMBER))
.thenReturn(CompletableFuture.completedFuture(PNI));
}
@ParameterizedTest