You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-29 16:43:09 +03:00
Reset megolm session when people join/leave the room
This commit is contained in:
@@ -403,6 +403,8 @@ function setupCryptoEventHandler(client) {
|
|||||||
}
|
}
|
||||||
onCryptoEvent(client, event);
|
onCryptoEvent(client, event);
|
||||||
});
|
});
|
||||||
|
client.on("RoomMember.membership",
|
||||||
|
client._crypto.onRoomMembership.bind(client._crypto));
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCryptoEvent(client, event) {
|
function onCryptoEvent(client, event) {
|
||||||
|
|||||||
@@ -90,6 +90,13 @@ EncryptionAlgorithm.prototype.initRoomEncryption = function(roomMembers) {
|
|||||||
* @return {module:client.Promise} Promise which resolves to the new event body
|
* @return {module:client.Promise} Promise which resolves to the new event body
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the membership of a member of the room changes.
|
||||||
|
*
|
||||||
|
* @param {module:models/event.MatrixEvent} event event causing the change
|
||||||
|
* @param {module:models/room-member} member user whose membership changed
|
||||||
|
*/
|
||||||
|
EncryptionAlgorithm.prototype.onRoomMembership = function(event, member) {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* base type for decryption implementations
|
* base type for decryption implementations
|
||||||
@@ -125,7 +132,7 @@ module.exports.DecryptionAlgorithm = DecryptionAlgorithm;
|
|||||||
*
|
*
|
||||||
* @method module:crypto-algorithms/base.DecryptionAlgorithm#onRoomKeyEvent
|
* @method module:crypto-algorithms/base.DecryptionAlgorithm#onRoomKeyEvent
|
||||||
*
|
*
|
||||||
* @param {module:modules/event~MatrixEvent} event key event
|
* @param {module:models/event.MatrixEvent} event key event
|
||||||
*/
|
*/
|
||||||
DecryptionAlgorithm.prototype.onRoomKeyEvent = function(params) {
|
DecryptionAlgorithm.prototype.onRoomKeyEvent = function(params) {
|
||||||
// ignore by default
|
// ignore by default
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ function MegolmEncryption(params) {
|
|||||||
base.EncryptionAlgorithm.call(this, params);
|
base.EncryptionAlgorithm.call(this, params);
|
||||||
this._prepPromise = null;
|
this._prepPromise = null;
|
||||||
this._outboundSessionId = null;
|
this._outboundSessionId = null;
|
||||||
|
this._discardNewSession = false;
|
||||||
}
|
}
|
||||||
utils.inherits(MegolmEncryption, base.EncryptionAlgorithm);
|
utils.inherits(MegolmEncryption, base.EncryptionAlgorithm);
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(room) {
|
|||||||
|
|
||||||
if (this._outboundSessionId) {
|
if (this._outboundSessionId) {
|
||||||
// prep already done
|
// prep already done
|
||||||
return q();
|
return q(this._outboundSessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var session_id = this._olmDevice.createOutboundGroupSession();
|
var session_id = this._olmDevice.createOutboundGroupSession();
|
||||||
@@ -138,11 +139,19 @@ MegolmEncryption.prototype._ensureOutboundSession = function(room) {
|
|||||||
undefined, "PUT", path, undefined, encryptedContent
|
undefined, "PUT", path, undefined, encryptedContent
|
||||||
);
|
);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
// don't set this until the keys are sent successfully; if we get an
|
if (self._discardNewSession) {
|
||||||
// error, the user can restart by resending the message.
|
// we've had cause to reset the session_id since starting this process.
|
||||||
self._outboundSessionId = session_id;
|
// we'll use the current session for any currently pending events, but
|
||||||
|
// don't save it as the current _outboundSessionId, so that new events
|
||||||
|
// will use a new session.
|
||||||
|
console.log("Session generation complete, but discarding");
|
||||||
|
} else {
|
||||||
|
self._outboundSessionId = session_id;
|
||||||
|
}
|
||||||
|
return session_id;
|
||||||
}).finally(function() {
|
}).finally(function() {
|
||||||
self._prepPromise = null;
|
self._prepPromise = null;
|
||||||
|
self._discardNewSession = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
return this._prepPromise;
|
return this._prepPromise;
|
||||||
@@ -159,7 +168,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(room) {
|
|||||||
*/
|
*/
|
||||||
MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) {
|
MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) {
|
||||||
var self = this;
|
var self = this;
|
||||||
return this._ensureOutboundSession(room).then(function() {
|
return this._ensureOutboundSession(room).then(function(session_id) {
|
||||||
var payloadJson = {
|
var payloadJson = {
|
||||||
room_id: self._roomId,
|
room_id: self._roomId,
|
||||||
type: eventType,
|
type: eventType,
|
||||||
@@ -167,14 +176,14 @@ MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var ciphertext = self._olmDevice.encryptGroupMessage(
|
var ciphertext = self._olmDevice.encryptGroupMessage(
|
||||||
self._outboundSessionId, JSON.stringify(payloadJson)
|
session_id, JSON.stringify(payloadJson)
|
||||||
);
|
);
|
||||||
|
|
||||||
var encryptedContent = {
|
var encryptedContent = {
|
||||||
algorithm: olmlib.MEGOLM_ALGORITHM,
|
algorithm: olmlib.MEGOLM_ALGORITHM,
|
||||||
sender_key: self._olmDevice.deviceCurve25519Key,
|
sender_key: self._olmDevice.deviceCurve25519Key,
|
||||||
body: ciphertext,
|
body: ciphertext,
|
||||||
session_id: self._outboundSessionId,
|
session_id: session_id,
|
||||||
signature: "FIXME",
|
signature: "FIXME",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -182,6 +191,36 @@ MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*
|
||||||
|
* @param {module:models/event.MatrixEvent} event event causing the change
|
||||||
|
* @param {module:models/room-member} member user whose membership changed
|
||||||
|
*/
|
||||||
|
MegolmEncryption.prototype.onRoomMembership = function(event, member) {
|
||||||
|
// start a new outbound session whenever someone joins or leaves the room.
|
||||||
|
//
|
||||||
|
// technically we don't need to reset on all membership transitions (eg,
|
||||||
|
// leave->ban), but we might as well.
|
||||||
|
|
||||||
|
// when people join the room, we could get away with sharing the current
|
||||||
|
// state of the ratchet with them; however, it's somewhat easier for now
|
||||||
|
// just to reset the session and start a new one.
|
||||||
|
|
||||||
|
if (this._outboundSessionId) {
|
||||||
|
console.log("Discarding outbound megolm session due to change in " +
|
||||||
|
"membership of " + member.userId);
|
||||||
|
this._outboundSessionId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._prepPromise) {
|
||||||
|
console.log("Discarding as-yet-incomplete megolm session due to " +
|
||||||
|
"change in membership of " + member.userId);
|
||||||
|
this._discardNewSession = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Megolm decryption implementation
|
* Megolm decryption implementation
|
||||||
*
|
*
|
||||||
@@ -231,7 +270,7 @@ MegolmDecryption.prototype.decryptEvent = function(event) {
|
|||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*
|
*
|
||||||
* @param {module:modules/event~MatrixEvent} event key event
|
* @param {module:models/event.MatrixEvent} event key event
|
||||||
*/
|
*/
|
||||||
MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
|
MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
|
||||||
console.log("Adding key from ", event);
|
console.log("Adding key from ", event);
|
||||||
|
|||||||
@@ -732,7 +732,7 @@ Crypto.prototype.decryptEvent = function(event) {
|
|||||||
/**
|
/**
|
||||||
* Handle a key event
|
* Handle a key event
|
||||||
*
|
*
|
||||||
* @param {module:modules/event~MatrixEvent} event key event
|
* @param {module:models/event.MatrixEvent} event key event
|
||||||
*/
|
*/
|
||||||
Crypto.prototype.onRoomKeyEvent = function(event) {
|
Crypto.prototype.onRoomKeyEvent = function(event) {
|
||||||
var content = event.getContent();
|
var content = event.getContent();
|
||||||
@@ -748,6 +748,32 @@ Crypto.prototype.onRoomKeyEvent = function(event) {
|
|||||||
alg.onRoomKeyEvent(event);
|
alg.onRoomKeyEvent(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a change in the membership state of a member of a room
|
||||||
|
*
|
||||||
|
* @param {module:models/event.MatrixEvent} event event causing the change
|
||||||
|
* @param {module:models/room-member} member user whose membership changed
|
||||||
|
*/
|
||||||
|
Crypto.prototype.onRoomMembership = function(event, member) {
|
||||||
|
|
||||||
|
// this event handler is registered on the *client* (as opposed to the
|
||||||
|
// room member itself), which means it is only called on changes to the
|
||||||
|
// *live* membership state (ie, it is not called when we back-paginate).
|
||||||
|
//
|
||||||
|
// Further, it is automatically registered and called when new members
|
||||||
|
// arrive in the room.
|
||||||
|
|
||||||
|
var roomId = member.roomId;
|
||||||
|
|
||||||
|
var alg = this._roomAlgorithms[roomId];
|
||||||
|
if (!alg) {
|
||||||
|
// not encrypting in this room
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
alg.onRoomMembership(event, member);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see module:crypto-algorithms/base.DecryptionError
|
* @see module:crypto-algorithms/base.DecryptionError
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ module.exports.MatrixClient = require("./client").MatrixClient;
|
|||||||
module.exports.Room = require("./models/room");
|
module.exports.Room = require("./models/room");
|
||||||
/** The {@link module:models/event-timeline~EventTimeline} class. */
|
/** The {@link module:models/event-timeline~EventTimeline} class. */
|
||||||
module.exports.EventTimeline = require("./models/event-timeline");
|
module.exports.EventTimeline = require("./models/event-timeline");
|
||||||
/** The {@link module:models/room-member~RoomMember|RoomMember} class. */
|
/** The {@link module:models/room-member|RoomMember} class. */
|
||||||
module.exports.RoomMember = require("./models/room-member");
|
module.exports.RoomMember = require("./models/room-member");
|
||||||
/** The {@link module:models/room-state~RoomState|RoomState} class. */
|
/** The {@link module:models/room-state~RoomState|RoomState} class. */
|
||||||
module.exports.RoomState = require("./models/room-state");
|
module.exports.RoomState = require("./models/room-state");
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ var utils = require("../utils");
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new room member.
|
* Construct a new room member.
|
||||||
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
|
* @alias module:models/room-member
|
||||||
|
*
|
||||||
* @param {string} roomId The room ID of the member.
|
* @param {string} roomId The room ID of the member.
|
||||||
* @param {string} userId The user ID of the member.
|
* @param {string} userId The user ID of the member.
|
||||||
* @prop {string} roomId The room ID for this member.
|
* @prop {string} roomId The room ID for this member.
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ Room.prototype.getTimelineForEvent = function(eventId) {
|
|||||||
* Get an event which is stored in our timelines
|
* Get an event which is stored in our timelines
|
||||||
*
|
*
|
||||||
* @param {string} eventId event ID to look for
|
* @param {string} eventId event ID to look for
|
||||||
* @return {?module:models/event~MatrixEvent} the given event, or undefined if unknown
|
* @return {?module:models/event.MatrixEvent} the given event, or undefined if unknown
|
||||||
*/
|
*/
|
||||||
Room.prototype.findEventById = function(eventId) {
|
Room.prototype.findEventById = function(eventId) {
|
||||||
var tl = this.getTimelineForEvent(eventId);
|
var tl = this.getTimelineForEvent(eventId);
|
||||||
@@ -796,9 +796,9 @@ Room.prototype.addPendingEvent = function(event, txnId) {
|
|||||||
* <p>We move the event to the live timeline if it isn't there already, and
|
* <p>We move the event to the live timeline if it isn't there already, and
|
||||||
* update it.
|
* update it.
|
||||||
*
|
*
|
||||||
* @param {module:models/event~MatrixEvent} remoteEvent The event received from
|
* @param {module:models/event.MatrixEvent} remoteEvent The event received from
|
||||||
* /sync
|
* /sync
|
||||||
* @param {module:models/event~MatrixEvent} localEvent The local echo, which
|
* @param {module:models/event.MatrixEvent} localEvent The local echo, which
|
||||||
* should be either in the _pendingEventList or the timeline.
|
* should be either in the _pendingEventList or the timeline.
|
||||||
*
|
*
|
||||||
* @fires module:client~MatrixClient#event:"Room.localEchoUpdated"
|
* @fires module:client~MatrixClient#event:"Room.localEchoUpdated"
|
||||||
|
|||||||
Reference in New Issue
Block a user