]> nmode's Git Repositories - signal-cli/commitdiff
Handle saving inside SignalAccount
authorAsamK <asamk@gmx.de>
Sun, 2 May 2021 20:03:41 +0000 (22:03 +0200)
committerAsamK <asamk@gmx.de>
Mon, 3 May 2021 16:43:45 +0000 (18:43 +0200)
lib/src/main/java/org/asamk/signal/manager/Manager.java
lib/src/main/java/org/asamk/signal/manager/ProvisioningManager.java
lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java
lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java

index 3c2d130d3d378e57ad0a1642cd7c86cd5e488b8d..e39394800700eb6dd8758d499f67bba10c6a6fa4 100644 (file)
@@ -316,11 +316,9 @@ public class Manager implements Closeable {
     public void checkAccountState() throws IOException {
         if (accountManager.getPreKeysCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) {
             refreshPreKeys();
-            account.save();
         }
         if (account.getUuid() == null) {
             account.setUuid(accountManager.getOwnUuid());
-            account.save();
         }
         updateAccountAttributes();
     }
@@ -411,13 +409,11 @@ public class Manager implements Closeable {
         accountManager.deleteAccount();
 
         account.setRegistered(false);
-        account.save();
     }
 
     public List<DeviceInfo> getLinkedDevices() throws IOException {
         var devices = accountManager.getDevices();
         account.setMultiDevice(devices.size() > 1);
-        account.save();
         return devices;
     }
 
@@ -425,7 +421,6 @@ public class Manager implements Closeable {
         accountManager.removeDevice(deviceId);
         var devices = accountManager.getDevices();
         account.setMultiDevice(devices.size() > 1);
-        account.save();
     }
 
     public void addDeviceLink(URI linkUri) throws IOException, InvalidKeyException {
@@ -444,7 +439,6 @@ public class Manager implements Closeable {
                 Optional.of(account.getProfileKey().serialize()),
                 verificationCode);
         account.setMultiDevice(true);
-        account.save();
     }
 
     public void setRegistrationLockPin(Optional<String> pin) throws IOException, UnauthenticatedResponseException {
@@ -458,8 +452,7 @@ public class Manager implements Closeable {
 
             pinHelper.setRegistrationLockPin(pin.get(), masterKey);
 
-            account.setRegistrationLockPin(pin.get());
-            account.setPinMasterKey(masterKey);
+            account.setRegistrationLockPin(pin.get(), masterKey);
         } else {
             // Remove legacy registration lock
             accountManager.removeRegistrationLockV1();
@@ -467,10 +460,8 @@ public class Manager implements Closeable {
             // Remove KBS Pin
             pinHelper.removeRegistrationLockPin();
 
-            account.setRegistrationLockPin(null);
-            account.setPinMasterKey(null);
+            account.setRegistrationLockPin(null, null);
         }
-        account.save();
     }
 
     void refreshPreKeys() throws IOException {
@@ -1082,7 +1073,6 @@ public class Manager implements Closeable {
             for (var address : signalServiceAddresses) {
                 handleEndSession(address);
             }
-            account.save();
             throw e;
         }
     }
@@ -1097,7 +1087,6 @@ public class Manager implements Closeable {
         var contact = account.getContactStore().getContact(recipientId);
         final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
         account.getContactStore().storeContact(recipientId, builder.withName(name).build());
-        account.save();
     }
 
     public void setContactBlocked(String number, boolean blocked) throws InvalidNumberException {
@@ -1108,7 +1097,6 @@ public class Manager implements Closeable {
         var contact = account.getContactStore().getContact(recipientId);
         final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
         account.getContactStore().storeContact(recipientId, builder.withBlocked(blocked).build());
-        account.save();
     }
 
     public void setGroupBlocked(final GroupId groupId, final boolean blocked) throws GroupNotFoundException {
@@ -1119,7 +1107,6 @@ public class Manager implements Closeable {
 
         group.setBlocked(blocked);
         account.getGroupStore().updateGroup(group);
-        account.save();
     }
 
     private void setExpirationTimer(RecipientId recipientId, int messageExpirationTimer) {
@@ -1146,7 +1133,6 @@ public class Manager implements Closeable {
         var recipientId = canonicalizeAndResolveRecipient(number);
         setExpirationTimer(recipientId, messageExpirationTimer);
         sendExpirationTimerUpdate(recipientId);
-        account.save();
     }
 
     /**
@@ -1179,7 +1165,6 @@ public class Manager implements Closeable {
 
         var sticker = new Sticker(StickerPackId.deserialize(Hex.fromStringCondensed(packId)), packKey);
         account.getStickerStore().updateSticker(sticker);
-        account.save();
 
         try {
             return new URI("https",
@@ -1376,7 +1361,6 @@ public class Manager implements Closeable {
                     handleEndSession(recipient);
                 }
             }
-            account.save();
         }
     }
 
@@ -1387,19 +1371,15 @@ public class Manager implements Closeable {
         messageBuilder.withTimestamp(timestamp);
         getOrCreateMessagePipe();
         getOrCreateUnidentifiedMessagePipe();
-        try {
-            final var recipientId = account.getSelfRecipientId();
+        final var recipientId = account.getSelfRecipientId();
 
-            final var contact = account.getContactStore().getContact(recipientId);
-            final var expirationTime = contact != null ? contact.getMessageExpirationTime() : 0;
-            messageBuilder.withExpiration(expirationTime);
+        final var contact = account.getContactStore().getContact(recipientId);
+        final var expirationTime = contact != null ? contact.getMessageExpirationTime() : 0;
+        messageBuilder.withExpiration(expirationTime);
 
-            var message = messageBuilder.build();
-            final var result = sendSelfMessage(message);
-            return new Pair<>(timestamp, result);
-        } finally {
-            account.save();
-        }
+        var message = messageBuilder.build();
+        final var result = sendSelfMessage(message);
+        return new Pair<>(timestamp, result);
     }
 
     private SendMessageResult sendSelfMessage(SignalServiceDataMessage message) throws IOException {
@@ -1715,7 +1695,6 @@ public class Manager implements Closeable {
             }
             actions = handleMessage(envelope, content, ignoreAttachments);
         }
-        account.save();
         handler.handleMessage(envelope, content, null);
         cachedMessage.delete();
         return actions;
@@ -1763,7 +1742,6 @@ public class Manager implements Closeable {
                                 logger.warn("Message action failed.", e);
                             }
                         }
-                        account.save();
                         queuedActions.clear();
                         queuedActions = null;
                     }
@@ -1803,7 +1781,6 @@ public class Manager implements Closeable {
                     queuedActions.addAll(actions);
                 }
             }
-            account.save();
             if (isMessageBlocked(envelope, content)) {
                 logger.info("Ignoring a message from blocked user/group: {}", envelope.getTimestamp());
             } else if (notAGroupMember) {
index c88692120ed76bfa74a24ed66ca5923dc9c3c804..37ac4cdb03ef43061ca6adf0d3f786b4baacb343 100644 (file)
@@ -125,7 +125,6 @@ public class ProvisioningManager {
                     ret.getIdentity(),
                     registrationId,
                     profileKey);
-            account.save();
 
             Manager m = null;
             try {
@@ -149,8 +148,6 @@ public class ProvisioningManager {
                     throw e;
                 }
 
-                account.save();
-
                 final var result = m;
                 account = null;
                 m = null;
index b3c524c62d492e7974c84fda5c44763b590edc08..72c9972987a1e402dae4584523ff9d37b4f44ef4 100644 (file)
@@ -29,6 +29,7 @@ import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
 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.kbs.MasterKey;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.util.SleepTimer;
 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
@@ -40,7 +41,6 @@ import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider
 import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
-import java.util.Date;
 import java.util.Locale;
 
 public class RegistrationManager implements Closeable {
@@ -103,7 +103,6 @@ public class RegistrationManager implements Closeable {
                     identityKey,
                     registrationId,
                     profileKey);
-            account.save();
 
             return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
         }
@@ -114,10 +113,6 @@ public class RegistrationManager implements Closeable {
     }
 
     public void register(boolean voiceVerification, String captcha) throws IOException {
-        if (account.getPassword() == null) {
-            account.setPassword(KeyUtils.createPassword());
-        }
-
         if (voiceVerification) {
             accountManager.requestVoiceVerificationCode(Locale.getDefault(),
                     Optional.fromNullable(captcha),
@@ -125,8 +120,6 @@ public class RegistrationManager implements Closeable {
         } else {
             accountManager.requestSmsVerificationCode(false, Optional.fromNullable(captcha), Optional.absent());
         }
-
-        account.save();
     }
 
     public Manager verifyAccount(
@@ -134,9 +127,11 @@ public class RegistrationManager implements Closeable {
     ) throws IOException, KeyBackupSystemNoDataException, KeyBackupServicePinException {
         verificationCode = verificationCode.replace("-", "");
         VerifyAccountResponse response;
+        MasterKey masterKey;
         try {
             response = verifyAccountWithCode(verificationCode, pin, null);
-            account.setPinMasterKey(null);
+
+            masterKey = null;
         } catch (LockedException e) {
             if (pin == null) {
                 throw e;
@@ -153,33 +148,21 @@ public class RegistrationManager implements Closeable {
             } catch (LockedException _e) {
                 throw new AssertionError("KBS Pin appeared to matched but reg lock still failed!");
             }
-            account.setPinMasterKey(registrationLockData.getMasterKey());
+            masterKey = registrationLockData.getMasterKey();
         }
 
         // TODO response.isStorageCapable()
         //accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID)));
-
-        account.setDeviceId(SignalServiceAddress.DEFAULT_DEVICE_ID);
-        account.setMultiDevice(false);
-        account.setRegistered(true);
-        account.setUuid(UuidUtil.parseOrNull(response.getUuid()));
-        account.setRegistrationLockPin(pin);
-        account.getSessionStore().archiveAllSessions();
-        final var recipientId = account.getRecipientStore().resolveRecipientTrusted(account.getSelfAddress());
-        final var publicKey = account.getIdentityKeyPair().getPublicKey();
-        account.getIdentityKeyStore().saveIdentity(recipientId, publicKey, new Date());
-        account.getIdentityKeyStore().setIdentityTrustLevel(recipientId, publicKey, TrustLevel.TRUSTED_VERIFIED);
+        account.finishRegistration(UuidUtil.parseOrNull(response.getUuid()), masterKey, pin);
 
         Manager m = null;
         try {
             m = new Manager(account, pathConfig, serviceEnvironmentConfig, userAgent);
+            account = null;
 
             m.refreshPreKeys();
 
-            account.save();
-
             final var result = m;
-            account = null;
             m = null;
 
             return result;
index f2d2d91d383f18eb9c2e8fbcbf826d273210e27d..6b05faa6c01371546f3470e29efcf25bc554ea4f 100644 (file)
@@ -3,6 +3,7 @@ package org.asamk.signal.manager.storage;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import org.asamk.signal.manager.TrustLevel;
 import org.asamk.signal.manager.groups.GroupId;
 import org.asamk.signal.manager.storage.contacts.ContactsStore;
 import org.asamk.signal.manager.storage.contacts.LegacyJsonContactsStore;
@@ -54,6 +55,7 @@ import java.nio.channels.ClosedChannelException;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
 import java.util.Base64;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.UUID;
@@ -139,6 +141,7 @@ public class SignalAccount implements Closeable {
         account.registered = false;
 
         account.migrateLegacyConfigs();
+        account.save();
 
         return account;
     }
@@ -196,15 +199,19 @@ public class SignalAccount implements Closeable {
 
         account.recipientStore.resolveRecipientTrusted(account.getSelfAddress());
         account.migrateLegacyConfigs();
+        account.save();
 
         return account;
     }
 
-    public void migrateLegacyConfigs() {
+    private void migrateLegacyConfigs() {
+        if (getPassword() == null) {
+            setPassword(KeyUtils.createPassword());
+        }
+
         if (getProfileKey() == null && isRegistered()) {
             // Old config file, creating new profile key
             setProfileKey(KeyUtils.createProfileKey());
-            save();
         }
         // Ensure our profile key is stored in profile store
         getProfileStore().storeProfileKey(getSelfRecipientId(), getProfileKey());
@@ -225,7 +232,7 @@ public class SignalAccount implements Closeable {
         return new File(dataPath, username + ".d");
     }
 
-    public static File getMessageCachePath(File dataPath, String username) {
+    private static File getMessageCachePath(File dataPath, String username) {
         return new File(getUserPath(dataPath, username), "msg-cache");
     }
 
@@ -324,6 +331,7 @@ public class SignalAccount implements Closeable {
             }
         }
 
+        var migratedLegacyConfig = false;
         final var legacySignalProtocolStore = rootNode.hasNonNull("axolotlStore")
                 ? jsonProcessor.convertValue(Utils.getNotNullNode(rootNode, "axolotlStore"),
                 LegacyJsonSignalProtocolStore.class)
@@ -331,11 +339,12 @@ public class SignalAccount implements Closeable {
         if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyIdentityKeyStore() != null) {
             identityKeyPair = legacySignalProtocolStore.getLegacyIdentityKeyStore().getIdentityKeyPair();
             registrationId = legacySignalProtocolStore.getLegacyIdentityKeyStore().getLocalRegistrationId();
+            migratedLegacyConfig = true;
         }
 
         initStores(dataPath, identityKeyPair, registrationId);
 
-        loadLegacyStores(rootNode, legacySignalProtocolStore);
+        migratedLegacyConfig = loadLegacyStores(rootNode, legacySignalProtocolStore) || migratedLegacyConfig;
 
         if (rootNode.hasNonNull("groupStore")) {
             groupStoreStorage = jsonProcessor.convertValue(rootNode.get("groupStore"), GroupStore.Storage.class);
@@ -356,12 +365,17 @@ public class SignalAccount implements Closeable {
             stickerStore = new StickerStore(this::saveStickerStore);
         }
 
-        loadLegacyThreadStore(rootNode);
+        migratedLegacyConfig = loadLegacyThreadStore(rootNode) || migratedLegacyConfig;
+
+        if (migratedLegacyConfig) {
+            save();
+        }
     }
 
-    private void loadLegacyStores(
+    private boolean loadLegacyStores(
             final JsonNode rootNode, final LegacyJsonSignalProtocolStore legacySignalProtocolStore
     ) {
+        var migrated = false;
         var legacyRecipientStoreNode = rootNode.get("recipientStore");
         if (legacyRecipientStoreNode != null) {
             logger.debug("Migrating legacy recipient store.");
@@ -370,6 +384,7 @@ public class SignalAccount implements Closeable {
                 recipientStore.resolveRecipientsTrusted(legacyRecipientStore.getAddresses());
             }
             recipientStore.resolveRecipientTrusted(getSelfAddress());
+            migrated = true;
         }
 
         if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyPreKeyStore() != null) {
@@ -381,6 +396,7 @@ public class SignalAccount implements Closeable {
                     logger.warn("Failed to migrate pre key, ignoring", e);
                 }
             }
+            migrated = true;
         }
 
         if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacySignedPreKeyStore() != null) {
@@ -392,6 +408,7 @@ public class SignalAccount implements Closeable {
                     logger.warn("Failed to migrate signed pre key, ignoring", e);
                 }
             }
+            migrated = true;
         }
 
         if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacySessionStore() != null) {
@@ -404,6 +421,7 @@ public class SignalAccount implements Closeable {
                     logger.warn("Failed to migrate session, ignoring", e);
                 }
             }
+            migrated = true;
         }
 
         if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyIdentityKeyStore() != null) {
@@ -415,6 +433,7 @@ public class SignalAccount implements Closeable {
                         identity.getIdentityKey(),
                         identity.getTrustLevel());
             }
+            migrated = true;
         }
 
         if (rootNode.hasNonNull("contactStore")) {
@@ -442,6 +461,7 @@ public class SignalAccount implements Closeable {
                     }
                 }
             }
+            migrated = true;
         }
 
         if (rootNode.hasNonNull("profileStore")) {
@@ -479,9 +499,11 @@ public class SignalAccount implements Closeable {
                 }
             }
         }
+
+        return migrated;
     }
 
-    private void loadLegacyThreadStore(final JsonNode rootNode) {
+    private boolean loadLegacyThreadStore(final JsonNode rootNode) {
         var threadStoreNode = rootNode.get("threadStore");
         if (threadStoreNode != null && !threadStoreNode.isNull()) {
             var threadStore = jsonProcessor.convertValue(threadStoreNode, LegacyJsonThreadStore.class);
@@ -511,7 +533,10 @@ public class SignalAccount implements Closeable {
                     logger.warn("Failed to read legacy thread info: {}", e.getMessage());
                 }
             }
+            return true;
         }
+
+        return false;
     }
 
     private void saveStickerStore(StickerStore.Storage storage) {
@@ -524,7 +549,7 @@ public class SignalAccount implements Closeable {
         save();
     }
 
-    public void save() {
+    private void save() {
         synchronized (fileChannel) {
             var rootNode = jsonProcessor.createObjectNode();
             rootNode.put("username", username)
@@ -645,6 +670,7 @@ public class SignalAccount implements Closeable {
 
     public void setUuid(final UUID uuid) {
         this.uuid = uuid;
+        save();
     }
 
     public SignalServiceAddress getSelfAddress() {
@@ -659,10 +685,6 @@ public class SignalAccount implements Closeable {
         return deviceId;
     }
 
-    public void setDeviceId(final int deviceId) {
-        this.deviceId = deviceId;
-    }
-
     public boolean isMasterDevice() {
         return deviceId == SignalServiceAddress.DEFAULT_DEVICE_ID;
     }
@@ -679,26 +701,25 @@ public class SignalAccount implements Closeable {
         return password;
     }
 
-    public void setPassword(final String password) {
+    private void setPassword(final String password) {
         this.password = password;
+        save();
     }
 
     public String getRegistrationLockPin() {
         return registrationLockPin;
     }
 
-    public void setRegistrationLockPin(final String registrationLockPin) {
+    public void setRegistrationLockPin(final String registrationLockPin, final MasterKey pinMasterKey) {
         this.registrationLockPin = registrationLockPin;
+        this.pinMasterKey = pinMasterKey;
+        save();
     }
 
     public MasterKey getPinMasterKey() {
         return pinMasterKey;
     }
 
-    public void setPinMasterKey(final MasterKey pinMasterKey) {
-        this.pinMasterKey = pinMasterKey;
-    }
-
     public StorageKey getStorageKey() {
         if (pinMasterKey != null) {
             return pinMasterKey.deriveStorageServiceKey();
@@ -707,7 +728,11 @@ public class SignalAccount implements Closeable {
     }
 
     public void setStorageKey(final StorageKey storageKey) {
+        if (storageKey.equals(this.storageKey)) {
+            return;
+        }
         this.storageKey = storageKey;
+        save();
     }
 
     public ProfileKey getProfileKey() {
@@ -715,7 +740,11 @@ public class SignalAccount implements Closeable {
     }
 
     public void setProfileKey(final ProfileKey profileKey) {
+        if (profileKey.equals(this.profileKey)) {
+            return;
+        }
         this.profileKey = profileKey;
+        save();
     }
 
     public byte[] getSelfUnidentifiedAccessKey() {
@@ -736,6 +765,7 @@ public class SignalAccount implements Closeable {
 
     public void setRegistered(final boolean registered) {
         this.registered = registered;
+        save();
     }
 
     public boolean isMultiDevice() {
@@ -743,7 +773,11 @@ public class SignalAccount implements Closeable {
     }
 
     public void setMultiDevice(final boolean multiDevice) {
+        if (isMultiDevice == multiDevice) {
+            return;
+        }
         isMultiDevice = multiDevice;
+        save();
     }
 
     public boolean isUnrestrictedUnidentifiedAccess() {
@@ -756,11 +790,24 @@ public class SignalAccount implements Closeable {
         return true;
     }
 
+    public void finishRegistration(final UUID uuid, final MasterKey masterKey, final String pin) {
+        this.pinMasterKey = masterKey;
+        this.deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
+        this.isMultiDevice = false;
+        this.registered = true;
+        this.uuid = uuid;
+        this.registrationLockPin = pin;
+        save();
+
+        getSessionStore().archiveAllSessions();
+        final var recipientId = getRecipientStore().resolveRecipientTrusted(getSelfAddress());
+        final var publicKey = getIdentityKeyPair().getPublicKey();
+        getIdentityKeyStore().saveIdentity(recipientId, publicKey, new Date());
+        getIdentityKeyStore().setIdentityTrustLevel(recipientId, publicKey, TrustLevel.TRUSTED_VERIFIED);
+    }
+
     @Override
     public void close() throws IOException {
-        if (fileChannel.isOpen()) {
-            save();
-        }
         synchronized (fileChannel) {
             try {
                 lock.close();