2020-12-02 06:39:33 +01:00
|
|
|
package org.session.libsession.messaging.sending_receiving
|
2020-11-25 02:06:41 +01:00
|
|
|
|
2021-04-26 03:14:45 +02:00
|
|
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
2020-12-07 05:22:02 +01:00
|
|
|
import org.session.libsession.messaging.messages.Message
|
2021-02-10 06:48:03 +01:00
|
|
|
import org.session.libsession.messaging.messages.control.*
|
2020-12-07 05:22:02 +01:00
|
|
|
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
2021-03-19 07:08:31 +01:00
|
|
|
import org.session.libsession.utilities.GroupUtil
|
2021-03-09 07:26:29 +01:00
|
|
|
import org.session.libsignal.service.internal.push.PushTransportDetails
|
2020-12-07 05:22:02 +01:00
|
|
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
2021-03-29 05:16:49 +02:00
|
|
|
import org.session.libsignal.utilities.logging.Log
|
2020-12-07 05:22:02 +01:00
|
|
|
|
2020-11-25 02:06:41 +01:00
|
|
|
object MessageReceiver {
|
2021-02-10 06:48:03 +01:00
|
|
|
|
|
|
|
private val lastEncryptionKeyPairRequest = mutableMapOf<String, Long>()
|
|
|
|
|
2021-03-16 06:31:52 +01:00
|
|
|
internal sealed class Error(val description: String) : Exception(description) {
|
2020-12-07 05:22:02 +01:00
|
|
|
object DuplicateMessage: Error("Duplicate message.")
|
2020-12-02 06:39:33 +01:00
|
|
|
object InvalidMessage: Error("Invalid message.")
|
|
|
|
object UnknownMessage: Error("Unknown message type.")
|
|
|
|
object UnknownEnvelopeType: Error("Unknown envelope type.")
|
2021-01-14 01:42:26 +01:00
|
|
|
object NoUserX25519KeyPair: Error("Couldn't find user X25519 key pair.")
|
|
|
|
object NoUserED25519KeyPair: Error("Couldn't find user ED25519 key pair.")
|
2021-02-10 06:48:03 +01:00
|
|
|
object InvalidSignature: Error("Invalid message signature.")
|
2020-12-02 06:39:33 +01:00
|
|
|
object NoData: Error("Received an empty envelope.")
|
|
|
|
object SenderBlocked: Error("Received a message from a blocked user.")
|
|
|
|
object NoThread: Error("Couldn't find thread for message.")
|
|
|
|
object SelfSend: Error("Message addressed at self.")
|
|
|
|
object ParsingFailed : Error("Couldn't parse ciphertext message.")
|
|
|
|
// Shared sender keys
|
|
|
|
object InvalidGroupPublicKey: Error("Invalid group public key.")
|
2021-01-14 01:42:26 +01:00
|
|
|
object NoGroupKeyPair: Error("Missing group key pair.")
|
2020-12-02 06:39:33 +01:00
|
|
|
|
|
|
|
internal val isRetryable: Boolean = when (this) {
|
2021-02-10 06:48:03 +01:00
|
|
|
is DuplicateMessage -> false
|
2020-12-02 06:39:33 +01:00
|
|
|
is InvalidMessage -> false
|
|
|
|
is UnknownMessage -> false
|
|
|
|
is UnknownEnvelopeType -> false
|
2021-02-10 06:48:03 +01:00
|
|
|
is InvalidSignature -> false
|
2020-12-02 06:39:33 +01:00
|
|
|
is NoData -> false
|
|
|
|
is SenderBlocked -> false
|
|
|
|
is SelfSend -> false
|
|
|
|
else -> true
|
|
|
|
}
|
|
|
|
}
|
2020-12-07 05:22:02 +01:00
|
|
|
|
2021-02-10 06:48:03 +01:00
|
|
|
internal fun parse(data: ByteArray, openGroupServerID: Long?, isRetry: Boolean = false): Pair<Message, SignalServiceProtos.Content> {
|
2021-04-26 03:14:45 +02:00
|
|
|
val storage = MessagingModuleConfiguration.shared.storage
|
2020-12-07 05:22:02 +01:00
|
|
|
val userPublicKey = storage.getUserPublicKey()
|
|
|
|
val isOpenGroupMessage = openGroupServerID != null
|
|
|
|
// Parse the envelope
|
|
|
|
val envelope = SignalServiceProtos.Envelope.parseFrom(data)
|
2021-02-10 06:48:03 +01:00
|
|
|
// If the message failed to process the first time around we retry it later (if the error is retryable). In this case the timestamp
|
|
|
|
// will already be in the database but we don't want to treat the message as a duplicate. The isRetry flag is a simple workaround
|
|
|
|
// for this issue.
|
2021-03-19 07:08:31 +01:00
|
|
|
if (storage.isMessageDuplicated(envelope.timestamp, GroupUtil.doubleEncodeGroupID(envelope.source)) && !isRetry) throw Error.DuplicateMessage
|
2020-12-07 05:22:02 +01:00
|
|
|
// Decrypt the contents
|
2021-01-14 01:42:26 +01:00
|
|
|
val ciphertext = envelope.content ?: throw Error.NoData
|
|
|
|
var plaintext: ByteArray? = null
|
|
|
|
var sender: String? = null
|
2020-12-07 05:22:02 +01:00
|
|
|
var groupPublicKey: String? = null
|
|
|
|
if (isOpenGroupMessage) {
|
|
|
|
plaintext = envelope.content.toByteArray()
|
|
|
|
sender = envelope.source
|
|
|
|
} else {
|
|
|
|
when (envelope.type) {
|
|
|
|
SignalServiceProtos.Envelope.Type.UNIDENTIFIED_SENDER -> {
|
2021-04-26 03:14:45 +02:00
|
|
|
val userX25519KeyPair = MessagingModuleConfiguration.shared.storage.getUserX25519KeyPair()
|
2021-01-14 01:42:26 +01:00
|
|
|
val decryptionResult = MessageReceiverDecryption.decryptWithSessionProtocol(ciphertext.toByteArray(), userX25519KeyPair)
|
2021-01-11 01:04:37 +01:00
|
|
|
plaintext = decryptionResult.first
|
|
|
|
sender = decryptionResult.second
|
2020-12-07 05:22:02 +01:00
|
|
|
}
|
|
|
|
SignalServiceProtos.Envelope.Type.CLOSED_GROUP_CIPHERTEXT -> {
|
2021-01-14 01:42:26 +01:00
|
|
|
val hexEncodedGroupPublicKey = envelope.source
|
2021-04-26 03:14:45 +02:00
|
|
|
if (hexEncodedGroupPublicKey == null || !MessagingModuleConfiguration.shared.storage.isClosedGroup(hexEncodedGroupPublicKey)) {
|
2021-01-14 01:42:26 +01:00
|
|
|
throw Error.InvalidGroupPublicKey
|
|
|
|
}
|
2021-04-26 03:14:45 +02:00
|
|
|
val encryptionKeyPairs = MessagingModuleConfiguration.shared.storage.getClosedGroupEncryptionKeyPairs(hexEncodedGroupPublicKey)
|
2021-01-14 01:42:26 +01:00
|
|
|
if (encryptionKeyPairs.isEmpty()) { throw Error.NoGroupKeyPair }
|
|
|
|
// Loop through all known group key pairs in reverse order (i.e. try the latest key pair first (which'll more than
|
|
|
|
// likely be the one we want) but try older ones in case that didn't work)
|
|
|
|
var encryptionKeyPair = encryptionKeyPairs.removeLast()
|
|
|
|
fun decrypt() {
|
|
|
|
try {
|
|
|
|
val decryptionResult = MessageReceiverDecryption.decryptWithSessionProtocol(ciphertext.toByteArray(), encryptionKeyPair)
|
|
|
|
plaintext = decryptionResult.first
|
|
|
|
sender = decryptionResult.second
|
|
|
|
} catch (e: Exception) {
|
|
|
|
if (encryptionKeyPairs.isNotEmpty()) {
|
|
|
|
encryptionKeyPair = encryptionKeyPairs.removeLast()
|
|
|
|
decrypt()
|
|
|
|
} else {
|
|
|
|
throw e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
groupPublicKey = envelope.source
|
2021-02-11 06:57:43 +01:00
|
|
|
decrypt()
|
2020-12-07 05:22:02 +01:00
|
|
|
}
|
|
|
|
else -> throw Error.UnknownEnvelopeType
|
|
|
|
}
|
|
|
|
}
|
2021-03-23 00:00:51 +01:00
|
|
|
// Don't process the envelope any further if the message has been handled already
|
|
|
|
if (storage.isMessageDuplicated(envelope.timestamp, sender!!) && !isRetry) throw Error.DuplicateMessage
|
2020-12-07 05:22:02 +01:00
|
|
|
// Don't process the envelope any further if the sender is blocked
|
2021-01-14 01:42:26 +01:00
|
|
|
if (isBlock(sender!!)) throw Error.SenderBlocked
|
2020-12-07 05:22:02 +01:00
|
|
|
// Parse the proto
|
2021-03-09 07:26:29 +01:00
|
|
|
val proto = SignalServiceProtos.Content.parseFrom(PushTransportDetails.getStrippedPaddingMessageBody(plaintext))
|
2020-12-07 05:22:02 +01:00
|
|
|
// Parse the message
|
|
|
|
val message: Message = ReadReceipt.fromProto(proto) ?:
|
|
|
|
TypingIndicator.fromProto(proto) ?:
|
2021-02-17 06:31:43 +01:00
|
|
|
ClosedGroupControlMessage.fromProto(proto) ?:
|
2021-03-09 06:27:12 +01:00
|
|
|
DataExtractionNotification.fromProto(proto) ?:
|
2020-12-07 05:22:02 +01:00
|
|
|
ExpirationTimerUpdate.fromProto(proto) ?:
|
2021-02-10 06:48:03 +01:00
|
|
|
ConfigurationMessage.fromProto(proto) ?:
|
2020-12-07 05:22:02 +01:00
|
|
|
VisibleMessage.fromProto(proto) ?: throw Error.UnknownMessage
|
2021-02-10 06:48:03 +01:00
|
|
|
// Ignore self sends if needed
|
|
|
|
if (!message.isSelfSendValid && sender == userPublicKey) throw Error.SelfSend
|
|
|
|
// Guard against control messages in open groups
|
2020-12-07 05:22:02 +01:00
|
|
|
if (isOpenGroupMessage && message !is VisibleMessage) throw Error.InvalidMessage
|
2021-02-10 06:48:03 +01:00
|
|
|
// Finish parsing
|
2020-12-07 05:22:02 +01:00
|
|
|
message.sender = sender
|
|
|
|
message.recipient = userPublicKey
|
|
|
|
message.sentTimestamp = envelope.timestamp
|
2021-03-29 05:16:49 +02:00
|
|
|
message.receivedTimestamp = if (envelope.hasServerTimestamp()) envelope.serverTimestamp else System.currentTimeMillis()
|
|
|
|
Log.d("Loki", "time: ${envelope.timestamp}, sent: ${envelope.serverTimestamp}")
|
2020-12-07 05:22:02 +01:00
|
|
|
message.groupPublicKey = groupPublicKey
|
|
|
|
message.openGroupServerMessageID = openGroupServerID
|
2021-02-10 06:48:03 +01:00
|
|
|
// Validate
|
2020-12-07 05:22:02 +01:00
|
|
|
var isValid = message.isValid()
|
2021-03-12 07:15:33 +01:00
|
|
|
if (message is VisibleMessage && !isValid && proto.dataMessage.attachmentsCount != 0) { isValid = true }
|
2020-12-07 05:22:02 +01:00
|
|
|
if (!isValid) { throw Error.InvalidMessage }
|
2021-02-10 06:48:03 +01:00
|
|
|
// Return
|
2020-12-07 05:22:02 +01:00
|
|
|
return Pair(message, proto)
|
|
|
|
}
|
2020-11-25 02:06:41 +01:00
|
|
|
}
|