start of fix of session-request processing

pull/1183/head
Audric Ackermann 5 years ago
parent cf94961736
commit 0a2af13cb1
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -57,7 +57,7 @@
async function sendSessionEstablishedMessage(pubKey) { async function sendSessionEstablishedMessage(pubKey) {
const user = libsession.Types.PubKey.from(pubKey); const user = libsession.Types.PubKey.from(pubKey);
const sessionEstablished = new window.libsession.Messages.Outgoing.SessionEstablished( const sessionEstablished = new window.libsession.Messages.Outgoing.SessionEstablishedMessage(
{ timestamp: Date.now() } { timestamp: Date.now() }
); );
await libsession.getMessageQueue().send(user, sessionEstablished); await libsession.getMessageQueue().send(user, sessionEstablished);

@ -45,39 +45,6 @@
signature: new Uint8Array(signedKey.signature), signature: new Uint8Array(signedKey.signature),
}; };
} }
async function saveContactPreKeyBundle({
pubKey,
preKeyId,
preKey,
signedKeyId,
signedKey,
signature,
}) {
const signedPreKey = {
keyId: signedKeyId,
publicKey: signedKey,
signature,
};
const signedKeyPromise = textsecure.storage.protocol.storeContactSignedPreKey(
pubKey,
signedPreKey
);
const preKeyObject = {
publicKey: preKey,
keyId: preKeyId,
};
const preKeyPromise = textsecure.storage.protocol.storeContactPreKey(
pubKey,
preKeyObject
);
await Promise.all([signedKeyPromise, preKeyPromise]);
}
async function removeContactPreKeyBundle(pubKey) { async function removeContactPreKeyBundle(pubKey) {
await Promise.all([ await Promise.all([
textsecure.storage.protocol.removeContactPreKey(pubKey), textsecure.storage.protocol.removeContactPreKey(pubKey),
@ -123,7 +90,6 @@
window.libloki.storage = { window.libloki.storage = {
getPreKeyBundleForContact, getPreKeyBundleForContact,
saveContactPreKeyBundle,
removeContactPreKeyBundle, removeContactPreKeyBundle,
verifyFriendRequestAcceptPreKey, verifyFriendRequestAcceptPreKey,
getGuardNodes, getGuardNodes,

@ -209,8 +209,8 @@ MessageReceiver.prototype.extend({
// We do the message decryption here, instead of in the ordered pending queue, // We do the message decryption here, instead of in the ordered pending queue,
// to avoid exposing the time it took us to process messages through the time-to-ack. // to avoid exposing the time it took us to process messages through the time-to-ack.
if (request.path !== '/api/v1/message') { if (request.path && request.path !== '/api/v1/message') {
window.log.info('got request', request.verb, request.path); window.log.info('got request', request, request.path);
request.respond(200, 'OK'); request.respond(200, 'OK');
if (request.verb === 'PUT' && request.path === '/api/v1/queue/empty') { if (request.verb === 'PUT' && request.path === '/api/v1/queue/empty') {
@ -1086,15 +1086,9 @@ MessageReceiver.prototype.extend({
if (shouldProcessSessionRequest) { if (shouldProcessSessionRequest) {
try { try {
// TODO remember to remove savePreKeyBundleMessage() from the codebase if it's actually irrelevant
// if (content.preKeyBundleMessage) {
// await this.savePreKeyBundleMessage(
// envelope.source,
// content.preKeyBundleMessage
// );
// }
// device id are always 1 with Session // device id are always 1 with Session
const deviceId = 1; const deviceId = 1;
const pubkey = envelope.source;
const address = new libsignal.SignalProtocolAddress( const address = new libsignal.SignalProtocolAddress(
envelope.source, envelope.source,
deviceId deviceId
@ -1102,18 +1096,53 @@ MessageReceiver.prototype.extend({
// we process the new prekeys and initiate a new session. // we process the new prekeys and initiate a new session.
// The old sessions will get deleted once the correspondant // The old sessions will get deleted once the correspondant
// has switch to the new session. // has switch to the new session.
const { preKey, signedKey, identityKey } = content.preKeyBundleMessage; const [identityKey, preKey, signedKey, signature] = [
content.preKeyBundleMessage.identityKey,
content.preKeyBundleMessage.preKey,
content.preKeyBundleMessage.signedKey,
content.preKeyBundleMessage.signature,
].map(k => dcodeIO.ByteBuffer.wrap(k).toArrayBuffer());
const { preKeyId, signedKeyId } = content.preKeyBundleMessage;
if (pubkey !== StringView.arrayBufferToHex(identityKey)) {
throw new Error(
'Error in savePreKeyBundleMessage: envelope pubkey does not match pubkey in prekey bundle'
);
}
if (preKey === undefined || signedKey === undefined) { if (preKey === undefined || signedKey === undefined) {
window.console.warn( window.console.warn(
"Couldn't process prekey bundle without preKey or signedKey" "Couldn't process prekey bundle without preKey or signedKey"
); );
return; return;
} }
const signedPreKey = {
keyId: signedKeyId,
publicKey: signedKey,
signature,
};
const signedKeyPromise = textsecure.storage.protocol.storeContactSignedPreKey(
pubkey,
signedPreKey
);
const preKeyObject = {
publicKey: preKey,
keyId: preKeyId,
};
const preKeyPromise = textsecure.storage.protocol.storeContactPreKey(
pubkey,
preKeyObject
);
await Promise.all([signedKeyPromise, preKeyPromise]);
const device = { const device = {
identityKey, identityKey,
deviceId, deviceId,
preKey, preKey: {...preKey, keyId: preKeyId},
signedPreKey: signedKey, signedPreKey,
registrationId: 0, registrationId: 0,
}; };
const builder = new libsignal.SessionBuilder( const builder = new libsignal.SessionBuilder(
@ -1123,13 +1152,13 @@ MessageReceiver.prototype.extend({
await builder.processPreKey(device); await builder.processPreKey(device);
await libsession.Protocols.SessionProtocol.onSessionRequestProcessed( await libsession.Protocols.SessionProtocol.onSessionRequestProcessed(
envelope.source new libsession.Types.PubKey(envelope.source)
); );
window.log.debug('sending session established to', envelope.source); window.log.debug('sending session established to', envelope.source);
// We don't need to await the call below because we just want to send it off // We don't need to await the call below because we just want to send it off
window.libloki.api.sendSessionEstablishedMessage(envelope.source); window.libloki.api.sendSessionEstablishedMessage(envelope.source);
} catch (e) { } catch (e) {
window.log.warn('Failed to process session request'); window.log.warn('Failed to process session request', e);
// TODO how to handle a failed session request? // TODO how to handle a failed session request?
} }
} }
@ -1138,6 +1167,8 @@ MessageReceiver.prototype.extend({
const content = textsecure.protobuf.Content.decode(plaintext); const content = textsecure.protobuf.Content.decode(plaintext);
const { SESSION_REQUEST } = textsecure.protobuf.Envelope.Type; const { SESSION_REQUEST } = textsecure.protobuf.Envelope.Type;
await ConversationController.getOrCreateAndWait(envelope.source, 'private');
if (envelope.type === SESSION_REQUEST) { if (envelope.type === SESSION_REQUEST) {
await this.handleSessionRequestMessage(envelope, content); await this.handleSessionRequestMessage(envelope, content);
} else { } else {
@ -1407,31 +1438,6 @@ MessageReceiver.prototype.extend({
return this.removeFromCache(envelope); return this.removeFromCache(envelope);
}, },
async savePreKeyBundleMessage(pubKey, preKeyBundleMessage) {
const [identityKey, preKey, signedKey, signature] = [
preKeyBundleMessage.identityKey,
preKeyBundleMessage.preKey,
preKeyBundleMessage.signedKey,
preKeyBundleMessage.signature,
].map(k => dcodeIO.ByteBuffer.wrap(k).toArrayBuffer());
const { preKeyId, signedKeyId } = preKeyBundleMessage;
if (pubKey !== StringView.arrayBufferToHex(identityKey)) {
throw new Error(
'Error in savePreKeyBundleMessage: envelope pubkey does not match pubkey in prekey bundle'
);
}
await libloki.storage.saveContactPreKeyBundle({
pubKey,
preKeyId,
signedKeyId,
preKey,
signedKey,
signature,
});
},
isBlocked(number) { isBlocked(number) {
return textsecure.storage.get('blocked', []).indexOf(number) >= 0; return textsecure.storage.get('blocked', []).indexOf(number) >= 0;
}, },
@ -1466,9 +1472,6 @@ textsecure.MessageReceiver = function MessageReceiverWrapper(
); );
this.getStatus = messageReceiver.getStatus.bind(messageReceiver); this.getStatus = messageReceiver.getStatus.bind(messageReceiver);
this.close = messageReceiver.close.bind(messageReceiver); this.close = messageReceiver.close.bind(messageReceiver);
this.savePreKeyBundleMessage = messageReceiver.savePreKeyBundleMessage.bind(
messageReceiver
);
this.pollForAdditionalId = messageReceiver.pollForAdditionalId.bind( this.pollForAdditionalId = messageReceiver.pollForAdditionalId.bind(
messageReceiver messageReceiver

@ -174,14 +174,14 @@ export class SessionProtocol {
if (!SessionProtocol.dbLoaded) { if (!SessionProtocol.dbLoaded) {
const sentItem = await getItemById('sentSessionsTimestamp'); const sentItem = await getItemById('sentSessionsTimestamp');
if (sentItem) { if (sentItem) {
SessionProtocol.sentSessionsTimestamp = sentItem.value; SessionProtocol.sentSessionsTimestamp = JSON.parse(sentItem.value);
} else { } else {
SessionProtocol.sentSessionsTimestamp = {}; SessionProtocol.sentSessionsTimestamp = {};
} }
const processedItem = await getItemById('processedSessionsTimestamp'); const processedItem = await getItemById('processedSessionsTimestamp');
if (processedItem) { if (processedItem) {
SessionProtocol.processedSessionsTimestamp = processedItem.value; SessionProtocol.processedSessionsTimestamp = JSON.parse(processedItem.value);
} else { } else {
SessionProtocol.processedSessionsTimestamp = {}; SessionProtocol.processedSessionsTimestamp = {};
} }
@ -215,6 +215,9 @@ export class SessionProtocol {
timestamp: number | undefined, timestamp: number | undefined,
map: StringToNumberMap map: StringToNumberMap
): Promise<boolean> { ): Promise<boolean> {
if (device === undefined) {
throw new Error('Device cannot be undefined');
}
if (map[device] === timestamp) { if (map[device] === timestamp) {
return false; return false;
} }

@ -156,6 +156,8 @@ export class MessageQueue implements MessageQueueInterface {
} }
private async processAllPending() { private async processAllPending() {
await this.pendingMessageCache.isReady;
const devices = this.pendingMessageCache.getDevices(); const devices = this.pendingMessageCache.getDevices();
const promises = devices.map(async device => this.processPending(device)); const promises = devices.map(async device => this.processPending(device));

Loading…
Cancel
Save