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
Don't handle key verification requests which are immediately cancelled
Fixes https://github.com/vector-im/riot-web/issues/10083 Fixes https://github.com/vector-im/riot-web/issues/9197 Fixes https://github.com/vector-im/riot-web/issues/8629 The issue is partially fixed by https://github.com/matrix-org/matrix-react-sdk/pull/3123 in that users would no longer see "Incoming request", but would launch their client to a bunch of "key verification cancelled" dialogs. To work around this, we just don't handle key verification requests which we know are cancelled. The changes are a bit awkward (flagging the event as cancelled instead of filtering it) because: * We probably don't want to prevent events getting sent over the EventEmitter because applications may still rely on them. * The cypto side only has visibility of 1 event at a time, so it needs to have some kind of flag to rely on. An attempt has been made to generalize the new event flag for possible future cases.
This commit is contained in:
@@ -1648,6 +1648,11 @@ Crypto.prototype._onRoomKeyEvent = function(event) {
|
|||||||
* @param {module:models/event.MatrixEvent} event verification request event
|
* @param {module:models/event.MatrixEvent} event verification request event
|
||||||
*/
|
*/
|
||||||
Crypto.prototype._onKeyVerificationRequest = function(event) {
|
Crypto.prototype._onKeyVerificationRequest = function(event) {
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
logger.warn("Ignoring flagged verification request from " + event.getSender());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const content = event.getContent();
|
const content = event.getContent();
|
||||||
if (!("from_device" in content) || typeof content.from_device !== "string"
|
if (!("from_device" in content) || typeof content.from_device !== "string"
|
||||||
|| !("transaction_id" in content) || typeof content.from_device !== "string"
|
|| !("transaction_id" in content) || typeof content.from_device !== "string"
|
||||||
@@ -1764,6 +1769,11 @@ Crypto.prototype._onKeyVerificationRequest = function(event) {
|
|||||||
* @param {module:models/event.MatrixEvent} event verification start event
|
* @param {module:models/event.MatrixEvent} event verification start event
|
||||||
*/
|
*/
|
||||||
Crypto.prototype._onKeyVerificationStart = function(event) {
|
Crypto.prototype._onKeyVerificationStart = function(event) {
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
logger.warn("Ignoring flagged verification start from " + event.getSender());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const sender = event.getSender();
|
const sender = event.getSender();
|
||||||
const content = event.getContent();
|
const content = event.getContent();
|
||||||
const transactionId = content.transaction_id;
|
const transactionId = content.transaction_id;
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ module.exports.MatrixEvent = function MatrixEvent(
|
|||||||
this._pushActions = null;
|
this._pushActions = null;
|
||||||
this._replacingEvent = null;
|
this._replacingEvent = null;
|
||||||
this._locallyRedacted = false;
|
this._locallyRedacted = false;
|
||||||
|
this._isCancelled = false;
|
||||||
|
|
||||||
this._clearEvent = {};
|
this._clearEvent = {};
|
||||||
|
|
||||||
@@ -956,6 +957,25 @@ utils.extend(module.exports.MatrixEvent.prototype, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags an event as cancelled due to future conditions. For example, a verification
|
||||||
|
* request event in the same sync transaction may be flagged as cancelled to warn
|
||||||
|
* listeners that a cancellation event is coming down the same pipe shortly.
|
||||||
|
* @param {boolean} cancelled Whether the event is to be cancelled or not.
|
||||||
|
*/
|
||||||
|
flagCancelled(cancelled = true) {
|
||||||
|
this._isCancelled = cancelled;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets whether or not the event is flagged as cancelled. See flagCancelled() for
|
||||||
|
* more information.
|
||||||
|
* @returns {boolean} True if the event is cancelled, false otherwise.
|
||||||
|
*/
|
||||||
|
isCancelled() {
|
||||||
|
return this._isCancelled;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Summarise the event as JSON for debugging. If encrypted, include both the
|
* Summarise the event as JSON for debugging. If encrypted, include both the
|
||||||
* decrypted and encrypted view of the event. This is named `toJSON` for use
|
* decrypted and encrypted view of the event. This is named `toJSON` for use
|
||||||
|
|||||||
26
src/sync.js
26
src/sync.js
@@ -1043,8 +1043,26 @@ SyncApi.prototype._processSyncResponse = async function(
|
|||||||
if (data.to_device && utils.isArray(data.to_device.events) &&
|
if (data.to_device && utils.isArray(data.to_device.events) &&
|
||||||
data.to_device.events.length > 0
|
data.to_device.events.length > 0
|
||||||
) {
|
) {
|
||||||
|
const cancelledKeyVerificationTxns = [];
|
||||||
data.to_device.events
|
data.to_device.events
|
||||||
.map(client.getEventMapper())
|
.map(client.getEventMapper())
|
||||||
|
.map((toDeviceEvent) => { // map is a cheap inline forEach
|
||||||
|
// We want to flag m.key.verification.start events as cancelled
|
||||||
|
// if there's an accompanying m.key.verification.cancel event, so
|
||||||
|
// we pull out the transaction IDs from the cancellation events
|
||||||
|
// so we can flag the verification events as cancelled in the loop
|
||||||
|
// below.
|
||||||
|
if (toDeviceEvent.getType() === "m.key.verification.cancel") {
|
||||||
|
const txnId = toDeviceEvent.getContent()['transaction_id'];
|
||||||
|
if (txnId) {
|
||||||
|
cancelledKeyVerificationTxns.push(txnId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// as mentioned above, .map is a cheap inline forEach, so return
|
||||||
|
// the unmodified event.
|
||||||
|
return toDeviceEvent;
|
||||||
|
})
|
||||||
.forEach(
|
.forEach(
|
||||||
function(toDeviceEvent) {
|
function(toDeviceEvent) {
|
||||||
const content = toDeviceEvent.getContent();
|
const content = toDeviceEvent.getContent();
|
||||||
@@ -1060,6 +1078,14 @@ SyncApi.prototype._processSyncResponse = async function(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (toDeviceEvent.getType() === "m.key.verification.start"
|
||||||
|
|| toDeviceEvent.getType() === "m.key.verification.request") {
|
||||||
|
const txnId = content['transaction_id'];
|
||||||
|
if (cancelledKeyVerificationTxns.includes(txnId)) {
|
||||||
|
toDeviceEvent.flagCancelled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
client.emit("toDeviceEvent", toDeviceEvent);
|
client.emit("toDeviceEvent", toDeviceEvent);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user