1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-26 17:03:12 +03:00

Merge remote-tracking branch 'origin/develop' into dbkr/cross_signing

This commit is contained in:
David Baker
2019-10-28 16:47:16 +00:00
47 changed files with 2968 additions and 862 deletions

View File

@@ -1224,6 +1224,132 @@ Crypto.prototype.setDeviceVerification = async function(
};
function verificationEventHandler(target, userId, roomId, eventId) {
return function(event) {
// listen for events related to this verification
if (event.getRoomId() !== roomId
|| event.getSender() !== userId) {
return;
}
const content = event.getContent();
if (!content["m.relates_to"]) {
return;
}
const relatesTo
= content["m.relationship"] || content["m.relates_to"];
if (!relatesTo.rel_type
|| relatesTo.rel_type !== "m.reference"
|| !relatesTo.event_id
|| relatesTo.event_id !== eventId) {
return;
}
// the event seems to be related to this verification, so pass it on to
// the verification handler
target.handleEvent(event);
};
}
Crypto.prototype.requestVerificationDM = async function(userId, roomId, methods) {
let methodMap;
if (methods) {
methodMap = new Map();
for (const method of methods) {
if (typeof method === "string") {
methodMap.set(method, defaultVerificationMethods[method]);
} else if (method.NAME) {
methodMap.set(method.NAME, method);
}
}
} else {
methodMap = this._baseApis._crypto._verificationMethods;
}
let eventId = undefined;
const listenPromise = new Promise((_resolve, _reject) => {
const listener = (event) => {
// listen for events related to this verification
if (event.getRoomId() !== roomId
|| event.getSender() !== userId) {
return;
}
const relatesTo = event.getRelation();
if (!relatesTo || !relatesTo.rel_type
|| relatesTo.rel_type !== "m.reference"
|| !relatesTo.event_id
|| relatesTo.event_id !== eventId) {
return;
}
const content = event.getContent();
// the event seems to be related to this verification
switch (event.getType()) {
case "m.key.verification.start": {
const verifier = new (methodMap.get(content.method))(
this._baseApis, userId, content.from_device, eventId,
roomId, event,
);
verifier.handler = verificationEventHandler(
verifier, userId, roomId, eventId,
);
// this handler gets removed when the verification finishes
// (see the verify method of crypto/verification/Base.js)
this._baseApis.on("event", verifier.handler);
resolve(verifier);
break;
}
case "m.key.verification.cancel": {
reject(event);
break;
}
}
};
this._baseApis.on("event", listener);
const resolve = (...args) => {
this._baseApis.off("event", listener);
_resolve(...args);
};
const reject = (...args) => {
this._baseApis.off("event", listener);
_reject(...args);
};
});
const res = await this._baseApis.sendEvent(
roomId, "m.room.message",
{
body: this._baseApis.getUserId() + " is requesting to verify " +
"your key, but your client does not support in-chat key " +
"verification. You will need to use legacy key " +
"verification to verify keys.",
msgtype: "m.key.verification.request",
to: userId,
from_device: this._baseApis.getDeviceId(),
methods: [...methodMap.keys()],
},
);
eventId = res.event_id;
return listenPromise;
};
Crypto.prototype.acceptVerificationDM = function(event, Method) {
if (typeof(Method) === "string") {
Method = defaultVerificationMethods[Method];
}
const content = event.getContent();
const verifier = new Method(
this._baseApis, event.getSender(), content.from_device, event.getId(),
event.getRoomId(),
);
verifier.handler = verificationEventHandler(
verifier, event.getSender(), event.getRoomId(), event.getId(),
);
this._baseApis.on("event", verifier.handler);
return verifier;
};
Crypto.prototype.requestVerification = function(userId, methods, devices) {
if (!methods) {
// .keys() returns an iterator, so we need to explicitly turn it into an array
@@ -1271,20 +1397,7 @@ Crypto.prototype.beginKeyVerification = function(
this._verificationTransactions.set(userId, new Map());
}
transactionId = transactionId || randomString(32);
if (method instanceof Array) {
if (method.length !== 2
|| !this._verificationMethods.has(method[0])
|| !this._verificationMethods.has(method[1])) {
throw newUnknownMethodError();
}
/*
return new TwoPartVerification(
this._verificationMethods[method[0]],
this._verificationMethods[method[1]],
userId, deviceId, transactionId,
);
*/
} else if (this._verificationMethods.has(method)) {
if (this._verificationMethods.has(method)) {
const verifier = new (this._verificationMethods.get(method))(
this._baseApis, userId, deviceId, transactionId,
);
@@ -1419,6 +1532,15 @@ Crypto.prototype.forceDiscardSession = function(roomId) {
* the device query is always inhibited as the members are not tracked.
*/
Crypto.prototype.setRoomEncryption = async function(roomId, config, inhibitDeviceQuery) {
// ignore crypto events with no algorithm defined
// This will happen if a crypto event is redacted before we fetch the room state
// It would otherwise just throw later as an unknown algorithm would, but we may
// as well catch this here
if (!config.algorithm) {
console.log("Ignoring setRoomEncryption with no algorithm");
return;
}
// if state is being replayed from storage, we might already have a configuration
// for this room as they are persisted as well.
// We just need to make sure the algorithm is initialized in this case.
@@ -1756,6 +1878,18 @@ Crypto.prototype.backupGroupSession = async function(
* upload in the background as soon as possible.
*/
Crypto.prototype.scheduleAllGroupSessionsForBackup = async function() {
await this.flagAllGroupSessionsForBackup();
// Schedule keys to upload in the background as soon as possible.
this.scheduleKeyBackupSend(0 /* maxDelay */);
};
/**
* Marks all group sessions as needing to be backed up without scheduling
* them to upload in the background.
* @returns {Promise<int>} Resolves to the number of sessions requiring a backup.
*/
Crypto.prototype.flagAllGroupSessionsForBackup = async function() {
await this._cryptoStore.doTxn(
'readwrite',
[
@@ -1773,9 +1907,7 @@ Crypto.prototype.scheduleAllGroupSessionsForBackup = async function() {
const remaining = await this._cryptoStore.countSessionsNeedingBackup();
this.emit("crypto.keyBackupSessionsRemaining", remaining);
// Schedule keys to upload in the background as soon as possible.
this.scheduleKeyBackupSend(0 /* maxDelay */);
return remaining;
};
/* eslint-disable valid-jsdoc */ //https://github.com/eslint/eslint/issues/7307
@@ -2122,6 +2254,11 @@ Crypto.prototype._onRoomKeyEvent = function(event) {
* @param {module:models/event.MatrixEvent} event verification request event
*/
Crypto.prototype._onKeyVerificationRequest = function(event) {
if (event.isCancelled()) {
logger.warn("Ignoring flagged verification request from " + event.getSender());
return;
}
const content = event.getContent();
if (!("from_device" in content) || typeof content.from_device !== "string"
|| !("transaction_id" in content) || typeof content.from_device !== "string"
@@ -2238,6 +2375,11 @@ Crypto.prototype._onKeyVerificationRequest = function(event) {
* @param {module:models/event.MatrixEvent} event verification start event
*/
Crypto.prototype._onKeyVerificationStart = function(event) {
if (event.isCancelled()) {
logger.warn("Ignoring flagged verification start from " + event.getSender());
return;
}
const sender = event.getSender();
const content = event.getContent();
const transactionId = content.transaction_id;
@@ -2271,22 +2413,6 @@ Crypto.prototype._onKeyVerificationStart = function(event) {
transaction_id: content.transactionId,
}));
return;
} else if (content.next_method) {
if (!this._verificationMethods.has(content.next_method)) {
cancel(newUnknownMethodError({
transaction_id: content.transactionId,
}));
return;
} else {
/* TODO:
const verification = new TwoPartVerification(
this._verificationMethods[content.method],
this._verificationMethods[content.next_method],
userId, deviceId,
);
this.emit(verification.event_type, verification);
this.emit(verification.first.event_type, verification);*/
}
} else {
const verifier = new (this._verificationMethods.get(content.method))(
this._baseApis, sender, deviceId, content.transaction_id,
@@ -2341,8 +2467,6 @@ Crypto.prototype._onKeyVerificationStart = function(event) {
handler.request.resolve(verifier);
}
} else {
// FIXME: make sure we're in a two-part verification, and the start matches the second part
}
}
this._baseApis.emit("crypto.verification.start", verifier);