Search in sources :

Example 31 with SignalServiceAddress

use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project Signal-Android by WhisperSystems.

the class MessageDecryptionUtil method decrypt.

/**
 * Takes a {@link SignalServiceEnvelope} and returns a {@link DecryptionResult}, which has either
 * a plaintext {@link SignalServiceContent} or information about an error that happened.
 *
 * Excluding the data updated in our protocol stores that results from decrypting a message, this
 * method is side-effect free, preferring to return the decryption results to be handled by the
 * caller.
 */
@NonNull
public static DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
    SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci();
    SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireServiceId(), Recipient.self().requireE164());
    SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
    List<Job> jobs = new LinkedList<>();
    if (envelope.isPreKeySignalMessage()) {
        jobs.add(new RefreshPreKeysJob());
    }
    try {
        try {
            return DecryptionResult.forSuccess(cipher.decrypt(envelope), jobs);
        } catch (ProtocolInvalidVersionException e) {
            Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
            return DecryptionResult.forError(MessageState.INVALID_VERSION, toExceptionMetadata(e), jobs);
        } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolUntrustedIdentityException | ProtocolNoSessionException | ProtocolInvalidMessageException e) {
            Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
            Recipient sender = Recipient.external(context, e.getSender());
            if (sender.supportsMessageRetries() && Recipient.self().supportsMessageRetries() && FeatureFlags.retryReceipts()) {
                jobs.add(handleRetry(context, sender, envelope, e));
                postInternalErrorNotification(context);
            } else {
                jobs.add(new AutomaticSessionResetJob(sender.getId(), e.getSenderDevice(), envelope.getTimestamp()));
            }
            return DecryptionResult.forNoop(jobs);
        } catch (ProtocolLegacyMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.LEGACY_MESSAGE, toExceptionMetadata(e), jobs);
        } catch (ProtocolDuplicateMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.DUPLICATE_MESSAGE, toExceptionMetadata(e), jobs);
        } catch (InvalidMetadataVersionException | InvalidMetadataMessageException | InvalidMessageStructureException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forNoop(jobs);
        } catch (SelfSendException e) {
            Log.i(TAG, "Dropping UD message from self.");
            return DecryptionResult.forNoop(jobs);
        } catch (UnsupportedDataMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.UNSUPPORTED_DATA_MESSAGE, toExceptionMetadata(e), jobs);
        }
    } catch (NoSenderException e) {
        Log.w(TAG, "Invalid message, but no sender info!");
        return DecryptionResult.forNoop(jobs);
    }
}
Also used : ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) ProtocolUntrustedIdentityException(org.signal.libsignal.metadata.ProtocolUntrustedIdentityException) ProtocolInvalidVersionException(org.signal.libsignal.metadata.ProtocolInvalidVersionException) InvalidMessageStructureException(org.whispersystems.signalservice.api.InvalidMessageStructureException) SelfSendException(org.signal.libsignal.metadata.SelfSendException) ProtocolInvalidKeyIdException(org.signal.libsignal.metadata.ProtocolInvalidKeyIdException) ProtocolDuplicateMessageException(org.signal.libsignal.metadata.ProtocolDuplicateMessageException) UnsupportedDataMessageException(org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ProtocolLegacyMessageException(org.signal.libsignal.metadata.ProtocolLegacyMessageException) SignalServiceAccountDataStore(org.whispersystems.signalservice.api.SignalServiceAccountDataStore) AutomaticSessionResetJob(org.thoughtcrime.securesms.jobs.AutomaticSessionResetJob) RefreshPreKeysJob(org.thoughtcrime.securesms.jobs.RefreshPreKeysJob) SendRetryReceiptJob(org.thoughtcrime.securesms.jobs.SendRetryReceiptJob) Job(org.thoughtcrime.securesms.jobmanager.Job) RefreshPreKeysJob(org.thoughtcrime.securesms.jobs.RefreshPreKeysJob) ProtocolNoSessionException(org.signal.libsignal.metadata.ProtocolNoSessionException) SignalServiceCipher(org.whispersystems.signalservice.api.crypto.SignalServiceCipher) Recipient(org.thoughtcrime.securesms.recipients.Recipient) AutomaticSessionResetJob(org.thoughtcrime.securesms.jobs.AutomaticSessionResetJob) LinkedList(java.util.LinkedList) InvalidMetadataMessageException(org.signal.libsignal.metadata.InvalidMetadataMessageException) ProtocolInvalidKeyException(org.signal.libsignal.metadata.ProtocolInvalidKeyException) InvalidMetadataVersionException(org.signal.libsignal.metadata.InvalidMetadataVersionException) NonNull(androidx.annotation.NonNull)

Example 32 with SignalServiceAddress

use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.

the class DeviceGroupsInputStream method read.

public DeviceGroup read() throws IOException {
    long detailsLength = readRawVarint32();
    byte[] detailsSerialized = new byte[(int) detailsLength];
    Util.readFully(in, detailsSerialized);
    GroupDetails details = GroupDetails.parseFrom(detailsSerialized);
    if (!details.hasId()) {
        throw new IOException("ID missing on group record!");
    }
    byte[] id = details.getId().toByteArray();
    Optional<String> name = Optional.fromNullable(details.getName());
    List<GroupDetails.Member> members = details.getMembersList();
    Optional<SignalServiceAttachmentStream> avatar = Optional.absent();
    boolean active = details.getActive();
    Optional<Integer> expirationTimer = Optional.absent();
    Optional<String> color = Optional.fromNullable(details.getColor());
    boolean blocked = details.getBlocked();
    if (details.hasAvatar()) {
        long avatarLength = details.getAvatar().getLength();
        InputStream avatarStream = new ChunkedInputStream.LimitedInputStream(in, avatarLength);
        String avatarContentType = details.getAvatar().getContentType();
        avatar = Optional.of(new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, Optional.<String>absent(), false, null));
    }
    if (details.hasExpireTimer() && details.getExpireTimer() > 0) {
        expirationTimer = Optional.of(details.getExpireTimer());
    }
    List<SignalServiceAddress> addressMembers = new ArrayList<>(members.size());
    for (GroupDetails.Member member : members) {
        if (SignalServiceAddress.isValidAddress(member.getUuid(), member.getE164())) {
            addressMembers.add(new SignalServiceAddress(UuidUtil.parseOrNull(member.getUuid()), member.getE164()));
        } else {
            throw new IOException("Missing group member address!");
        }
    }
    return new DeviceGroup(id, name, addressMembers, avatar, active, expirationTimer, color, blocked);
}
Also used : InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) IOException(java.io.IOException) SignalServiceAttachmentStream(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream) GroupDetails(org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupDetails) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress)

Example 33 with SignalServiceAddress

use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.

the class SignalServiceCipher method createSynchronizeMessage.

private SignalServiceSyncMessage createSynchronizeMessage(Metadata metadata, SyncMessage content) throws ProtocolInvalidMessageException, ProtocolInvalidKeyException, UnsupportedDataMessageException {
    if (content.hasSent()) {
        SyncMessage.Sent sentContent = content.getSent();
        SignalServiceDataMessage dataMessage = createSignalServiceMessage(metadata, sentContent.getMessage());
        Optional<SignalServiceAddress> address = SignalServiceAddress.isValidAddress(sentContent.getDestinationUuid(), sentContent.getDestinationE164()) ? Optional.of(new SignalServiceAddress(UuidUtil.parseOrNull(sentContent.getDestinationUuid()), sentContent.getDestinationE164())) : Optional.<SignalServiceAddress>absent();
        Map<SignalServiceAddress, Boolean> unidentifiedStatuses = new HashMap<>();
        if (!address.isPresent() && !dataMessage.getGroupInfo().isPresent()) {
            throw new ProtocolInvalidMessageException(new InvalidMessageException("SyncMessage missing both destination and group ID!"), null, 0);
        }
        for (SyncMessage.Sent.UnidentifiedDeliveryStatus status : sentContent.getUnidentifiedStatusList()) {
            if (SignalServiceAddress.isValidAddress(status.getDestinationUuid(), status.getDestinationE164())) {
                SignalServiceAddress recipient = new SignalServiceAddress(UuidUtil.parseOrNull(status.getDestinationUuid()), status.getDestinationE164());
                unidentifiedStatuses.put(recipient, status.getUnidentified());
            } else {
                Log.w(TAG, "Encountered an invalid UnidentifiedDeliveryStatus in a SentTranscript! Ignoring.");
            }
        }
        return SignalServiceSyncMessage.forSentTranscript(new SentTranscriptMessage(address, sentContent.getTimestamp(), dataMessage, sentContent.getExpirationStartTimestamp(), unidentifiedStatuses, sentContent.getIsRecipientUpdate()));
    }
    if (content.hasRequest()) {
        return SignalServiceSyncMessage.forRequest(new RequestMessage(content.getRequest()));
    }
    if (content.getReadList().size() > 0) {
        List<ReadMessage> readMessages = new LinkedList<>();
        for (SyncMessage.Read read : content.getReadList()) {
            if (SignalServiceAddress.isValidAddress(read.getSenderUuid(), read.getSenderE164())) {
                SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parseOrNull(read.getSenderUuid()), read.getSenderE164());
                readMessages.add(new ReadMessage(address, read.getTimestamp()));
            } else {
                Log.w(TAG, "Encountered an invalid ReadMessage! Ignoring.");
            }
        }
        return SignalServiceSyncMessage.forRead(readMessages);
    }
    if (content.hasViewOnceOpen()) {
        if (SignalServiceAddress.isValidAddress(content.getViewOnceOpen().getSenderUuid(), content.getViewOnceOpen().getSenderE164())) {
            SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parseOrNull(content.getViewOnceOpen().getSenderUuid()), content.getViewOnceOpen().getSenderE164());
            ViewOnceOpenMessage timerRead = new ViewOnceOpenMessage(address, content.getViewOnceOpen().getTimestamp());
            return SignalServiceSyncMessage.forViewOnceOpen(timerRead);
        } else {
            throw new ProtocolInvalidMessageException(new InvalidMessageException("ViewOnceOpen message has no sender!"), null, 0);
        }
    }
    if (content.hasVerified()) {
        if (SignalServiceAddress.isValidAddress(content.getVerified().getDestinationUuid(), content.getVerified().getDestinationE164())) {
            try {
                Verified verified = content.getVerified();
                SignalServiceAddress destination = new SignalServiceAddress(UuidUtil.parseOrNull(verified.getDestinationUuid()), verified.getDestinationE164());
                IdentityKey identityKey = new IdentityKey(verified.getIdentityKey().toByteArray(), 0);
                VerifiedState verifiedState;
                if (verified.getState() == Verified.State.DEFAULT) {
                    verifiedState = VerifiedState.DEFAULT;
                } else if (verified.getState() == Verified.State.VERIFIED) {
                    verifiedState = VerifiedState.VERIFIED;
                } else if (verified.getState() == Verified.State.UNVERIFIED) {
                    verifiedState = VerifiedState.UNVERIFIED;
                } else {
                    throw new ProtocolInvalidMessageException(new InvalidMessageException("Unknown state: " + verified.getState().getNumber()), metadata.getSender().getIdentifier(), metadata.getSenderDevice());
                }
                return SignalServiceSyncMessage.forVerified(new VerifiedMessage(destination, identityKey, verifiedState, System.currentTimeMillis()));
            } catch (InvalidKeyException e) {
                throw new ProtocolInvalidKeyException(e, metadata.getSender().getIdentifier(), metadata.getSenderDevice());
            }
        } else {
            throw new ProtocolInvalidMessageException(new InvalidMessageException("Verified message has no sender!"), null, 0);
        }
    }
    if (content.getStickerPackOperationList().size() > 0) {
        List<StickerPackOperationMessage> operations = new LinkedList<>();
        for (SyncMessage.StickerPackOperation operation : content.getStickerPackOperationList()) {
            byte[] packId = operation.hasPackId() ? operation.getPackId().toByteArray() : null;
            byte[] packKey = operation.hasPackKey() ? operation.getPackKey().toByteArray() : null;
            StickerPackOperationMessage.Type type = null;
            if (operation.hasType()) {
                switch(operation.getType()) {
                    case INSTALL:
                        type = StickerPackOperationMessage.Type.INSTALL;
                        break;
                    case REMOVE:
                        type = StickerPackOperationMessage.Type.REMOVE;
                        break;
                }
            }
            operations.add(new StickerPackOperationMessage(packId, packKey, type));
        }
        return SignalServiceSyncMessage.forStickerPackOperations(operations);
    }
    if (content.hasBlocked()) {
        List<String> numbers = content.getBlocked().getNumbersList();
        List<String> uuids = content.getBlocked().getUuidsList();
        List<SignalServiceAddress> addresses = new ArrayList<>(numbers.size() + uuids.size());
        List<byte[]> groupIds = new ArrayList<>(content.getBlocked().getGroupIdsList().size());
        for (String e164 : numbers) {
            Optional<SignalServiceAddress> address = SignalServiceAddress.fromRaw(null, e164);
            if (address.isPresent()) {
                addresses.add(address.get());
            }
        }
        for (String uuid : uuids) {
            Optional<SignalServiceAddress> address = SignalServiceAddress.fromRaw(uuid, null);
            if (address.isPresent()) {
                addresses.add(address.get());
            }
        }
        for (ByteString groupId : content.getBlocked().getGroupIdsList()) {
            groupIds.add(groupId.toByteArray());
        }
        return SignalServiceSyncMessage.forBlocked(new BlockedListMessage(addresses, groupIds));
    }
    if (content.hasConfiguration()) {
        Boolean readReceipts = content.getConfiguration().hasReadReceipts() ? content.getConfiguration().getReadReceipts() : null;
        Boolean unidentifiedDeliveryIndicators = content.getConfiguration().hasUnidentifiedDeliveryIndicators() ? content.getConfiguration().getUnidentifiedDeliveryIndicators() : null;
        Boolean typingIndicators = content.getConfiguration().hasTypingIndicators() ? content.getConfiguration().getTypingIndicators() : null;
        Boolean linkPreviews = content.getConfiguration().hasLinkPreviews() ? content.getConfiguration().getLinkPreviews() : null;
        return SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.fromNullable(readReceipts), Optional.fromNullable(unidentifiedDeliveryIndicators), Optional.fromNullable(typingIndicators), Optional.fromNullable(linkPreviews)));
    }
    if (content.hasFetchLatest() && content.getFetchLatest().hasType()) {
        switch(content.getFetchLatest().getType()) {
            case LOCAL_PROFILE:
                return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE);
            case STORAGE_MANIFEST:
                return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.STORAGE_MANIFEST);
        }
    }
    return SignalServiceSyncMessage.empty();
}
Also used : ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) HashMap(java.util.HashMap) ByteString(com.google.protobuf.ByteString) ArrayList(java.util.ArrayList) ByteString(com.google.protobuf.ByteString) BlockedListMessage(org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage) Verified(org.whispersystems.signalservice.internal.push.SignalServiceProtos.Verified) ViewOnceOpenMessage(org.whispersystems.signalservice.api.messages.multidevice.ViewOnceOpenMessage) RequestMessage(org.whispersystems.signalservice.api.messages.multidevice.RequestMessage) StickerPackOperationMessage(org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ConfigurationMessage(org.whispersystems.signalservice.api.messages.multidevice.ConfigurationMessage) SentTranscriptMessage(org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage) IdentityKey(org.whispersystems.libsignal.IdentityKey) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) ProtocolInvalidKeyException(org.signal.libsignal.metadata.ProtocolInvalidKeyException) LinkedList(java.util.LinkedList) SyncMessage(org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage) SignalServiceSyncMessage(org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage) ProtocolInvalidKeyException(org.signal.libsignal.metadata.ProtocolInvalidKeyException) SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) ReadMessage(org.whispersystems.signalservice.api.messages.multidevice.ReadMessage) VerifiedState(org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage.VerifiedState) VerifiedMessage(org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage)

Example 34 with SignalServiceAddress

use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.

the class SignalServiceMessageSender method createMultiDeviceSentTranscriptContent.

private byte[] createMultiDeviceSentTranscriptContent(SentTranscriptMessage transcript, Optional<UnidentifiedAccessPair> unidentifiedAccess) throws IOException {
    SignalServiceAddress address = transcript.getDestination().get();
    SendMessageResult result = SendMessageResult.success(address, unidentifiedAccess.isPresent(), true);
    return createMultiDeviceSentTranscriptContent(createMessageContent(transcript.getMessage()), Optional.of(address), transcript.getTimestamp(), Collections.singletonList(result), false);
}
Also used : SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) SendMessageResult(org.whispersystems.signalservice.api.messages.SendMessageResult)

Example 35 with SignalServiceAddress

use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.

the class SignalServiceMessageSender method createMultiDeviceBlockedContent.

private byte[] createMultiDeviceBlockedContent(BlockedListMessage blocked) {
    Content.Builder container = Content.newBuilder();
    SyncMessage.Builder syncMessage = createSyncMessageBuilder();
    SyncMessage.Blocked.Builder blockedMessage = SyncMessage.Blocked.newBuilder();
    for (SignalServiceAddress address : blocked.getAddresses()) {
        if (address.getUuid().isPresent()) {
            blockedMessage.addUuids(address.getUuid().get().toString());
        }
        if (address.getNumber().isPresent()) {
            blockedMessage.addNumbers(address.getNumber().get());
        }
    }
    for (byte[] groupId : blocked.getGroupIds()) {
        blockedMessage.addGroupIds(ByteString.copyFrom(groupId));
    }
    return container.setSyncMessage(syncMessage.setBlocked(blockedMessage)).build().toByteArray();
}
Also used : SyncMessage(org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage) SignalServiceSyncMessage(org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage) Content(org.whispersystems.signalservice.internal.push.SignalServiceProtos.Content) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress)

Aggregations

SignalServiceAddress (org.whispersystems.signalservice.api.push.SignalServiceAddress)113 Recipient (org.thoughtcrime.securesms.recipients.Recipient)44 SignalServiceMessageSender (org.whispersystems.signalservice.api.SignalServiceMessageSender)32 SendMessageResult (org.whispersystems.signalservice.api.messages.SendMessageResult)28 LinkedList (java.util.LinkedList)27 Optional (org.whispersystems.libsignal.util.guava.Optional)23 SignalServiceDataMessage (org.whispersystems.signalservice.api.messages.SignalServiceDataMessage)21 NotPushRegisteredException (org.thoughtcrime.securesms.net.NotPushRegisteredException)20 UnidentifiedAccessPair (org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair)20 NonNull (androidx.annotation.NonNull)18 RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)18 InvalidKeyException (org.whispersystems.libsignal.InvalidKeyException)17 IOException (java.io.IOException)16 ArrayList (java.util.ArrayList)16 SignalServiceAttachment (org.whispersystems.signalservice.api.messages.SignalServiceAttachment)15 List (java.util.List)14 ByteString (com.google.protobuf.ByteString)13 Nullable (androidx.annotation.Nullable)12 UntrustedIdentityException (org.whispersystems.signalservice.api.crypto.UntrustedIdentityException)12 InvalidMessageException (org.whispersystems.libsignal.InvalidMessageException)10