Search in sources :

Example 11 with BadGroupIdException

use of org.thoughtcrime.securesms.groups.BadGroupIdException in project Signal-Android by WhisperSystems.

the class PushProcessMessageQueueJobMigration method migratePushProcessMessageJob.

@NonNull
private static JobData migratePushProcessMessageJob(@NonNull Context context, @NonNull JobData jobData) throws IOException {
    Data data = jobData.getData();
    String suffix = "";
    if (data.getInt("message_state") == 0) {
        SignalServiceContent content = SignalServiceContent.deserialize(Base64.decode(data.getString("message_content")));
        if (content != null && content.getDataMessage().isPresent() && content.getDataMessage().get().getGroupContext().isPresent()) {
            Log.i(TAG, "Migrating a group message.");
            try {
                GroupId groupId = GroupUtil.idFromGroupContext(content.getDataMessage().get().getGroupContext().get());
                Recipient recipient = Recipient.externalGroupExact(context, groupId);
                suffix = recipient.getId().toQueueKey();
            } catch (BadGroupIdException e) {
                Log.w(TAG, "Bad groupId! Using default queue.");
            }
        } else if (content != null) {
            Log.i(TAG, "Migrating an individual message.");
            suffix = RecipientId.from(content.getSender()).toQueueKey();
        }
    } else {
        Log.i(TAG, "Migrating an exception message.");
        String exceptionSender = data.getString("exception_sender");
        GroupId exceptionGroup = GroupId.parseNullableOrThrow(data.getStringOrDefault("exception_groupId", null));
        if (exceptionGroup != null) {
            suffix = Recipient.externalGroupExact(context, exceptionGroup).getId().toQueueKey();
        } else if (exceptionSender != null) {
            suffix = Recipient.external(context, exceptionSender).getId().toQueueKey();
        }
    }
    return jobData.withQueueKey("__PUSH_PROCESS_JOB__" + suffix);
}
Also used : SignalServiceContent(org.whispersystems.signalservice.api.messages.SignalServiceContent) Data(org.thoughtcrime.securesms.jobmanager.Data) Recipient(org.thoughtcrime.securesms.recipients.Recipient) BadGroupIdException(org.thoughtcrime.securesms.groups.BadGroupIdException) GroupId(org.thoughtcrime.securesms.groups.GroupId) NonNull(androidx.annotation.NonNull)

Example 12 with BadGroupIdException

use of org.thoughtcrime.securesms.groups.BadGroupIdException in project Signal-Android by WhisperSystems.

the class MessageContentProcessor method handleMessage.

private void handleMessage(@NonNull SignalServiceContent content, long timestamp, @NonNull Recipient senderRecipient, @NonNull Optional<Long> smsMessageId) throws IOException, GroupChangeBusyException {
    try {
        Recipient threadRecipient = getMessageDestination(content);
        if (shouldIgnore(content, senderRecipient, threadRecipient)) {
            log(content.getTimestamp(), "Ignoring message.");
            return;
        }
        PendingRetryReceiptModel pending = ApplicationDependencies.getPendingRetryReceiptCache().get(senderRecipient.getId(), content.getTimestamp());
        long receivedTime = handlePendingRetry(pending, content, threadRecipient);
        log(String.valueOf(content.getTimestamp()), "Beginning message processing. Sender: " + formatSender(senderRecipient, content));
        if (content.getDataMessage().isPresent()) {
            GroupDatabase groupDatabase = SignalDatabase.groups();
            SignalServiceDataMessage message = content.getDataMessage().get();
            boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent() || message.getMentions().isPresent();
            Optional<GroupId> groupId = GroupUtil.idFromGroupContext(message.getGroupContext());
            boolean isGv2Message = groupId.isPresent() && groupId.get().isV2();
            if (isGv2Message) {
                if (handleGv2PreProcessing(groupId.orNull().requireV2(), content, content.getDataMessage().get().getGroupContext().get().getGroupV2().get(), senderRecipient)) {
                    return;
                }
            }
            MessageId messageId = null;
            if (isInvalidMessage(message))
                handleInvalidMessage(content.getSender(), content.getSenderDevice(), groupId, content.getTimestamp(), smsMessageId);
            else if (message.isEndSession())
                messageId = handleEndSessionMessage(content, smsMessageId, senderRecipient);
            else if (message.isGroupV1Update())
                handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), senderRecipient, threadRecipient, receivedTime);
            else if (message.isExpirationUpdate())
                messageId = handleExpirationUpdate(content, message, smsMessageId, groupId, senderRecipient, threadRecipient, receivedTime);
            else if (message.getReaction().isPresent())
                messageId = handleReaction(content, message, senderRecipient);
            else if (message.getRemoteDelete().isPresent())
                messageId = handleRemoteDelete(content, message, senderRecipient);
            else if (message.getPayment().isPresent())
                handlePayment(content, message, senderRecipient);
            else if (message.getStoryContext().isPresent())
                handleStoryMessage(content);
            else if (isMediaMessage)
                messageId = handleMediaMessage(content, message, smsMessageId, senderRecipient, threadRecipient, receivedTime);
            else if (message.getBody().isPresent())
                messageId = handleTextMessage(content, message, smsMessageId, groupId, senderRecipient, threadRecipient, receivedTime);
            else if (Build.VERSION.SDK_INT > 19 && message.getGroupCallUpdate().isPresent())
                handleGroupCallUpdateMessage(content, message, groupId, senderRecipient);
            if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) {
                handleUnknownGroupMessage(content, message.getGroupContext().get(), senderRecipient);
            }
            if (message.getProfileKey().isPresent()) {
                handleProfileKey(content, message.getProfileKey().get(), senderRecipient);
            }
            if (content.isNeedsReceipt() && messageId != null) {
                handleNeedsDeliveryReceipt(content, message, messageId);
            } else if (!content.isNeedsReceipt()) {
                if (RecipientUtil.shouldHaveProfileKey(context, threadRecipient)) {
                    Log.w(TAG, "Received an unsealed sender message from " + senderRecipient.getId() + ", but they should already have our profile key. Correcting.");
                    if (groupId.isPresent() && groupId.get().isV2()) {
                        Log.i(TAG, "Message was to a GV2 group. Ensuring our group profile keys are up to date.");
                        ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false)).then(GroupV2UpdateSelfProfileKeyJob.withQueueLimits(groupId.get().requireV2())).enqueue();
                    } else if (!threadRecipient.isGroup()) {
                        Log.i(TAG, "Message was to a 1:1. Ensuring this user has our profile key.");
                        ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false)).then(ProfileKeySendJob.create(context, SignalDatabase.threads().getOrCreateThreadIdFor(threadRecipient), true)).enqueue();
                    }
                }
            }
        } else if (content.getSyncMessage().isPresent()) {
            TextSecurePreferences.setMultiDevice(context, true);
            SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
            if (syncMessage.getSent().isPresent())
                handleSynchronizeSentMessage(content, syncMessage.getSent().get(), senderRecipient);
            else if (syncMessage.getRequest().isPresent())
                handleSynchronizeRequestMessage(syncMessage.getRequest().get(), content.getTimestamp());
            else if (syncMessage.getRead().isPresent())
                handleSynchronizeReadMessage(syncMessage.getRead().get(), content.getTimestamp(), senderRecipient);
            else if (syncMessage.getViewed().isPresent())
                handleSynchronizeViewedMessage(syncMessage.getViewed().get(), content.getTimestamp());
            else if (syncMessage.getViewOnceOpen().isPresent())
                handleSynchronizeViewOnceOpenMessage(syncMessage.getViewOnceOpen().get(), content.getTimestamp());
            else if (syncMessage.getVerified().isPresent())
                handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
            else if (syncMessage.getStickerPackOperations().isPresent())
                handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get(), content.getTimestamp());
            else if (syncMessage.getConfiguration().isPresent())
                handleSynchronizeConfigurationMessage(syncMessage.getConfiguration().get(), content.getTimestamp());
            else if (syncMessage.getBlockedList().isPresent())
                handleSynchronizeBlockedListMessage(syncMessage.getBlockedList().get());
            else if (syncMessage.getFetchType().isPresent())
                handleSynchronizeFetchMessage(syncMessage.getFetchType().get(), content.getTimestamp());
            else if (syncMessage.getMessageRequestResponse().isPresent())
                handleSynchronizeMessageRequestResponse(syncMessage.getMessageRequestResponse().get(), content.getTimestamp());
            else if (syncMessage.getOutgoingPaymentMessage().isPresent())
                handleSynchronizeOutgoingPayment(content, syncMessage.getOutgoingPaymentMessage().get());
            else if (syncMessage.getKeys().isPresent())
                handleSynchronizeKeys(syncMessage.getKeys().get(), content.getTimestamp());
            else if (syncMessage.getContacts().isPresent())
                handleSynchronizeContacts(syncMessage.getContacts().get(), content.getTimestamp());
            else
                warn(String.valueOf(content.getTimestamp()), "Contains no known sync types...");
        } else if (content.getCallMessage().isPresent()) {
            log(String.valueOf(content.getTimestamp()), "Got call message...");
            SignalServiceCallMessage message = content.getCallMessage().get();
            Optional<Integer> destinationDeviceId = message.getDestinationDeviceId();
            if (destinationDeviceId.isPresent() && destinationDeviceId.get() != SignalStore.account().getDeviceId()) {
                log(String.valueOf(content.getTimestamp()), String.format(Locale.US, "Ignoring call message that is not for this device! intended: %d, this: %d", destinationDeviceId.get(), SignalStore.account().getDeviceId()));
                return;
            }
            if (message.getOfferMessage().isPresent())
                handleCallOfferMessage(content, message.getOfferMessage().get(), smsMessageId, senderRecipient);
            else if (message.getAnswerMessage().isPresent())
                handleCallAnswerMessage(content, message.getAnswerMessage().get(), senderRecipient);
            else if (message.getIceUpdateMessages().isPresent())
                handleCallIceUpdateMessage(content, message.getIceUpdateMessages().get(), senderRecipient);
            else if (message.getHangupMessage().isPresent())
                handleCallHangupMessage(content, message.getHangupMessage().get(), smsMessageId, senderRecipient);
            else if (message.getBusyMessage().isPresent())
                handleCallBusyMessage(content, message.getBusyMessage().get(), senderRecipient);
            else if (message.getOpaqueMessage().isPresent())
                handleCallOpaqueMessage(content, message.getOpaqueMessage().get(), senderRecipient);
        } else if (content.getReceiptMessage().isPresent()) {
            SignalServiceReceiptMessage message = content.getReceiptMessage().get();
            if (message.isReadReceipt())
                handleReadReceipt(content, message, senderRecipient);
            else if (message.isDeliveryReceipt())
                handleDeliveryReceipt(content, message, senderRecipient);
            else if (message.isViewedReceipt())
                handleViewedReceipt(content, message, senderRecipient);
        } else if (content.getTypingMessage().isPresent()) {
            handleTypingMessage(content, content.getTypingMessage().get(), senderRecipient);
        } else if (content.getDecryptionErrorMessage().isPresent()) {
            handleRetryReceipt(content, content.getDecryptionErrorMessage().get(), senderRecipient);
        } else if (content.getSenderKeyDistributionMessage().isPresent()) {
        // Already handled, here in order to prevent unrecognized message log
        } else {
            warn(String.valueOf(content.getTimestamp()), "Got unrecognized message!");
        }
        resetRecipientToPush(senderRecipient);
        if (pending != null) {
            warn(content.getTimestamp(), "Pending retry was processed. Deleting.");
            ApplicationDependencies.getPendingRetryReceiptCache().delete(pending);
        }
    } catch (StorageFailedException e) {
        warn(String.valueOf(content.getTimestamp()), e);
        handleCorruptMessage(e.getSender(), e.getSenderDevice(), timestamp, smsMessageId);
    } catch (BadGroupIdException e) {
        warn(String.valueOf(content.getTimestamp()), "Ignoring message with bad group id", e);
    }
}
Also used : PendingRetryReceiptModel(org.thoughtcrime.securesms.database.model.PendingRetryReceiptModel) SignalServiceReceiptMessage(org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage) Recipient(org.thoughtcrime.securesms.recipients.Recipient) SignalServiceSyncMessage(org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage) GroupId(org.thoughtcrime.securesms.groups.GroupId) SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) RefreshAttributesJob(org.thoughtcrime.securesms.jobs.RefreshAttributesJob) GroupDatabase(org.thoughtcrime.securesms.database.GroupDatabase) SignalServiceCallMessage(org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage) BadGroupIdException(org.thoughtcrime.securesms.groups.BadGroupIdException) MessageId(org.thoughtcrime.securesms.database.model.MessageId) SyncMessageId(org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId)

Example 13 with BadGroupIdException

use of org.thoughtcrime.securesms.groups.BadGroupIdException in project Signal-Android by WhisperSystems.

the class MessageDecryptionUtil method handleRetry.

@NonNull
private static Job handleRetry(@NonNull Context context, @NonNull Recipient sender, @NonNull SignalServiceEnvelope envelope, @NonNull ProtocolException protocolException) {
    ContentHint contentHint = ContentHint.fromType(protocolException.getContentHint());
    int senderDevice = protocolException.getSenderDevice();
    long receivedTimestamp = System.currentTimeMillis();
    Optional<GroupId> groupId = Optional.absent();
    if (protocolException.getGroupId().isPresent()) {
        try {
            groupId = Optional.of(GroupId.push(protocolException.getGroupId().get()));
        } catch (BadGroupIdException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] Bad groupId!");
        }
    }
    Log.w(TAG, "[" + envelope.getTimestamp() + "] Could not decrypt a message with a type of " + contentHint);
    long threadId;
    if (groupId.isPresent()) {
        Recipient groupRecipient = Recipient.externalPossiblyMigratedGroup(context, groupId.get());
        threadId = SignalDatabase.threads().getOrCreateThreadIdFor(groupRecipient);
    } else {
        threadId = SignalDatabase.threads().getOrCreateThreadIdFor(sender);
    }
    switch(contentHint) {
        case DEFAULT:
            Log.w(TAG, "[" + envelope.getTimestamp() + "] Inserting an error right away because it's " + contentHint);
            SignalDatabase.sms().insertBadDecryptMessage(sender.getId(), senderDevice, envelope.getTimestamp(), receivedTimestamp, threadId);
            break;
        case RESENDABLE:
            Log.w(TAG, "[" + envelope.getTimestamp() + "] Inserting into pending retries store because it's " + contentHint);
            ApplicationDependencies.getPendingRetryReceiptCache().insert(sender.getId(), senderDevice, envelope.getTimestamp(), receivedTimestamp, threadId);
            ApplicationDependencies.getPendingRetryReceiptManager().scheduleIfNecessary();
            break;
        case IMPLICIT:
            Log.w(TAG, "[" + envelope.getTimestamp() + "] Not inserting any error because it's " + contentHint);
            break;
    }
    byte[] originalContent;
    int envelopeType;
    if (protocolException.getUnidentifiedSenderMessageContent().isPresent()) {
        originalContent = protocolException.getUnidentifiedSenderMessageContent().get().getContent();
        envelopeType = protocolException.getUnidentifiedSenderMessageContent().get().getType();
    } else {
        originalContent = envelope.getContent();
        envelopeType = envelopeTypeToCiphertextMessageType(envelope.getType());
    }
    DecryptionErrorMessage decryptionErrorMessage = DecryptionErrorMessage.forOriginalMessage(originalContent, envelopeType, envelope.getTimestamp(), senderDevice);
    return new SendRetryReceiptJob(sender.getId(), groupId, decryptionErrorMessage);
}
Also used : DecryptionErrorMessage(org.whispersystems.libsignal.protocol.DecryptionErrorMessage) ContentHint(org.whispersystems.signalservice.api.crypto.ContentHint) SendRetryReceiptJob(org.thoughtcrime.securesms.jobs.SendRetryReceiptJob) Recipient(org.thoughtcrime.securesms.recipients.Recipient) BadGroupIdException(org.thoughtcrime.securesms.groups.BadGroupIdException) ContentHint(org.whispersystems.signalservice.api.crypto.ContentHint) GroupId(org.thoughtcrime.securesms.groups.GroupId) NonNull(androidx.annotation.NonNull)

Example 14 with BadGroupIdException

use of org.thoughtcrime.securesms.groups.BadGroupIdException in project Signal-Android by WhisperSystems.

the class ChooseNewAdminActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
    super.onCreate(savedInstanceState, ready);
    setContentView(R.layout.choose_new_admin_activity);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    // noinspection ConstantConditions
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    try {
        groupId = GroupId.parse(Objects.requireNonNull(getIntent().getStringExtra(EXTRA_GROUP_ID))).requireV2();
    } catch (BadGroupIdException e) {
        throw new AssertionError(e);
    }
    groupList = findViewById(R.id.choose_new_admin_group_list);
    done = findViewById(R.id.choose_new_admin_done);
    done.setIndeterminateProgressMode(true);
    initializeViewModel();
    groupList.initializeAdapter(this);
    groupList.setRecipientSelectionChangeListener(selection -> viewModel.setSelection(Stream.of(selection).select(GroupMemberEntry.FullMember.class).collect(Collectors.toSet())));
    done.setOnClickListener(v -> {
        done.setClickable(false);
        done.setProgress(50);
        viewModel.updateAdminsAndLeave(this::handleUpdateAndLeaveResult);
    });
}
Also used : BadGroupIdException(org.thoughtcrime.securesms.groups.BadGroupIdException) Toolbar(androidx.appcompat.widget.Toolbar)

Example 15 with BadGroupIdException

use of org.thoughtcrime.securesms.groups.BadGroupIdException in project Signal-Android by signalapp.

the class ChooseNewAdminActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
    super.onCreate(savedInstanceState, ready);
    setContentView(R.layout.choose_new_admin_activity);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    // noinspection ConstantConditions
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    try {
        groupId = GroupId.parse(Objects.requireNonNull(getIntent().getStringExtra(EXTRA_GROUP_ID))).requireV2();
    } catch (BadGroupIdException e) {
        throw new AssertionError(e);
    }
    groupList = findViewById(R.id.choose_new_admin_group_list);
    done = findViewById(R.id.choose_new_admin_done);
    done.setIndeterminateProgressMode(true);
    initializeViewModel();
    groupList.initializeAdapter(this);
    groupList.setRecipientSelectionChangeListener(selection -> viewModel.setSelection(Stream.of(selection).select(GroupMemberEntry.FullMember.class).collect(Collectors.toSet())));
    done.setOnClickListener(v -> {
        done.setClickable(false);
        done.setProgress(50);
        viewModel.updateAdminsAndLeave(this::handleUpdateAndLeaveResult);
    });
}
Also used : BadGroupIdException(org.thoughtcrime.securesms.groups.BadGroupIdException) Toolbar(androidx.appcompat.widget.Toolbar)

Aggregations

BadGroupIdException (org.thoughtcrime.securesms.groups.BadGroupIdException)16 GroupId (org.thoughtcrime.securesms.groups.GroupId)10 Recipient (org.thoughtcrime.securesms.recipients.Recipient)10 NonNull (androidx.annotation.NonNull)6 ContentValues (android.content.ContentValues)2 Context (android.content.Context)2 TextView (android.widget.TextView)2 WorkerThread (androidx.annotation.WorkerThread)2 Toolbar (androidx.appcompat.widget.Toolbar)2 RecyclerView (androidx.recyclerview.widget.RecyclerView)2 InvalidInputException (org.signal.zkgroup.InvalidInputException)2 GroupMasterKey (org.signal.zkgroup.groups.GroupMasterKey)2 GroupDatabase (org.thoughtcrime.securesms.database.GroupDatabase)2 SyncMessageId (org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId)2 MessageId (org.thoughtcrime.securesms.database.model.MessageId)2 PendingRetryReceiptModel (org.thoughtcrime.securesms.database.model.PendingRetryReceiptModel)2 Data (org.thoughtcrime.securesms.jobmanager.Data)2 NetworkConstraint (org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint)2 RefreshAttributesJob (org.thoughtcrime.securesms.jobs.RefreshAttributesJob)2 SendRetryReceiptJob (org.thoughtcrime.securesms.jobs.SendRetryReceiptJob)2