Remove source field from envelope

pull/778/head
Maxim Shishmarev 6 years ago
parent 02999fa3f9
commit dadd4b97ad

@ -2041,7 +2041,9 @@
// If we don't return early here, we can get into infinite error loops. So, no // If we don't return early here, we can get into infinite error loops. So, no
// delivery receipts for sealed sender errors. // delivery receipts for sealed sender errors.
if (isError || !data.unidentifiedDeliveryReceived) {
// Note(LOKI): don't send receipt for FR as we don't have a session yet
if (isError || !data.unidentifiedDeliveryReceived || data.friendRequest) {
return message; return message;
} }

@ -654,6 +654,9 @@ MessageReceiver.prototype.extend({
}, },
async decrypt(envelope, ciphertext) { async decrypt(envelope, ciphertext) {
let promise; let promise;
// We don't have source at this point yet (with sealed sender)
// This needs a massive cleanup!
const address = new libsignal.SignalProtocolAddress( const address = new libsignal.SignalProtocolAddress(
envelope.source, envelope.source,
envelope.sourceDevice envelope.sourceDevice
@ -668,33 +671,19 @@ MessageReceiver.prototype.extend({
options.messageKeysLimit = false; options.messageKeysLimit = false;
} }
// Will become obsolete
const sessionCipher = new libsignal.SessionCipher( const sessionCipher = new libsignal.SessionCipher(
textsecure.storage.protocol, textsecure.storage.protocol,
address, address,
options options
); );
const secretSessionCipher = new window.Signal.Metadata.SecretSessionCipher(
textsecure.storage.protocol
);
const fallBackSessionCipher = new libloki.crypto.FallBackSessionCipher(
address
);
const me = { const me = {
number: ourNumber, number: ourNumber,
deviceId: parseInt(textsecure.storage.user.getDeviceId(), 10), deviceId: parseInt(textsecure.storage.user.getDeviceId(), 10),
}; };
let conversation; // Will become obsolete
try {
conversation = await window.ConversationController.getOrCreateAndWait(
envelope.source,
'private'
);
} catch (e) {
window.log.info('Error getting conversation: ', envelope.source);
}
const getCurrentSessionBaseKey = async () => { const getCurrentSessionBaseKey = async () => {
const record = await sessionCipher.getRecord(address.toString()); const record = await sessionCipher.getRecord(address.toString());
if (!record) { if (!record) {
@ -707,71 +696,28 @@ MessageReceiver.prototype.extend({
const { baseKey } = openSession.indexInfo; const { baseKey } = openSession.indexInfo;
return baseKey; return baseKey;
}; };
// Will become obsolete
const captureActiveSession = async () => { const captureActiveSession = async () => {
this.activeSessionBaseKey = await getCurrentSessionBaseKey(sessionCipher); this.activeSessionBaseKey = await getCurrentSessionBaseKey(sessionCipher);
}; };
const restoreActiveSession = async () => {
const record = await sessionCipher.getRecord(address.toString()); const handleSessionReset = async result => result;
if (!record) {
return;
}
record.archiveCurrentState();
const sessionToRestore = record.sessions[this.activeSessionBaseKey];
record.promoteState(sessionToRestore);
record.updateSessionState(sessionToRestore);
await textsecure.storage.protocol.storeSession(
address.toString(),
record.serialize()
);
};
const deleteAllSessionExcept = async sessionBaseKey => {
const record = await sessionCipher.getRecord(address.toString());
if (!record) {
return;
}
const sessionToKeep = record.sessions[sessionBaseKey];
record.sessions = {};
record.updateSessionState(sessionToKeep);
await textsecure.storage.protocol.storeSession(
address.toString(),
record.serialize()
);
};
let handleSessionReset;
if (conversation.isSessionResetOngoing()) {
handleSessionReset = async result => {
const currentSessionBaseKey = await getCurrentSessionBaseKey(
sessionCipher
);
if (
this.activeSessionBaseKey &&
currentSessionBaseKey !== this.activeSessionBaseKey
) {
if (conversation.isSessionResetReceived()) {
await restoreActiveSession();
} else {
await deleteAllSessionExcept(currentSessionBaseKey);
await conversation.onNewSessionAdopted();
}
} else if (conversation.isSessionResetReceived()) {
await deleteAllSessionExcept(this.activeSessionBaseKey);
await conversation.onNewSessionAdopted();
}
return result;
};
} else {
handleSessionReset = async result => result;
}
switch (envelope.type) { switch (envelope.type) {
case textsecure.protobuf.Envelope.Type.CIPHERTEXT: case textsecure.protobuf.Envelope.Type.CIPHERTEXT:
window.log.info('message from', this.getEnvelopeId(envelope)); window.log.info('message from', this.getEnvelopeId(envelope));
promise = captureActiveSession() promise = captureActiveSession()
.then(() => sessionCipher.decryptWhisperMessage(ciphertext)) .then(() => sessionCipher.decryptWhisperMessage(ciphertext))
.then(this.unpad) .then(this.unpad);
.then(handleSessionReset);
break; break;
case textsecure.protobuf.Envelope.Type.FRIEND_REQUEST: { case textsecure.protobuf.Envelope.Type.FRIEND_REQUEST: {
window.log.info('friend-request message from ', envelope.source); window.log.info('friend-request message from ', envelope.source);
const fallBackSessionCipher = new libloki.crypto.FallBackSessionCipher(
address
);
promise = fallBackSessionCipher promise = fallBackSessionCipher
.decrypt(ciphertext.toArrayBuffer()) .decrypt(ciphertext.toArrayBuffer())
.then(this.unpad); .then(this.unpad);
@ -779,30 +725,33 @@ MessageReceiver.prototype.extend({
} }
case textsecure.protobuf.Envelope.Type.PREKEY_BUNDLE: case textsecure.protobuf.Envelope.Type.PREKEY_BUNDLE:
window.log.info('prekey message from', this.getEnvelopeId(envelope)); window.log.info('prekey message from', this.getEnvelopeId(envelope));
promise = captureActiveSession(sessionCipher) promise = captureActiveSession(sessionCipher).then(async () => {
.then(async () => { if (!this.activeSessionBaseKey) {
if (!this.activeSessionBaseKey) { try {
try { const buffer = dcodeIO.ByteBuffer.wrap(ciphertext);
const buffer = dcodeIO.ByteBuffer.wrap(ciphertext); await window.libloki.storage.verifyFriendRequestAcceptPreKey(
await window.libloki.storage.verifyFriendRequestAcceptPreKey( envelope.source,
envelope.source, buffer
buffer );
); } catch (e) {
} catch (e) { await this.removeFromCache(envelope);
await this.removeFromCache(envelope); throw e;
throw e;
}
} }
return this.decryptPreKeyWhisperMessage( }
ciphertext, return this.decryptPreKeyWhisperMessage(
sessionCipher, ciphertext,
address sessionCipher,
); address
}) );
.then(handleSessionReset); });
break; break;
case textsecure.protobuf.Envelope.Type.UNIDENTIFIED_SENDER: case textsecure.protobuf.Envelope.Type.UNIDENTIFIED_SENDER:
window.log.info('received unidentified sender message'); window.log.info('received unidentified sender message');
const secretSessionCipher = new window.Signal.Metadata.SecretSessionCipher(
textsecure.storage.protocol
);
promise = secretSessionCipher promise = secretSessionCipher
.decrypt(ciphertext.toArrayBuffer(), me) .decrypt(ciphertext.toArrayBuffer(), me)
.then( .then(
@ -872,8 +821,7 @@ MessageReceiver.prototype.extend({
throw error; throw error;
}); });
} }
) );
.then(handleSessionReset);
break; break;
default: default:
promise = Promise.reject(new Error('Unknown message type')); promise = Promise.reject(new Error('Unknown message type'));
@ -887,6 +835,75 @@ MessageReceiver.prototype.extend({
return null; return null;
} }
let conversation;
try {
conversation = await window.ConversationController.getOrCreateAndWait(
envelope.source,
'private'
);
} catch (e) {
window.log.info('Error getting conversation: ', envelope.source);
}
/// *** BEGIN: session reset ***
const address = new libsignal.SignalProtocolAddress(
envelope.source,
envelope.sourceDevice
);
const restoreActiveSession = async () => {
const record = await sessionCipher.getRecord(address.toString());
if (!record) {
return;
}
record.archiveCurrentState();
// NOTE: activeSessionBaseKey will be undefined here...
const sessionToRestore = record.sessions[this.activeSessionBaseKey];
record.promoteState(sessionToRestore);
record.updateSessionState(sessionToRestore);
await textsecure.storage.protocol.storeSession(
address.toString(),
record.serialize()
);
};
const deleteAllSessionExcept = async sessionBaseKey => {
const record = await sessionCipher.getRecord(address.toString());
if (!record) {
return;
}
const sessionToKeep = record.sessions[sessionBaseKey];
record.sessions = {};
record.updateSessionState(sessionToKeep);
await textsecure.storage.protocol.storeSession(
address.toString(),
record.serialize()
);
};
if (conversation.isSessionResetOngoing()) {
const currentSessionBaseKey = await getCurrentSessionBaseKey(
sessionCipher
);
if (
this.activeSessionBaseKey &&
currentSessionBaseKey !== this.activeSessionBaseKey
) {
if (conversation.isSessionResetReceived()) {
await restoreActiveSession();
} else {
await deleteAllSessionExcept(currentSessionBaseKey);
await conversation.onNewSessionAdopted();
}
} else if (conversation.isSessionResetReceived()) {
await deleteAllSessionExcept(this.activeSessionBaseKey);
await conversation.onNewSessionAdopted();
}
}
/// *** END ***
// Type here can actually be UNIDENTIFIED_SENDER even if // Type here can actually be UNIDENTIFIED_SENDER even if
// the underlying message is FRIEND_REQUEST // the underlying message is FRIEND_REQUEST
if ( if (

@ -266,9 +266,15 @@ OutgoingMessage.prototype = {
return this.convertMessageToText(messageBuffer); return this.convertMessageToText(messageBuffer);
}, },
async wrapInWebsocketMessage(outgoingObject) { async wrapInWebsocketMessage(outgoingObject) {
const source =
outgoingObject.type ===
textsecure.protobuf.Envelope.Type.UNIDENTIFIED_SENDER
? null
: outgoingObject.ourKey;
const messageEnvelope = new textsecure.protobuf.Envelope({ const messageEnvelope = new textsecure.protobuf.Envelope({
type: outgoingObject.type, type: outgoingObject.type,
source: outgoingObject.ourKey, source,
sourceDevice: outgoingObject.sourceDevice, sourceDevice: outgoingObject.sourceDevice,
timestamp: this.timestamp, timestamp: this.timestamp,
content: outgoingObject.content, content: outgoingObject.content,

Loading…
Cancel
Save