mirror of
https://github.com/signalapp/Signal-Server
synced 2026-02-15 12:25:40 +00:00
Pass carrier data from lookup services to registration service
This commit is contained in:
committed by
Jon Chambers
parent
5043175cb4
commit
9ffb588c6a
@@ -1118,7 +1118,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||
config.getCdnConfiguration().bucket()),
|
||||
new VerificationController(registrationServiceClient, new VerificationSessionManager(verificationSessions),
|
||||
pushNotificationManager, registrationCaptchaManager, registrationRecoveryPasswordsManager,
|
||||
phoneNumberIdentifiers, rateLimiters, accountsManager, registrationFraudChecker,
|
||||
phoneNumberIdentifiers, rateLimiters, accountsManager, carrierDataProvider, registrationFraudChecker,
|
||||
dynamicConfigurationManager, clock)
|
||||
);
|
||||
if (config.getSubscription() != null && config.getOneTimeDonations() != null) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration.dynamic;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.Duration;
|
||||
|
||||
public record DynamicCarrierDataLookupConfiguration(boolean enabled, @NotNull Duration maxCacheAge) {
|
||||
|
||||
public static Duration DEFAULT_MAX_CACHE_AGE = Duration.ofDays(7);
|
||||
|
||||
public DynamicCarrierDataLookupConfiguration() {
|
||||
this(false, DEFAULT_MAX_CACHE_AGE);
|
||||
}
|
||||
|
||||
public DynamicCarrierDataLookupConfiguration {
|
||||
if (maxCacheAge == null) {
|
||||
maxCacheAge = DEFAULT_MAX_CACHE_AGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,10 @@ public class DynamicConfiguration {
|
||||
@Valid
|
||||
private DynamicBackupConfiguration backup = new DynamicBackupConfiguration();
|
||||
|
||||
@JsonProperty
|
||||
@Valid
|
||||
private DynamicCarrierDataLookupConfiguration carrierDataLookup = new DynamicCarrierDataLookupConfiguration();
|
||||
|
||||
public Optional<DynamicExperimentEnrollmentConfiguration> getExperimentEnrollmentConfiguration(
|
||||
final String experimentName) {
|
||||
return Optional.ofNullable(experiments.get(experimentName));
|
||||
@@ -121,4 +125,8 @@ public class DynamicConfiguration {
|
||||
public DynamicBackupConfiguration getBackupConfiguration() {
|
||||
return backup;
|
||||
}
|
||||
|
||||
public DynamicCarrierDataLookupConfiguration getCarrierDataLookupConfiguration() {
|
||||
return carrierDataLookup;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,9 @@ 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.telephony.CarrierData;
|
||||
import org.whispersystems.textsecuregcm.telephony.CarrierDataException;
|
||||
import org.whispersystems.textsecuregcm.telephony.CarrierDataProvider;
|
||||
import org.whispersystems.textsecuregcm.util.ExceptionUtils;
|
||||
import org.whispersystems.textsecuregcm.util.ObsoletePhoneNumberFormatException;
|
||||
import org.whispersystems.textsecuregcm.util.Pair;
|
||||
@@ -129,6 +132,7 @@ public class VerificationController {
|
||||
private final PhoneNumberIdentifiers phoneNumberIdentifiers;
|
||||
private final RateLimiters rateLimiters;
|
||||
private final AccountsManager accountsManager;
|
||||
private final CarrierDataProvider carrierDataProvider;
|
||||
private final RegistrationFraudChecker registrationFraudChecker;
|
||||
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||
private final Clock clock;
|
||||
@@ -141,6 +145,7 @@ public class VerificationController {
|
||||
final PhoneNumberIdentifiers phoneNumberIdentifiers,
|
||||
final RateLimiters rateLimiters,
|
||||
final AccountsManager accountsManager,
|
||||
final CarrierDataProvider carrierDataProvider,
|
||||
final RegistrationFraudChecker registrationFraudChecker,
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager,
|
||||
final Clock clock) {
|
||||
@@ -152,6 +157,7 @@ public class VerificationController {
|
||||
this.phoneNumberIdentifiers = phoneNumberIdentifiers;
|
||||
this.rateLimiters = rateLimiters;
|
||||
this.accountsManager = accountsManager;
|
||||
this.carrierDataProvider = carrierDataProvider;
|
||||
this.registrationFraudChecker = registrationFraudChecker;
|
||||
this.dynamicConfigurationManager = dynamicConfigurationManager;
|
||||
this.clock = clock;
|
||||
@@ -187,14 +193,29 @@ public class VerificationController {
|
||||
throw new ServerErrorException("could not parse already validated number", Response.Status.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
Optional<CarrierData> maybeCarrierData;
|
||||
|
||||
if (dynamicConfigurationManager.getConfiguration().getCarrierDataLookupConfiguration().enabled()) {
|
||||
try {
|
||||
maybeCarrierData = carrierDataProvider.lookupCarrierData(phoneNumber,
|
||||
dynamicConfigurationManager.getConfiguration().getCarrierDataLookupConfiguration().maxCacheAge());
|
||||
} catch (final IOException | CarrierDataException e) {
|
||||
logger.warn("Failed to retrieve carrier data", e);
|
||||
maybeCarrierData = Optional.empty();
|
||||
}
|
||||
} else {
|
||||
maybeCarrierData = Optional.empty();
|
||||
}
|
||||
|
||||
final RegistrationServiceSession registrationServiceSession;
|
||||
try {
|
||||
final String sourceHost = (String) requestContext.getProperty(RemoteAddressFilter.REMOTE_ADDRESS_ATTRIBUTE_NAME);
|
||||
|
||||
registrationServiceSession = registrationServiceClient.createRegistrationSession(phoneNumber, sourceHost,
|
||||
registrationServiceSession = registrationServiceClient.createRegistrationSession(phoneNumber,
|
||||
sourceHost,
|
||||
accountsManager.getByE164(request.number()).isPresent(),
|
||||
request.updateVerificationSessionRequest().mcc(),
|
||||
request.updateVerificationSessionRequest().mnc(),
|
||||
maybeCarrierData.flatMap(CarrierData::mcc).orElse(null),
|
||||
maybeCarrierData.flatMap(CarrierData::mnc).orElse(null),
|
||||
REGISTRATION_RPC_TIMEOUT).join();
|
||||
} catch (final CancellationException e) {
|
||||
|
||||
|
||||
@@ -47,12 +47,12 @@ message CreateRegistrationSessionRequest {
|
||||
string rate_limit_collation_key = 3;
|
||||
|
||||
/**
|
||||
* The MCC for the given `e164` as reported by the client.
|
||||
* The MCC for the given `e164` as reported by a number lookup service.
|
||||
*/
|
||||
string mcc = 4;
|
||||
|
||||
/**
|
||||
* The MNC for the given `e164` as reported by the client.
|
||||
* The MNC for the given `e164` as reported by a number lookup service.
|
||||
*/
|
||||
string mnc = 5;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.whispersystems.textsecuregcm.captcha.AssessmentResult;
|
||||
import org.whispersystems.textsecuregcm.captcha.RegistrationCaptchaManager;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicCarrierDataLookupConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicRegistrationConfiguration;
|
||||
import org.whispersystems.textsecuregcm.entities.RegistrationServiceSession;
|
||||
@@ -83,6 +84,7 @@ 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.telephony.CarrierDataProvider;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
import org.whispersystems.textsecuregcm.util.TestRemoteAddressFilterProvider;
|
||||
|
||||
@@ -106,6 +108,7 @@ class VerificationControllerTest {
|
||||
private final PhoneNumberIdentifiers phoneNumberIdentifiers = mock(PhoneNumberIdentifiers.class);
|
||||
private final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
private final AccountsManager accountsManager = mock(AccountsManager.class);
|
||||
private final CarrierDataProvider carrierDataProvider = mock(CarrierDataProvider.class);
|
||||
private final Clock clock = Clock.systemUTC();
|
||||
|
||||
private final RateLimiter captchaLimiter = mock(RateLimiter.class);
|
||||
@@ -127,7 +130,7 @@ class VerificationControllerTest {
|
||||
.addResource(
|
||||
new VerificationController(registrationServiceClient, verificationSessionManager, pushNotificationManager,
|
||||
registrationCaptchaManager, registrationRecoveryPasswordsManager, phoneNumberIdentifiers, rateLimiters, accountsManager,
|
||||
RegistrationFraudChecker.noop(), dynamicConfigurationManager, clock))
|
||||
carrierDataProvider, RegistrationFraudChecker.noop(), dynamicConfigurationManager, clock))
|
||||
.build();
|
||||
|
||||
@BeforeEach
|
||||
@@ -140,6 +143,8 @@ class VerificationControllerTest {
|
||||
.thenReturn(Optional.empty());
|
||||
when(dynamicConfiguration.getRegistrationConfiguration())
|
||||
.thenReturn(new DynamicRegistrationConfiguration(false));
|
||||
when(dynamicConfiguration.getCarrierDataLookupConfiguration())
|
||||
.thenReturn(new DynamicCarrierDataLookupConfiguration());
|
||||
when(dynamicConfigurationManager.getConfiguration())
|
||||
.thenReturn(dynamicConfiguration);
|
||||
when(phoneNumberIdentifiers.getPhoneNumberIdentifier(NUMBER))
|
||||
|
||||
Reference in New Issue
Block a user