From 207764e0be91aeb9a6c52fa8639a822555f8759a Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 30 Oct 2022 11:00:25 +0100 Subject: [PATCH] Add option to disable adding message to send log --- .../manager/ProvisioningManagerImpl.java | 8 ++--- .../org/asamk/signal/manager/Settings.java | 8 +++++ .../signal/manager/SignalAccountFiles.java | 15 +++++---- .../signal/manager/storage/SignalAccount.java | 31 ++++++++++--------- .../storage/sendLog/MessageSendLogStore.java | 17 +++++++++- man/signal-cli.1.adoc | 3 ++ src/main/java/org/asamk/signal/App.java | 9 +++++- 7 files changed, 60 insertions(+), 31 deletions(-) create mode 100644 lib/src/main/java/org/asamk/signal/manager/Settings.java diff --git a/lib/src/main/java/org/asamk/signal/manager/ProvisioningManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ProvisioningManagerImpl.java index 17569401..c8df9774 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ProvisioningManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ProvisioningManagerImpl.java @@ -21,7 +21,6 @@ import org.asamk.signal.manager.config.ServiceConfig; import org.asamk.signal.manager.config.ServiceEnvironmentConfig; import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.storage.accounts.AccountsStore; -import org.asamk.signal.manager.storage.identities.TrustNewIdentity; import org.asamk.signal.manager.util.KeyUtils; import org.signal.libsignal.protocol.IdentityKeyPair; import org.signal.libsignal.protocol.util.KeyHelper; @@ -147,7 +146,7 @@ class ProvisioningManagerImpl implements ProvisioningManager { registrationId, pniRegistrationId, profileKey, - TrustNewIdentity.ON_FIRST_USE); + Settings.DEFAULT); ManagerImpl m = null; try { @@ -194,10 +193,7 @@ class ProvisioningManagerImpl implements ProvisioningManager { private boolean canRelinkExistingAccount(final String accountPath) throws IOException { final SignalAccount signalAccount; try { - signalAccount = SignalAccount.load(pathConfig.dataPath(), - accountPath, - false, - TrustNewIdentity.ON_FIRST_USE); + signalAccount = SignalAccount.load(pathConfig.dataPath(), accountPath, false, Settings.DEFAULT); } catch (IOException e) { logger.debug("Account in use or failed to load.", e); return false; diff --git a/lib/src/main/java/org/asamk/signal/manager/Settings.java b/lib/src/main/java/org/asamk/signal/manager/Settings.java new file mode 100644 index 00000000..e4f4554b --- /dev/null +++ b/lib/src/main/java/org/asamk/signal/manager/Settings.java @@ -0,0 +1,8 @@ +package org.asamk.signal.manager; + +import org.asamk.signal.manager.storage.identities.TrustNewIdentity; + +public record Settings(TrustNewIdentity trustNewIdentity, boolean disableMessageSendLog) { + + public static Settings DEFAULT = new Settings(TrustNewIdentity.ON_FIRST_USE, false); +} diff --git a/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java b/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java index 9d0b344a..12eb3d99 100644 --- a/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java +++ b/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java @@ -7,7 +7,6 @@ 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.accounts.AccountsStore; -import org.asamk.signal.manager.storage.identities.TrustNewIdentity; import org.asamk.signal.manager.util.KeyUtils; import org.signal.libsignal.protocol.util.KeyHelper; import org.slf4j.Logger; @@ -28,27 +27,27 @@ public class SignalAccountFiles { private final ServiceEnvironment serviceEnvironment; private final ServiceEnvironmentConfig serviceEnvironmentConfig; private final String userAgent; - private final TrustNewIdentity trustNewIdentity; + private final Settings settings; private final AccountsStore accountsStore; public SignalAccountFiles( final File settingsPath, final ServiceEnvironment serviceEnvironment, final String userAgent, - final TrustNewIdentity trustNewIdentity + final Settings settings ) throws IOException { this.pathConfig = PathConfig.createDefault(settingsPath); this.serviceEnvironment = serviceEnvironment; this.serviceEnvironmentConfig = ServiceConfig.getServiceEnvironmentConfig(this.serviceEnvironment, userAgent); this.userAgent = userAgent; - this.trustNewIdentity = trustNewIdentity; + this.settings = settings; this.accountsStore = new AccountsStore(pathConfig.dataPath(), serviceEnvironment, accountPath -> { if (accountPath == null || !SignalAccount.accountFileExists(pathConfig.dataPath(), accountPath)) { return null; } try { - return SignalAccount.load(pathConfig.dataPath(), accountPath, false, trustNewIdentity); + return SignalAccount.load(pathConfig.dataPath(), accountPath, false, settings); } catch (Exception e) { return null; } @@ -90,7 +89,7 @@ public class SignalAccountFiles { throw new NotRegisteredException(); } - var account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, trustNewIdentity); + var account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, settings); if (!number.equals(account.getNumber())) { account.close(); throw new IOException("Number in account file doesn't match expected number: " + account.getNumber()); @@ -168,7 +167,7 @@ public class SignalAccountFiles { registrationId, pniRegistrationId, profileKey, - trustNewIdentity); + settings); return new RegistrationManagerImpl(account, pathConfig, @@ -178,7 +177,7 @@ public class SignalAccountFiles { new AccountFileUpdaterImpl(accountsStore, newAccountPath)); } - var account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, trustNewIdentity); + var account = SignalAccount.load(pathConfig.dataPath(), accountPath, true, settings); if (!number.equals(account.getNumber())) { account.close(); throw new IOException("Number in account file doesn't match expected number: " + account.getNumber()); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index 1759649e..dac8de94 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -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.Settings; import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.TrustLevel; import org.asamk.signal.manager.config.ServiceEnvironment; @@ -17,7 +18,6 @@ import org.asamk.signal.manager.storage.groups.LegacyGroupStore; import org.asamk.signal.manager.storage.identities.IdentityKeyStore; import org.asamk.signal.manager.storage.identities.LegacyIdentityKeyStore; import org.asamk.signal.manager.storage.identities.SignalIdentityKeyStore; -import org.asamk.signal.manager.storage.identities.TrustNewIdentity; import org.asamk.signal.manager.storage.messageCache.MessageCache; import org.asamk.signal.manager.storage.prekeys.LegacyPreKeyStore; import org.asamk.signal.manager.storage.prekeys.LegacySignedPreKeyStore; @@ -136,7 +136,7 @@ public class SignalAccount implements Closeable { private IdentityKeyPair pniIdentityKeyPair; private int localRegistrationId; private int localPniRegistrationId; - private TrustNewIdentity trustNewIdentity; + private Settings settings; private long lastReceiveTimestamp = 0; private boolean registered = false; @@ -170,7 +170,7 @@ public class SignalAccount implements Closeable { } public static SignalAccount load( - File dataPath, String accountPath, boolean waitForLock, final TrustNewIdentity trustNewIdentity + File dataPath, String accountPath, boolean waitForLock, final Settings settings ) throws IOException { logger.trace("Opening account file"); final var fileName = getFileName(dataPath, accountPath); @@ -178,7 +178,7 @@ public class SignalAccount implements Closeable { try { var signalAccount = new SignalAccount(pair.first(), pair.second()); logger.trace("Loading account file"); - signalAccount.load(dataPath, accountPath, trustNewIdentity); + signalAccount.load(dataPath, accountPath, settings); logger.trace("Migrating legacy parts of account file"); signalAccount.migrateLegacyConfigs(); @@ -200,7 +200,7 @@ public class SignalAccount implements Closeable { int registrationId, int pniRegistrationId, ProfileKey profileKey, - final TrustNewIdentity trustNewIdentity + final Settings settings ) throws IOException { IOUtils.createPrivateDirectories(dataPath); var fileName = getFileName(dataPath, accountPath); @@ -221,7 +221,7 @@ public class SignalAccount implements Closeable { signalAccount.pniIdentityKeyPair = pniIdentityKey; signalAccount.localRegistrationId = registrationId; signalAccount.localPniRegistrationId = pniRegistrationId; - signalAccount.trustNewIdentity = trustNewIdentity; + signalAccount.settings = settings; signalAccount.configurationStore = new ConfigurationStore(signalAccount::saveConfigurationStore); signalAccount.registered = false; @@ -248,7 +248,7 @@ public class SignalAccount implements Closeable { int registrationId, int pniRegistrationId, ProfileKey profileKey, - final TrustNewIdentity trustNewIdentity + final Settings settings ) throws IOException { IOUtils.createPrivateDirectories(dataPath); var fileName = getFileName(dataPath, accountPath); @@ -267,10 +267,10 @@ public class SignalAccount implements Closeable { registrationId, pniRegistrationId, profileKey, - trustNewIdentity); + settings); } - final var signalAccount = load(dataPath, accountPath, true, trustNewIdentity); + final var signalAccount = load(dataPath, accountPath, true, settings); signalAccount.setProvisioningData(number, aci, pni, @@ -318,7 +318,7 @@ public class SignalAccount implements Closeable { int registrationId, int pniRegistrationId, ProfileKey profileKey, - final TrustNewIdentity trustNewIdentity + final Settings settings ) throws IOException { var fileName = getFileName(dataPath, accountPath); IOUtils.createPrivateFile(fileName); @@ -331,7 +331,7 @@ public class SignalAccount implements Closeable { signalAccount.serviceEnvironment = serviceEnvironment; signalAccount.localRegistrationId = registrationId; signalAccount.localPniRegistrationId = pniRegistrationId; - signalAccount.trustNewIdentity = trustNewIdentity; + signalAccount.settings = settings; signalAccount.setProvisioningData(number, aci, pni, @@ -502,7 +502,7 @@ public class SignalAccount implements Closeable { } private void load( - File dataPath, String accountPath, final TrustNewIdentity trustNewIdentity + File dataPath, String accountPath, final Settings settings ) throws IOException { this.dataPath = dataPath; this.accountPath = accountPath; @@ -685,7 +685,7 @@ public class SignalAccount implements Closeable { this.aciIdentityKeyPair = aciIdentityKeyPair; this.localRegistrationId = registrationId; - this.trustNewIdentity = trustNewIdentity; + this.settings = settings; migratedLegacyConfig = loadLegacyStores(rootNode, legacySignalProtocolStore) || migratedLegacyConfig; @@ -1156,7 +1156,7 @@ public class SignalAccount implements Closeable { public IdentityKeyStore getIdentityKeyStore() { return getOrCreate(() -> identityKeyStore, - () -> identityKeyStore = new IdentityKeyStore(getAccountDatabase(), trustNewIdentity)); + () -> identityKeyStore = new IdentityKeyStore(getAccountDatabase(), settings.trustNewIdentity())); } public SignalIdentityKeyStore getAciIdentityKeyStore() { @@ -1242,7 +1242,8 @@ public class SignalAccount implements Closeable { public MessageSendLogStore getMessageSendLogStore() { return getOrCreate(() -> messageSendLogStore, - () -> messageSendLogStore = new MessageSendLogStore(getAccountDatabase())); + () -> messageSendLogStore = new MessageSendLogStore(getAccountDatabase(), + settings.disableMessageSendLog())); } public CredentialsProvider getCredentialsProvider() { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java index f672667d..bab0aa4f 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/sendLog/MessageSendLogStore.java @@ -33,9 +33,11 @@ public class MessageSendLogStore implements AutoCloseable { private final Database database; private final Thread cleanupThread; + private final boolean sendLogDisabled; - public MessageSendLogStore(final Database database) { + public MessageSendLogStore(final Database database, final boolean disableMessageSendLog) { this.database = database; + this.sendLogDisabled = disableMessageSendLog; this.cleanupThread = new Thread(() -> { try { final var interval = Duration.ofHours(1).toMillis(); @@ -43,6 +45,7 @@ public class MessageSendLogStore implements AutoCloseable { try (final var connection = database.getConnection()) { deleteOutdatedEntries(connection); } catch (SQLException e) { + logger.debug("MSL", e); logger.warn("Deleting outdated entries failed"); break; } @@ -113,6 +116,9 @@ public class MessageSendLogStore implements AutoCloseable { public long insertIfPossible( long sentTimestamp, SendMessageResult sendMessageResult, ContentHint contentHint, boolean urgent ) { + if (sendLogDisabled) { + return -1; + } final RecipientDevices recipientDevice = getRecipientDevices(sendMessageResult); if (recipientDevice == null) { return -1; @@ -128,6 +134,9 @@ public class MessageSendLogStore implements AutoCloseable { public long insertIfPossible( long sentTimestamp, List sendMessageResults, ContentHint contentHint, boolean urgent ) { + if (sendLogDisabled) { + return -1; + } final var recipientDevices = sendMessageResults.stream() .map(this::getRecipientDevices) .filter(Objects::nonNull) @@ -146,6 +155,9 @@ public class MessageSendLogStore implements AutoCloseable { } public void addRecipientToExistingEntryIfPossible(final long contentId, final SendMessageResult sendMessageResult) { + if (sendLogDisabled) { + return; + } final RecipientDevices recipientDevice = getRecipientDevices(sendMessageResult); if (recipientDevice == null) { return; @@ -157,6 +169,9 @@ public class MessageSendLogStore implements AutoCloseable { public void addRecipientToExistingEntryIfPossible( final long contentId, final List sendMessageResults ) { + if (sendLogDisabled) { + return; + } final var recipientDevices = sendMessageResults.stream() .map(this::getRecipientDevices) .filter(Objects::nonNull) diff --git a/man/signal-cli.1.adoc b/man/signal-cli.1.adoc index 9b6ec2db..90b2c97d 100644 --- a/man/signal-cli.1.adoc +++ b/man/signal-cli.1.adoc @@ -79,6 +79,9 @@ Choose when to trust new identities: - `always`: Trust any new identity key without verification - `never`: Don't trust any unknown identity key, every key must be verified manually +*--disable-send-log*:: +Disable message send log (for resending messages that recipient couldn't decrypt). + == Commands === register diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 4f045345..058ae6bb 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -23,6 +23,7 @@ import org.asamk.signal.dbus.DbusProvisioningManagerImpl; import org.asamk.signal.dbus.DbusRegistrationManagerImpl; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.RegistrationManager; +import org.asamk.signal.manager.Settings; import org.asamk.signal.manager.SignalAccountFiles; import org.asamk.signal.manager.api.AccountCheckException; import org.asamk.signal.manager.api.NotRegisteredException; @@ -101,6 +102,10 @@ public class App { .type(Arguments.enumStringType(TrustNewIdentityCli.class)) .setDefault(TrustNewIdentityCli.ON_FIRST_USE); + parser.addArgument("--disable-send-log") + .help("Disable message send log (for resending messages that recipient couldn't decrypt)") + .action(Arguments.storeTrue()); + var subparsers = parser.addSubparsers().title("subcommands").dest("command"); Commands.getCommandSubparserAttachers().forEach((key, value) -> { @@ -167,12 +172,14 @@ public class App { ? TrustNewIdentity.ON_FIRST_USE : trustNewIdentityCli == TrustNewIdentityCli.ALWAYS ? TrustNewIdentity.ALWAYS : TrustNewIdentity.NEVER; + final var disableSendLog = Boolean.TRUE.equals(ns.getBoolean("disable-send-log")); + final SignalAccountFiles signalAccountFiles; try { signalAccountFiles = new SignalAccountFiles(configPath, serviceEnvironment, BaseConfig.USER_AGENT, - trustNewIdentity); + new Settings(trustNewIdentity, disableSendLog)); } catch (IOException e) { throw new IOErrorException("Failed to read local accounts list", e); } -- 2.50.1