start of fix of session-request processing

This commit is contained in:
Audric Ackermann 2020-06-18 17:45:32 +10:00
parent cf94961736
commit 0a2af13cb1
No known key found for this signature in database
GPG key ID: 999F434D76324AD4
5 changed files with 53 additions and 79 deletions

View file

@ -57,7 +57,7 @@
async function sendSessionEstablishedMessage(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() }
);
await libsession.getMessageQueue().send(user, sessionEstablished);

View file

@ -45,39 +45,6 @@
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) {
await Promise.all([
textsecure.storage.protocol.removeContactPreKey(pubKey),
@ -123,7 +90,6 @@
window.libloki.storage = {
getPreKeyBundleForContact,
saveContactPreKeyBundle,
removeContactPreKeyBundle,
verifyFriendRequestAcceptPreKey,
getGuardNodes,

View file

@ -209,8 +209,8 @@ MessageReceiver.prototype.extend({
// 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.
if (request.path !== '/api/v1/message') {
window.log.info('got request', request.verb, request.path);
if (request.path && request.path !== '/api/v1/message') {
window.log.info('got request', request, request.path);
request.respond(200, 'OK');
if (request.verb === 'PUT' && request.path === '/api/v1/queue/empty') {
@ -1086,15 +1086,9 @@ MessageReceiver.prototype.extend({
if (shouldProcessSessionRequest) {
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
const deviceId = 1;
const pubkey = envelope.source;
const address = new libsignal.SignalProtocolAddress(
envelope.source,
deviceId
@ -1102,18 +1096,53 @@ MessageReceiver.prototype.extend({
// we process the new prekeys and initiate a new session.
// The old sessions will get deleted once the correspondant
// 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) {
window.console.warn(
"Couldn't process prekey bundle without preKey or signedKey"
);
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 = {
identityKey,
deviceId,
preKey,
signedPreKey: signedKey,
preKey: {...preKey, keyId: preKeyId},
signedPreKey,
registrationId: 0,
};
const builder = new libsignal.SessionBuilder(
@ -1123,13 +1152,13 @@ MessageReceiver.prototype.extend({
await builder.processPreKey(device);
await libsession.Protocols.SessionProtocol.onSessionRequestProcessed(
envelope.source
new libsession.Types.PubKey(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
window.libloki.api.sendSessionEstablishedMessage(envelope.source);
} 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?
}
}
@ -1138,6 +1167,8 @@ MessageReceiver.prototype.extend({
const content = textsecure.protobuf.Content.decode(plaintext);
const { SESSION_REQUEST } = textsecure.protobuf.Envelope.Type;
await ConversationController.getOrCreateAndWait(envelope.source, 'private');
if (envelope.type === SESSION_REQUEST) {
await this.handleSessionRequestMessage(envelope, content);
} else {
@ -1407,31 +1438,6 @@ MessageReceiver.prototype.extend({
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) {
return textsecure.storage.get('blocked', []).indexOf(number) >= 0;
},
@ -1466,9 +1472,6 @@ textsecure.MessageReceiver = function MessageReceiverWrapper(
);
this.getStatus = messageReceiver.getStatus.bind(messageReceiver);
this.close = messageReceiver.close.bind(messageReceiver);
this.savePreKeyBundleMessage = messageReceiver.savePreKeyBundleMessage.bind(
messageReceiver
);
this.pollForAdditionalId = messageReceiver.pollForAdditionalId.bind(
messageReceiver

View file

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

View file

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