You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-09 10:22:46 +03:00
Merge branch 'develop' into kegan/indexeddb
This commit is contained in:
@@ -556,6 +556,9 @@ function _decryptEvent(client, event) {
|
||||
try {
|
||||
client._crypto.decryptEvent(event);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`Error decrypting event (id=${event.getId()}): ${e}`,
|
||||
);
|
||||
if (!(e instanceof Crypto.DecryptionError)) {
|
||||
throw e;
|
||||
}
|
||||
|
@@ -64,7 +64,13 @@ export default class DeviceList {
|
||||
// just wait for the existing download to complete
|
||||
promises.push(this._keyDownloadsInProgressByUser[u]);
|
||||
} else {
|
||||
if (forceDownload || !this.getStoredDevicesForUser(u)) {
|
||||
if (forceDownload) {
|
||||
console.log("Invalidating device list for " + u +
|
||||
" for forceDownload");
|
||||
this.invalidateUserDeviceList(u);
|
||||
} else if (!this.getStoredDevicesForUser(u)) {
|
||||
console.log("Invalidating device list for " + u +
|
||||
" due to empty cache");
|
||||
this.invalidateUserDeviceList(u);
|
||||
}
|
||||
if (this._pendingUsersWithNewDevices[u]) {
|
||||
@@ -398,7 +404,7 @@ function _updateStoredDeviceKeysForUser(_olmDevice, userId, userStore,
|
||||
const signKeyId = "ed25519:" + deviceId;
|
||||
const signKey = deviceResult.keys[signKeyId];
|
||||
if (!signKey) {
|
||||
console.log("Device " + userId + ":" + deviceId +
|
||||
console.warn("Device " + userId + ":" + deviceId +
|
||||
" has no ed25519 key");
|
||||
return false;
|
||||
}
|
||||
@@ -408,8 +414,8 @@ function _updateStoredDeviceKeysForUser(_olmDevice, userId, userStore,
|
||||
try {
|
||||
olmlib.verifySignature(_olmDevice, deviceResult, userId, deviceId, signKey);
|
||||
} catch (e) {
|
||||
console.log("Unable to verify signature on device " +
|
||||
userId + ":" + deviceId + ":", e);
|
||||
console.warn("Unable to verify signature on device " +
|
||||
userId + ":" + deviceId + ":" + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -425,7 +431,7 @@ function _updateStoredDeviceKeysForUser(_olmDevice, userId, userStore,
|
||||
// best off sticking with the original keys.
|
||||
//
|
||||
// Should we warn the user about it somehow?
|
||||
console.warn("Ed25519 key for device" + userId + ": " +
|
||||
console.warn("Ed25519 key for device " + userId + ":" +
|
||||
deviceId + " has changed");
|
||||
return false;
|
||||
}
|
||||
|
@@ -148,14 +148,42 @@ DecryptionAlgorithm.prototype.importRoomKey = function(session) {
|
||||
/**
|
||||
* Exception thrown when decryption fails
|
||||
*
|
||||
* @alias module:crypto/algorithms/base.DecryptionError
|
||||
* @constructor
|
||||
* @param {string} msg message describing the problem
|
||||
* @param {string} msg user-visible message describing the problem
|
||||
*
|
||||
* @param {Object=} details key/value pairs reported in the logs but not shown
|
||||
* to the user.
|
||||
*
|
||||
* @extends Error
|
||||
*/
|
||||
module.exports.DecryptionError = function(msg) {
|
||||
const DecryptionError = function(msg, details) {
|
||||
this.name = 'DecryptionError';
|
||||
this.message = msg;
|
||||
this.details = details;
|
||||
};
|
||||
utils.inherits(module.exports.DecryptionError, Error);
|
||||
utils.inherits(DecryptionError, Error);
|
||||
|
||||
/** override the string used when logging
|
||||
*
|
||||
* @returns {String}
|
||||
*/
|
||||
DecryptionError.prototype.toString = function() {
|
||||
let result = this.name + '[msg: ' + this.message;
|
||||
|
||||
if (this.details) {
|
||||
result += ', ' +
|
||||
Object.keys(this.details).map(
|
||||
(k) => k + ': ' + this.details[k],
|
||||
).join(', ');
|
||||
}
|
||||
|
||||
result += ']';
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports.DecryptionError = DecryptionError;
|
||||
|
||||
/**
|
||||
* Exception thrown specifically when we want to warn the user to consider
|
||||
|
@@ -544,7 +544,11 @@ MegolmDecryption.prototype.decryptEvent = function(event) {
|
||||
if (e.message === 'OLM.UNKNOWN_MESSAGE_INDEX') {
|
||||
this._addEventToPendingList(event);
|
||||
}
|
||||
throw new base.DecryptionError(e);
|
||||
throw new base.DecryptionError(
|
||||
e.toString(), {
|
||||
session: content.sender_key + '|' + content.session_id,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (res === null) {
|
||||
@@ -552,6 +556,9 @@ MegolmDecryption.prototype.decryptEvent = function(event) {
|
||||
this._addEventToPendingList(event);
|
||||
throw new base.DecryptionError(
|
||||
"The sender's device has not sent us the keys for this message.",
|
||||
{
|
||||
session: content.sender_key + '|' + content.session_id,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -593,24 +600,30 @@ MegolmDecryption.prototype._addEventToPendingList = function(event) {
|
||||
* @param {module:models/event.MatrixEvent} event key event
|
||||
*/
|
||||
MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
|
||||
console.log("Adding key from ", event);
|
||||
const content = event.getContent();
|
||||
const senderKey = event.getSenderKey();
|
||||
const sessionId = content.session_id;
|
||||
|
||||
if (!content.room_id ||
|
||||
!content.session_id ||
|
||||
!sessionId ||
|
||||
!content.session_key
|
||||
) {
|
||||
console.error("key event is missing fields");
|
||||
return;
|
||||
}
|
||||
if (!senderKey) {
|
||||
console.error("key event has no sender key (not encrypted?)");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Adding key for megolm session ${senderKey}|${sessionId}`);
|
||||
this._olmDevice.addInboundGroupSession(
|
||||
content.room_id, event.getSenderKey(), content.session_id,
|
||||
content.room_id, senderKey, sessionId,
|
||||
content.session_key, event.getKeysClaimed(),
|
||||
);
|
||||
|
||||
// have another go at decrypting events sent with this session.
|
||||
this._retryDecryption(event.getSenderKey, content.session_id);
|
||||
this._retryDecryption(senderKey, sessionId);
|
||||
};
|
||||
|
||||
|
||||
|
@@ -64,7 +64,7 @@ OlmEncryption.prototype._ensureSession = function(roomMembers) {
|
||||
}
|
||||
|
||||
const self = this;
|
||||
this._prepPromise = self._crypto.downloadKeys(roomMembers, true).then(function(res) {
|
||||
this._prepPromise = self._crypto.downloadKeys(roomMembers).then(function(res) {
|
||||
return self._crypto.ensureOlmSessionsForUsers(roomMembers);
|
||||
}).then(function() {
|
||||
self._sessionPrepared = true;
|
||||
@@ -174,12 +174,12 @@ OlmDecryption.prototype.decryptEvent = function(event) {
|
||||
try {
|
||||
payloadString = this._decryptMessage(deviceKey, message);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
"Failed to decrypt Olm event (id=" +
|
||||
event.getId() + ") from " + deviceKey +
|
||||
": " + e.message,
|
||||
throw new base.DecryptionError(
|
||||
"Bad Encrypted Message", {
|
||||
sender: deviceKey,
|
||||
err: e,
|
||||
},
|
||||
);
|
||||
throw new base.DecryptionError("Bad Encrypted Message");
|
||||
}
|
||||
|
||||
const payload = JSON.parse(payloadString);
|
||||
@@ -187,22 +187,18 @@ OlmDecryption.prototype.decryptEvent = function(event) {
|
||||
// check that we were the intended recipient, to avoid unknown-key attack
|
||||
// https://github.com/vector-im/vector-web/issues/2483
|
||||
if (payload.recipient != this._userId) {
|
||||
console.warn(
|
||||
"Event " + event.getId() + ": Intended recipient " +
|
||||
payload.recipient + " does not match our id " + this._userId,
|
||||
);
|
||||
throw new base.DecryptionError(
|
||||
"Message was intented for " + payload.recipient,
|
||||
);
|
||||
}
|
||||
|
||||
if (payload.recipient_keys.ed25519 !=
|
||||
this._olmDevice.deviceEd25519Key) {
|
||||
console.warn(
|
||||
"Event " + event.getId() + ": Intended recipient ed25519 key " +
|
||||
payload.recipient_keys.ed25519 + " did not match ours",
|
||||
if (payload.recipient_keys.ed25519 != this._olmDevice.deviceEd25519Key) {
|
||||
throw new base.DecryptionError(
|
||||
"Message not intended for this device", {
|
||||
intended: payload.recipient_keys.ed25519,
|
||||
our_key: this._olmDevice.deviceEd25519Key,
|
||||
},
|
||||
);
|
||||
throw new base.DecryptionError("Message not intended for this device");
|
||||
}
|
||||
|
||||
// check that the original sender matches what the homeserver told us, to
|
||||
@@ -210,23 +206,19 @@ OlmDecryption.prototype.decryptEvent = function(event) {
|
||||
// (this check is also provided via the sender's embedded ed25519 key,
|
||||
// which is checked elsewhere).
|
||||
if (payload.sender != event.getSender()) {
|
||||
console.warn(
|
||||
"Event " + event.getId() + ": original sender " + payload.sender +
|
||||
" does not match reported sender " + event.getSender(),
|
||||
);
|
||||
throw new base.DecryptionError(
|
||||
"Message forwarded from " + payload.sender,
|
||||
"Message forwarded from " + payload.sender, {
|
||||
reported_sender: event.getSender(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Olm events intended for a room have a room_id.
|
||||
if (payload.room_id !== event.getRoomId()) {
|
||||
console.warn(
|
||||
"Event " + event.getId() + ": original room " + payload.room_id +
|
||||
" does not match reported room " + event.room_id,
|
||||
);
|
||||
throw new base.DecryptionError(
|
||||
"Message intended for room " + payload.room_id,
|
||||
"Message intended for room " + payload.room_id, {
|
||||
reported_room: event.room_id,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -86,9 +86,6 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId,
|
||||
);
|
||||
|
||||
if (!myDevices) {
|
||||
// we don't yet have a list of our own devices; make sure we
|
||||
// get one when we flush the pendingUsersWithNewDevices.
|
||||
this._deviceList.invalidateUserDeviceList(this._userId);
|
||||
myDevices = {};
|
||||
}
|
||||
|
||||
@@ -545,6 +542,23 @@ Crypto.prototype.setRoomEncryption = function(roomId, config) {
|
||||
config: config,
|
||||
});
|
||||
this._roomEncryptors[roomId] = alg;
|
||||
|
||||
// if encryption was not previously enabled in this room, we will have been
|
||||
// ignoring new device events for these users so far. We may well have
|
||||
// up-to-date lists for some users, for instance if we were sharing other
|
||||
// e2e rooms with them, so there is room for optimisation here, but for now
|
||||
// we just invalidate everyone in the room.
|
||||
if (!existingConfig) {
|
||||
console.log("Enabling encryption in " + roomId + " for the first time; " +
|
||||
"invalidating device lists for all users therein");
|
||||
const room = this._clientStore.getRoom(roomId);
|
||||
const members = room.getJoinedMembers();
|
||||
members.forEach((m) => {
|
||||
this._deviceList.invalidateUserDeviceList(m.userId);
|
||||
});
|
||||
// the actual refresh happens once we've finished processing the sync,
|
||||
// in _onSyncCompleted.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -769,6 +783,8 @@ Crypto.prototype._onSyncCompleted = function(syncData) {
|
||||
} else {
|
||||
// otherwise, we have to invalidate all devices for all users we
|
||||
// share a room with.
|
||||
console.log("Completed first initialsync; invalidating all " +
|
||||
"device list caches");
|
||||
this._invalidateDeviceListForAllActiveUsers();
|
||||
}
|
||||
}
|
||||
|
14
src/sync.js
14
src/sync.js
@@ -363,9 +363,6 @@ SyncApi.prototype.getSyncState = function() {
|
||||
* Main entry point
|
||||
*/
|
||||
SyncApi.prototype.sync = function() {
|
||||
debuglog("SyncApi.sync: starting with sync token " +
|
||||
this.client.store.getSyncToken());
|
||||
|
||||
const client = this.client;
|
||||
const self = this;
|
||||
|
||||
@@ -520,7 +517,7 @@ SyncApi.prototype._sync = function(syncOptions) {
|
||||
// Don't do an HTTP hit to /sync. Instead, load up the persisted /sync data,
|
||||
// if there is data there.
|
||||
if (data.nextBatch) {
|
||||
console.log("sync(): not doing HTTP hit, instead returning stored /sync");
|
||||
debuglog("sync(): not doing HTTP hit, instead returning stored /sync data");
|
||||
this._currentSyncRequest = q.resolve({
|
||||
next_batch: data.nextBatch,
|
||||
rooms: data.roomsData,
|
||||
@@ -530,12 +527,15 @@ SyncApi.prototype._sync = function(syncOptions) {
|
||||
}
|
||||
|
||||
if (!isCachedResponse) {
|
||||
debuglog('Starting sync since=' + syncToken);
|
||||
this._currentSyncRequest = client._http.authedRequest(
|
||||
undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs,
|
||||
);
|
||||
}
|
||||
|
||||
this._currentSyncRequest.done(function(data) {
|
||||
debuglog('Completed sync, next_batch=' + data.next_batch);
|
||||
|
||||
// set the sync token NOW *before* processing the events. We do this so
|
||||
// if something barfs on an event we can skip it rather than constantly
|
||||
// polling with the same token.
|
||||
@@ -697,8 +697,10 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
|
||||
toDeviceEvent.getType() == "m.room.message" &&
|
||||
content.msgtype == "m.bad.encrypted"
|
||||
) {
|
||||
console.warn(
|
||||
"Unable to decrypt to-device event: " + content.body,
|
||||
// the mapper already logged a warning.
|
||||
console.log(
|
||||
'Ignoring undecryptable to-device event from ' +
|
||||
toDeviceEvent.getSender(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user