1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-12-01 04:43:29 +03:00

Avoid sending unencrypted messages in e2e room

Reshuffle the logic for determining whether to encrypt a message so that it can
run independently of whether our app actually supports e2e - and then throw an
error if it looks like we should be encrypting but don't support it.

This seems a preferable situation to just falling back to plain text if we get
a dodgy build.
This commit is contained in:
Richard van der Hoff
2017-08-08 12:29:26 +01:00
parent 8563dd5860
commit 3e79575602
2 changed files with 75 additions and 34 deletions

View File

@@ -605,11 +605,28 @@ MatrixClient.prototype.setRoomEncryption = function(roomId, config) {
* @return {bool} whether encryption is enabled. * @return {bool} whether encryption is enabled.
*/ */
MatrixClient.prototype.isRoomEncrypted = function(roomId) { MatrixClient.prototype.isRoomEncrypted = function(roomId) {
if (!this._crypto) { const room = this.getRoom(roomId);
if (!room) {
// we don't know about this room, so can't determine if it should be
// encrypted. Let's assume not.
return false; return false;
} }
return this._crypto.isRoomEncrypted(roomId); // if there is an 'm.room.encryption' event in this room, it should be
// encrypted (independently of whether we actually support encryption)
const ev = room.currentState.getStateEvents("m.room.encryption", "");
if (ev) {
return true;
}
// we don't have an m.room.encrypted event, but that might be because
// the server is hiding it from us. Check the store to see if it was
// previously encrypted.
if (!this._sessionStore) {
return false;
}
return Boolean(this._sessionStore.getEndToEndRoom(roomId));
}; };
/** /**
@@ -997,17 +1014,16 @@ function _sendEvent(client, room, event, callback) {
// so that we can handle synchronous and asynchronous exceptions with the // so that we can handle synchronous and asynchronous exceptions with the
// same code path. // same code path.
return Promise.resolve().then(function() { return Promise.resolve().then(function() {
let encryptionPromise = null; const encryptionPromise = _encryptEventIfNeeded(client, event, room);
if (client._crypto) {
encryptionPromise = client._crypto.encryptEventIfNeeded(event, room); if (!encryptionPromise) {
return null;
} }
if (encryptionPromise) {
_updatePendingEventStatus(room, event, EventStatus.ENCRYPTING); _updatePendingEventStatus(room, event, EventStatus.ENCRYPTING);
encryptionPromise = encryptionPromise.then(function() { return encryptionPromise.then(() => {
_updatePendingEventStatus(room, event, EventStatus.SENDING); _updatePendingEventStatus(room, event, EventStatus.SENDING);
}); });
}
return encryptionPromise;
}).then(function() { }).then(function() {
let promise; let promise;
// this event may be queued // this event may be queued
@@ -1054,6 +1070,43 @@ function _sendEvent(client, room, event, callback) {
}); });
} }
/**
* Encrypt an event according to the configuration of the room, if necessary.
*
* @param {MatrixClient} client
*
* @param {module:models/event.MatrixEvent} event event to be sent
*
* @param {module:models/room?} room destination room. Null if the destination
* is not a room we have seen over the sync pipe.
*
* @return {module:client.Promise?} Promise which resolves when the event has been
* encrypted, or null if nothing was needed
*/
function _encryptEventIfNeeded(client, event, room) {
if (event.isEncrypted()) {
// this event has already been encrypted; this happens if the
// encryption step succeeded, but the send step failed on the first
// attempt.
return null;
}
if (!client.isRoomEncrypted(event.getRoomId())) {
// looks like this room isn't encrypted.
return null;
}
if (!client._crypto) {
throw new Error(
"This room is configured to use encryption, but your client does " +
"not support encryption.",
);
}
return client._crypto.encryptEvent(event, room);
}
function _updatePendingEventStatus(room, event, newStatus) { function _updatePendingEventStatus(room, event, newStatus) {
if (room) { if (room) {
room.updatePendingEvent(event, newStatus); room.updatePendingEvent(event, newStatus);

View File

@@ -723,24 +723,16 @@ Crypto.prototype.importRoomKeys = function(keys) {
}; };
/** /**
* Encrypt an event according to the configuration of the room, if necessary. * Encrypt an event according to the configuration of the room.
* *
* @param {module:models/event.MatrixEvent} event event to be sent * @param {module:models/event.MatrixEvent} event event to be sent
* *
* @param {module:models/room?} room destination room. Null if the destination * @param {module:models/room} room destination room.
* is not a room we have seen over the sync pipe.
* *
* @return {module:client.Promise?} Promise which resolves when the event has been * @return {module:client.Promise?} Promise which resolves when the event has been
* encrypted, or null if nothing was needed * encrypted, or null if nothing was needed
*/ */
Crypto.prototype.encryptEventIfNeeded = function(event, room) { Crypto.prototype.encryptEvent = function(event, room) {
if (event.isEncrypted()) {
// this event has already been encrypted; this happens if the
// encryption step succeeded, but the send step failed on the first
// attempt.
return null;
}
if (!room) { if (!room) {
throw new Error("Cannot send encrypted messages in unknown rooms"); throw new Error("Cannot send encrypted messages in unknown rooms");
} }
@@ -749,18 +741,14 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) {
const alg = this._roomEncryptors[roomId]; const alg = this._roomEncryptors[roomId];
if (!alg) { if (!alg) {
// not encrypting messages in this room // MatrixClient has already checked that this room should be encrypted,
// so this is an unexpected situation.
// check that the HS hasn't hidden the crypto event
if (this._sessionStore.getEndToEndRoom(roomId)) {
throw new Error( throw new Error(
"Room was previously configured to use encryption, but is " + "Room was previously configured to use encryption, but is " +
"no longer. Perhaps the homeserver is hiding the " + "no longer. Perhaps the homeserver is hiding the " +
"configuration event.", "configuration event.",
); );
} }
return null;
}
return alg.encryptMessage( return alg.encryptMessage(
room, event.getType(), event.getContent(), room, event.getType(), event.getContent(),