mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-21 16:18:00 +01:00
Forbid linked devices from setting backup-ids
This commit is contained in:
committed by
ravi-signal
parent
5de848bf38
commit
9dfe51eac4
@@ -61,6 +61,7 @@ import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.RedeemedReceiptsManager;
|
||||
import org.whispersystems.textsecuregcm.tests.util.ExperimentHelper;
|
||||
import org.whispersystems.textsecuregcm.util.CompletableFutureTestUtil;
|
||||
@@ -119,7 +120,7 @@ public class BackupAuthManagerTest {
|
||||
final BackupAuthCredentialRequest messagesCredentialRequest = backupAuthTestUtil.getRequest(messagesBackupKey, aci);
|
||||
final BackupAuthCredentialRequest mediaCredentialRequest = backupAuthTestUtil.getRequest(mediaBackupKey, aci);
|
||||
|
||||
authManager.commitBackupId(account, messagesCredentialRequest, mediaCredentialRequest).join();
|
||||
authManager.commitBackupId(account, primaryDevice(), messagesCredentialRequest, mediaCredentialRequest).join();
|
||||
|
||||
verify(account).setBackupCredentialRequests(messagesCredentialRequest.serialize(), mediaCredentialRequest.serialize());
|
||||
}
|
||||
@@ -135,6 +136,7 @@ public class BackupAuthManagerTest {
|
||||
|
||||
final ThrowableAssert.ThrowingCallable commit = () ->
|
||||
authManager.commitBackupId(account,
|
||||
primaryDevice(),
|
||||
backupAuthTestUtil.getRequest(messagesBackupKey, aci),
|
||||
backupAuthTestUtil.getRequest(mediaBackupKey, aci)).join();
|
||||
if (backupLevel == null) {
|
||||
@@ -147,6 +149,24 @@ public class BackupAuthManagerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void commitRequiresPrimary() {
|
||||
final BackupAuthManager authManager = create(BackupLevel.FREE);
|
||||
final Account account = mock(Account.class);
|
||||
when(account.getUuid()).thenReturn(aci);
|
||||
when(accountsManager.updateAsync(any(), any())).thenReturn(CompletableFuture.completedFuture(account));
|
||||
|
||||
final ThrowableAssert.ThrowingCallable commit = () ->
|
||||
authManager.commitBackupId(account,
|
||||
linkedDevice(),
|
||||
backupAuthTestUtil.getRequest(messagesBackupKey, aci),
|
||||
backupAuthTestUtil.getRequest(mediaBackupKey, aci)).join();
|
||||
assertThatExceptionOfType(StatusRuntimeException.class)
|
||||
.isThrownBy(commit)
|
||||
.extracting(ex -> ex.getStatus().getCode())
|
||||
.isEqualTo(Status.Code.PERMISSION_DENIED);
|
||||
}
|
||||
|
||||
@CartesianTest
|
||||
void getBackupAuthCredentials(@CartesianTest.Enum final BackupLevel backupLevel,
|
||||
@CartesianTest.Enum final BackupCredentialType credentialType) {
|
||||
@@ -504,7 +524,7 @@ public class BackupAuthManagerTest {
|
||||
: storedMediaCredential;
|
||||
|
||||
final boolean expectRateLimit = (changeMedia || changeMessage) && rateLimitBackupId;
|
||||
final CompletableFuture<Void> future = authManager.commitBackupId(account, newMessagesCredential, newMediaCredential);
|
||||
final CompletableFuture<Void> future = authManager.commitBackupId(account, primaryDevice(), newMessagesCredential, newMediaCredential);
|
||||
if (expectRateLimit) {
|
||||
CompletableFutureTestUtil.assertFailsWithCause(RateLimitExceededException.class, future);
|
||||
} else {
|
||||
@@ -538,7 +558,7 @@ public class BackupAuthManagerTest {
|
||||
|
||||
// We should get rate limited iff we are out of paid media changes and we changed the media backup-id
|
||||
final boolean expectRateLimit = changeMedia && paid && rateLimitPaidMedia;
|
||||
final CompletableFuture<Void> future = authManager.commitBackupId(account, newMessagesCredential, newMediaCredential);
|
||||
final CompletableFuture<Void> future = authManager.commitBackupId(account, primaryDevice(), newMessagesCredential, newMediaCredential);
|
||||
if (expectRateLimit) {
|
||||
CompletableFutureTestUtil.assertFailsWithCause(RateLimitExceededException.class, future);
|
||||
} else {
|
||||
@@ -562,6 +582,17 @@ public class BackupAuthManagerTest {
|
||||
return account;
|
||||
}
|
||||
|
||||
private Device primaryDevice() {
|
||||
final Device device = mock(Device.class);
|
||||
when(device.isPrimary()).thenReturn(true);
|
||||
return device;
|
||||
}
|
||||
|
||||
private Device linkedDevice() {
|
||||
final Device device = mock(Device.class);
|
||||
when(device.isPrimary()).thenReturn(false);
|
||||
return device;
|
||||
}
|
||||
|
||||
private static String experimentName(@Nullable BackupLevel backupLevel) {
|
||||
return switch (backupLevel) {
|
||||
|
||||
@@ -157,7 +157,7 @@ public class ArchiveControllerTest {
|
||||
|
||||
@Test
|
||||
public void setBackupId() {
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
|
||||
final Response response = resources.getJerseyTest()
|
||||
.target("v1/archives/backupid")
|
||||
@@ -170,7 +170,7 @@ public class ArchiveControllerTest {
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(204);
|
||||
|
||||
verify(backupAuthManager).commitBackupId(AuthHelper.VALID_ACCOUNT,
|
||||
verify(backupAuthManager).commitBackupId(AuthHelper.VALID_ACCOUNT, AuthHelper.VALID_DEVICE,
|
||||
backupAuthTestUtil.getRequest(messagesBackupKey, aci),
|
||||
backupAuthTestUtil.getRequest(mediaBackupKey, aci));
|
||||
}
|
||||
@@ -275,9 +275,9 @@ public class ArchiveControllerTest {
|
||||
@MethodSource
|
||||
public void setBackupIdException(final Exception ex, final boolean sync, final int expectedStatus) {
|
||||
if (sync) {
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any())).thenThrow(ex);
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any(), any())).thenThrow(ex);
|
||||
} else {
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any())).thenReturn(CompletableFuture.failedFuture(ex));
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any(), any())).thenReturn(CompletableFuture.failedFuture(ex));
|
||||
}
|
||||
final Response response = resources.getJerseyTest()
|
||||
.target("v1/archives/backupid")
|
||||
|
||||
@@ -57,6 +57,7 @@ import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||
import org.whispersystems.textsecuregcm.metrics.BackupMetrics;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.util.EnumMapUtil;
|
||||
import org.whispersystems.textsecuregcm.util.TestRandomUtil;
|
||||
|
||||
@@ -69,7 +70,8 @@ class BackupsGrpcServiceTest extends SimpleBaseGrpcTest<BackupsGrpcService, Back
|
||||
backupAuthTestUtil.getRequest(mediaBackupKey, AUTHENTICATED_ACI);
|
||||
final BackupAuthCredentialRequest messagesAuthCredRequest =
|
||||
backupAuthTestUtil.getRequest(messagesBackupKey, AUTHENTICATED_ACI);
|
||||
private final Account account = mock(Account.class);
|
||||
private Account account;
|
||||
private Device device;
|
||||
|
||||
@Mock
|
||||
private BackupAuthManager backupAuthManager;
|
||||
@@ -83,14 +85,19 @@ class BackupsGrpcServiceTest extends SimpleBaseGrpcTest<BackupsGrpcService, Back
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
account = mock(Account.class);
|
||||
device = mock(Device.class);
|
||||
when(device.isPrimary()).thenReturn(true);
|
||||
when(accountsManager.getByAccountIdentifierAsync(AUTHENTICATED_ACI))
|
||||
.thenReturn(CompletableFuture.completedFuture(Optional.of(account)));
|
||||
when(account.getDevice(AUTHENTICATED_DEVICE_ID)).thenReturn(Optional.of(device));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void setBackupId() {
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any(), any()))
|
||||
.thenReturn(CompletableFuture.completedFuture(null));
|
||||
|
||||
authenticatedServiceStub().setBackupId(
|
||||
SetBackupIdRequest.newBuilder()
|
||||
@@ -98,7 +105,7 @@ class BackupsGrpcServiceTest extends SimpleBaseGrpcTest<BackupsGrpcService, Back
|
||||
.setMessagesBackupAuthCredentialRequest(ByteString.copyFrom(messagesAuthCredRequest.serialize()))
|
||||
.build());
|
||||
|
||||
verify(backupAuthManager).commitBackupId(account, messagesAuthCredRequest, mediaAuthCredRequest);
|
||||
verify(backupAuthManager).commitBackupId(account, device, messagesAuthCredRequest, mediaAuthCredRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -147,9 +154,10 @@ class BackupsGrpcServiceTest extends SimpleBaseGrpcTest<BackupsGrpcService, Back
|
||||
@MethodSource
|
||||
void setBackupIdException(final Exception ex, final boolean sync, final Status expected) {
|
||||
if (sync) {
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any())).thenThrow(ex);
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any(), any())).thenThrow(ex);
|
||||
} else {
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any())).thenReturn(CompletableFuture.failedFuture(ex));
|
||||
when(backupAuthManager.commitBackupId(any(), any(), any(), any()))
|
||||
.thenReturn(CompletableFuture.failedFuture(ex));
|
||||
}
|
||||
|
||||
GrpcTestUtils.assertStatusException(
|
||||
|
||||
Reference in New Issue
Block a user