From 91ed49e0193ced5e8dda559cbc3dcc9c4fc78021 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 18 Feb 2024 16:31:34 +0100 Subject: [PATCH] Includ pni signatures if necessary --- .../helper/IncomingMessageHandler.java | 6 +++ .../signal/manager/helper/SendHelper.java | 47 ++++++++++++------- .../manager/storage/AccountDatabase.java | 10 +++- .../storage/recipients/RecipientStore.java | 39 +++++++++++++++ 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java index 0f062828..f80b605c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java @@ -299,6 +299,12 @@ public final class IncomingMessageHandler { final var senderDeviceId = senderDeviceAddress.deviceId(); final var destination = getDestination(envelope); + if (account.getPni().equals(destination.serviceId)) { + account.getRecipientStore().markNeedsPniSignature(destination.recipientId, true); + } else if (account.getAci().equals(destination.serviceId)) { + account.getRecipientStore().markNeedsPniSignature(destination.recipientId, false); + } + if (content.getReceiptMessage().isPresent()) { final var message = content.getReceiptMessage().get(); if (message.isDeliveryReceipt()) { diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/SendHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/SendHelper.java index a9ca6a12..d3068fc4 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/SendHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/SendHelper.java @@ -127,10 +127,10 @@ public class SendHelper { ) { final var messageSendLogStore = account.getMessageSendLogStore(); final var result = handleSendMessage(recipientId, - (messageSender, address, unidentifiedAccess) -> messageSender.sendReceipt(address, + (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.sendReceipt(address, unidentifiedAccess, receiptMessage, - false)); + includePniSignature)); messageSendLogStore.insertIfPossible(receiptMessage.getWhen(), result, ContentHint.IMPLICIT, false); handleSendMessageResult(result); return result; @@ -144,13 +144,14 @@ public class SendHelper { .withProfileKey(profileKey) .build(); return handleSendMessage(recipientId, - (messageSender, address, unidentifiedAccess) -> messageSender.sendDataMessage(address, + (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.sendDataMessage( + address, unidentifiedAccess, ContentHint.IMPLICIT, message, SignalServiceMessageSender.IndividualSendEvents.EMPTY, false, - false)); + includePniSignature)); } public SendMessageResult sendRetryReceipt( @@ -161,7 +162,8 @@ public class SendHelper { recipientId, errorMessage.getDeviceId()); final var result = handleSendMessage(recipientId, - (messageSender, address, unidentifiedAccess) -> messageSender.sendRetryReceipt(address, + (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.sendRetryReceipt( + address, unidentifiedAccess, groupId.map(GroupId::serialize), errorMessage)); @@ -170,7 +172,10 @@ public class SendHelper { } public SendMessageResult sendNullMessage(RecipientId recipientId) { - final var result = handleSendMessage(recipientId, SignalServiceMessageSender::sendNullMessage); + final var result = handleSendMessage(recipientId, + (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.sendNullMessage( + address, + unidentifiedAccess)); handleSendMessageResult(result); return result; } @@ -220,10 +225,8 @@ public class SendHelper { SignalServiceTypingMessage message, RecipientId recipientId ) { final var result = handleSendMessage(recipientId, - (messageSender, address, unidentifiedAccess) -> messageSender.sendTyping(List.of(address), - List.of(unidentifiedAccess), - message, - null).getFirst()); + (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.sendTyping(List.of( + address), List.of(unidentifiedAccess), message, null).getFirst()); handleSendMessageResult(result); return result; } @@ -247,7 +250,8 @@ public class SendHelper { logger.trace("Resending message {} to {}", timestamp, recipientId); if (messageSendLogEntry.groupId().isEmpty()) { return handleSendMessage(recipientId, - (messageSender, address, unidentifiedAccess) -> messageSender.resendContent(address, + (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.resendContent( + address, unidentifiedAccess, timestamp, messageSendLogEntry.content(), @@ -277,7 +281,7 @@ public class SendHelper { .build(); final var result = handleSendMessage(recipientId, - (messageSender, address, unidentifiedAccess) -> messageSender.resendContent(address, + (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.resendContent(address, unidentifiedAccess, timestamp, contentToSend, @@ -660,17 +664,18 @@ public class SendHelper { ) { final var messageSendLogStore = account.getMessageSendLogStore(); final var urgent = true; - final var includePniSignature = false; final var result = handleSendMessage(recipientId, editTargetTimestamp.isEmpty() - ? (messageSender, address, unidentifiedAccess) -> messageSender.sendDataMessage(address, + ? (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.sendDataMessage( + address, unidentifiedAccess, ContentHint.RESENDABLE, message, SignalServiceMessageSender.IndividualSendEvents.EMPTY, urgent, includePniSignature) - : (messageSender, address, unidentifiedAccess) -> messageSender.sendEditMessage(address, + : (messageSender, address, unidentifiedAccess, includePniSignature) -> messageSender.sendEditMessage( + address, unidentifiedAccess, ContentHint.RESENDABLE, message, @@ -687,8 +692,12 @@ public class SendHelper { var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId); try { + final boolean includePniSignature = account.getRecipientStore().needsPniSignature(recipientId); try { - return s.send(messageSender, address, context.getUnidentifiedAccessHelper().getAccessFor(recipientId)); + return s.send(messageSender, + address, + context.getUnidentifiedAccessHelper().getAccessFor(recipientId), + includePniSignature); } catch (UnregisteredUserException e) { final RecipientId newRecipientId; try { @@ -699,7 +708,8 @@ public class SendHelper { address = context.getRecipientHelper().resolveSignalServiceAddress(newRecipientId); return s.send(messageSender, address, - context.getUnidentifiedAccessHelper().getAccessFor(newRecipientId)); + context.getUnidentifiedAccessHelper().getAccessFor(newRecipientId), + includePniSignature); } } catch (UnregisteredUserException e) { return SendMessageResult.unregisteredFailure(address); @@ -774,7 +784,8 @@ public class SendHelper { SendMessageResult send( SignalServiceMessageSender messageSender, SignalServiceAddress address, - Optional unidentifiedAccess + Optional unidentifiedAccess, + boolean includePniSignature ) throws IOException, UnregisteredUserException, ProofRequiredException, RateLimitException, org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java b/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java index ba51d9c0..6cf725a0 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java @@ -33,7 +33,7 @@ import java.util.UUID; public class AccountDatabase extends Database { private static final Logger logger = LoggerFactory.getLogger(AccountDatabase.class); - private static final long DATABASE_VERSION = 23; + private static final long DATABASE_VERSION = 24; private AccountDatabase(final HikariDataSource dataSource) { super(logger, DATABASE_VERSION, dataSource); @@ -573,6 +573,14 @@ public class AccountDatabase extends Database { """); } } + if (oldVersion < 24) { + logger.debug("Updating database: Create needs_pni_signature column"); + try (final var statement = connection.createStatement()) { + statement.executeUpdate(""" + ALTER TABLE recipient ADD needs_pni_signature INTEGER NOT NULL DEFAULT FALSE; + """); + } + } } private static void createUuidMappingTable( diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index 5bd972ab..7d47839b 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -66,6 +66,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re unregistered_timestamp INTEGER, profile_key BLOB, profile_key_credential BLOB, + needs_pni_signature INTEGER NOT NULL DEFAULT FALSE, given_name TEXT, family_name TEXT, @@ -856,6 +857,44 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re return count; } + public void markNeedsPniSignature(final RecipientId recipientId, final boolean value) { + logger.debug("Marking {} numbers as need pni signature = {}", recipientId, value); + try (final var connection = database.getConnection()) { + final var sql = ( + """ + UPDATE %s + SET needs_pni_signature = ? + WHERE _id = ? + """ + ).formatted(TABLE_RECIPIENT); + try (final var statement = connection.prepareStatement(sql)) { + statement.setBoolean(1, value); + statement.setLong(2, recipientId.id()); + statement.executeUpdate(); + } + } catch (SQLException e) { + throw new RuntimeException("Failed update recipient store", e); + } + } + + public boolean needsPniSignature(final RecipientId recipientId) { + try (final var connection = database.getConnection()) { + final var sql = ( + """ + SELECT needs_pni_signature + FROM %s + WHERE _id = ? + """ + ).formatted(TABLE_RECIPIENT); + try (final var statement = connection.prepareStatement(sql)) { + statement.setLong(1, recipientId.id()); + return Utils.executeQuerySingleRow(statement, resultSet -> resultSet.getBoolean("needs_pni_signature")); + } + } catch (SQLException e) { + throw new RuntimeException("Failed read recipient store", e); + } + } + public void markUnregistered(final Set unregisteredUsers) { logger.debug("Marking {} numbers as unregistered", unregisteredUsers.size()); try (final var connection = database.getConnection()) { -- 2.50.1