From a3a7d7108b7e8767a8938e1080daf47b958163a1 Mon Sep 17 00:00:00 2001 From: Katherine Yen Date: Tue, 21 Mar 2023 12:46:35 -0700 Subject: [PATCH] Change reglock expiration check to be > 0 instead of >= 0 --- .../RegistrationLockVerificationManager.java | 2 +- .../auth/StoredRegistrationLock.java | 21 ++++++++----------- .../textsecuregcm/storage/Account.java | 2 +- .../auth/StoredRegistrationLockTest.java | 3 ++- .../controllers/AccountControllerTest.java | 9 ++++---- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManager.java index b68887ad8..467c40f3e 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManager.java @@ -141,7 +141,7 @@ public class RegistrationLockVerificationManager { backupServiceCredentialGenerator.generateForUuid(account.getUuid()); throw new WebApplicationException(Response.status(FAILURE_HTTP_STATUS) - .entity(new RegistrationLockFailure(existingRegistrationLock.getTimeRemaining(), + .entity(new RegistrationLockFailure(existingRegistrationLock.getTimeRemaining().toMillis(), existingRegistrationLock.needsFailureCredentials() ? existingBackupCredentials : null)) .build()); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLock.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLock.java index bf469e727..276a4d6f7 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLock.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLock.java @@ -7,8 +7,9 @@ package org.whispersystems.textsecuregcm.auth; import com.google.common.annotations.VisibleForTesting; import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.Optional; -import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import org.whispersystems.textsecuregcm.util.Util; @@ -27,13 +28,13 @@ public class StoredRegistrationLock { private final Optional registrationLockSalt; - private final long lastSeen; + private final Instant lastSeen; /** * @return milliseconds since the last time the account was seen. */ private long timeSinceLastSeen() { - return System.currentTimeMillis() - lastSeen; + return System.currentTimeMillis() - lastSeen.toEpochMilli(); } /** @@ -47,21 +48,17 @@ public class StoredRegistrationLock { return hasLockAndSalt(); } - public StoredRegistrationLock(Optional registrationLock, Optional registrationLockSalt, long lastSeen) { + public StoredRegistrationLock(Optional registrationLock, Optional registrationLockSalt, Instant lastSeen) { this.registrationLock = registrationLock; this.registrationLockSalt = registrationLockSalt; this.lastSeen = lastSeen; } - private boolean hasTimeRemaining() { - return getTimeRemaining() >= 0; - } - public Status getStatus() { if (!isPresent()) { return Status.ABSENT; } - if (hasTimeRemaining()) { + if (getTimeRemaining().toMillis() > 0) { return Status.REQUIRED; } return Status.EXPIRED; @@ -71,8 +68,8 @@ public class StoredRegistrationLock { return hasLockAndSalt(); } - public long getTimeRemaining() { - return REGISTRATION_LOCK_EXPIRATION_DAYS.toMillis() - timeSinceLastSeen(); + public Duration getTimeRemaining() { + return REGISTRATION_LOCK_EXPIRATION_DAYS.minus(timeSinceLastSeen(), ChronoUnit.MILLIS); } public boolean verify(@Nullable String clientRegistrationLock) { @@ -86,6 +83,6 @@ public class StoredRegistrationLock { @VisibleForTesting public StoredRegistrationLock forTime(long timestamp) { - return new StoredRegistrationLock(registrationLock, registrationLockSalt, timestamp); + return new StoredRegistrationLock(registrationLock, registrationLockSalt, Instant.ofEpochMilli(timestamp)); } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java index 25719fae5..989da6a3e 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java @@ -414,7 +414,7 @@ public class Account { public StoredRegistrationLock getRegistrationLock() { requireNotStale(); - return new StoredRegistrationLock(Optional.ofNullable(registrationLock), Optional.ofNullable(registrationLockSalt), getLastSeen()); + return new StoredRegistrationLock(Optional.ofNullable(registrationLock), Optional.ofNullable(registrationLockSalt), Instant.ofEpochMilli(getLastSeen())); } public Optional getUnidentifiedAccessKey() { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLockTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLockTest.java index 2538d8b25..da71585ec 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLockTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredRegistrationLockTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import javax.swing.text.html.Option; import java.time.Duration; +import java.time.Instant; import java.util.Optional; import java.util.stream.Stream; @@ -19,7 +20,7 @@ public class StoredRegistrationLockTest { @MethodSource void getStatus(final Optional registrationLock, final Optional salt, final long lastSeen, final StoredRegistrationLock.Status expectedStatus) { - final StoredRegistrationLock storedLock = new StoredRegistrationLock(registrationLock, salt, lastSeen); + final StoredRegistrationLock storedLock = new StoredRegistrationLock(registrationLock, salt, Instant.ofEpochMilli(lastSeen)); assertEquals(expectedStatus, storedLock.getStatus()); } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java index e150c7ceb..d5e1ecd9c 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java @@ -36,6 +36,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.time.Duration; +import java.time.Instant; import java.util.Arrays; import java.util.Base64; import java.util.Collections; @@ -256,22 +257,22 @@ class AccountControllerTest { when(senderPinAccount.getLastSeen()).thenReturn(System.currentTimeMillis()); when(senderPinAccount.getRegistrationLock()).thenReturn( - new StoredRegistrationLock(Optional.empty(), Optional.empty(), System.currentTimeMillis())); + new StoredRegistrationLock(Optional.empty(), Optional.empty(), Instant.ofEpochMilli(System.currentTimeMillis()))); when(senderHasStorage.getUuid()).thenReturn(UUID.randomUUID()); when(senderHasStorage.isStorageSupported()).thenReturn(true); when(senderHasStorage.getRegistrationLock()).thenReturn( - new StoredRegistrationLock(Optional.empty(), Optional.empty(), System.currentTimeMillis())); + new StoredRegistrationLock(Optional.empty(), Optional.empty(), Instant.ofEpochMilli(System.currentTimeMillis()))); when(senderRegLockAccount.getRegistrationLock()).thenReturn( new StoredRegistrationLock(Optional.of(registrationLockCredentials.hash()), - Optional.of(registrationLockCredentials.salt()), System.currentTimeMillis())); + Optional.of(registrationLockCredentials.salt()), Instant.ofEpochMilli(System.currentTimeMillis()))); when(senderRegLockAccount.getLastSeen()).thenReturn(System.currentTimeMillis()); when(senderRegLockAccount.getUuid()).thenReturn(SENDER_REG_LOCK_UUID); when(senderRegLockAccount.getNumber()).thenReturn(SENDER_REG_LOCK); when(senderTransfer.getRegistrationLock()).thenReturn( - new StoredRegistrationLock(Optional.empty(), Optional.empty(), System.currentTimeMillis())); + new StoredRegistrationLock(Optional.empty(), Optional.empty(), Instant.ofEpochMilli(System.currentTimeMillis()))); when(senderTransfer.getUuid()).thenReturn(SENDER_TRANSFER_UUID); when(senderTransfer.getNumber()).thenReturn(SENDER_TRANSFER);