Add support for capabilities

This commit is contained in:
Moxie Marlinspike
2019-09-23 12:01:12 -07:00
parent 62a10047ca
commit c623f70caa
12 changed files with 154 additions and 32 deletions

View File

@@ -487,7 +487,7 @@ public class AccountController {
device.setFetchesMessages(attributes.getFetchesMessages());
device.setName(attributes.getName());
device.setLastSeen(Util.todayInMillis());
device.setUnauthenticatedDeliverySupported(attributes.getUnidentifiedAccessKey() != null);
device.setCapabilities(attributes.getCapabilities());
device.setRegistrationId(attributes.getRegistrationId());
device.setSignalingKey(attributes.getSignalingKey());
device.setUserAgent(userAgent);
@@ -599,7 +599,7 @@ public class AccountController {
device.setFetchesMessages(accountAttributes.getFetchesMessages());
device.setRegistrationId(accountAttributes.getRegistrationId());
device.setName(accountAttributes.getName());
device.setUnauthenticatedDeliverySupported(accountAttributes.getUnidentifiedAccessKey() != null);
device.setCapabilities(accountAttributes.getCapabilities());
device.setCreated(System.currentTimeMillis());
device.setLastSeen(Util.todayInMillis());
device.setUserAgent(userAgent);

View File

@@ -33,6 +33,7 @@ import org.whispersystems.textsecuregcm.sqs.DirectoryQueue;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.Device.DeviceCapabilities;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.PendingDevicesManager;
import org.whispersystems.textsecuregcm.util.Util;
@@ -221,7 +222,15 @@ public class DeviceController {
@Path("/unauthenticated_delivery")
public void setUnauthenticatedDelivery(@Auth Account account) {
assert(account.getAuthenticatedDevice().isPresent());
account.getAuthenticatedDevice().get().setUnauthenticatedDeliverySupported(true);
// Deprecated
}
@Timed
@PUT
@Path("/capabilities")
public void setCapabiltities(@Auth Account account, @Valid DeviceCapabilities capabilities) {
assert(account.getAuthenticatedDevice().isPresent());
account.getAuthenticatedDevice().get().setCapabilities(capabilities);
accounts.update(account);
}

View File

@@ -17,6 +17,7 @@ import org.whispersystems.textsecuregcm.auth.UnidentifiedAccessChecksum;
import org.whispersystems.textsecuregcm.configuration.CdnConfiguration;
import org.whispersystems.textsecuregcm.entities.Profile;
import org.whispersystems.textsecuregcm.entities.ProfileAvatarUploadAttributes;
import org.whispersystems.textsecuregcm.entities.UserCapabilities;
import org.whispersystems.textsecuregcm.limits.RateLimiters;
import org.whispersystems.textsecuregcm.s3.PolicySigner;
import org.whispersystems.textsecuregcm.s3.PostPolicyGenerator;
@@ -102,8 +103,9 @@ public class ProfileController {
return new Profile(accountProfile.get().getProfileName(),
accountProfile.get().getAvatar(),
accountProfile.get().getIdentityKey(),
accountProfile.get().isUnauthenticatedDeliverySupported() ? UnidentifiedAccessChecksum.generateFor(accountProfile.get().getUnidentifiedAccessKey()) : null,
accountProfile.get().isUnrestrictedUnidentifiedAccess());
UnidentifiedAccessChecksum.generateFor(accountProfile.get().getUnidentifiedAccessKey()),
accountProfile.get().isUnrestrictedUnidentifiedAccess(),
new UserCapabilities(accountProfile.get().isUuidAddressingSupported()));
}
@Timed

View File

@@ -19,6 +19,8 @@ package org.whispersystems.textsecuregcm.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import org.hibernate.validator.constraints.Length;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.Device.DeviceCapabilities;
public class AccountAttributes {
@@ -47,6 +49,9 @@ public class AccountAttributes {
@JsonProperty
private boolean unrestrictedUnidentifiedAccess;
@JsonProperty
private DeviceCapabilities capabilities;
public AccountAttributes() {}
@VisibleForTesting
@@ -95,4 +100,8 @@ public class AccountAttributes {
public boolean isUnrestrictedUnidentifiedAccess() {
return unrestrictedUnidentifiedAccess;
}
public DeviceCapabilities getCapabilities() {
return capabilities;
}
}

View File

@@ -3,10 +3,6 @@ package org.whispersystems.textsecuregcm.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Max;
public class Profile {
@JsonProperty
@@ -24,14 +20,21 @@ public class Profile {
@JsonProperty
private boolean unrestrictedUnidentifiedAccess;
@JsonProperty
private UserCapabilities capabilities;
public Profile() {}
public Profile(String name, String avatar, String identityKey, String unidentifiedAccess, boolean unrestrictedUnidentifiedAccess) {
public Profile(String name, String avatar, String identityKey,
String unidentifiedAccess, boolean unrestrictedUnidentifiedAccess,
UserCapabilities capabilities)
{
this.name = name;
this.avatar = avatar;
this.identityKey = identityKey;
this.unidentifiedAccess = unidentifiedAccess;
this.unrestrictedUnidentifiedAccess = unrestrictedUnidentifiedAccess;
this.capabilities = capabilities;
}
@VisibleForTesting
@@ -59,4 +62,9 @@ public class Profile {
return unrestrictedUnidentifiedAccess;
}
@VisibleForTesting
public UserCapabilities getCapabilities() {
return capabilities;
}
}

View File

@@ -0,0 +1,18 @@
package org.whispersystems.textsecuregcm.entities;
import com.fasterxml.jackson.annotation.JsonProperty;
public class UserCapabilities {
@JsonProperty
private boolean uuid;
public UserCapabilities() {}
public UserCapabilities(boolean uuid) {
this.uuid = uuid;
}
public boolean isUuid() {
return uuid;
}
}

View File

@@ -20,7 +20,6 @@ package org.whispersystems.textsecuregcm.storage;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import org.whispersystems.textsecuregcm.auth.AmbiguousIdentifier;
import javax.security.auth.Subject;
@@ -33,8 +32,6 @@ import java.util.concurrent.TimeUnit;
public class Account implements Principal {
static final int MEMCACHE_VERION = 5;
@JsonIgnore
private UUID uuid;
@@ -114,7 +111,7 @@ public class Account implements Principal {
}
public void removeDevice(long deviceId) {
this.devices.remove(new Device(deviceId, null, null, null, null, null, null, null, false, 0, null, 0, 0, "NA", false, 0));
this.devices.remove(new Device(deviceId, null, null, null, null, null, null, null, false, 0, null, 0, 0, "NA", 0, null));
}
public Set<Device> getDevices() {
@@ -135,8 +132,8 @@ public class Account implements Principal {
return Optional.empty();
}
public boolean isUnauthenticatedDeliverySupported() {
return devices.stream().filter(Device::isEnabled).allMatch(Device::isUnauthenticatedDeliverySupported);
public boolean isUuidAddressingSupported() {
return devices.stream().filter(Device::isEnabled).allMatch(device -> device.getCapabilities().isUuid());
}
public boolean isEnabled() {

View File

@@ -19,6 +19,7 @@ package org.whispersystems.textsecuregcm.storage;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.whispersystems.textsecuregcm.auth.AuthenticationCredentials;
import org.whispersystems.textsecuregcm.entities.UserCapabilities;
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
import org.whispersystems.textsecuregcm.util.Util;
@@ -77,7 +78,7 @@ public class Device {
private String userAgent;
@JsonProperty
private boolean unauthenticatedDelivery;
private DeviceCapabilities capabilities;
public Device() {}
@@ -86,7 +87,7 @@ public class Device {
String voipApnId, boolean fetchesMessages,
int registrationId, SignedPreKey signedPreKey,
long lastSeen, long created, String userAgent,
boolean unauthenticatedDelivery, long uninstalledFeedback)
long uninstalledFeedback, DeviceCapabilities capabilities)
{
this.id = id;
this.name = name;
@@ -102,8 +103,8 @@ public class Device {
this.lastSeen = lastSeen;
this.created = created;
this.userAgent = userAgent;
this.unauthenticatedDelivery = unauthenticatedDelivery;
this.uninstalledFeedback = uninstalledFeedback;
this.capabilities = capabilities;
}
public String getApnId() {
@@ -178,14 +179,6 @@ public class Device {
this.name = name;
}
public boolean isUnauthenticatedDeliverySupported() {
return unauthenticatedDelivery;
}
public void setUnauthenticatedDeliverySupported(boolean unauthenticatedDelivery) {
this.unauthenticatedDelivery = unauthenticatedDelivery;
}
public void setAuthenticationCredentials(AuthenticationCredentials credentials) {
this.authToken = credentials.getHashedAuthenticationToken();
this.salt = credentials.getSalt();
@@ -195,6 +188,14 @@ public class Device {
return new AuthenticationCredentials(authToken, salt);
}
public DeviceCapabilities getCapabilities() {
return capabilities;
}
public void setCapabilities(DeviceCapabilities capabilities) {
this.capabilities = capabilities;
}
public String getSignalingKey() {
return signalingKey;
}
@@ -262,4 +263,20 @@ public class Device {
public int hashCode() {
return (int)this.id;
}
public static class DeviceCapabilities {
@JsonProperty
private boolean uuid;
public DeviceCapabilities() {}
public DeviceCapabilities(boolean uuid) {
this.uuid = uuid;
}
public boolean isUuid() {
return uuid;
}
}
}