Support for configured test devices with hardcoded verification.

Closes #40

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2015-05-13 14:34:06 -07:00
parent c6810d7460
commit 6363be81e0
5 changed files with 65 additions and 6 deletions

View File

@ -25,12 +25,18 @@ import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration;
import org.whispersystems.textsecuregcm.configuration.RedPhoneConfiguration;
import org.whispersystems.textsecuregcm.configuration.RedisConfiguration;
import org.whispersystems.textsecuregcm.configuration.S3Configuration;
import org.whispersystems.textsecuregcm.configuration.TestDeviceConfiguration;
import org.whispersystems.textsecuregcm.configuration.TwilioConfiguration;
import org.whispersystems.textsecuregcm.configuration.WebsocketConfiguration;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import io.dropwizard.Configuration;
import io.dropwizard.client.JerseyClientConfiguration;
import io.dropwizard.db.DataSourceFactory;
@ -70,6 +76,10 @@ public class WhisperServerConfiguration extends Configuration {
@JsonProperty
private DataSourceFactory messageStore;
@Valid
@NotNull
@JsonProperty
private List<TestDeviceConfiguration> testDevices = new LinkedList<>();
@Valid
@JsonProperty
@ -157,4 +167,15 @@ public class WhisperServerConfiguration extends Configuration {
public RedPhoneConfiguration getRedphoneConfiguration() {
return redphone;
}
public Map<String, Integer> getTestDevices() {
Map<String, Integer> results = new HashMap<>();
for (TestDeviceConfiguration testDeviceConfiguration : testDevices) {
results.put(testDeviceConfiguration.getNumber(),
testDeviceConfiguration.getCode());
}
return results;
}
}

View File

@ -192,7 +192,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
deviceAuthenticator,
Device.class, "WhisperServer"));
environment.jersey().register(new AccountController(pendingAccountsManager, accountsManager, rateLimiters, smsSender, messagesManager, new TimeProvider(), authorizationKey));
environment.jersey().register(new AccountController(pendingAccountsManager, accountsManager, rateLimiters, smsSender, messagesManager, new TimeProvider(), authorizationKey, config.getTestDevices()));
environment.jersey().register(new DeviceController(pendingDevicesManager, accountsManager, rateLimiters));
environment.jersey().register(new DirectoryController(rateLimiters, directory));
environment.jersey().register(new FederationControllerV1(accountsManager, attachmentController, messageController, keysControllerV1));

View File

@ -0,0 +1,25 @@
package org.whispersystems.textsecuregcm.configuration;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
public class TestDeviceConfiguration {
@JsonProperty
@NotEmpty
private String number;
@JsonProperty
@NotNull
private int code;
public String getNumber() {
return number;
}
public int getCode() {
return code;
}
}

View File

@ -56,6 +56,7 @@ import javax.ws.rs.core.Response;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Map;
import io.dropwizard.auth.Auth;
@ -71,6 +72,7 @@ public class AccountController {
private final MessagesManager messagesManager;
private final TimeProvider timeProvider;
private final Optional<byte[]> authorizationKey;
private final Map<String, Integer> testDevices;
public AccountController(PendingAccountsManager pendingAccounts,
AccountsManager accounts,
@ -78,7 +80,8 @@ public class AccountController {
SmsSender smsSenderFactory,
MessagesManager messagesManager,
TimeProvider timeProvider,
Optional<byte[]> authorizationKey)
Optional<byte[]> authorizationKey,
Map<String, Integer> testDevices)
{
this.pendingAccounts = pendingAccounts;
this.accounts = accounts;
@ -87,6 +90,7 @@ public class AccountController {
this.messagesManager = messagesManager;
this.timeProvider = timeProvider;
this.authorizationKey = authorizationKey;
this.testDevices = testDevices;
}
@Timed
@ -112,10 +116,12 @@ public class AccountController {
throw new WebApplicationException(Response.status(422).build());
}
VerificationCode verificationCode = generateVerificationCode();
VerificationCode verificationCode = generateVerificationCode(number);
pendingAccounts.store(number, verificationCode.getVerificationCode());
if (transport.equals("sms")) {
if (testDevices.containsKey(number)) {
// noop
} else if (transport.equals("sms")) {
smsSender.deliverSmsVerification(number, verificationCode.getVerificationCodeDisplay());
} else if (transport.equals("voice")) {
smsSender.deliverVoxVerification(number, verificationCode.getVerificationCodeSpeech());
@ -289,8 +295,12 @@ public class AccountController {
logger.debug("Stored device...");
}
@VisibleForTesting protected VerificationCode generateVerificationCode() {
@VisibleForTesting protected VerificationCode generateVerificationCode(String number) {
try {
if (testDevices.containsKey(number)) {
return new VerificationCode(testDevices.get(number));
}
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
int randomInt = 100000 + random.nextInt(900000);
return new VerificationCode(randomInt);

View File

@ -22,6 +22,8 @@ import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import javax.ws.rs.core.MediaType;
import java.util.HashMap;
import io.dropwizard.testing.junit.ResourceTestRule;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
@ -49,7 +51,8 @@ public class AccountControllerTest {
smsSender,
storedMessages,
timeProvider,
Optional.of(authorizationKey)))
Optional.of(authorizationKey),
new HashMap<String, Integer>()))
.build();