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;
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;
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;
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;
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);
// 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);
} 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());
}
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());
}
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);
}
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);
}
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 {
}
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(SyncStorageDataAction.create());
}
- if (keysMessage.getMaster().isPresent()) {
- final var masterKey = keysMessage.getMaster().get();
- account.setMasterKey(masterKey);
+ if (keysMessage.getMediaRootBackupKey() != null) {
+ final var mrb = keysMessage.getMediaRootBackupKey();
+ account.setMediaRootBackupKey(mrb);
actions.add(SyncStorageDataAction.create());
}
}
}
} else if (conversationPartnerAddress != null) {
context.getContactHelper()
- .setExpirationTimer(conversationPartnerAddress.recipientId(), message.getExpiresInSeconds());
+ .setExpirationTimer(conversationPartnerAddress.recipientId(),
+ message.getExpiresInSeconds(),
+ message.getExpireTimerVersion());
}
}
if (!ignoreAttachments) {
}
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()) {
}
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());
}