1
0
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:
Kegan Dougal
2017-02-10 16:11:05 +00:00
12 changed files with 256 additions and 85 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
};

View File

@@ -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,
},
);
}

View File

@@ -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();
}
}

View File

@@ -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;
}