|
|
|
@ -4,13 +4,12 @@ import { getEnvelopeId } from './common';
|
|
|
|
|
|
|
|
|
|
import { removeFromCache, updateCache } from './cache';
|
|
|
|
|
import { SignalService } from '../protobuf';
|
|
|
|
|
import { toNumber } from 'lodash';
|
|
|
|
|
import * as Lodash from 'lodash';
|
|
|
|
|
import * as libsession from '../session';
|
|
|
|
|
import { handleSessionRequestMessage } from './sessionHandling';
|
|
|
|
|
import { handlePairingAuthorisationMessage } from './multidevice';
|
|
|
|
|
import {
|
|
|
|
|
MediumGroupRequestKeysMessage,
|
|
|
|
|
ReceiptMessage,
|
|
|
|
|
} from '../session/messages/outgoing';
|
|
|
|
|
import { MultiDeviceProtocol, SessionProtocol } from '../session/protocols';
|
|
|
|
|
import { PubKey } from '../session/types';
|
|
|
|
@ -20,6 +19,7 @@ import { onError } from './errors';
|
|
|
|
|
import ByteBuffer from 'bytebuffer';
|
|
|
|
|
import { BlockedNumberController } from '../util/blockedNumberController';
|
|
|
|
|
import { decryptWithSenderKey } from '../session/medium_group/ratchet';
|
|
|
|
|
import { StringUtils } from '../session/utils';
|
|
|
|
|
|
|
|
|
|
export async function handleContentMessage(envelope: EnvelopePlus) {
|
|
|
|
|
const plaintext = await decrypt(envelope, envelope.content);
|
|
|
|
@ -188,12 +188,6 @@ async function decryptUnidentifiedSender(
|
|
|
|
|
envelope.type = SignalService.Envelope.Type.FALLBACK_MESSAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const blocked = await isBlocked(sender.getName());
|
|
|
|
|
if (blocked) {
|
|
|
|
|
window.log.info('Dropping blocked message after sealed sender decryption');
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Here we take this sender information and attach it back to the envelope
|
|
|
|
|
// to make the rest of the app work properly.
|
|
|
|
|
|
|
|
|
@ -336,6 +330,50 @@ async function decrypt(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function shouldDropBlockedUserMessage(content: SignalService.Content): boolean {
|
|
|
|
|
// Even if the user is blocked, we should allow the message if:
|
|
|
|
|
// - it is a group message AND
|
|
|
|
|
// - the group exists already on the db (to not join a closed group created by a blocked user) AND
|
|
|
|
|
// - the group is not blocked AND
|
|
|
|
|
// - the message is only control (no body/attachments/quote/groupInvitation/contact/preview)
|
|
|
|
|
|
|
|
|
|
if (!content?.dataMessage?.group?.id) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
const groupId = StringUtils.decode(content.dataMessage.group.id, 'utf8');
|
|
|
|
|
|
|
|
|
|
const groupConvo = window.ConversationController.get(groupId);
|
|
|
|
|
if (!groupConvo) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (groupConvo.isBlocked()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// first check that dataMessage is the only field set in the Content
|
|
|
|
|
let msgWithoutDataMessage = Lodash.pickBy(
|
|
|
|
|
content,
|
|
|
|
|
(_, key) => key !== 'dataMessage' && key !== 'toJSON'
|
|
|
|
|
);
|
|
|
|
|
msgWithoutDataMessage = Lodash.pickBy(msgWithoutDataMessage, Lodash.identity);
|
|
|
|
|
|
|
|
|
|
const isMessageDataMessageOnly = Lodash.isEmpty(msgWithoutDataMessage);
|
|
|
|
|
if (!isMessageDataMessageOnly) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
const data = content.dataMessage;
|
|
|
|
|
const isControlDataMessageOnly =
|
|
|
|
|
!data.body &&
|
|
|
|
|
!data.contact?.length &&
|
|
|
|
|
!data.preview?.length &&
|
|
|
|
|
!data.attachments?.length &&
|
|
|
|
|
!data.groupInvitation &&
|
|
|
|
|
!data.quote;
|
|
|
|
|
|
|
|
|
|
return !isControlDataMessageOnly;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function innerHandleContentMessage(
|
|
|
|
|
envelope: EnvelopePlus,
|
|
|
|
|
plaintext: ArrayBuffer
|
|
|
|
@ -344,6 +382,17 @@ export async function innerHandleContentMessage(
|
|
|
|
|
|
|
|
|
|
const content = SignalService.Content.decode(new Uint8Array(plaintext));
|
|
|
|
|
|
|
|
|
|
const blocked = await isBlocked(envelope.source);
|
|
|
|
|
if (blocked) {
|
|
|
|
|
// We want to allow a blocked user message if that's a control message for a known group and the group is not blocked
|
|
|
|
|
if (shouldDropBlockedUserMessage(content)) {
|
|
|
|
|
window.log.info('Dropping blocked user message');
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
window.log.info('Allowing group-control message only from blocked user');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { FALLBACK_MESSAGE } = SignalService.Envelope.Type;
|
|
|
|
|
|
|
|
|
|
await ConversationController.getOrCreateAndWait(envelope.source, 'private');
|
|
|
|
@ -451,14 +500,14 @@ async function handleReceiptMessage(
|
|
|
|
|
const results = [];
|
|
|
|
|
if (type === SignalService.ReceiptMessage.Type.DELIVERY) {
|
|
|
|
|
for (const ts of timestamp) {
|
|
|
|
|
const promise = onDeliveryReceipt(envelope.source, toNumber(ts));
|
|
|
|
|
const promise = onDeliveryReceipt(envelope.source, Lodash.toNumber(ts));
|
|
|
|
|
results.push(promise);
|
|
|
|
|
}
|
|
|
|
|
} else if (type === SignalService.ReceiptMessage.Type.READ) {
|
|
|
|
|
for (const ts of timestamp) {
|
|
|
|
|
const promise = onReadReceipt(
|
|
|
|
|
toNumber(envelope.timestamp),
|
|
|
|
|
toNumber(ts),
|
|
|
|
|
Lodash.toNumber(envelope.timestamp),
|
|
|
|
|
Lodash.toNumber(ts),
|
|
|
|
|
envelope.source
|
|
|
|
|
);
|
|
|
|
|
results.push(promise);
|
|
|
|
@ -494,8 +543,8 @@ async function handleTypingMessage(
|
|
|
|
|
await removeFromCache(envelope);
|
|
|
|
|
|
|
|
|
|
if (envelope.timestamp && timestamp) {
|
|
|
|
|
const envelopeTimestamp = toNumber(envelope.timestamp);
|
|
|
|
|
const typingTimestamp = toNumber(timestamp);
|
|
|
|
|
const envelopeTimestamp = Lodash.toNumber(envelope.timestamp);
|
|
|
|
|
const typingTimestamp = Lodash.toNumber(timestamp);
|
|
|
|
|
|
|
|
|
|
if (typingTimestamp !== envelopeTimestamp) {
|
|
|
|
|
window.log.warn(
|
|
|
|
|