create stub message contents for encryption failures
This commit is contained in:
parent
ee1c938f2a
commit
7c820f7b32
|
@ -3,6 +3,7 @@ package im.conversations.android.axolotl;
|
|||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -12,6 +13,7 @@ import im.conversations.android.AbstractAccountService;
|
|||
import im.conversations.android.database.AxolotlDatabaseStore;
|
||||
import im.conversations.android.database.ConversationsDatabase;
|
||||
import im.conversations.android.database.model.Account;
|
||||
import im.conversations.android.transformer.MessageContentWrapper;
|
||||
import im.conversations.android.xmpp.model.axolotl.Encrypted;
|
||||
import im.conversations.android.xmpp.model.axolotl.Header;
|
||||
import im.conversations.android.xmpp.model.axolotl.Key;
|
||||
|
@ -109,6 +111,27 @@ public class AxolotlService extends AbstractAccountService {
|
|||
return session;
|
||||
}
|
||||
|
||||
public boolean decryptEmptyMessage(final BareJid from, final Encrypted encrypted) {
|
||||
Preconditions.checkArgument(
|
||||
!encrypted.hasPayload(), "Use decryptToMessageContent to decrypt payload messages");
|
||||
try {
|
||||
final var payload = decrypt(from, encrypted);
|
||||
return !payload.hasPayload();
|
||||
} catch (final AxolotlDecryptionException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public MessageContentWrapper decryptToMessageContent(
|
||||
final BareJid from, final Encrypted encrypted) {
|
||||
Preconditions.checkArgument(encrypted.hasPayload());
|
||||
try {
|
||||
return MessageContentWrapper.ofAxolotl(decrypt(from, encrypted));
|
||||
} catch (final AxolotlDecryptionException e) {
|
||||
return MessageContentWrapper.ofAxolotlException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public AxolotlPayload decrypt(final Jid from, final Encrypted encrypted)
|
||||
throws AxolotlDecryptionException {
|
||||
final AxolotlPayload axolotlPayload;
|
||||
|
@ -150,10 +173,6 @@ public class AxolotlService extends AbstractAccountService {
|
|||
final Header header = encrypted.getHeader();
|
||||
final Key ourKey = header.getKey(signalProtocolStore.getLocalRegistrationId());
|
||||
if (ourKey == null) {
|
||||
LOGGER.info(
|
||||
"looking for {} in {}",
|
||||
signalProtocolStore.getLocalRegistrationId(),
|
||||
header.getKeys());
|
||||
throw new NotEncryptedForThisDeviceException();
|
||||
}
|
||||
final byte[] keyWithAuthTag;
|
||||
|
|
|
@ -2,6 +2,7 @@ package im.conversations.android.database.model;
|
|||
|
||||
public enum Encryption {
|
||||
OMEMO,
|
||||
FAILURE,
|
||||
CLEARTEXT,
|
||||
PGP
|
||||
}
|
||||
|
|
|
@ -7,5 +7,7 @@ public enum PartType {
|
|||
MODERATION,
|
||||
VIDEO_CALL,
|
||||
AUDIO_CALL,
|
||||
MISSED_CALL
|
||||
MISSED_CALL,
|
||||
NOT_ENCRYPTED_FOR_THIS_DEVICE,
|
||||
DECRYPTION_FAILURE
|
||||
}
|
||||
|
|
|
@ -2,9 +2,12 @@ package im.conversations.android.transformer;
|
|||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import im.conversations.android.axolotl.AxolotlDecryptionException;
|
||||
import im.conversations.android.axolotl.AxolotlPayload;
|
||||
import im.conversations.android.axolotl.NotEncryptedForThisDeviceException;
|
||||
import im.conversations.android.database.model.Encryption;
|
||||
import im.conversations.android.database.model.MessageContent;
|
||||
import im.conversations.android.database.model.PartType;
|
||||
|
@ -23,6 +26,10 @@ public class MessageContentWrapper {
|
|||
Encryption.CLEARTEXT,
|
||||
null);
|
||||
|
||||
private static final List<MessageContent> NOT_ENCRYPTED_FOR_THIS_DEVICE =
|
||||
ImmutableList.of(
|
||||
new MessageContent(null, PartType.NOT_ENCRYPTED_FOR_THIS_DEVICE, null, null));
|
||||
|
||||
public final List<MessageContent> contents;
|
||||
public final Encryption encryption;
|
||||
public final IdentityKey identityKey;
|
||||
|
@ -86,6 +93,29 @@ public class MessageContentWrapper {
|
|||
String.format("%s does not have payload", payload.getClass().getSimpleName()));
|
||||
}
|
||||
|
||||
public static MessageContentWrapper ofAxolotlException(final AxolotlDecryptionException e) {
|
||||
final Throwable cause = Throwables.getRootCause(e);
|
||||
if (cause instanceof NotEncryptedForThisDeviceException) {
|
||||
return new MessageContentWrapper(
|
||||
NOT_ENCRYPTED_FOR_THIS_DEVICE, Encryption.FAILURE, null);
|
||||
} else {
|
||||
return new MessageContentWrapper(
|
||||
ImmutableList.of(
|
||||
new MessageContent(
|
||||
null,
|
||||
PartType.DECRYPTION_FAILURE,
|
||||
exceptionToMessage(cause),
|
||||
null)),
|
||||
Encryption.FAILURE,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
private static String exceptionToMessage(final Throwable throwable) {
|
||||
final String message = throwable.getMessage();
|
||||
return message == null ? throwable.getClass().getSimpleName() : message;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.contents.isEmpty();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.content.Context;
|
|||
import androidx.annotation.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import im.conversations.android.axolotl.AxolotlDecryptionException;
|
||||
import im.conversations.android.axolotl.AxolotlService;
|
||||
import im.conversations.android.database.ConversationsDatabase;
|
||||
import im.conversations.android.database.model.Account;
|
||||
|
@ -131,18 +130,13 @@ public class Transformer {
|
|||
final Encrypted encrypted = transformation.getExtension(Encrypted.class);
|
||||
final MessageContentWrapper contents;
|
||||
if (encrypted != null) {
|
||||
try {
|
||||
final var payload =
|
||||
axolotlService.decrypt(transformation.senderIdentity(), encrypted);
|
||||
if (payload.hasPayload()) {
|
||||
contents = MessageContentWrapper.ofAxolotl(payload);
|
||||
if (encrypted.hasPayload()) {
|
||||
contents =
|
||||
axolotlService.decryptToMessageContent(
|
||||
transformation.senderIdentity(), encrypted);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (final AxolotlDecryptionException e) {
|
||||
LOGGER.error("Could not decrypt message", e);
|
||||
// TODO if message had payload create error message entry
|
||||
return false;
|
||||
return axolotlService.decryptEmptyMessage(
|
||||
transformation.senderIdentity(), encrypted);
|
||||
}
|
||||
} else {
|
||||
// TODO we need to remove fallbacks for reactions, retractions and potentially other
|
||||
|
|
|
@ -97,9 +97,10 @@ public class ArchiveManager extends AbstractManager {
|
|||
final var transformation =
|
||||
this.transformationFactory.create(
|
||||
forwardedMessage, stanzaId, receivedAt, privilegedExtensionBuilder.build());
|
||||
// TODO only when there is something to transform
|
||||
if (transformation.isAnythingToTransform()) {
|
||||
runningQuery.addTransformation(transformation);
|
||||
}
|
||||
}
|
||||
|
||||
private ListenableFuture<Metadata> fetchMetadata(final Jid archive) {
|
||||
final var iq = new Iq(Iq.Type.GET);
|
||||
|
|
|
@ -20,6 +20,7 @@ import im.conversations.android.xmpp.model.mam.Result;
|
|||
import im.conversations.android.xmpp.model.pubsub.event.Event;
|
||||
import im.conversations.android.xmpp.model.stanza.Message;
|
||||
import im.conversations.android.xmpp.model.state.ChatStateNotification;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -71,12 +72,6 @@ public class MessageProcessor extends XmppConnection.Delegate implements Consume
|
|||
return;
|
||||
}
|
||||
|
||||
LOGGER.debug(
|
||||
"Message from {} with {} in level {}",
|
||||
message.getFrom(),
|
||||
message.getExtensionIds(),
|
||||
this.level);
|
||||
|
||||
final var from = message.getFrom();
|
||||
|
||||
final var id = message.getId();
|
||||
|
@ -92,7 +87,9 @@ public class MessageProcessor extends XmppConnection.Delegate implements Consume
|
|||
} else {
|
||||
sendReceipts = true;
|
||||
}
|
||||
if (sendReceipts) {
|
||||
if (sendReceipts
|
||||
&& Arrays.asList(Message.Type.CHAT, Message.Type.NORMAL)
|
||||
.contains(message.getType())) {
|
||||
getManager(ReceiptManager.class)
|
||||
.received(from, id, transformation.deliveryReceiptRequests);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue