mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Refactor ServiceConfig and add sandbox config
This commit is contained in:
parent
4eaec83594
commit
7d802fb8c5
15 changed files with 433 additions and 203 deletions
|
@ -16,6 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.asamk.signal.manager;
|
package org.asamk.signal.manager;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
|
import org.asamk.signal.manager.config.ServiceEnvironment;
|
||||||
|
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.groups.GroupIdV1;
|
import org.asamk.signal.manager.groups.GroupIdV1;
|
||||||
import org.asamk.signal.manager.groups.GroupIdV2;
|
import org.asamk.signal.manager.groups.GroupIdV2;
|
||||||
|
@ -131,7 +134,6 @@ import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
|
||||||
import org.whispersystems.signalservice.internal.contacts.crypto.Quote;
|
import org.whispersystems.signalservice.internal.contacts.crypto.Quote;
|
||||||
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException;
|
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException;
|
||||||
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
|
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
|
||||||
|
@ -169,17 +171,15 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.asamk.signal.manager.ServiceConfig.CDS_MRENCLAVE;
|
import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
|
||||||
import static org.asamk.signal.manager.ServiceConfig.capabilities;
|
|
||||||
import static org.asamk.signal.manager.ServiceConfig.getIasKeyStore;
|
|
||||||
|
|
||||||
public class Manager implements Closeable {
|
public class Manager implements Closeable {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(Manager.class);
|
private final static Logger logger = LoggerFactory.getLogger(Manager.class);
|
||||||
|
|
||||||
private final CertificateValidator certificateValidator = new CertificateValidator(ServiceConfig.getUnidentifiedSenderTrustRoot());
|
private final CertificateValidator certificateValidator;
|
||||||
|
|
||||||
private final SignalServiceConfiguration serviceConfiguration;
|
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
|
||||||
private final String userAgent;
|
private final String userAgent;
|
||||||
|
|
||||||
private SignalAccount account;
|
private SignalAccount account;
|
||||||
|
@ -202,16 +202,17 @@ public class Manager implements Closeable {
|
||||||
Manager(
|
Manager(
|
||||||
SignalAccount account,
|
SignalAccount account,
|
||||||
PathConfig pathConfig,
|
PathConfig pathConfig,
|
||||||
SignalServiceConfiguration serviceConfiguration,
|
ServiceEnvironmentConfig serviceEnvironmentConfig,
|
||||||
String userAgent
|
String userAgent
|
||||||
) {
|
) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.serviceConfiguration = serviceConfiguration;
|
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
|
||||||
|
this.certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
|
||||||
this.userAgent = userAgent;
|
this.userAgent = userAgent;
|
||||||
this.groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
|
this.groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
|
||||||
serviceConfiguration)) : null;
|
serviceEnvironmentConfig.getSignalServiceConfiguration())) : null;
|
||||||
final SleepTimer timer = new UptimeSleepTimer();
|
final SleepTimer timer = new UptimeSleepTimer();
|
||||||
this.accountManager = new SignalServiceAccountManager(serviceConfiguration,
|
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
new DynamicCredentialsProvider(account.getUuid(),
|
new DynamicCredentialsProvider(account.getUuid(),
|
||||||
account.getUsername(),
|
account.getUsername(),
|
||||||
account.getPassword(),
|
account.getPassword(),
|
||||||
|
@ -222,11 +223,18 @@ public class Manager implements Closeable {
|
||||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY,
|
ServiceConfig.AUTOMATIC_NETWORK_RETRY,
|
||||||
timer);
|
timer);
|
||||||
this.groupsV2Api = accountManager.getGroupsV2Api();
|
this.groupsV2Api = accountManager.getGroupsV2Api();
|
||||||
final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager);
|
final KeyBackupService keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(),
|
||||||
|
serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
|
||||||
|
serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
|
||||||
|
serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
|
||||||
|
10);
|
||||||
|
|
||||||
this.pinHelper = new PinHelper(keyBackupService);
|
this.pinHelper = new PinHelper(keyBackupService);
|
||||||
this.clientZkProfileOperations = capabilities.isGv2() ? ClientZkOperations.create(serviceConfiguration)
|
this.clientZkProfileOperations = capabilities.isGv2()
|
||||||
.getProfileOperations() : null;
|
? ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration())
|
||||||
this.messageReceiver = new SignalServiceMessageReceiver(serviceConfiguration,
|
.getProfileOperations()
|
||||||
|
: null;
|
||||||
|
this.messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
account.getUuid(),
|
account.getUuid(),
|
||||||
account.getUsername(),
|
account.getUsername(),
|
||||||
account.getPassword(),
|
account.getPassword(),
|
||||||
|
@ -275,7 +283,7 @@ public class Manager implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Manager init(
|
public static Manager init(
|
||||||
String username, File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent
|
String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
|
||||||
) throws IOException, NotRegisteredException {
|
) throws IOException, NotRegisteredException {
|
||||||
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
|
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
|
||||||
|
|
||||||
|
@ -289,7 +297,11 @@ public class Manager implements Closeable {
|
||||||
throw new NotRegisteredException();
|
throw new NotRegisteredException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Manager(account, pathConfig, serviceConfiguration, userAgent);
|
final ServiceEnvironmentConfig serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(
|
||||||
|
serviceEnvironment,
|
||||||
|
userAgent);
|
||||||
|
|
||||||
|
return new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> getAllLocalUsernames(File settingsPath) {
|
public static List<String> getAllLocalUsernames(File settingsPath) {
|
||||||
|
@ -498,7 +510,7 @@ public class Manager implements Closeable {
|
||||||
|
|
||||||
private SignalServiceMessageSender createMessageSender() {
|
private SignalServiceMessageSender createMessageSender() {
|
||||||
final ExecutorService executor = null;
|
final ExecutorService executor = null;
|
||||||
return new SignalServiceMessageSender(serviceConfiguration,
|
return new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
account.getUuid(),
|
account.getUuid(),
|
||||||
account.getUsername(),
|
account.getUsername(),
|
||||||
account.getPassword(),
|
account.getPassword(),
|
||||||
|
@ -1262,7 +1274,9 @@ public class Manager implements Closeable {
|
||||||
|
|
||||||
private Map<String, UUID> getRegisteredUsers(final Set<String> numbersMissingUuid) throws IOException {
|
private Map<String, UUID> getRegisteredUsers(final Set<String> numbersMissingUuid) throws IOException {
|
||||||
try {
|
try {
|
||||||
return accountManager.getRegisteredUsers(getIasKeyStore(), numbersMissingUuid, CDS_MRENCLAVE);
|
return accountManager.getRegisteredUsers(ServiceConfig.getIasKeyStore(),
|
||||||
|
numbersMissingUuid,
|
||||||
|
serviceEnvironmentConfig.getCdsMrenclave());
|
||||||
} catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException | InvalidKeyException e) {
|
} catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException | InvalidKeyException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.asamk.signal.manager;
|
package org.asamk.signal.manager;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
|
import org.asamk.signal.manager.config.ServiceEnvironment;
|
||||||
|
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||||
import org.asamk.signal.manager.storage.SignalAccount;
|
import org.asamk.signal.manager.storage.SignalAccount;
|
||||||
import org.asamk.signal.manager.util.KeyUtils;
|
import org.asamk.signal.manager.util.KeyUtils;
|
||||||
import org.signal.zkgroup.InvalidInputException;
|
import org.signal.zkgroup.InvalidInputException;
|
||||||
|
@ -31,7 +34,6 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
|
||||||
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -43,7 +45,7 @@ public class ProvisioningManager {
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ProvisioningManager.class);
|
private final static Logger logger = LoggerFactory.getLogger(ProvisioningManager.class);
|
||||||
|
|
||||||
private final PathConfig pathConfig;
|
private final PathConfig pathConfig;
|
||||||
private final SignalServiceConfiguration serviceConfiguration;
|
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
|
||||||
private final String userAgent;
|
private final String userAgent;
|
||||||
|
|
||||||
private final SignalServiceAccountManager accountManager;
|
private final SignalServiceAccountManager accountManager;
|
||||||
|
@ -51,9 +53,9 @@ public class ProvisioningManager {
|
||||||
private final int registrationId;
|
private final int registrationId;
|
||||||
private final String password;
|
private final String password;
|
||||||
|
|
||||||
public ProvisioningManager(File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent) {
|
ProvisioningManager(PathConfig pathConfig, ServiceEnvironmentConfig serviceEnvironmentConfig, String userAgent) {
|
||||||
this.pathConfig = PathConfig.createDefault(settingsPath);
|
this.pathConfig = pathConfig;
|
||||||
this.serviceConfiguration = serviceConfiguration;
|
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
|
||||||
this.userAgent = userAgent;
|
this.userAgent = userAgent;
|
||||||
|
|
||||||
identityKey = KeyUtils.generateIdentityKeyPair();
|
identityKey = KeyUtils.generateIdentityKeyPair();
|
||||||
|
@ -62,11 +64,11 @@ public class ProvisioningManager {
|
||||||
final SleepTimer timer = new UptimeSleepTimer();
|
final SleepTimer timer = new UptimeSleepTimer();
|
||||||
GroupsV2Operations groupsV2Operations;
|
GroupsV2Operations groupsV2Operations;
|
||||||
try {
|
try {
|
||||||
groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceConfiguration));
|
groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()));
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
groupsV2Operations = null;
|
groupsV2Operations = null;
|
||||||
}
|
}
|
||||||
accountManager = new SignalServiceAccountManager(serviceConfiguration,
|
accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
new DynamicCredentialsProvider(null, null, password, null, SignalServiceAddress.DEFAULT_DEVICE_ID),
|
new DynamicCredentialsProvider(null, null, password, null, SignalServiceAddress.DEFAULT_DEVICE_ID),
|
||||||
userAgent,
|
userAgent,
|
||||||
groupsV2Operations,
|
groupsV2Operations,
|
||||||
|
@ -74,6 +76,18 @@ public class ProvisioningManager {
|
||||||
timer);
|
timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ProvisioningManager init(
|
||||||
|
File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
|
||||||
|
) {
|
||||||
|
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
|
||||||
|
|
||||||
|
final ServiceEnvironmentConfig serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(
|
||||||
|
serviceEnvironment,
|
||||||
|
userAgent);
|
||||||
|
|
||||||
|
return new ProvisioningManager(pathConfig, serviceConfiguration, userAgent);
|
||||||
|
}
|
||||||
|
|
||||||
public String getDeviceLinkUri() throws TimeoutException, IOException {
|
public String getDeviceLinkUri() throws TimeoutException, IOException {
|
||||||
String deviceUuid = accountManager.getNewDeviceUuid();
|
String deviceUuid = accountManager.getNewDeviceUuid();
|
||||||
|
|
||||||
|
@ -120,7 +134,7 @@ public class ProvisioningManager {
|
||||||
profileKey)) {
|
profileKey)) {
|
||||||
account.save();
|
account.save();
|
||||||
|
|
||||||
try (Manager m = new Manager(account, pathConfig, serviceConfiguration, userAgent)) {
|
try (Manager m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m.refreshPreKeys();
|
m.refreshPreKeys();
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.asamk.signal.manager;
|
package org.asamk.signal.manager;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
|
import org.asamk.signal.manager.config.ServiceEnvironment;
|
||||||
|
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||||
import org.asamk.signal.manager.helper.PinHelper;
|
import org.asamk.signal.manager.helper.PinHelper;
|
||||||
import org.asamk.signal.manager.storage.SignalAccount;
|
import org.asamk.signal.manager.storage.SignalAccount;
|
||||||
import org.asamk.signal.manager.util.KeyUtils;
|
import org.asamk.signal.manager.util.KeyUtils;
|
||||||
|
@ -28,11 +31,12 @@ import org.whispersystems.signalservice.api.KeyBackupService;
|
||||||
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
||||||
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
|
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||||
|
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
|
||||||
import org.whispersystems.signalservice.internal.push.LockedException;
|
import org.whispersystems.signalservice.internal.push.LockedException;
|
||||||
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
||||||
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
||||||
|
@ -46,7 +50,7 @@ public class RegistrationManager implements Closeable {
|
||||||
|
|
||||||
private SignalAccount account;
|
private SignalAccount account;
|
||||||
private final PathConfig pathConfig;
|
private final PathConfig pathConfig;
|
||||||
private final SignalServiceConfiguration serviceConfiguration;
|
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
|
||||||
private final String userAgent;
|
private final String userAgent;
|
||||||
|
|
||||||
private final SignalServiceAccountManager accountManager;
|
private final SignalServiceAccountManager accountManager;
|
||||||
|
@ -55,31 +59,49 @@ public class RegistrationManager implements Closeable {
|
||||||
public RegistrationManager(
|
public RegistrationManager(
|
||||||
SignalAccount account,
|
SignalAccount account,
|
||||||
PathConfig pathConfig,
|
PathConfig pathConfig,
|
||||||
SignalServiceConfiguration serviceConfiguration,
|
ServiceEnvironmentConfig serviceEnvironmentConfig,
|
||||||
String userAgent
|
String userAgent
|
||||||
) {
|
) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.pathConfig = pathConfig;
|
this.pathConfig = pathConfig;
|
||||||
this.serviceConfiguration = serviceConfiguration;
|
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
|
||||||
this.userAgent = userAgent;
|
this.userAgent = userAgent;
|
||||||
|
|
||||||
final SleepTimer timer = new UptimeSleepTimer();
|
final SleepTimer timer = new UptimeSleepTimer();
|
||||||
this.accountManager = new SignalServiceAccountManager(serviceConfiguration, new DynamicCredentialsProvider(
|
GroupsV2Operations groupsV2Operations;
|
||||||
// Using empty UUID, because registering doesn't work otherwise
|
try {
|
||||||
null,
|
groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration()));
|
||||||
account.getUsername(),
|
} catch (Throwable ignored) {
|
||||||
account.getPassword(),
|
groupsV2Operations = null;
|
||||||
account.getSignalingKey(),
|
}
|
||||||
SignalServiceAddress.DEFAULT_DEVICE_ID), userAgent, null, ServiceConfig.AUTOMATIC_NETWORK_RETRY, timer);
|
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||||
final KeyBackupService keyBackupService = ServiceConfig.createKeyBackupService(accountManager);
|
new DynamicCredentialsProvider(
|
||||||
|
// Using empty UUID, because registering doesn't work otherwise
|
||||||
|
null,
|
||||||
|
account.getUsername(),
|
||||||
|
account.getPassword(),
|
||||||
|
account.getSignalingKey(),
|
||||||
|
SignalServiceAddress.DEFAULT_DEVICE_ID),
|
||||||
|
userAgent,
|
||||||
|
groupsV2Operations,
|
||||||
|
ServiceConfig.AUTOMATIC_NETWORK_RETRY,
|
||||||
|
timer);
|
||||||
|
final KeyBackupService keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(),
|
||||||
|
serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
|
||||||
|
serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
|
||||||
|
serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
|
||||||
|
10);
|
||||||
this.pinHelper = new PinHelper(keyBackupService);
|
this.pinHelper = new PinHelper(keyBackupService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RegistrationManager init(
|
public static RegistrationManager init(
|
||||||
String username, File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent
|
String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
|
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
|
||||||
|
|
||||||
|
final ServiceEnvironmentConfig serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(
|
||||||
|
serviceEnvironment,
|
||||||
|
userAgent);
|
||||||
if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) {
|
if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) {
|
||||||
IdentityKeyPair identityKey = KeyUtils.generateIdentityKeyPair();
|
IdentityKeyPair identityKey = KeyUtils.generateIdentityKeyPair();
|
||||||
int registrationId = KeyHelper.generateRegistrationId(false);
|
int registrationId = KeyHelper.generateRegistrationId(false);
|
||||||
|
@ -159,7 +181,7 @@ public class RegistrationManager implements Closeable {
|
||||||
account.getSignalProtocolStore().getIdentityKeyPair().getPublicKey(),
|
account.getSignalProtocolStore().getIdentityKeyPair().getPublicKey(),
|
||||||
TrustLevel.TRUSTED_VERIFIED);
|
TrustLevel.TRUSTED_VERIFIED);
|
||||||
|
|
||||||
try (Manager m = new Manager(account, pathConfig, serviceConfiguration, userAgent)) {
|
try (Manager m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent)) {
|
||||||
|
|
||||||
m.refreshPreKeys();
|
m.refreshPreKeys();
|
||||||
|
|
||||||
|
|
|
@ -1,141 +0,0 @@
|
||||||
package org.asamk.signal.manager;
|
|
||||||
|
|
||||||
import org.bouncycastle.util.encoders.Hex;
|
|
||||||
import org.signal.zkgroup.ServerPublicParams;
|
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
|
||||||
import org.whispersystems.libsignal.ecc.Curve;
|
|
||||||
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.KeyBackupService;
|
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
|
||||||
import org.whispersystems.signalservice.api.account.AccountAttributes;
|
|
||||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalContactDiscoveryUrl;
|
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalKeyBackupServiceUrl;
|
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl;
|
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import okhttp3.Dns;
|
|
||||||
import okhttp3.Interceptor;
|
|
||||||
|
|
||||||
public class ServiceConfig {
|
|
||||||
|
|
||||||
final static byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
|
|
||||||
.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
|
|
||||||
final static int PREKEY_MINIMUM_COUNT = 20;
|
|
||||||
final static int PREKEY_BATCH_SIZE = 100;
|
|
||||||
final static int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024;
|
|
||||||
final static long MAX_ENVELOPE_SIZE = 0;
|
|
||||||
final static long AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE = 10 * 1024 * 1024;
|
|
||||||
final static boolean AUTOMATIC_NETWORK_RETRY = true;
|
|
||||||
|
|
||||||
final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";
|
|
||||||
|
|
||||||
final static String KEY_BACKUP_ENCLAVE_NAME = "fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe";
|
|
||||||
final static byte[] KEY_BACKUP_SERVICE_ID = Hex.decode(
|
|
||||||
"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe");
|
|
||||||
final static String KEY_BACKUP_MRENCLAVE = "a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87";
|
|
||||||
|
|
||||||
private final static String URL = "https://textsecure-service.whispersystems.org";
|
|
||||||
private final static String CDN_URL = "https://cdn.signal.org";
|
|
||||||
private final static String CDN2_URL = "https://cdn2.signal.org";
|
|
||||||
private final static String SIGNAL_CONTACT_DISCOVERY_URL = "https://api.directory.signal.org";
|
|
||||||
private final static String SIGNAL_KEY_BACKUP_URL = "https://api.backup.signal.org";
|
|
||||||
private final static String STORAGE_URL = "https://storage.signal.org";
|
|
||||||
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
|
|
||||||
private final static TrustStore IAS_TRUST_STORE = new IasTrustStore();
|
|
||||||
|
|
||||||
private final static Optional<Dns> dns = Optional.absent();
|
|
||||||
|
|
||||||
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
|
|
||||||
.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X0=");
|
|
||||||
|
|
||||||
static final AccountAttributes.Capabilities capabilities;
|
|
||||||
|
|
||||||
static {
|
|
||||||
boolean zkGroupAvailable;
|
|
||||||
try {
|
|
||||||
new ServerPublicParams(zkGroupServerPublicParams);
|
|
||||||
zkGroupAvailable = true;
|
|
||||||
} catch (Throwable ignored) {
|
|
||||||
zkGroupAvailable = false;
|
|
||||||
}
|
|
||||||
capabilities = new AccountAttributes.Capabilities(false, zkGroupAvailable, false, zkGroupAvailable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignalServiceConfiguration createDefaultServiceConfiguration(String userAgent) {
|
|
||||||
final Interceptor userAgentInterceptor = chain -> chain.proceed(chain.request()
|
|
||||||
.newBuilder()
|
|
||||||
.header("User-Agent", userAgent)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
final List<Interceptor> interceptors = List.of(userAgentInterceptor);
|
|
||||||
|
|
||||||
return new SignalServiceConfiguration(new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)},
|
|
||||||
makeSignalCdnUrlMapFor(new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)},
|
|
||||||
new SignalCdnUrl[]{new SignalCdnUrl(CDN2_URL, TRUST_STORE)}),
|
|
||||||
new SignalContactDiscoveryUrl[]{new SignalContactDiscoveryUrl(SIGNAL_CONTACT_DISCOVERY_URL,
|
|
||||||
TRUST_STORE)},
|
|
||||||
new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)},
|
|
||||||
new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)},
|
|
||||||
interceptors,
|
|
||||||
dns,
|
|
||||||
zkGroupServerPublicParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AccountAttributes.Capabilities getCapabilities() {
|
|
||||||
return capabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
static KeyStore getIasKeyStore() {
|
|
||||||
try {
|
|
||||||
TrustStore contactTrustStore = IAS_TRUST_STORE;
|
|
||||||
|
|
||||||
KeyStore keyStore = KeyStore.getInstance("BKS");
|
|
||||||
keyStore.load(contactTrustStore.getKeyStoreInputStream(),
|
|
||||||
contactTrustStore.getKeyStorePassword().toCharArray());
|
|
||||||
|
|
||||||
return keyStore;
|
|
||||||
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static KeyBackupService createKeyBackupService(SignalServiceAccountManager accountManager) {
|
|
||||||
KeyStore keyStore = ServiceConfig.getIasKeyStore();
|
|
||||||
|
|
||||||
return accountManager.getKeyBackupService(keyStore,
|
|
||||||
ServiceConfig.KEY_BACKUP_ENCLAVE_NAME,
|
|
||||||
ServiceConfig.KEY_BACKUP_SERVICE_ID,
|
|
||||||
ServiceConfig.KEY_BACKUP_MRENCLAVE,
|
|
||||||
10);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ECPublicKey getUnidentifiedSenderTrustRoot() {
|
|
||||||
try {
|
|
||||||
return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0);
|
|
||||||
} catch (InvalidKeyException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<Integer, SignalCdnUrl[]> makeSignalCdnUrlMapFor(
|
|
||||||
SignalCdnUrl[] cdn0Urls, SignalCdnUrl[] cdn2Urls
|
|
||||||
) {
|
|
||||||
return Map.of(0, cdn0Urls, 2, cdn2Urls);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ServiceConfig() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.asamk.signal.manager;
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
|
public class KeyBackupConfig {
|
||||||
|
|
||||||
|
private final String enclaveName;
|
||||||
|
private final byte[] serviceId;
|
||||||
|
private final String mrenclave;
|
||||||
|
|
||||||
|
public KeyBackupConfig(final String enclaveName, final byte[] serviceId, final String mrenclave) {
|
||||||
|
this.enclaveName = enclaveName;
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
this.mrenclave = mrenclave;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnclaveName() {
|
||||||
|
return enclaveName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getServiceId() {
|
||||||
|
return serviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMrenclave() {
|
||||||
|
return mrenclave;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
|
import org.whispersystems.libsignal.ecc.Curve;
|
||||||
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalContactDiscoveryUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalKeyBackupServiceUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.Dns;
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
|
||||||
|
class LiveConfig {
|
||||||
|
|
||||||
|
private final static byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
|
||||||
|
.decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
|
||||||
|
private final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";
|
||||||
|
|
||||||
|
private final static String KEY_BACKUP_ENCLAVE_NAME = "fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe";
|
||||||
|
private final static byte[] KEY_BACKUP_SERVICE_ID = Hex.decode(
|
||||||
|
"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe");
|
||||||
|
private final static String KEY_BACKUP_MRENCLAVE = "a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87";
|
||||||
|
|
||||||
|
private final static String URL = "https://textsecure-service.whispersystems.org";
|
||||||
|
private final static String CDN_URL = "https://cdn.signal.org";
|
||||||
|
private final static String CDN2_URL = "https://cdn2.signal.org";
|
||||||
|
private final static String SIGNAL_CONTACT_DISCOVERY_URL = "https://api.directory.signal.org";
|
||||||
|
private final static String SIGNAL_KEY_BACKUP_URL = "https://api.backup.signal.org";
|
||||||
|
private final static String STORAGE_URL = "https://storage.signal.org";
|
||||||
|
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
|
||||||
|
|
||||||
|
private final static Optional<Dns> dns = Optional.absent();
|
||||||
|
|
||||||
|
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
|
||||||
|
.decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X0=");
|
||||||
|
|
||||||
|
static SignalServiceConfiguration createDefaultServiceConfiguration(
|
||||||
|
final List<Interceptor> interceptors
|
||||||
|
) {
|
||||||
|
return new SignalServiceConfiguration(new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)},
|
||||||
|
Map.of(0,
|
||||||
|
new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)},
|
||||||
|
2,
|
||||||
|
new SignalCdnUrl[]{new SignalCdnUrl(CDN2_URL, TRUST_STORE)}),
|
||||||
|
new SignalContactDiscoveryUrl[]{new SignalContactDiscoveryUrl(SIGNAL_CONTACT_DISCOVERY_URL,
|
||||||
|
TRUST_STORE)},
|
||||||
|
new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)},
|
||||||
|
new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)},
|
||||||
|
interceptors,
|
||||||
|
dns,
|
||||||
|
zkGroupServerPublicParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECPublicKey getUnidentifiedSenderTrustRoot() {
|
||||||
|
try {
|
||||||
|
return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static KeyBackupConfig createKeyBackupConfig() {
|
||||||
|
return new KeyBackupConfig(KEY_BACKUP_ENCLAVE_NAME, KEY_BACKUP_SERVICE_ID, KEY_BACKUP_MRENCLAVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getCdsMrenclave() {
|
||||||
|
return CDS_MRENCLAVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LiveConfig() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
|
import org.whispersystems.libsignal.ecc.Curve;
|
||||||
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalContactDiscoveryUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalKeyBackupServiceUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import okhttp3.Dns;
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
|
||||||
|
class SandboxConfig {
|
||||||
|
|
||||||
|
private final static byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
|
||||||
|
.decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx");
|
||||||
|
private final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15";
|
||||||
|
|
||||||
|
private final static String KEY_BACKUP_ENCLAVE_NAME = "823a3b2c037ff0cbe305cc48928cfcc97c9ed4a8ca6d49af6f7d6981fb60a4e9";
|
||||||
|
private final static byte[] KEY_BACKUP_SERVICE_ID = Hex.decode(
|
||||||
|
"038c40bbbacdc873caa81ac793bb75afde6dfe436a99ab1f15e3f0cbb7434ced");
|
||||||
|
private final static String KEY_BACKUP_MRENCLAVE = "a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87";
|
||||||
|
|
||||||
|
private final static String URL = "https://textsecure-service-staging.whispersystems.org";
|
||||||
|
private final static String CDN_URL = "https://cdn-staging.signal.org";
|
||||||
|
private final static String CDN2_URL = "https://cdn2-staging.signal.org";
|
||||||
|
private final static String SIGNAL_CONTACT_DISCOVERY_URL = "https://api-staging.directory.signal.org";
|
||||||
|
private final static String SIGNAL_KEY_BACKUP_URL = "https://api-staging.backup.signal.org";
|
||||||
|
private final static String STORAGE_URL = "https://storage-staging.signal.org";
|
||||||
|
private final static TrustStore TRUST_STORE = new WhisperTrustStore();
|
||||||
|
|
||||||
|
private final static Optional<Dns> dns = Optional.absent();
|
||||||
|
|
||||||
|
private final static byte[] zkGroupServerPublicParams = Base64.getDecoder()
|
||||||
|
.decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdls=");
|
||||||
|
|
||||||
|
static SignalServiceConfiguration createDefaultServiceConfiguration(
|
||||||
|
final List<Interceptor> interceptors
|
||||||
|
) {
|
||||||
|
return new SignalServiceConfiguration(new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)},
|
||||||
|
Map.of(0,
|
||||||
|
new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)},
|
||||||
|
2,
|
||||||
|
new SignalCdnUrl[]{new SignalCdnUrl(CDN2_URL, TRUST_STORE)}),
|
||||||
|
new SignalContactDiscoveryUrl[]{new SignalContactDiscoveryUrl(SIGNAL_CONTACT_DISCOVERY_URL,
|
||||||
|
TRUST_STORE)},
|
||||||
|
new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)},
|
||||||
|
new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)},
|
||||||
|
interceptors,
|
||||||
|
dns,
|
||||||
|
zkGroupServerPublicParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ECPublicKey getUnidentifiedSenderTrustRoot() {
|
||||||
|
try {
|
||||||
|
return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static KeyBackupConfig createKeyBackupConfig() {
|
||||||
|
return new KeyBackupConfig(KEY_BACKUP_ENCLAVE_NAME, KEY_BACKUP_SERVICE_ID, KEY_BACKUP_MRENCLAVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getCdsMrenclave() {
|
||||||
|
return CDS_MRENCLAVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SandboxConfig() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
|
import org.signal.zkgroup.internal.Native;
|
||||||
|
import org.whispersystems.signalservice.api.account.AccountAttributes;
|
||||||
|
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
|
||||||
|
public class ServiceConfig {
|
||||||
|
|
||||||
|
public final static int PREKEY_MINIMUM_COUNT = 20;
|
||||||
|
public final static int PREKEY_BATCH_SIZE = 100;
|
||||||
|
public final static int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024;
|
||||||
|
public final static long MAX_ENVELOPE_SIZE = 0;
|
||||||
|
public final static long AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE = 10 * 1024 * 1024;
|
||||||
|
public final static boolean AUTOMATIC_NETWORK_RETRY = true;
|
||||||
|
|
||||||
|
private final static KeyStore iasKeyStore;
|
||||||
|
|
||||||
|
public static final AccountAttributes.Capabilities capabilities;
|
||||||
|
|
||||||
|
static {
|
||||||
|
boolean zkGroupAvailable;
|
||||||
|
try {
|
||||||
|
Native.serverPublicParamsCheckValidContentsJNI(new byte[]{});
|
||||||
|
zkGroupAvailable = true;
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
zkGroupAvailable = false;
|
||||||
|
}
|
||||||
|
capabilities = new AccountAttributes.Capabilities(false, zkGroupAvailable, false, zkGroupAvailable);
|
||||||
|
|
||||||
|
try {
|
||||||
|
TrustStore contactTrustStore = new IasTrustStore();
|
||||||
|
|
||||||
|
KeyStore keyStore = KeyStore.getInstance("BKS");
|
||||||
|
keyStore.load(contactTrustStore.getKeyStoreInputStream(),
|
||||||
|
contactTrustStore.getKeyStorePassword().toCharArray());
|
||||||
|
|
||||||
|
iasKeyStore = keyStore;
|
||||||
|
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AccountAttributes.Capabilities getCapabilities() {
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyStore getIasKeyStore() {
|
||||||
|
return iasKeyStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServiceEnvironmentConfig getServiceEnvironmentConfig(
|
||||||
|
ServiceEnvironment serviceEnvironment, String userAgent
|
||||||
|
) {
|
||||||
|
final Interceptor userAgentInterceptor = chain -> chain.proceed(chain.request()
|
||||||
|
.newBuilder()
|
||||||
|
.header("User-Agent", userAgent)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
final List<Interceptor> interceptors = List.of(userAgentInterceptor);
|
||||||
|
|
||||||
|
switch (serviceEnvironment) {
|
||||||
|
case LIVE:
|
||||||
|
return new ServiceEnvironmentConfig(LiveConfig.createDefaultServiceConfiguration(interceptors),
|
||||||
|
LiveConfig.getUnidentifiedSenderTrustRoot(),
|
||||||
|
LiveConfig.createKeyBackupConfig(),
|
||||||
|
LiveConfig.getCdsMrenclave());
|
||||||
|
case SANDBOX:
|
||||||
|
return new ServiceEnvironmentConfig(SandboxConfig.createDefaultServiceConfiguration(interceptors),
|
||||||
|
SandboxConfig.getUnidentifiedSenderTrustRoot(),
|
||||||
|
SandboxConfig.createKeyBackupConfig(),
|
||||||
|
SandboxConfig.getCdsMrenclave());
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unsupported environment");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
|
public enum ServiceEnvironment {
|
||||||
|
LIVE,
|
||||||
|
SANDBOX,
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
|
import org.whispersystems.libsignal.ecc.ECPublicKey;
|
||||||
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||||
|
|
||||||
|
public class ServiceEnvironmentConfig {
|
||||||
|
|
||||||
|
private final SignalServiceConfiguration signalServiceConfiguration;
|
||||||
|
|
||||||
|
private final ECPublicKey unidentifiedSenderTrustRoot;
|
||||||
|
|
||||||
|
private final KeyBackupConfig keyBackupConfig;
|
||||||
|
|
||||||
|
private final String cdsMrenclave;
|
||||||
|
|
||||||
|
public ServiceEnvironmentConfig(
|
||||||
|
final SignalServiceConfiguration signalServiceConfiguration,
|
||||||
|
final ECPublicKey unidentifiedSenderTrustRoot,
|
||||||
|
final KeyBackupConfig keyBackupConfig,
|
||||||
|
final String cdsMrenclave
|
||||||
|
) {
|
||||||
|
this.signalServiceConfiguration = signalServiceConfiguration;
|
||||||
|
this.unidentifiedSenderTrustRoot = unidentifiedSenderTrustRoot;
|
||||||
|
this.keyBackupConfig = keyBackupConfig;
|
||||||
|
this.cdsMrenclave = cdsMrenclave;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignalServiceConfiguration getSignalServiceConfiguration() {
|
||||||
|
return signalServiceConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ECPublicKey getUnidentifiedSenderTrustRoot() {
|
||||||
|
return unidentifiedSenderTrustRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyBackupConfig getKeyBackupConfig() {
|
||||||
|
return keyBackupConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCdsMrenclave() {
|
||||||
|
return cdsMrenclave;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.asamk.signal.manager;
|
package org.asamk.signal.manager.config;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||||
|
|
|
@ -21,14 +21,14 @@ import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.NotRegisteredException;
|
import org.asamk.signal.manager.NotRegisteredException;
|
||||||
import org.asamk.signal.manager.ProvisioningManager;
|
import org.asamk.signal.manager.ProvisioningManager;
|
||||||
import org.asamk.signal.manager.RegistrationManager;
|
import org.asamk.signal.manager.RegistrationManager;
|
||||||
import org.asamk.signal.manager.ServiceConfig;
|
import org.asamk.signal.manager.config.ServiceConfig;
|
||||||
|
import org.asamk.signal.manager.config.ServiceEnvironment;
|
||||||
import org.asamk.signal.util.IOUtils;
|
import org.asamk.signal.util.IOUtils;
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
import org.freedesktop.dbus.exceptions.DBusException;
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -114,8 +114,7 @@ public class App {
|
||||||
dataPath = getDefaultDataPath();
|
dataPath = getDefaultDataPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
final SignalServiceConfiguration serviceConfiguration = ServiceConfig.createDefaultServiceConfiguration(
|
final ServiceEnvironment serviceEnvironment = ServiceEnvironment.LIVE;
|
||||||
BaseConfig.USER_AGENT);
|
|
||||||
|
|
||||||
if (!ServiceConfig.getCapabilities().isGv2()) {
|
if (!ServiceConfig.getCapabilities().isGv2()) {
|
||||||
logger.warn("WARNING: Support for new group V2 is disabled,"
|
logger.warn("WARNING: Support for new group V2 is disabled,"
|
||||||
|
@ -128,7 +127,7 @@ public class App {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceConfiguration);
|
return handleProvisioningCommand((ProvisioningCommand) command, dataPath, serviceEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username == null) {
|
if (username == null) {
|
||||||
|
@ -139,7 +138,7 @@ public class App {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command instanceof MultiLocalCommand) {
|
if (command instanceof MultiLocalCommand) {
|
||||||
return handleMultiLocalCommand((MultiLocalCommand) command, dataPath, serviceConfiguration, usernames);
|
return handleMultiLocalCommand((MultiLocalCommand) command, dataPath, serviceEnvironment, usernames);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usernames.size() > 1) {
|
if (usernames.size() > 1) {
|
||||||
|
@ -154,7 +153,7 @@ public class App {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command instanceof RegistrationCommand) {
|
if (command instanceof RegistrationCommand) {
|
||||||
return handleRegistrationCommand((RegistrationCommand) command, username, dataPath, serviceConfiguration);
|
return handleRegistrationCommand((RegistrationCommand) command, username, dataPath, serviceEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(command instanceof LocalCommand)) {
|
if (!(command instanceof LocalCommand)) {
|
||||||
|
@ -162,15 +161,13 @@ public class App {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleLocalCommand((LocalCommand) command, username, dataPath, serviceConfiguration);
|
return handleLocalCommand((LocalCommand) command, username, dataPath, serviceEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int handleProvisioningCommand(
|
private int handleProvisioningCommand(
|
||||||
final ProvisioningCommand command,
|
final ProvisioningCommand command, final File dataPath, final ServiceEnvironment serviceEnvironment
|
||||||
final File dataPath,
|
|
||||||
final SignalServiceConfiguration serviceConfiguration
|
|
||||||
) {
|
) {
|
||||||
ProvisioningManager pm = new ProvisioningManager(dataPath, serviceConfiguration, BaseConfig.USER_AGENT);
|
ProvisioningManager pm = ProvisioningManager.init(dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
|
||||||
return command.handleCommand(ns, pm);
|
return command.handleCommand(ns, pm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,11 +175,11 @@ public class App {
|
||||||
final RegistrationCommand command,
|
final RegistrationCommand command,
|
||||||
final String username,
|
final String username,
|
||||||
final File dataPath,
|
final File dataPath,
|
||||||
final SignalServiceConfiguration serviceConfiguration
|
final ServiceEnvironment serviceEnvironment
|
||||||
) {
|
) {
|
||||||
final RegistrationManager manager;
|
final RegistrationManager manager;
|
||||||
try {
|
try {
|
||||||
manager = RegistrationManager.init(username, dataPath, serviceConfiguration, BaseConfig.USER_AGENT);
|
manager = RegistrationManager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.error("Error loading or creating state file: {}", e.getMessage());
|
logger.error("Error loading or creating state file: {}", e.getMessage());
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -199,9 +196,9 @@ public class App {
|
||||||
final LocalCommand command,
|
final LocalCommand command,
|
||||||
final String username,
|
final String username,
|
||||||
final File dataPath,
|
final File dataPath,
|
||||||
final SignalServiceConfiguration serviceConfiguration
|
final ServiceEnvironment serviceEnvironment
|
||||||
) {
|
) {
|
||||||
try (Manager m = loadManager(username, dataPath, serviceConfiguration)) {
|
try (Manager m = loadManager(username, dataPath, serviceEnvironment)) {
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -216,11 +213,11 @@ public class App {
|
||||||
private int handleMultiLocalCommand(
|
private int handleMultiLocalCommand(
|
||||||
final MultiLocalCommand command,
|
final MultiLocalCommand command,
|
||||||
final File dataPath,
|
final File dataPath,
|
||||||
final SignalServiceConfiguration serviceConfiguration,
|
final ServiceEnvironment serviceEnvironment,
|
||||||
final List<String> usernames
|
final List<String> usernames
|
||||||
) {
|
) {
|
||||||
final List<Manager> managers = usernames.stream()
|
final List<Manager> managers = usernames.stream()
|
||||||
.map(u -> loadManager(u, dataPath, serviceConfiguration))
|
.map(u -> loadManager(u, dataPath, serviceEnvironment))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
@ -237,11 +234,11 @@ public class App {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manager loadManager(
|
private Manager loadManager(
|
||||||
final String username, final File dataPath, final SignalServiceConfiguration serviceConfiguration
|
final String username, final File dataPath, final ServiceEnvironment serviceEnvironment
|
||||||
) {
|
) {
|
||||||
Manager manager;
|
Manager manager;
|
||||||
try {
|
try {
|
||||||
manager = Manager.init(username, dataPath, serviceConfiguration, BaseConfig.USER_AGENT);
|
manager = Manager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
|
||||||
} catch (NotRegisteredException e) {
|
} catch (NotRegisteredException e) {
|
||||||
logger.error("User " + username + " is not registered.");
|
logger.error("User " + username + " is not registered.");
|
||||||
return null;
|
return null;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue