mirror of
https://github.com/signalapp/Signal-Server
synced 2026-08-22 21:07:39 +01:00
Increase DeviceCheck key limit
This commit is contained in:
committed by
Jon Chambers
parent
7d39f2952b
commit
e7ec47aa25
+6
@@ -14,6 +14,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.ForbiddenException;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
@@ -35,6 +36,7 @@ import org.whispersystems.textsecuregcm.backup.BackupAuthManager;
|
||||
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.devicecheck.AppleDeviceCheckManager;
|
||||
import org.whispersystems.textsecuregcm.storage.devicecheck.ChallengeNotFoundException;
|
||||
import org.whispersystems.textsecuregcm.storage.devicecheck.DeviceCheckKeyIdNotFoundException;
|
||||
@@ -139,6 +141,10 @@ public class DeviceCheckController {
|
||||
@RequestBody(description = "The attestation data, created by [attestKey](https://developer.apple.com/documentation/devicecheck/dcappattestservice/attestkey(_:clientdatahash:completionhandler:))")
|
||||
@NotNull final byte[] attestation) {
|
||||
|
||||
if (authenticatedDevice.deviceId() != Device.PRIMARY_ID) {
|
||||
throw new ForbiddenException("Only primary devices may register attestations");
|
||||
}
|
||||
|
||||
final Account account = accountsManager.getByAccountIdentifier(authenticatedDevice.accountIdentifier())
|
||||
.orElseThrow(() -> new WebApplicationException(Response.Status.UNAUTHORIZED));
|
||||
|
||||
|
||||
+10
-1
@@ -30,8 +30,11 @@ import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.metrics.MetricsUtil;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisClusterClient;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.util.ResilienceUtil;
|
||||
@@ -56,7 +59,9 @@ public class AppleDeviceCheckManager {
|
||||
|
||||
// How many distinct device keys we're willing to accept for a single Account
|
||||
@VisibleForTesting
|
||||
static final int MAX_DEVICE_KEYS = 100;
|
||||
static final int MAX_DEVICE_KEYS = 200;
|
||||
|
||||
private static final String KEY_COUNT_DISTRIBUTION_NAME = MetricsUtil.name(AppleDeviceCheckManager.class, "keyCount");
|
||||
|
||||
private final AppleDeviceChecks appleDeviceChecks;
|
||||
private final FaultTolerantRedisClusterClient redisClient;
|
||||
@@ -109,6 +114,10 @@ public class AppleDeviceCheckManager {
|
||||
return;
|
||||
}
|
||||
|
||||
DistributionSummary.builder(KEY_COUNT_DISTRIBUTION_NAME)
|
||||
.register(Metrics.globalRegistry)
|
||||
.record(existingKeys.size());
|
||||
|
||||
if (existingKeys.size() >= MAX_DEVICE_KEYS) {
|
||||
// This is best-effort, since we don't check the number of keys transactionally. We just don't want to allow
|
||||
// the keys for an account to grow arbitrarily large
|
||||
|
||||
+19
@@ -12,6 +12,7 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.dropwizard.auth.AuthValueFactoryProvider;
|
||||
@@ -193,6 +194,24 @@ class DeviceCheckControllerTest {
|
||||
.registerAttestation(any(), eq(keyId), eq(attestation));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerKeyNonPrimary() {
|
||||
final byte[] keyId = TestRandomUtil.nextBytes(16);
|
||||
final byte[] attestation = TestRandomUtil.nextBytes(32);
|
||||
final Response response = resources.getJerseyTest()
|
||||
.target("v1/devicecheck/attest")
|
||||
.queryParam("keyId", Base64.getUrlEncoder().encodeToString(keyId))
|
||||
.request()
|
||||
.header("Authorization", AuthHelper.getAuthHeader(
|
||||
AuthHelper.VALID_UUID_3,
|
||||
AuthHelper.VALID_DEVICE_3_LINKED_ID,
|
||||
AuthHelper.VALID_PASSWORD_3_LINKED))
|
||||
.put(Entity.entity(attestation, MediaType.APPLICATION_OCTET_STREAM));
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(403);
|
||||
verifyNoInteractions(appleDeviceCheckManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkAssertion()
|
||||
throws DeviceCheckKeyIdNotFoundException, DeviceCheckVerificationFailedException, ChallengeNotFoundException, RequestReuseException {
|
||||
|
||||
Reference in New Issue
Block a user