Add: LID support with lid-map and migrations of sessions (#1694)
* fix: add lid-map logic * fix: lint and simplified version * fix: single device migration * fix: lid map discovery * fix: lint * fix: lid migration in socket connection * fix: lint * fix: decode-wa-message consistency * fix: yarn lock * fix: lint * fix: retry logic * fix: logger level
This commit is contained in:
@@ -10,11 +10,51 @@ import {
|
||||
isJidNewsletter,
|
||||
isJidStatusBroadcast,
|
||||
isJidUser,
|
||||
isLidUser
|
||||
isLidUser,
|
||||
jidDecode,
|
||||
jidEncode,
|
||||
jidNormalizedUser
|
||||
} from '../WABinary'
|
||||
import { unpadRandomMax16 } from './generics'
|
||||
import type { ILogger } from './logger'
|
||||
|
||||
const getDecryptionJid = async (sender: string, repository: SignalRepository): Promise<string> => {
|
||||
if (!sender.includes('@s.whatsapp.net')) {
|
||||
return sender
|
||||
}
|
||||
|
||||
const lidMapping = repository.getLIDMappingStore()
|
||||
const normalizedSender = jidNormalizedUser(sender)
|
||||
const lidForPN = await lidMapping.getLIDForPN(normalizedSender)
|
||||
|
||||
if (lidForPN?.includes('@lid')) {
|
||||
const senderDecoded = jidDecode(sender)
|
||||
const deviceId = senderDecoded?.device || 0
|
||||
return jidEncode(jidDecode(lidForPN)!.user, 'lid', deviceId)
|
||||
}
|
||||
|
||||
return sender
|
||||
}
|
||||
|
||||
const storeMappingFromEnvelope = async (
|
||||
stanza: BinaryNode,
|
||||
sender: string,
|
||||
decryptionJid: string,
|
||||
repository: SignalRepository,
|
||||
logger: ILogger
|
||||
): Promise<void> => {
|
||||
const { senderAlt } = extractAddressingContext(stanza)
|
||||
|
||||
if (senderAlt && isLidUser(senderAlt) && isJidUser(sender) && decryptionJid === sender) {
|
||||
try {
|
||||
await repository.storeLIDPNMapping(senderAlt, sender)
|
||||
logger.debug({ sender, senderAlt }, 'Stored LID mapping from envelope')
|
||||
} catch (error) {
|
||||
logger.warn({ sender, senderAlt, error }, 'Failed to store LID mapping')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node'
|
||||
export const MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled'
|
||||
|
||||
@@ -43,6 +83,28 @@ type MessageType =
|
||||
| 'other_status'
|
||||
| 'newsletter'
|
||||
|
||||
export const extractAddressingContext = (stanza: BinaryNode) => {
|
||||
const addressingMode = stanza.attrs.addressing_mode || 'pn'
|
||||
let senderAlt: string | undefined
|
||||
let recipientAlt: string | undefined
|
||||
|
||||
if (addressingMode === 'lid') {
|
||||
// Message is LID-addressed: sender is LID, extract corresponding PN
|
||||
senderAlt = stanza.attrs.participant_pn || stanza.attrs.sender_pn
|
||||
recipientAlt = stanza.attrs.recipient_pn
|
||||
} else {
|
||||
// Message is PN-addressed: sender is PN, extract corresponding LID
|
||||
senderAlt = stanza.attrs.participant_lid || stanza.attrs.sender_lid
|
||||
recipientAlt = stanza.attrs.recipient_lid
|
||||
}
|
||||
|
||||
return {
|
||||
addressingMode,
|
||||
senderAlt,
|
||||
recipientAlt
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the received node as a message.
|
||||
* @note this will only parse the message, not decrypt it
|
||||
@@ -187,11 +249,15 @@ export const decryptMessageNode = (
|
||||
case 'pkmsg':
|
||||
case 'msg':
|
||||
const user = isJidUser(sender) ? sender : author
|
||||
const decryptionJid = await getDecryptionJid(user, repository)
|
||||
|
||||
msgBuffer = await repository.decryptMessage({
|
||||
jid: user,
|
||||
jid: decryptionJid,
|
||||
type: e2eType,
|
||||
ciphertext: content
|
||||
})
|
||||
|
||||
await storeMappingFromEnvelope(stanza, user, decryptionJid, repository, logger)
|
||||
break
|
||||
case 'plaintext':
|
||||
msgBuffer = content
|
||||
|
||||
Reference in New Issue
Block a user