]> 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.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;
 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();
             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(),
 
             var profileKey = KeyUtils.createProfileKey();
             var account = SignalAccount.create(pathConfig.dataPath(),
@@ -170,8 +167,6 @@ public class SignalAccountFiles {
                     serviceEnvironment,
                     aciIdentityKey,
                     pniIdentityKey,
                     serviceEnvironment,
                     aciIdentityKey,
                     pniIdentityKey,
-                    registrationId,
-                    pniRegistrationId,
                     profileKey,
                     settings);
 
                     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.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.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;
 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 SignalServiceAccountManager accountManager;
     private final IdentityKeyPair tempIdentityKey;
-    private final int registrationId;
-    private final int pniRegistrationId;
     private final String password;
 
     public ProvisioningManagerImpl(
     private final String password;
 
     public ProvisioningManagerImpl(
@@ -77,8 +75,6 @@ public class ProvisioningManagerImpl implements ProvisioningManager {
         this.accountsStore = accountsStore;
 
         tempIdentityKey = KeyUtils.generateIdentityKeyPair();
         this.accountsStore = accountsStore;
 
         tempIdentityKey = KeyUtils.generateIdentityKeyPair();
-        registrationId = KeyHelper.generateRegistrationId(false);
-        pniRegistrationId = KeyHelper.generateRegistrationId(false);
         password = KeyUtils.createPassword();
         GroupsV2Operations groupsV2Operations;
         try {
         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) {
             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) {
             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());
         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 {
         // 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,
                     aci,
                     pni,
                     password,
                     encryptedDeviceName,
-                    deviceId,
                     ret.getAciIdentity(),
                     ret.getPniIdentity(),
                     ret.getAciIdentity(),
                     ret.getPniIdentity(),
-                    registrationId,
-                    pniRegistrationId,
-                    profileKey,
-                    Settings.DEFAULT);
+                    profileKey);
+
             account.getConfigurationStore().setReadReceipts(ret.isReadReceipts());
 
             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,
             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 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;
     private String password;
     private String registrationLockPin;
     private MasterKey pinMasterKey;
@@ -204,8 +204,6 @@ public class SignalAccount implements Closeable {
             ServiceEnvironment serviceEnvironment,
             IdentityKeyPair aciIdentityKey,
             IdentityKeyPair pniIdentityKey,
             ServiceEnvironment serviceEnvironment,
             IdentityKeyPair aciIdentityKey,
             IdentityKeyPair pniIdentityKey,
-            int registrationId,
-            int pniRegistrationId,
             ProfileKey profileKey,
             final Settings settings
     ) throws IOException {
             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.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.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.settings = settings;
 
         signalAccount.registered = false;
 
         signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
         signalAccount.migrateLegacyConfigs();
-        signalAccount.clearAllPreKeys();
         signalAccount.save();
 
         return signalAccount;
     }
 
         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 {
             final Settings settings
     ) throws IOException {
+        IOUtils.createPrivateDirectories(dataPath);
         var fileName = getFileName(dataPath, accountPath);
         IOUtils.createPrivateFile(fileName);
 
         final var pair = openFileChannel(fileName, true);
         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.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.settings = settings;
-        signalAccount.setProvisioningData(number,
-                aci,
-                pni,
-                password,
-                encryptedDeviceName,
-                deviceId,
-                aciIdentityKey,
-                pniIdentityKey,
-                profileKey);
 
 
-        signalAccount.getRecipientTrustedResolver()
-                .resolveSelfRecipientTrusted(signalAccount.getSelfRecipientAddress());
         signalAccount.previousStorageVersion = CURRENT_STORAGE_VERSION;
         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;
     }
 
         return signalAccount;
     }
 
-    private void setProvisioningData(
+    public void setProvisioningData(
             final String number,
             final ACI aci,
             final PNI pni,
             final String password,
             final String encryptedDeviceName,
             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
     ) {
             final IdentityKeyPair aciIdentity,
             final IdentityKeyPair pniIdentity,
             final ProfileKey profileKey
     ) {
+        this.deviceId = 0;
         this.number = number;
         this.aciAccountData.setServiceId(aci);
         this.pniAccountData.setServiceId(pni);
         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.password = password;
         this.profileKey = profileKey;
         getProfileStore().storeSelfProfileKey(getSelfRecipientId(), getProfileKey());
         this.encryptedDeviceName = encryptedDeviceName;
-        this.deviceId = deviceId;
         this.aciAccountData.setIdentityKeyPair(aciIdentity);
         this.pniAccountData.setIdentityKeyPair(pniIdentity);
         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;
         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);
         trustSelfIdentity(ServiceIdType.ACI);
         trustSelfIdentity(ServiceIdType.PNI);
+        aciAccountData.getSessionStore().archiveAllSessions();
+        pniAccountData.getSessionStore().archiveAllSessions();
+        clearAllPreKeys();
         getKeyValueStore().storeEntry(lastRecipientsRefresh, null);
         getKeyValueStore().storeEntry(lastRecipientsRefresh, null);
+        save();
+    }
+
+    public void finishLinking(final int deviceId) {
+        this.registered = true;
+        this.deviceId = deviceId;
+        save();
     }
 
     public void finishRegistration(
     }
 
     public void finishRegistration(
@@ -476,7 +405,7 @@ public class SignalAccount implements Closeable {
             return false;
         }
         var f = getFileName(dataPath, account);
             return false;
         }
         var f = getFileName(dataPath, account);
-        return !(!f.exists() || f.isDirectory());
+        return f.exists() && !f.isDirectory() && f.length() > 0L;
     }
 
     private void load(
     }
 
     private void load(