]> nmode's Git Repositories - signal-cli/commitdiff
Refactor creating linked account files
authorAsamK <asamk@gmx.de>
Mon, 16 Oct 2023 16:28:08 +0000 (18:28 +0200)
committerAsamK <asamk@gmx.de>
Mon, 16 Oct 2023 17:01:31 +0000 (19:01 +0200)
lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java
lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java

index da8a3f3a837bf5ff32696d9da1e833e63c07f7c5..ef1606211fb041b8a33aeb4e237effa8bfac5a6a 100644 (file)
@@ -14,7 +14,6 @@ import org.asamk.signal.manager.internal.RegistrationManagerImpl;
 import org.asamk.signal.manager.storage.SignalAccount;
 import org.asamk.signal.manager.storage.accounts.AccountsStore;
 import org.asamk.signal.manager.util.KeyUtils;
-import org.signal.libsignal.protocol.util.KeyHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
@@ -160,8 +159,6 @@ public class SignalAccountFiles {
             final var newAccountPath = accountPath == null ? accountsStore.addAccount(number, null) : accountPath;
             var aciIdentityKey = KeyUtils.generateIdentityKeyPair();
             var pniIdentityKey = KeyUtils.generateIdentityKeyPair();
-            var registrationId = KeyHelper.generateRegistrationId(false);
-            var pniRegistrationId = KeyHelper.generateRegistrationId(false);
 
             var profileKey = KeyUtils.createProfileKey();
             var account = SignalAccount.create(pathConfig.dataPath(),
@@ -170,8 +167,6 @@ public class SignalAccountFiles {
                     serviceEnvironment,
                     aciIdentityKey,
                     pniIdentityKey,
-                    registrationId,
-                    pniRegistrationId,
                     profileKey,
                     settings);
 
index 405657b018ec706c9bec80ec316f35d500d1f8d1..155756c9f726759fe9fda4a9b28ce341a2c550d6 100644 (file)
@@ -27,12 +27,12 @@ import org.asamk.signal.manager.storage.SignalAccount;
 import org.asamk.signal.manager.storage.accounts.AccountsStore;
 import org.asamk.signal.manager.util.KeyUtils;
 import org.signal.libsignal.protocol.IdentityKeyPair;
-import org.signal.libsignal.protocol.util.KeyHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 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.ServiceIdType;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
 import org.whispersystems.signalservice.api.util.DeviceNameUtil;
@@ -59,8 +59,6 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
 
     private final SignalServiceAccountManager accountManager;
     private final IdentityKeyPair tempIdentityKey;
-    private final int registrationId;
-    private final int pniRegistrationId;
     private final String password;
 
     public ProvisioningManagerImpl(
@@ -77,8 +75,6 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
         this.accountsStore = accountsStore;
 
         tempIdentityKey = KeyUtils.generateIdentityKeyPair();
-        registrationId = KeyHelper.generateRegistrationId(false);
-        pniRegistrationId = KeyHelper.generateRegistrationId(false);
         password = KeyUtils.createPassword();
         GroupsV2Operations groupsV2Operations;
         try {
@@ -114,9 +110,9 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
         if (accountPath == null) {
             accountPath = accountsStore.getPathByNumber(number);
         }
-        if (accountPath != null
-                && SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)
-                && !canRelinkExistingAccount(accountPath)) {
+        final var accountExists = accountPath != null && SignalAccount.accountFileExists(pathConfig.dataPath(),
+                accountPath);
+        if (accountExists && !canRelinkExistingAccount(accountPath)) {
             throw new UserAlreadyExistsException(number, SignalAccount.getFileName(pathConfig.dataPath(), accountPath));
         }
         if (accountPath == null) {
@@ -128,38 +124,42 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
         var encryptedDeviceName = deviceName == null
                 ? null
                 : DeviceNameUtil.encryptDeviceName(deviceName, ret.getAciIdentity().getPrivateKey());
-
-        logger.debug("Finishing new device registration");
-        var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
-                new ConfirmCodeMessage(false,
-                        true,
-                        registrationId,
-                        pniRegistrationId,
-                        encryptedDeviceName,
-                        getCapabilities(false)));
-
         // Create new account with the synced identity
         var profileKey = ret.getProfileKey() == null ? KeyUtils.createProfileKey() : ret.getProfileKey();
 
         SignalAccount account = null;
         try {
-            account = SignalAccount.createOrUpdateLinkedAccount(pathConfig.dataPath(),
-                    accountPath,
-                    number,
-                    serviceEnvironmentConfig.type(),
+            if (!accountExists) {
+                account = SignalAccount.createLinkedAccount(pathConfig.dataPath(),
+                        accountPath,
+                        serviceEnvironmentConfig.type(),
+                        Settings.DEFAULT);
+            } else {
+                account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, Settings.DEFAULT);
+            }
+
+            account.setProvisioningData(number,
                     aci,
                     pni,
                     password,
                     encryptedDeviceName,
-                    deviceId,
                     ret.getAciIdentity(),
                     ret.getPniIdentity(),
-                    registrationId,
-                    pniRegistrationId,
-                    profileKey,
-                    Settings.DEFAULT);
+                    profileKey);
+
             account.getConfigurationStore().setReadReceipts(ret.isReadReceipts());
 
+            logger.debug("Finishing new device registration");
+            var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(),
+                    new ConfirmCodeMessage(false,
+                            true,
+                            account.getAccountData(ServiceIdType.ACI).getLocalRegistrationId(),
+                            account.getAccountData(ServiceIdType.PNI).getLocalRegistrationId(),
+                            encryptedDeviceName,
+                            getCapabilities(false)));
+
+            account.finishLinking(deviceId);
+
             ManagerImpl m = null;
             try {
                 m = new ManagerImpl(account,
index a51136a064975b9721fe3e0fcaa82c4a0091f360..57300b11b4f5b22b853e00356bbc63244b43a283 100644 (file)
@@ -130,7 +130,7 @@ public class SignalAccount implements Closeable {
     private String number;
     private String username;
     private String encryptedDeviceName;
-    private int deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
+    private int deviceId = 0;
     private String password;
     private String registrationLockPin;
     private MasterKey pinMasterKey;
@@ -204,8 +204,6 @@ public class SignalAccount implements Closeable {
             ServiceEnvironment serviceEnvironment,
             IdentityKeyPair aciIdentityKey,
             IdentityKeyPair pniIdentityKey,
-            int registrationId,
-            int pniRegistrationId,
             ProfileKey profileKey,
             final Settings settings
     ) throws IOException {
@@ -223,160 +221,91 @@ public class SignalAccount implements Closeable {
         signalAccount.serviceEnvironment = serviceEnvironment;
         signalAccount.profileKey = profileKey;
         signalAccount.password = KeyUtils.createPassword();
+        signalAccount.deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
 
         signalAccount.dataPath = dataPath;
         signalAccount.aciAccountData.setIdentityKeyPair(aciIdentityKey);
         signalAccount.pniAccountData.setIdentityKeyPair(pniIdentityKey);
-        signalAccount.aciAccountData.setLocalRegistrationId(registrationId);
-        signalAccount.pniAccountData.setLocalRegistrationId(pniRegistrationId);
+        signalAccount.aciAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
+        signalAccount.pniAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
         signalAccount.settings = settings;
 
         signalAccount.registered = false;
 
         signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
         signalAccount.migrateLegacyConfigs();
-        signalAccount.clearAllPreKeys();
         signalAccount.save();
 
         return signalAccount;
     }
 
-    private static SignalAccount createLinkedAccount(
-            File dataPath,
-            String accountPath,
-            String number,
-            ServiceEnvironment serviceEnvironment,
-            ACI aci,
-            PNI pni,
-            String password,
-            String encryptedDeviceName,
-            int deviceId,
-            IdentityKeyPair aciIdentityKey,
-            IdentityKeyPair pniIdentityKey,
-            int registrationId,
-            int pniRegistrationId,
-            ProfileKey profileKey,
+    public static SignalAccount createLinkedAccount(
+            final File dataPath,
+            final String accountPath,
+            final ServiceEnvironment serviceEnvironment,
             final Settings settings
     ) throws IOException {
+        IOUtils.createPrivateDirectories(dataPath);
         var fileName = getFileName(dataPath, accountPath);
         IOUtils.createPrivateFile(fileName);
 
         final var pair = openFileChannel(fileName, true);
-        var signalAccount = new SignalAccount(pair.first(), pair.second());
+        final var signalAccount = new SignalAccount(pair.first(), pair.second());
 
         signalAccount.dataPath = dataPath;
         signalAccount.accountPath = accountPath;
         signalAccount.serviceEnvironment = serviceEnvironment;
-        signalAccount.aciAccountData.setLocalRegistrationId(registrationId);
-        signalAccount.pniAccountData.setLocalRegistrationId(pniRegistrationId);
+        signalAccount.aciAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
+        signalAccount.pniAccountData.setLocalRegistrationId(KeyHelper.generateRegistrationId(false));
         signalAccount.settings = settings;
-        signalAccount.setProvisioningData(number,
-                aci,
-                pni,
-                password,
-                encryptedDeviceName,
-                deviceId,
-                aciIdentityKey,
-                pniIdentityKey,
-                profileKey);
 
-        signalAccount.getRecipientTrustedResolver()
-                .resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
         signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
-        signalAccount.migrateLegacyConfigs();
-        signalAccount.clearAllPreKeys();
-        signalAccount.save();
-
-        return signalAccount;
-    }
 
-    public static SignalAccount createOrUpdateLinkedAccount(
-            File dataPath,
-            String accountPath,
-            String number,
-            ServiceEnvironment serviceEnvironment,
-            ACI aci,
-            PNI pni,
-            String password,
-            String encryptedDeviceName,
-            int deviceId,
-            IdentityKeyPair aciIdentityKey,
-            IdentityKeyPair pniIdentityKey,
-            int registrationId,
-            int pniRegistrationId,
-            ProfileKey profileKey,
-            final Settings settings
-    ) throws IOException {
-        IOUtils.createPrivateDirectories(dataPath);
-        var fileName = getFileName(dataPath, accountPath);
-        if (!fileName.exists()) {
-            return createLinkedAccount(dataPath,
-                    accountPath,
-                    number,
-                    serviceEnvironment,
-                    aci,
-                    pni,
-                    password,
-                    encryptedDeviceName,
-                    deviceId,
-                    aciIdentityKey,
-                    pniIdentityKey,
-                    registrationId,
-                    pniRegistrationId,
-                    profileKey,
-                    settings);
-        }
-
-        final var signalAccount = load(dataPath, accountPath, true, settings);
-        signalAccount.setProvisioningData(number,
-                aci,
-                pni,
-                password,
-                encryptedDeviceName,
-                deviceId,
-                aciIdentityKey,
-                pniIdentityKey,
-                profileKey);
-        signalAccount.getRecipientTrustedResolver()
-                .resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
-        signalAccount.aciAccountData.getSessionStore().archiveAllSessions();
-        signalAccount.pniAccountData.getSessionStore().archiveAllSessions();
-        signalAccount.getSenderKeyStore().deleteAll();
-        signalAccount.clearAllPreKeys();
         return signalAccount;
     }
 
-    private void setProvisioningData(
+    public void setProvisioningData(
             final String number,
             final ACI aci,
             final PNI pni,
             final String password,
             final String encryptedDeviceName,
-            final int deviceId,
             final IdentityKeyPair aciIdentity,
             final IdentityKeyPair pniIdentity,
             final ProfileKey profileKey
     ) {
+        this.deviceId = 0;
         this.number = number;
         this.aciAccountData.setServiceId(aci);
         this.pniAccountData.setServiceId(pni);
+        getRecipientTrustedResolver().resolveSelfRecipientTrusted(getSelfRecipientAddress());
         this.password = password;
         this.profileKey = profileKey;
         getProfileStore().storeSelfProfileKey(getSelfRecipientId(), getProfileKey());
         this.encryptedDeviceName = encryptedDeviceName;
-        this.deviceId = deviceId;
         this.aciAccountData.setIdentityKeyPair(aciIdentity);
         this.pniAccountData.setIdentityKeyPair(pniIdentity);
-        this.registered = true;
+        this.registered = false;
         this.isMultiDevice = true;
         getKeyValueStore().storeEntry(lastReceiveTimestamp, 0L);
         this.pinMasterKey = null;
         getKeyValueStore().storeEntry(storageManifestVersion, -1L);
         this.setStorageManifest(null);
         this.storageKey = null;
+        getSenderKeyStore().deleteAll();
         trustSelfIdentity(ServiceIdType.ACI);
         trustSelfIdentity(ServiceIdType.PNI);
+        aciAccountData.getSessionStore().archiveAllSessions();
+        pniAccountData.getSessionStore().archiveAllSessions();
+        clearAllPreKeys();
         getKeyValueStore().storeEntry(lastRecipientsRefresh, null);
+        save();
+    }
+
+    public void finishLinking(final int deviceId) {
+        this.registered = true;
+        this.deviceId = deviceId;
+        save();
     }
 
     public void finishRegistration(
@@ -476,7 +405,7 @@ public class SignalAccount implements Closeable {
             return false;
         }
         var f = getFileName(dataPath, account);
-        return !(!f.exists() || f.isDirectory());
+        return f.exists() && !f.isDirectory() && f.length() > 0L;
     }
 
     private void load(