]> nmode's Git Repositories - signal-cli/blobdiff - lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java
Update libsignal-service-java
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / IncomingMessageHandler.java
index cf9c43a2a6dcd99bad2fc38768cb94c5d8cb690f..dd9cb38fa5e9dd431b3216ffc699d87814c8fb85 100644 (file)
@@ -6,7 +6,6 @@ import org.asamk.signal.manager.actions.RefreshPreKeysAction;
 import org.asamk.signal.manager.actions.RenewSessionAction;
 import org.asamk.signal.manager.actions.ResendMessageAction;
 import org.asamk.signal.manager.actions.RetrieveProfileAction;
-import org.asamk.signal.manager.actions.RetrieveStorageDataAction;
 import org.asamk.signal.manager.actions.SendGroupInfoAction;
 import org.asamk.signal.manager.actions.SendGroupInfoRequestAction;
 import org.asamk.signal.manager.actions.SendProfileKeyAction;
@@ -17,12 +16,12 @@ import org.asamk.signal.manager.actions.SendSyncConfigurationAction;
 import org.asamk.signal.manager.actions.SendSyncContactsAction;
 import org.asamk.signal.manager.actions.SendSyncGroupsAction;
 import org.asamk.signal.manager.actions.SendSyncKeysAction;
+import org.asamk.signal.manager.actions.SyncStorageDataAction;
 import org.asamk.signal.manager.actions.UpdateAccountAttributesAction;
 import org.asamk.signal.manager.api.GroupId;
 import org.asamk.signal.manager.api.GroupNotFoundException;
 import org.asamk.signal.manager.api.MessageEnvelope;
 import org.asamk.signal.manager.api.Pair;
-import org.asamk.signal.manager.api.Profile;
 import org.asamk.signal.manager.api.ReceiveConfig;
 import org.asamk.signal.manager.api.StickerPackId;
 import org.asamk.signal.manager.api.TrustLevel;
@@ -32,6 +31,7 @@ import org.asamk.signal.manager.internal.SignalDependencies;
 import org.asamk.signal.manager.jobs.RetrieveStickerPackJob;
 import org.asamk.signal.manager.storage.SignalAccount;
 import org.asamk.signal.manager.storage.groups.GroupInfoV1;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
 import org.asamk.signal.manager.storage.recipients.RecipientId;
 import org.asamk.signal.manager.storage.stickers.StickerPack;
 import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
@@ -41,6 +41,7 @@ import org.signal.libsignal.metadata.ProtocolNoSessionException;
 import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
 import org.signal.libsignal.metadata.SelfSendException;
 import org.signal.libsignal.protocol.InvalidMessageException;
+import org.signal.libsignal.protocol.UsePqRatchet;
 import org.signal.libsignal.protocol.groups.GroupSessionBuilder;
 import org.signal.libsignal.protocol.message.DecryptionErrorMessage;
 import org.signal.libsignal.zkgroup.InvalidInputException;
@@ -64,6 +65,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSy
 import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
 import org.whispersystems.signalservice.api.push.ServiceId;
 import org.whispersystems.signalservice.api.push.ServiceId.ACI;
+import org.whispersystems.signalservice.api.push.ServiceIdType;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.internal.push.Envelope;
 import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException;
@@ -100,9 +102,11 @@ public final class IncomingMessageHandler {
         SignalServiceContent content = null;
         if (!envelope.isReceipt()) {
             account.getIdentityKeyStore().setRetryingDecryption(true);
+            final var destination = getDestination(envelope).serviceId();
             try {
-                final var cipherResult = dependencies.getCipher()
-                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp());
+                final var cipherResult = dependencies.getCipher(destination == null
+                                || destination.equals(account.getAci()) ? ServiceIdType.ACI : ServiceIdType.PNI)
+                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp(), UsePqRatchet.NO);
                 content = validate(envelope.getProto(), cipherResult, envelope.getServerDeliveredTimestamp());
                 if (content == null) {
                     return new Pair<>(List.of(), null);
@@ -136,9 +140,11 @@ public final class IncomingMessageHandler {
                 // uuid in envelope is sent by server
                 .ifPresent(serviceId -> account.getRecipientResolver().resolveRecipient(serviceId));
         if (!envelope.isReceipt()) {
+            final var destination = getDestination(envelope).serviceId();
             try {
-                final var cipherResult = dependencies.getCipher()
-                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp());
+                final var cipherResult = dependencies.getCipher(destination == null
+                                || destination.equals(account.getAci()) ? ServiceIdType.ACI : ServiceIdType.PNI)
+                        .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp(), UsePqRatchet.NO);
                 content = validate(envelope.getProto(), cipherResult, envelope.getServerDeliveredTimestamp());
                 if (content == null) {
                     return new Pair<>(List.of(), null);
@@ -152,34 +158,22 @@ public final class IncomingMessageHandler {
             } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException |
                      ProtocolInvalidMessageException e) {
                 logger.debug("Failed to decrypt incoming message", e);
+                if (e instanceof ProtocolInvalidKeyIdException) {
+                    actions.add(RefreshPreKeysAction.create());
+                }
                 final var sender = account.getRecipientResolver().resolveRecipient(e.getSender());
                 if (context.getContactHelper().isContactBlocked(sender)) {
                     logger.debug("Received invalid message from blocked contact, ignoring.");
                 } else {
-                    final var senderProfile = context.getProfileHelper().getRecipientProfile(sender);
-                    final var selfProfile = context.getProfileHelper().getSelfProfile();
                     var serviceId = ServiceId.parseOrNull(e.getSender());
-                    if (serviceId == null) {
-                        // Workaround for libsignal-client issue #492
-                        serviceId = account.getRecipientAddressResolver()
-                                .resolveRecipientAddress(sender)
-                                .serviceId()
-                                .orElse(null);
-                    }
                     if (serviceId != null) {
                         final var isSelf = sender.equals(account.getSelfRecipientId())
                                 && e.getSenderDevice() == account.getDeviceId();
-                        final var isSenderSenderKeyCapable = senderProfile != null && senderProfile.getCapabilities()
-                                .contains(Profile.Capability.senderKey);
-                        final var isSelfSenderKeyCapable = selfProfile != null && selfProfile.getCapabilities()
-                                .contains(Profile.Capability.senderKey);
-                        final var destination = getDestination(envelope).serviceId();
-                        if (!isSelf && isSenderSenderKeyCapable && isSelfSenderKeyCapable) {
+                        logger.debug("Received invalid message, queuing renew session action.");
+                        actions.add(new RenewSessionAction(sender, serviceId, destination));
+                        if (!isSelf) {
                             logger.debug("Received invalid message, requesting message resend.");
-                            actions.add(new SendRetryMessageRequestAction(sender, serviceId, e, envelope, destination));
-                        } else {
-                            logger.debug("Received invalid message, queuing renew session action.");
-                            actions.add(new RenewSessionAction(sender, serviceId, destination));
+                            actions.add(new SendRetryMessageRequestAction(sender, e, envelope));
                         }
                     } else {
                         logger.debug("Received invalid message from invalid sender: {}", e.getSender());
@@ -200,11 +194,13 @@ public final class IncomingMessageHandler {
     }
 
     private SignalServiceContent validate(
-            Envelope envelope, SignalServiceCipherResult cipherResult, long serverDeliveredTimestamp
+            Envelope envelope,
+            SignalServiceCipherResult cipherResult,
+            long serverDeliveredTimestamp
     ) throws ProtocolInvalidKeyException, ProtocolInvalidMessageException, UnsupportedDataMessageException, InvalidMessageStructureException {
         final var content = cipherResult.getContent();
         final var envelopeMetadata = cipherResult.getMetadata();
-        final var validationResult = EnvelopeContentValidator.INSTANCE.validate(envelope, content);
+        final var validationResult = EnvelopeContentValidator.INSTANCE.validate(envelope, content, account.getAci());
 
         if (validationResult instanceof EnvelopeContentValidator.Result.Invalid v) {
             logger.warn("Invalid content! {}", v.getReason(), v.getThrowable());
@@ -290,7 +286,9 @@ public final class IncomingMessageHandler {
     }
 
     public List<HandleAction> handleMessage(
-            SignalServiceEnvelope envelope, SignalServiceContent content, ReceiveConfig receiveConfig
+            SignalServiceEnvelope envelope,
+            SignalServiceContent content,
+            ReceiveConfig receiveConfig
     ) {
         var actions = new ArrayList<HandleAction>();
         final var senderDeviceAddress = getSender(envelope, content);
@@ -299,6 +297,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()) {
@@ -385,7 +389,8 @@ public final class IncomingMessageHandler {
     }
 
     private boolean handlePniSignatureMessage(
-            final SignalServicePniSignatureMessage message, final SignalServiceAddress senderAddress
+            final SignalServicePniSignatureMessage message,
+            final SignalServiceAddress senderAddress
     ) {
         final var aci = senderAddress.getServiceId();
         final var aciIdentity = account.getIdentityKeyStore().getIdentityInfo(aci);
@@ -511,6 +516,7 @@ public final class IncomingMessageHandler {
             if (rm.isConfigurationRequest()) {
                 actions.add(SendSyncConfigurationAction.create());
             }
+            actions.add(SyncStorageDataAction.create());
         }
         if (syncMessage.getGroups().isPresent()) {
             try {
@@ -523,12 +529,12 @@ public final class IncomingMessageHandler {
         }
         if (syncMessage.getBlockedList().isPresent()) {
             final var blockedListMessage = syncMessage.getBlockedList().get();
-            for (var address : blockedListMessage.getAddresses()) {
-                context.getContactHelper()
-                        .setContactBlocked(account.getRecipientResolver().resolveRecipient(address), true);
+            for (var individual : blockedListMessage.individuals) {
+                final var address = new RecipientAddress(individual.getAci(), individual.getE164());
+                final var recipientId = account.getRecipientResolver().resolveRecipient(address);
+                context.getContactHelper().setContactBlocked(recipientId, true);
             }
-            for (var groupId : blockedListMessage.getGroupIds()
-                    .stream()
+            for (var groupId : blockedListMessage.groupIds.stream()
                     .map(GroupId::unknownVersion)
                     .collect(Collectors.toSet())) {
                 try {
@@ -578,15 +584,28 @@ public final class IncomingMessageHandler {
         if (syncMessage.getFetchType().isPresent()) {
             switch (syncMessage.getFetchType().get()) {
                 case LOCAL_PROFILE -> actions.add(new RetrieveProfileAction(account.getSelfRecipientId()));
-                case STORAGE_MANIFEST -> actions.add(RetrieveStorageDataAction.create());
+                case STORAGE_MANIFEST -> actions.add(SyncStorageDataAction.create());
             }
         }
         if (syncMessage.getKeys().isPresent()) {
             final var keysMessage = syncMessage.getKeys().get();
-            if (keysMessage.getStorageService().isPresent()) {
-                final var storageKey = keysMessage.getStorageService().get();
+            if (keysMessage.getAccountEntropyPool() != null) {
+                final var aep = keysMessage.getAccountEntropyPool();
+                account.setAccountEntropyPool(aep);
+                actions.add(SyncStorageDataAction.create());
+            } else if (keysMessage.getMaster() != null) {
+                final var masterKey = keysMessage.getMaster();
+                account.setMasterKey(masterKey);
+                actions.add(SyncStorageDataAction.create());
+            } else if (keysMessage.getStorageService() != null) {
+                final var storageKey = keysMessage.getStorageService();
                 account.setStorageKey(storageKey);
-                actions.add(RetrieveStorageDataAction.create());
+                actions.add(SyncStorageDataAction.create());
+            }
+            if (keysMessage.getMediaRootBackupKey() != null) {
+                final var mrb = keysMessage.getMediaRootBackupKey();
+                account.setMediaRootBackupKey(mrb);
+                actions.add(SyncStorageDataAction.create());
             }
         }
         if (syncMessage.getConfiguration().isPresent()) {
@@ -800,7 +819,9 @@ public final class IncomingMessageHandler {
                 }
             } else if (conversationPartnerAddress != null) {
                 context.getContactHelper()
-                        .setExpirationTimer(conversationPartnerAddress.recipientId(), message.getExpiresInSeconds());
+                        .setExpirationTimer(conversationPartnerAddress.recipientId(),
+                                message.getExpiresInSeconds(),
+                                message.getExpireTimerVersion());
             }
         }
         if (!ignoreAttachments) {
@@ -861,7 +882,9 @@ public final class IncomingMessageHandler {
     }
 
     private List<HandleAction> handleSignalServiceStoryMessage(
-            SignalServiceStoryMessage message, RecipientId source, boolean ignoreAttachments
+            SignalServiceStoryMessage message,
+            RecipientId source,
+            boolean ignoreAttachments
     ) {
         var actions = new ArrayList<HandleAction>();
         if (message.getGroupContext().isPresent()) {
@@ -941,16 +964,12 @@ public final class IncomingMessageHandler {
     }
 
     private DeviceAddress getDestination(SignalServiceEnvelope envelope) {
-        if (!envelope.hasDestinationUuid()) {
-            return new DeviceAddress(account.getSelfRecipientId(), account.getAci(), account.getDeviceId());
-        }
-        final var addressOptional = SignalServiceAddress.fromRaw(envelope.getDestinationServiceId(), null);
-        if (addressOptional.isEmpty()) {
+        final var destination = envelope.getDestinationServiceId();
+        if (destination == null || destination.isUnknown()) {
             return new DeviceAddress(account.getSelfRecipientId(), account.getAci(), account.getDeviceId());
         }
-        final var address = addressOptional.get();
-        return new DeviceAddress(account.getRecipientResolver().resolveRecipient(address),
-                address.getServiceId(),
+        return new DeviceAddress(account.getRecipientResolver().resolveRecipient(destination),
+                destination,
                 account.getDeviceId());
     }