You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-26 17:03:12 +03:00
Processing of received room key requests
Doesn't actually do any of the crypto magic yet.
This commit is contained in:
@@ -40,6 +40,8 @@ const SyncApi = require("./sync");
|
|||||||
const MatrixBaseApis = require("./base-apis");
|
const MatrixBaseApis = require("./base-apis");
|
||||||
const MatrixError = httpApi.MatrixError;
|
const MatrixError = httpApi.MatrixError;
|
||||||
|
|
||||||
|
import reEmit from './reemit';
|
||||||
|
|
||||||
const SCROLLBACK_DELAY_MS = 3000;
|
const SCROLLBACK_DELAY_MS = 3000;
|
||||||
let CRYPTO_ENABLED = false;
|
let CRYPTO_ENABLED = false;
|
||||||
|
|
||||||
@@ -166,6 +168,9 @@ function MatrixClient(opts) {
|
|||||||
this.store,
|
this.store,
|
||||||
opts.cryptoStore,
|
opts.cryptoStore,
|
||||||
);
|
);
|
||||||
|
reEmit(this, this._crypto, [
|
||||||
|
"crypto.roomKeyRequest",
|
||||||
|
]);
|
||||||
|
|
||||||
this.olmVersion = Crypto.getOlmVersion();
|
this.olmVersion = Crypto.getOlmVersion();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,26 @@ class DecryptionAlgorithm {
|
|||||||
importRoomKey(session) {
|
importRoomKey(session) {
|
||||||
// ignore by default
|
// ignore by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if we have the keys necessary to respond to a room key request
|
||||||
|
*
|
||||||
|
* @param {module:crypto#RoomKeyRequest} keyRequest
|
||||||
|
* @return {boolean} true if we have the keys and could (theoretically) share
|
||||||
|
* them; else false.
|
||||||
|
*/
|
||||||
|
hasKeysForKeyRequest(keyRequest) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the response to a room key request
|
||||||
|
*
|
||||||
|
* @param {module:crypto#RoomKeyRequest} keyRequest
|
||||||
|
*/
|
||||||
|
shareKeysWithDevice(keyRequest) {
|
||||||
|
throw new Error("shareKeysWithDevice not supported for this DecryptionAlgorithm");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export {DecryptionAlgorithm}; // https://github.com/jsdoc3/jsdoc/issues/1272
|
export {DecryptionAlgorithm}; // https://github.com/jsdoc3/jsdoc/issues/1272
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ limitations under the License.
|
|||||||
|
|
||||||
const anotherjson = require('another-json');
|
const anotherjson = require('another-json');
|
||||||
const q = require("q");
|
const q = require("q");
|
||||||
|
import {EventEmitter} from 'events';
|
||||||
|
|
||||||
const utils = require("../utils");
|
const utils = require("../utils");
|
||||||
const OlmDevice = require("./OlmDevice");
|
const OlmDevice = require("./OlmDevice");
|
||||||
@@ -93,6 +94,9 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId,
|
|||||||
|
|
||||||
this._globalBlacklistUnverifiedDevices = false;
|
this._globalBlacklistUnverifiedDevices = false;
|
||||||
|
|
||||||
|
// list of IncomingRoomKeyRequests we received in the current sync.
|
||||||
|
this._receivedRoomKeyRequests = [];
|
||||||
|
|
||||||
let myDevices = this._sessionStore.getEndToEndDevicesForUser(
|
let myDevices = this._sessionStore.getEndToEndDevicesForUser(
|
||||||
this._userId,
|
this._userId,
|
||||||
);
|
);
|
||||||
@@ -118,6 +122,8 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId,
|
|||||||
|
|
||||||
_registerEventHandlers(this, eventEmitter);
|
_registerEventHandlers(this, eventEmitter);
|
||||||
}
|
}
|
||||||
|
utils.inherits(Crypto, EventEmitter);
|
||||||
|
|
||||||
|
|
||||||
function _registerEventHandlers(crypto, eventEmitter) {
|
function _registerEventHandlers(crypto, eventEmitter) {
|
||||||
eventEmitter.on("sync", function(syncState, oldState, data) {
|
eventEmitter.on("sync", function(syncState, oldState, data) {
|
||||||
@@ -149,6 +155,8 @@ function _registerEventHandlers(crypto, eventEmitter) {
|
|||||||
crypto._onRoomKeyEvent(event);
|
crypto._onRoomKeyEvent(event);
|
||||||
} else if (event.getType() == "m.new_device") {
|
} else if (event.getType() == "m.new_device") {
|
||||||
crypto._onNewDeviceEvent(event);
|
crypto._onNewDeviceEvent(event);
|
||||||
|
} else if (event.getType() == "m.room_key_request") {
|
||||||
|
crypto._onRoomKeyRequestEvent(event);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error handling toDeviceEvent:", e);
|
console.error("Error handling toDeviceEvent:", e);
|
||||||
@@ -868,6 +876,7 @@ Crypto.prototype._onSyncCompleted = function(syncData) {
|
|||||||
// (https://github.com/vector-im/riot-web/issues/2782).
|
// (https://github.com/vector-im/riot-web/issues/2782).
|
||||||
if (!syncData.catchingUp) {
|
if (!syncData.catchingUp) {
|
||||||
_maybeUploadOneTimeKeys(this);
|
_maybeUploadOneTimeKeys(this);
|
||||||
|
this._processReceivedRoomKeyRequests();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1056,6 +1065,89 @@ Crypto.prototype._onNewDeviceEvent = function(event) {
|
|||||||
this._deviceList.invalidateUserDeviceList(userId);
|
this._deviceList.invalidateUserDeviceList(userId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when we get an m.room_key_request event.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {module:models/event.MatrixEvent} event key request event
|
||||||
|
*/
|
||||||
|
Crypto.prototype._onRoomKeyRequestEvent = function(event) {
|
||||||
|
const content = event.getContent();
|
||||||
|
if (content.action === "request") {
|
||||||
|
// Queue it up for now, because they tend to arrive before the room state
|
||||||
|
// events at initial sync, and we want to see if we know anything about the
|
||||||
|
// room before passing them on to the app.
|
||||||
|
const req = new IncomingRoomKeyRequest(event);
|
||||||
|
this._receivedRoomKeyRequests.push(req);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process any m.room_key_request events which were queued up during the
|
||||||
|
* current sync.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
Crypto.prototype._processReceivedRoomKeyRequests = function() {
|
||||||
|
const requests = this._receivedRoomKeyRequests;
|
||||||
|
this._receivedRoomKeyRequests = [];
|
||||||
|
for (const req of requests) {
|
||||||
|
const userId = req.userId;
|
||||||
|
const deviceId = req.deviceId;
|
||||||
|
|
||||||
|
const body = req.requestBody;
|
||||||
|
const roomId = body.room_id;
|
||||||
|
const alg = body.algorithm;
|
||||||
|
|
||||||
|
console.log(`m.room_key_request from ${userId}:${deviceId}` +
|
||||||
|
` for ${roomId} / ${body.session_id}`);
|
||||||
|
|
||||||
|
if (userId !== this._userId) {
|
||||||
|
// TODO: determine if we sent this device the keys already: in
|
||||||
|
// which case we can do so again.
|
||||||
|
console.log("Ignoring room key request from other user for now");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: should we queue up requests we don't yet have keys for,
|
||||||
|
// in case they turn up later?
|
||||||
|
|
||||||
|
// if we don't have a decryptor for this room/alg, we don't have
|
||||||
|
// the keys for the requested events, and can drop the requests.
|
||||||
|
if (!this._roomDecryptors[roomId]) {
|
||||||
|
console.log(`room key request for unencrypted room ${roomId}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const decryptor = this._roomDecryptors[roomId][alg];
|
||||||
|
if (!decryptor) {
|
||||||
|
console.log(`room key request for unknown alg ${alg} in room ${roomId}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decryptor.hasKeysForKeyRequest(req)) {
|
||||||
|
console.log(
|
||||||
|
`room key request for unknown session ${roomId} / ` +
|
||||||
|
body.session_id,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
req._shareCallback = () => {
|
||||||
|
decryptor.shareKeysWithDevice(req);
|
||||||
|
};
|
||||||
|
|
||||||
|
// if the device is is verified already, share the keys
|
||||||
|
const device = this._deviceList.getStoredDevice(userId, deviceId);
|
||||||
|
if (device && device.isVerified()) {
|
||||||
|
console.log('device is already verified: sharing keys');
|
||||||
|
req.share();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emit("crypto.roomKeyRequest", req);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a decryptor for a given room and algorithm.
|
* Get a decryptor for a given room and algorithm.
|
||||||
@@ -1126,5 +1218,42 @@ Crypto.prototype._signObject = function(obj) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a received m.room_key_request event
|
||||||
|
*
|
||||||
|
* @property {string} userId user requesting the key
|
||||||
|
* @property {string} deviceId device requesting the key
|
||||||
|
* @property {RoomKeyRequestBody} requestBody
|
||||||
|
*/
|
||||||
|
class IncomingRoomKeyRequest {
|
||||||
|
constructor(event) {
|
||||||
|
const content = event.getContent();
|
||||||
|
|
||||||
|
this.userId = event.getSender();
|
||||||
|
this.deviceId = content.requesting_device_id;
|
||||||
|
this.requestBody = content.body || {};
|
||||||
|
this._shareCallback = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the relevant crypto algorithm implementation to share the keys for
|
||||||
|
* this request
|
||||||
|
*/
|
||||||
|
share() {
|
||||||
|
if (this._shareCallback) {
|
||||||
|
this._shareCallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Error("don't know how to share keys for this request yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires when we receive a room key request
|
||||||
|
*
|
||||||
|
* @event module:client~MatrixClient#"crypto.roomKeyRequest"
|
||||||
|
* @param {module:crypto~IncomingRoomKeyRequest} req request details
|
||||||
|
*/
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
module.exports = Crypto;
|
module.exports = Crypto;
|
||||||
|
|||||||
Reference in New Issue
Block a user