Send a 'm.new_device' when we get a message for an unknown group session
This should reduce the risk of a device getting permenantly stuck unable to receive encrypted group messages.
This commit is contained in:
@@ -539,7 +539,9 @@ OlmDevice.prototype._saveInboundGroupSession = function(
|
||||
* @param {string} senderKey
|
||||
* @param {string} sessionId
|
||||
* @param {function} func
|
||||
* @return {object} result of func
|
||||
* @return {object} Object with two keys "result": result of func, "exists"
|
||||
* whether the session exists. if the session doesn't exist then the function
|
||||
* isn't called and the "result" is undefined.
|
||||
* @private
|
||||
*/
|
||||
OlmDevice.prototype._getInboundGroupSession = function(
|
||||
@@ -550,7 +552,7 @@ OlmDevice.prototype._getInboundGroupSession = function(
|
||||
);
|
||||
|
||||
if (r === null) {
|
||||
throw new Error("Unknown inbound group session id");
|
||||
return {sessionExists: false}
|
||||
}
|
||||
|
||||
r = JSON.parse(r);
|
||||
@@ -567,7 +569,7 @@ OlmDevice.prototype._getInboundGroupSession = function(
|
||||
var session = new Olm.InboundGroupSession();
|
||||
try {
|
||||
session.unpickle(this._pickleKey, r.session);
|
||||
return func(session);
|
||||
return {sessionExists: true, result: func(session)};
|
||||
} finally {
|
||||
session.free();
|
||||
}
|
||||
@@ -603,7 +605,7 @@ OlmDevice.prototype.addInboundGroupSession = function(
|
||||
* @param {string} sessionId session identifier
|
||||
* @param {string} body base64-encoded body of the encrypted message
|
||||
*
|
||||
* @return {string} plaintext
|
||||
* @return {object} {result: "plaintext"|undefined, sessionExists: Boolean}
|
||||
*/
|
||||
OlmDevice.prototype.decryptGroupMessage = function(
|
||||
roomId, senderKey, sessionId, body
|
||||
|
||||
@@ -356,7 +356,8 @@ utils.inherits(MegolmDecryption, base.DecryptionAlgorithm);
|
||||
*
|
||||
* @param {object} event raw event
|
||||
*
|
||||
* @return {object} decrypted payload (with properties 'type', 'content')
|
||||
* @return {object} object with 'result' key with decrypted payload (with
|
||||
* properties 'type', 'content') and a 'sessionKey' key.
|
||||
*
|
||||
* @throws {module:crypto/algorithms/base.DecryptionError} if there is a
|
||||
* problem decrypting the event
|
||||
@@ -377,7 +378,11 @@ MegolmDecryption.prototype.decryptEvent = function(event) {
|
||||
var res = this._olmDevice.decryptGroupMessage(
|
||||
event.room_id, content.sender_key, content.session_id, content.ciphertext
|
||||
);
|
||||
return JSON.parse(res);
|
||||
if (res.sessionExists) {
|
||||
return {result: JSON.parse(res.result), sessionExists: true};
|
||||
} else {
|
||||
return {sessionExists: false};
|
||||
}
|
||||
} catch (e) {
|
||||
throw new base.DecryptionError(e);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,9 @@ utils.inherits(OlmDecryption, base.DecryptionAlgorithm);
|
||||
*
|
||||
* @param {object} event raw event
|
||||
*
|
||||
* @return {object} decrypted payload (with properties 'type', 'content')
|
||||
* @return {object} result object with result property with the decrypted
|
||||
* payload (with properties 'type', 'content'), and a "sessionExists" key
|
||||
* always set to true.
|
||||
*
|
||||
* @throws {module:crypto/algorithms/base.DecryptionError} if there is a
|
||||
* problem decrypting the event
|
||||
@@ -198,7 +200,7 @@ OlmDecryption.prototype.decryptEvent = function(event) {
|
||||
// TODO: Check the sender user id matches the sender key.
|
||||
// TODO: check the room_id and fingerprint
|
||||
if (payloadString !== null) {
|
||||
return JSON.parse(payloadString);
|
||||
return {result: JSON.parse(payloadString), sessionExists: true};
|
||||
} else {
|
||||
throw new base.DecryptionError("Bad Encrypted Message");
|
||||
}
|
||||
|
||||
+35
-1
@@ -820,7 +820,41 @@ Crypto.prototype.decryptEvent = function(event) {
|
||||
var alg = new AlgClass({
|
||||
olmDevice: this._olmDevice,
|
||||
});
|
||||
return alg.decryptEvent(event);
|
||||
var r = alg.decryptEvent(event);
|
||||
if (r.sessionExists) {
|
||||
return r.result;
|
||||
} else {
|
||||
// We've got a message for a session we don't have.
|
||||
// Maybe the sender forgot to tell us about the session.
|
||||
// Remind the sender that we exists so that they might
|
||||
// tell us about the sender.
|
||||
if (event.getRoomId !== undefined && event.getSender !== undefined) {
|
||||
var senderUserId = event.getSender();
|
||||
var roomId = event.getRoomId();
|
||||
var content = {};
|
||||
var senderDeviceId = event.content.device_id;
|
||||
if (senderDeviceId !== undefined) {
|
||||
content[senderUserId][senderDeviceId] = {
|
||||
device_id: this._deviceId,
|
||||
rooms: [roomId],
|
||||
};
|
||||
} else {
|
||||
content[senderUserId]["*"] = {
|
||||
device_id: this._deviceId,
|
||||
rooms: [roomId],
|
||||
};
|
||||
}
|
||||
// TODO: Ratelimit the "m.new_device" messages to make sure we don't
|
||||
// flood the target device with messages if we get lots of encrypted
|
||||
// messages from them at once.
|
||||
this._baseApis.sendToDevice(
|
||||
"m.new_device", // OH HAI!
|
||||
content
|
||||
).done(function() {});
|
||||
}
|
||||
|
||||
throw new algorithms.DecryptionError("Unknown inbound session id");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user