Automatically recover from bad encrypted messages.

This commit is contained in:
Greyson Parrelli
2021-01-08 10:23:46 -05:00
parent adea15df10
commit 728f1707b6
22 changed files with 331 additions and 51 deletions

View File

@@ -149,6 +149,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract Optional<InsertResult> insertMessageInbox(IncomingMediaMessage retrieved, String contentLocation, long threadId) throws MmsException;
public abstract Pair<Long, Long> insertMessageInbox(@NonNull NotificationInd notification, int subscriptionId);
public abstract Optional<InsertResult> insertSecureDecryptedMessageInbox(IncomingMediaMessage retrieved, long threadId) throws MmsException;
public abstract @NonNull InsertResult insertDecryptionFailedMessage(@NonNull RecipientId recipientId, long senderDeviceId, long sentTimestamp);
public abstract long insertMessageOutbox(long threadId, OutgoingTextMessage message, boolean forceSms, long date, InsertListener insertListener);
public abstract long insertMessageOutbox(@NonNull OutgoingMediaMessage message, long threadId, boolean forceSms, @Nullable SmsDatabase.InsertListener insertListener) throws MmsException;
public abstract long insertMessageOutbox(@NonNull OutgoingMediaMessage message, long threadId, boolean forceSms, int defaultReceiptStatus, @Nullable SmsDatabase.InsertListener insertListener) throws MmsException;

View File

@@ -1383,6 +1383,11 @@ public class MmsDatabase extends MessageDatabase {
return new Pair<>(messageId, threadId);
}
@Override
public @NonNull InsertResult insertDecryptionFailedMessage(@NonNull RecipientId recipientId, long senderDeviceId, long sentTimestamp) {
throw new UnsupportedOperationException();
}
@Override
public void markIncomingNotificationReceived(long threadId) {
notifyConversationListeners(threadId);

View File

@@ -1038,7 +1038,7 @@ public class SmsDatabase extends MessageDatabase {
if (groupRecipient == null) threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
else threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
ContentValues values = new ContentValues(6);
ContentValues values = new ContentValues();
values.put(RECIPIENT_ID, message.getSender().serialize());
values.put(ADDRESS_DEVICE_ID, message.getSenderDeviceId());
values.put(DATE_RECEIVED, System.currentTimeMillis());
@@ -1093,6 +1093,36 @@ public class SmsDatabase extends MessageDatabase {
return insertMessageInbox(message, Types.BASE_INBOX_TYPE);
}
@Override
public @NonNull InsertResult insertDecryptionFailedMessage(@NonNull RecipientId recipientId, long senderDeviceId, long sentTimestamp) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.resolved(recipientId));
long type = Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT;
type = type & (Types.TOTAL_MASK - Types.ENCRYPTION_MASK) | Types.ENCRYPTION_REMOTE_FAILED_BIT;
ContentValues values = new ContentValues();
values.put(RECIPIENT_ID, recipientId.serialize());
values.put(ADDRESS_DEVICE_ID, senderDeviceId);
values.put(DATE_RECEIVED, System.currentTimeMillis());
values.put(DATE_SENT, sentTimestamp);
values.put(DATE_SERVER, -1);
values.put(READ, 0);
values.put(TYPE, type);
values.put(THREAD_ID, threadId);
long messageId = db.insert(TABLE_NAME, null, values);
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
notifyConversationListeners(threadId);
ApplicationDependencies.getJobManager().add(new TrimThreadJob(threadId));
return new InsertResult(messageId, threadId);
}
@Override
public long insertMessageOutbox(long threadId, OutgoingTextMessage message,
boolean forceSms, long date, InsertListener insertListener)

View File

@@ -191,6 +191,8 @@ public abstract class MessageRecord extends DisplayRecord {
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
} else if (isGroupV1MigrationEvent()) {
return getGroupMigrationEventDescription(context);
} else if (isFailedDecryptionType()) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_chat_session_refreshed), R.drawable.ic_refresh_16);
}
return null;
@@ -436,7 +438,7 @@ public abstract class MessageRecord extends DisplayRecord {
public boolean isUpdate() {
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
isProfileChange() || isGroupV1MigrationEvent();
isProfileChange() || isGroupV1MigrationEvent() || isFailedDecryptionType();
}
public boolean isMediaPending() {
@@ -471,6 +473,10 @@ public abstract class MessageRecord extends DisplayRecord {
return isFailed() && ((getRecipient().isPushGroup() && hasNetworkFailures()) || !isIdentityMismatchFailure());
}
public boolean isFailedDecryptionType() {
return MmsSmsColumns.Types.isFailedDecryptType(type);
}
protected static SpannableString emphasisAdded(String sequence) {
SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new RelativeSizeSpan(0.9f), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

View File

@@ -66,7 +66,7 @@ public class SmsMessageRecord extends MessageRecord {
@Override
public SpannableString getDisplayBody(@NonNull Context context) {
if (SmsDatabase.Types.isFailedDecryptType(type)) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
return emphasisAdded(context.getString(R.string.MessageRecord_chat_session_refreshed));
} else if (isCorruptedKeyExchange()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_received_corrupted_key_exchange_message));
} else if (isInvalidVersionKeyExchange()) {