Skip to content

Commit

Permalink
Merge pull request #178 from matrix-org/rav/refactor_ensuresessions
Browse files Browse the repository at this point in the history
Change the result structure for ensureOlmSessionsForUsers
  • Loading branch information
richvdh authored Aug 23, 2016
2 parents e4bfb3c + df43b19 commit c72f613
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 41 deletions.
9 changes: 9 additions & 0 deletions lib/crypto-deviceinfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ DeviceInfo.prototype.getFingerprint = function() {
return this.keys["ed25519:" + this.deviceId];
};

/**
* Get the identity key for this device (ie, the Curve25519 key)
*
* @return {string} base64-encoded identity key of this device
*/
DeviceInfo.prototype.getIdentityKey = function() {
return this.keys["curve25519:" + this.deviceId];
};

/**
* Get the configured display name for this device, if any
*
Expand Down
97 changes: 60 additions & 37 deletions lib/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -546,56 +546,81 @@ Crypto.prototype.setRoomEncryption = function(roomId, config, roomMembers) {
return alg.initRoomEncryption(roomMembers);
};


/**
* @typedef {Object} module:crypto~OlmSessionResult
* @property {module:crypto-deviceinfo} device device info
* @property {string?} sessionId base64 olm session id; null if no session
* could be established
*/

/**
* Try to make sure we have established olm sessions for the given users.
*
* @param {string[]} users list of user ids
*
* @return {module:client.Promise} resolves once the sessions are complete, to
* an object with keys <tt>missingUsers</tt> (a list of users with no known
* olm devices), and <tt>missingDevices</tt> a list of olm devices with no
* known one-time keys.
* an Object mapping from userId to deviceId to
* {@link module:crypto~OlmSessionResult}
*/
Crypto.prototype.ensureOlmSessionsForUsers = function(users) {
var devicesWithoutSession = [];
var userWithoutDevices = [];
var devicesWithoutSession = [
// [userId, deviceId, deviceInfo], ...
];
var result = {};

for (var i = 0; i < users.length; ++i) {
var userId = users[i];
var devices = this._sessionStore.getEndToEndDevicesForUser(userId);
if (!devices) {
userWithoutDevices.push(userId);
} else {
for (var deviceId in devices) {
if (devices.hasOwnProperty(deviceId)) {
var keys = devices[deviceId];
var key = keys.keys["curve25519:" + deviceId];
if (key == this._olmDevice.deviceCurve25519Key) {
continue;
}
if (!this._sessionStore.getEndToEndSessions(key)) {
devicesWithoutSession.push([userId, deviceId, key]);
}
}
result[userId] = {};

var devices = this.getStoredDevicesForUser(userId);
for (var j = 0; j < devices.length; ++j) {
var deviceInfo = devices[j];
var deviceId = deviceInfo.deviceId;

var key = deviceInfo.getIdentityKey();
if (key == this._olmDevice.deviceCurve25519Key) {
// don't bother setting up session to ourself
continue;
}
if (deviceInfo.verified == DeviceVerification.BLOCKED) {
// don't bother setting up sessions with blocked users
continue;
}

var sessionId = this._olmDevice.getSessionIdForDevice(key);
if (sessionId === null) {
devicesWithoutSession.push([userId, deviceId, deviceInfo]);
}
result[userId][deviceId] = {
device: deviceInfo,
sessionId: sessionId,
};
}
}

if (devicesWithoutSession.length === 0) {
return q({
missingUsers: userWithoutDevices,
missingDevices: []
});
return q(result);
}

// TODO: this has a race condition - if we try to send another message
// while we are claiming a key, we will end up claiming two and setting up
// two sessions.
//
// That should eventually resolve itself, but it's poor form.

var self = this;
return this._baseApis.claimOneTimeKeys(
devicesWithoutSession
).then(function(res) {
var missing = {};
for (i = 0; i < devicesWithoutSession.length; ++i) {
for (var i = 0; i < devicesWithoutSession.length; ++i) {
var device = devicesWithoutSession[i];
var userRes = res.one_time_keys[device[0]] || {};
var deviceRes = userRes[device[1]];
var userId = device[0];
var deviceId = device[1];
var deviceInfo = device[2];

var userRes = res.one_time_keys[userId] || {};
var deviceRes = userRes[deviceId];
var oneTimeKey;
for (var keyId in deviceRes) {
if (keyId.indexOf("curve25519:") === 0) {
Expand All @@ -604,20 +629,18 @@ Crypto.prototype.ensureOlmSessionsForUsers = function(users) {
}
if (oneTimeKey) {
var sid = self._olmDevice.createOutboundSession(
device[2], oneTimeKey
deviceInfo.getIdentityKey(), oneTimeKey
);
console.log("Started new sessionid " + sid +
" for device " + device[2]);
" for device " + userId + ":" + deviceId);

result[userId][deviceId].sessionId = sid;
} else {
missing[device[0]] = missing[device[0]] || [];
missing[device[0]].push([device[1]]);
console.warn("No one-time keys for device " +
userId + ":" + deviceId);
}
}

return {
missingUsers: userWithoutDevices,
missingDevices: missing
};
return result;
});
};

Expand Down
10 changes: 6 additions & 4 deletions spec/integ/matrix-client-crypto.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,9 @@ function aliEnablesEncryption() {
var p = aliClient.setRoomEncryption(roomId, {
algorithm: "m.olm.v1.curve25519-aes-sha2",
}).then(function(res) {
expect(res.missingUsers).toEqual([]);
expect(res.missingDevices).toEqual({});
expect(res[aliUserId]).toEqual({});
expect(res[bobUserId][bobDeviceId].device).toBeDefined();
expect(res[bobUserId][bobDeviceId].sessionId).toBeDefined();
expect(aliClient.isRoomEncrypted(roomId)).toBeTruthy();
});
aliHttpBackend.flush();
Expand All @@ -226,8 +227,9 @@ function bobEnablesEncryption() {
return bobClient.setRoomEncryption(roomId, {
algorithm: "m.olm.v1.curve25519-aes-sha2",
}).then(function(res) {
expect(res.missingUsers).toEqual([]);
expect(res.missingDevices).toEqual({});
expect(res[aliUserId][aliDeviceId].device).toBeDefined();
expect(res[aliUserId][aliDeviceId].sessionId).toBeDefined();
expect(res[bobUserId]).toEqual({});
expect(bobClient.isRoomEncrypted(roomId)).toBeTruthy();
});
}
Expand Down

0 comments on commit c72f613

Please sign in to comment.