Skip to content

Commit

Permalink
Merge pull request #962 from matrix-org/travis/sas-cancel
Browse files Browse the repository at this point in the history
Don't handle key verification requests which are immediately cancelled
  • Loading branch information
turt2live authored Jun 20, 2019
2 parents 81eefc1 + 6d09231 commit 5538575
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/crypto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,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"
Expand Down Expand Up @@ -1764,6 +1769,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;
Expand Down
20 changes: 20 additions & 0 deletions src/models/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ module.exports.MatrixEvent = function MatrixEvent(
this._pushActions = null;
this._replacingEvent = null;
this._locallyRedacted = false;
this._isCancelled = false;

this._clearEvent = {};

Expand Down Expand Up @@ -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
* decrypted and encrypted view of the event. This is named `toJSON` for use
Expand Down
26 changes: 26 additions & 0 deletions src/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -1043,8 +1043,26 @@ SyncApi.prototype._processSyncResponse = async function(
if (data.to_device && utils.isArray(data.to_device.events) &&
data.to_device.events.length > 0
) {
const cancelledKeyVerificationTxns = [];
data.to_device.events
.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(
function(toDeviceEvent) {
const content = toDeviceEvent.getContent();
Expand All @@ -1060,6 +1078,14 @@ SyncApi.prototype._processSyncResponse = async function(
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);
},
);
Expand Down

0 comments on commit 5538575

Please sign in to comment.