From 0b51fc0168d7237c9266ea7e8f30dc7d2eaf0aa1 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 7 Mar 2023 17:27:27 +0530 Subject: [PATCH] Throw specific error when cancelled --- src/matrix/verification/CrossSigning.ts | 20 +++++- .../verification/SAS/SASVerification.ts | 15 +++- .../SAS/VerificationCancelledError.ts | 25 +++++++ .../verification/SAS/channel/Channel.ts | 59 ++++++++++++---- .../SAS/stages/BaseSASVerificationStage.ts | 11 --- .../SAS/stages/CalculateSASStage.ts | 17 ++--- .../SAS/stages/RequestVerificationStage.ts | 39 +---------- .../stages/SelectVerificationMethodStage.ts | 12 ++-- .../SAS/stages/SendAcceptVerificationStage.ts | 25 ++----- .../verification/SAS/stages/SendDoneStage.ts | 6 -- .../verification/SAS/stages/SendKeyStage.ts | 7 +- .../verification/SAS/stages/SendMacStage.ts | 6 +- .../verification/SAS/stages/SendReadyStage.ts | 12 +--- .../verification/SAS/stages/VerifyMacStage.ts | 8 +-- .../SAS/stages/WaitForIncomingMessageStage.ts | 69 ------------------- 15 files changed, 125 insertions(+), 206 deletions(-) create mode 100644 src/matrix/verification/SAS/VerificationCancelledError.ts delete mode 100644 src/matrix/verification/SAS/stages/WaitForIncomingMessageStage.ts diff --git a/src/matrix/verification/CrossSigning.ts b/src/matrix/verification/CrossSigning.ts index 2f152481..40b90585 100644 --- a/src/matrix/verification/CrossSigning.ts +++ b/src/matrix/verification/CrossSigning.ts @@ -45,6 +45,7 @@ export class CrossSigning { private readonly deviceMessageHandler: DeviceMessageHandler; private _isMasterKeyTrusted: boolean = false; private readonly deviceId: string; + private sasVerificationInProgress?: SASVerification; constructor(options: { storage: Storage, @@ -72,12 +73,20 @@ export class CrossSigning { this.deviceMessageHandler = options.deviceMessageHandler; this.deviceMessageHandler.on("message", async ({ unencrypted: unencryptedEvent }) => { + if (this.sasVerificationInProgress && + ( + !this.sasVerificationInProgress.finished || + // If the start message is for the previous sasverification, ignore it. + this.sasVerificationInProgress.channel.id === unencryptedEvent.content.transaction_id + )) { + return; + } console.log("unencrypted event", unencryptedEvent); if (unencryptedEvent.type === VerificationEventTypes.Request || unencryptedEvent.type === VerificationEventTypes.Start) { await this.platform.logger.run("Start verification from request", async (log) => { const sas = this.startVerification(unencryptedEvent.sender, log, unencryptedEvent); - await sas.start(); + await sas?.start(); }); } }) @@ -134,7 +143,10 @@ export class CrossSigning { return this._isMasterKeyTrusted; } - startVerification(userId: string, log: ILogItem, event?: any): SASVerification { + startVerification(userId: string, log: ILogItem, event?: any): SASVerification | undefined { + if (this.sasVerificationInProgress && !this.sasVerificationInProgress.finished) { + return; + } const channel = new ToDeviceChannel({ deviceTracker: this.deviceTracker, hsApi: this.hsApi, @@ -143,7 +155,8 @@ export class CrossSigning { deviceMessageHandler: this.deviceMessageHandler, log }, event); - return new SASVerification({ + + this.sasVerificationInProgress = new SASVerification({ olm: this.olm, olmUtil: this.olmUtil, ourUser: { userId: this.ownUserId, deviceId: this.deviceId }, @@ -154,6 +167,7 @@ export class CrossSigning { deviceTracker: this.deviceTracker, hsApi: this.hsApi, }); + return this.sasVerificationInProgress; } } diff --git a/src/matrix/verification/SAS/SASVerification.ts b/src/matrix/verification/SAS/SASVerification.ts index 76839d98..6f6f67b9 100644 --- a/src/matrix/verification/SAS/SASVerification.ts +++ b/src/matrix/verification/SAS/SASVerification.ts @@ -24,6 +24,7 @@ import {HomeServerApi} from "../../net/HomeServerApi"; import {VerificationEventTypes} from "./channel/types"; import {SendReadyStage} from "./stages/SendReadyStage"; import {SelectVerificationMethodStage} from "./stages/SelectVerificationMethodStage"; +import {VerificationCancelledError} from "./VerificationCancelledError"; type Olm = typeof OlmNamespace; @@ -42,14 +43,16 @@ type Options = { export class SASVerification { private startStage: BaseSASVerificationStage; private olmSas: Olm.SAS; + public finished: boolean = false; + public readonly channel: IChannel; constructor(options: Options) { const { ourUser, otherUserId, log, olmUtil, olm, channel, e2eeAccount, deviceTracker, hsApi } = options; const olmSas = new olm.SAS(); this.olmSas = olmSas; - // channel.send("m.key.verification.request", {}, log); + this.channel = channel; try { - const options = { ourUser, otherUserId, log, olmSas, olmUtil, channel, e2eeAccount, deviceTracker, hsApi }; + const options = { ourUser, otherUserId, log, olmSas, olmUtil, channel, e2eeAccount, deviceTracker, hsApi}; let stage: BaseSASVerificationStage; if (channel.receivedMessages.get(VerificationEventTypes.Start)) { stage = new SelectVerificationMethodStage(options); @@ -71,12 +74,20 @@ export class SASVerification { try { let stage = this.startStage; do { + console.log("Running next stage"); await stage.completeStage(); stage = stage.nextStage; } while (stage); } + catch (e) { + if (!(e instanceof VerificationCancelledError)) { + throw e; + } + console.log("Caught error in start()"); + } finally { this.olmSas.free(); + this.finished = true; } } } diff --git a/src/matrix/verification/SAS/VerificationCancelledError.ts b/src/matrix/verification/SAS/VerificationCancelledError.ts new file mode 100644 index 00000000..12d2a402 --- /dev/null +++ b/src/matrix/verification/SAS/VerificationCancelledError.ts @@ -0,0 +1,25 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export class VerificationCancelledError extends Error { + get name(): string { + return "VerificationCancelledError"; + } + + get message(): string { + return "Verification is cancelled!"; + } +} diff --git a/src/matrix/verification/SAS/channel/Channel.ts b/src/matrix/verification/SAS/channel/Channel.ts index 3339a7d2..24c1b6fb 100644 --- a/src/matrix/verification/SAS/channel/Channel.ts +++ b/src/matrix/verification/SAS/channel/Channel.ts @@ -21,9 +21,11 @@ import type {Platform} from "../../../../platform/web/Platform.js"; import type {DeviceMessageHandler} from "../../../DeviceMessageHandler.js"; import {makeTxnId} from "../../../common.js"; import {CancelTypes, VerificationEventTypes} from "./types"; +import {Disposables} from "../../../../lib"; +import {VerificationCancelledError} from "../VerificationCancelledError"; const messageFromErrorType = { - [CancelTypes.UserCancelled]: "User cancelled this request.", + [CancelTypes.UserCancelled]: "User declined", [CancelTypes.InvalidMessage]: "Invalid Message.", [CancelTypes.KeyMismatch]: "Key Mismatch.", [CancelTypes.OtherUserAccepted]: "Another device has accepted this request.", @@ -49,12 +51,12 @@ export interface IChannel { otherUserDeviceId: string; sentMessages: Map; receivedMessages: Map; - localMessages: Map; setStartMessage(content: any): void; setInitiatedByUs(value: boolean): void; initiatedByUs: boolean; startMessage: any; cancelVerification(cancellationType: CancelTypes): Promise; + getEvent(eventType: VerificationEventTypes.Accept): any; } type Options = { @@ -66,7 +68,7 @@ type Options = { log: ILogItem; } -export class ToDeviceChannel implements IChannel { +export class ToDeviceChannel extends Disposables implements IChannel { private readonly hsApi: HomeServerApi; private readonly deviceTracker: DeviceTracker; private readonly otherUserId: string; @@ -74,19 +76,20 @@ export class ToDeviceChannel implements IChannel { private readonly deviceMessageHandler: DeviceMessageHandler; public readonly sentMessages: Map = new Map(); public readonly receivedMessages: Map = new Map(); - public readonly localMessages: Map = new Map(); - private readonly waitMap: Map}> = new Map(); + private readonly waitMap: Map}> = new Map(); private readonly log: ILogItem; public otherUserDeviceId: string; public startMessage: any; public id: string; private _initiatedByUs: boolean; + private _isCancelled = false; /** * * @param startingMessage Create the channel with existing message in the receivedMessage buffer */ constructor(options: Options, startingMessage?: any) { + super(); this.hsApi = options.hsApi; this.deviceTracker = options.deviceTracker; this.otherUserId = options.otherUserId; @@ -94,7 +97,10 @@ export class ToDeviceChannel implements IChannel { this.log = options.log; this.deviceMessageHandler = options.deviceMessageHandler; // todo: find a way to dispose this subscription - this.deviceMessageHandler.on("message", ({unencrypted}) => this.handleDeviceMessage(unencrypted)) + this.track(this.deviceMessageHandler.disposableOn("message", ({ unencrypted }) => this.handleDeviceMessage(unencrypted))); + this.track(() => { + this.waitMap.forEach((value) => { value.reject(new VerificationCancelledError()); }); + }); // Copy over request message if (startingMessage) { /** @@ -105,14 +111,22 @@ export class ToDeviceChannel implements IChannel { this.receivedMessages.set(eventType, startingMessage); this.otherUserDeviceId = startingMessage.content.from_device; } + (window as any).foo = () => this.cancelVerification(CancelTypes.OtherUserAccepted); } get type() { return ChannelType.ToDeviceMessage; } + get isCancelled(): boolean { + return this._isCancelled; + } + async send(eventType: string, content: any, log: ILogItem): Promise { await log.wrap("ToDeviceChannel.send", async () => { + if (this.isCancelled) { + throw new VerificationCancelledError(); + } if (eventType === VerificationEventTypes.Request) { // Handle this case specially await this.handleRequestEventSpecially(eventType, content, log); @@ -128,12 +142,12 @@ export class ToDeviceChannel implements IChannel { } } } - await this.hsApi.sendToDevice(eventType, payload, this.id, { log }).response(); + await this.hsApi.sendToDevice(eventType, payload, makeTxnId(), { log }).response(); this.sentMessages.set(eventType, {content}); }); } - async handleRequestEventSpecially(eventType: string, content: any, log: ILogItem) { + private async handleRequestEventSpecially(eventType: string, content: any, log: ILogItem) { await log.wrap("ToDeviceChannel.handleRequestEventSpecially", async () => { const timestamp = this.platform.clock.now(); const txnId = makeTxnId(); @@ -146,10 +160,14 @@ export class ToDeviceChannel implements IChannel { } } } - await this.hsApi.sendToDevice(eventType, payload, txnId, { log }).response(); + await this.hsApi.sendToDevice(eventType, payload, makeTxnId(), { log }).response(); }); } + getEvent(eventType: VerificationEventTypes.Accept) { + return this.receivedMessages.get(eventType) ?? this.sentMessages.get(eventType); + } + private handleDeviceMessage(event) { this.log.wrap("ToDeviceChannel.handleDeviceMessage", (log) => { @@ -159,6 +177,11 @@ export class ToDeviceChannel implements IChannel { this.receivedMessages.set(event.type, event); if (event.type === VerificationEventTypes.Ready) { this.handleReadyMessage(event, log); + return; + } + if (event.type === VerificationEventTypes.Cancel) { + this.dispose(); + return; } }); } @@ -181,7 +204,7 @@ export class ToDeviceChannel implements IChannel { [this.otherUserId]: deviceMessages } } - await this.hsApi.sendToDevice(VerificationEventTypes.Cancel, payload, this.id, { log }).response(); + await this.hsApi.sendToDevice(VerificationEventTypes.Cancel, payload, makeTxnId(), { log }).response(); } catch (e) { console.log(e); @@ -191,6 +214,9 @@ export class ToDeviceChannel implements IChannel { async cancelVerification(cancellationType: CancelTypes) { await this.log.wrap("Channel.cancelVerification", async log => { + if (this.isCancelled) { + throw new VerificationCancelledError(); + } const payload = { messages: { [this.otherUserId]: { @@ -202,7 +228,9 @@ export class ToDeviceChannel implements IChannel { } } } - await this.hsApi.sendToDevice(VerificationEventTypes.Cancel, payload, this.id, { log }).response(); + await this.hsApi.sendToDevice(VerificationEventTypes.Cancel, payload, makeTxnId(), { log }).response(); + this._isCancelled = true; + this.dispose(); }); } @@ -226,12 +254,13 @@ export class ToDeviceChannel implements IChannel { if (existingWait) { return existingWait.promise; } - let resolve; + let resolve, reject; // Add to wait map - const promise = new Promise(r => { - resolve = r; + const promise = new Promise((_resolve, _reject) => { + resolve = _resolve; + reject = _reject; }); - this.waitMap.set(eventType, { resolve, promise }); + this.waitMap.set(eventType, { resolve, reject, promise }); return promise; } diff --git a/src/matrix/verification/SAS/stages/BaseSASVerificationStage.ts b/src/matrix/verification/SAS/stages/BaseSASVerificationStage.ts index 82de5572..a61a2ce9 100644 --- a/src/matrix/verification/SAS/stages/BaseSASVerificationStage.ts +++ b/src/matrix/verification/SAS/stages/BaseSASVerificationStage.ts @@ -70,16 +70,6 @@ export abstract class BaseSASVerificationStage extends Disposables { this.hsApi = options.hsApi; } - setRequestEventId(id: string) { - this.requestEventId = id; - // todo: can this race with incoming message? - this.nextStage?.setRequestEventId(id); - } - - setResultFromPreviousStage(result?: any) { - this.previousResult = result; - } - setNextStage(stage: BaseSASVerificationStage) { this._nextStage = stage; } @@ -88,6 +78,5 @@ export abstract class BaseSASVerificationStage extends Disposables { return this._nextStage; } - abstract get type(): string; abstract completeStage(): Promise; } diff --git a/src/matrix/verification/SAS/stages/CalculateSASStage.ts b/src/matrix/verification/SAS/stages/CalculateSASStage.ts index 4e20ff1d..cea4d297 100644 --- a/src/matrix/verification/SAS/stages/CalculateSASStage.ts +++ b/src/matrix/verification/SAS/stages/CalculateSASStage.ts @@ -88,8 +88,8 @@ export class CalculateSASStage extends BaseSASVerificationStage { this.olmSAS.set_their_key(this.theirKey); const sasBytes = this.generateSASBytes(); const emoji = generateEmojiSas(Array.from(sasBytes)); - console.log("emoji", emoji); - this._nextStage = new SendMacStage(this.options); + console.log("Emoji calculated:", emoji); + this.setNextStage(new SendMacStage(this.options)); this.dispose(); }); } @@ -98,9 +98,10 @@ export class CalculateSASStage extends BaseSASVerificationStage { return await log.wrap("CalculateSASStage.verifyHashCommitment", async () => { const acceptMessage = this.channel.receivedMessages.get(VerificationEventTypes.Accept).content; const keyMessage = this.channel.receivedMessages.get(VerificationEventTypes.Key).content; - const commitmentStr = keyMessage.key + anotherjson.stringify(acceptMessage); + const commitmentStr = keyMessage.key + anotherjson.stringify(this.channel.startMessage.content); const receivedCommitment = acceptMessage.commitment; - if (this.olmUtil.sha256(commitmentStr) !== receivedCommitment) { + const hash = this.olmUtil.sha256(commitmentStr); + if (hash !== receivedCommitment) { log.set("Commitment mismatched!", {}); // cancel the process! await this.channel.cancelVerification(CancelTypes.MismatchedCommitment); @@ -120,8 +121,8 @@ export class CalculateSASStage extends BaseSASVerificationStage { } private generateSASBytes(): Uint8Array { - const keyAgreement = this.channel.sentMessages.get(VerificationEventTypes.Accept).content.key_agreement_protocol; - const otherUserDeviceId = this.channel.startMessage.content.from_device; + const keyAgreement = this.channel.getEvent(VerificationEventTypes.Accept).content.key_agreement_protocol; + const otherUserDeviceId = this.channel.otherUserDeviceId; const sasBytes = calculateKeyAgreement[keyAgreement]({ our: { userId: this.ourUser.userId, @@ -150,8 +151,4 @@ export class CalculateSASStage extends BaseSASVerificationStage { const { content } = this.channel.receivedMessages.get(VerificationEventTypes.Key); return content.key; } - - get type() { - return "m.key.verification.accept"; - } } diff --git a/src/matrix/verification/SAS/stages/RequestVerificationStage.ts b/src/matrix/verification/SAS/stages/RequestVerificationStage.ts index 1b9e2e6e..a5e4c6de 100644 --- a/src/matrix/verification/SAS/stages/RequestVerificationStage.ts +++ b/src/matrix/verification/SAS/stages/RequestVerificationStage.ts @@ -19,51 +19,16 @@ import {SelectVerificationMethodStage} from "./SelectVerificationMethodStage"; import {VerificationEventTypes} from "../channel/types"; export class RequestVerificationStage extends BaseSASVerificationStage { - async completeStage() { await this.log.wrap("StartVerificationStage.completeStage", async (log) => { const content = { - // "body": `${this.ourUser.userId} is requesting to verify your device, but your client does not support verification, so you may need to use a different verification method.`, "from_device": this.ourUser.deviceId, "methods": ["m.sas.v1"], - // "msgtype": "m.key.verification.request", - // "to": this.otherUserId, }; - // const promise = this.trackEventId(); - // await this.room.sendEvent("m.room.message", content, null, log); await this.channel.send(VerificationEventTypes.Request, content, log); - this._nextStage = new SelectVerificationMethodStage(this.options); - const readyContent = await this.channel.waitForEvent("m.key.verification.ready"); - // const eventId = await promise; - // console.log("eventId", eventId); - // this.setRequestEventId(eventId); + this.setNextStage(new SelectVerificationMethodStage(this.options)); + await this.channel.waitForEvent("m.key.verification.ready"); this.dispose(); }); } - - // private trackEventId(): Promise { - // return new Promise(resolve => { - // this.track( - // this.room._timeline.entries.subscribe({ - // onAdd: (_, entry) => { - // if (entry instanceof FragmentBoundaryEntry) { - // return; - // } - // if (!entry.isPending && - // entry.content["msgtype"] === "m.key.verification.request" && - // entry.content["from_device"] === this.ourUser.deviceId) { - // console.log("found event", entry); - // resolve(entry.id); - // } - // }, - // onRemove: () => { /**noop*/ }, - // onUpdate: () => { /**noop*/ }, - // }) - // ); - // }); - // } - - get type() { - return "m.key.verification.request"; - } } diff --git a/src/matrix/verification/SAS/stages/SelectVerificationMethodStage.ts b/src/matrix/verification/SAS/stages/SelectVerificationMethodStage.ts index dfe6dc35..af95d70e 100644 --- a/src/matrix/verification/SAS/stages/SelectVerificationMethodStage.ts +++ b/src/matrix/verification/SAS/stages/SelectVerificationMethodStage.ts @@ -18,6 +18,7 @@ import {KEY_AGREEMENT_LIST, HASHES_LIST, MAC_LIST, SAS_LIST} from "./constants"; import {CancelTypes, VerificationEventTypes} from "../channel/types"; import type {ILogItem} from "../../../../logging/types"; import {SendAcceptVerificationStage} from "./SendAcceptVerificationStage"; +import {SendKeyStage} from "./SendKeyStage"; export class SelectVerificationMethodStage extends BaseSASVerificationStage { private hasSentStartMessage = false; @@ -26,6 +27,7 @@ export class SelectVerificationMethodStage extends BaseSASVerificationStage { async completeStage() { await this.log.wrap("SelectVerificationMethodStage.completeStage", async (log) => { + (window as any).select = () => this.selectEmojiMethod(log); const startMessage = this.channel.waitForEvent(VerificationEventTypes.Start); const acceptMessage = this.channel.waitForEvent(VerificationEventTypes.Accept); const { content } = await Promise.race([startMessage, acceptMessage]); @@ -45,7 +47,11 @@ export class SelectVerificationMethodStage extends BaseSASVerificationStage { this.channel.setStartMessage(this.channel.sentMessages.get(VerificationEventTypes.Start)); this.channel.setInitiatedByUs(true); } - if (!this.channel.initiatedByUs) { + if (this.channel.initiatedByUs) { + await acceptMessage; + this.setNextStage(new SendKeyStage(this.options)); + } + else { // We need to send the accept message next this.setNextStage(new SendAcceptVerificationStage(this.options)); } @@ -86,8 +92,4 @@ export class SelectVerificationMethodStage extends BaseSASVerificationStage { await this.channel.send(VerificationEventTypes.Start, content, log); this.hasSentStartMessage = true; } - - get type() { - return "SelectVerificationStage"; - } } diff --git a/src/matrix/verification/SAS/stages/SendAcceptVerificationStage.ts b/src/matrix/verification/SAS/stages/SendAcceptVerificationStage.ts index 6b964445..9c7c86be 100644 --- a/src/matrix/verification/SAS/stages/SendAcceptVerificationStage.ts +++ b/src/matrix/verification/SAS/stages/SendAcceptVerificationStage.ts @@ -15,19 +15,14 @@ limitations under the License. */ import {BaseSASVerificationStage} from "./BaseSASVerificationStage"; import anotherjson from "another-json"; -import type { KeyAgreement, MacMethod } from "./constants"; import {HASHES_LIST, MAC_LIST, SAS_SET, KEY_AGREEMENT_LIST} from "./constants"; -import { VerificationEventTypes } from "../channel/types"; -import { SendKeyStage } from "./SendKeyStage"; +import {VerificationEventTypes} from "../channel/types"; +import {SendKeyStage} from "./SendKeyStage"; export class SendAcceptVerificationStage extends BaseSASVerificationStage { async completeStage() { await this.log.wrap("SendAcceptVerificationStage.completeStage", async (log) => { - const event = this.channel.startMessage; - const content = { - ...event.content, - // "m.relates_to": event.relation, - }; + const { content } = this.channel.startMessage; const keyAgreement = intersection(KEY_AGREEMENT_LIST, new Set(content.key_agreement_protocols))[0]; const hashMethod = intersection(HASHES_LIST, new Set(content.hashes))[0]; const macMethod = intersection(MAC_LIST, new Set(content.message_authentication_codes))[0]; @@ -50,24 +45,12 @@ export class SendAcceptVerificationStage extends BaseSASVerificationStage { rel_type: "m.reference", } }; - // await this.room.sendEvent("m.key.verification.accept", contentToSend, null, log); await this.channel.send(VerificationEventTypes.Accept, contentToSend, log); - this.channel.localMessages.set("our_pub_key", ourPubKey); await this.channel.waitForEvent(VerificationEventTypes.Key); - this._nextStage = new SendKeyStage(this.options); - // this.nextStage?.setResultFromPreviousStage({ - // ...this.previousResult, - // [this.type]: contentToSend, - // "our_pub_key": ourPubKey, - // }); + this.setNextStage(new SendKeyStage(this.options)); this.dispose(); }); } - - - get type() { - return "m.key.verification.accept"; - } } function intersection(anArray: T[], aSet: Set): T[] { diff --git a/src/matrix/verification/SAS/stages/SendDoneStage.ts b/src/matrix/verification/SAS/stages/SendDoneStage.ts index d19ab723..d090b3c0 100644 --- a/src/matrix/verification/SAS/stages/SendDoneStage.ts +++ b/src/matrix/verification/SAS/stages/SendDoneStage.ts @@ -16,17 +16,11 @@ limitations under the License. import {BaseSASVerificationStage} from "./BaseSASVerificationStage"; import {VerificationEventTypes} from "../channel/types"; - export class SendDoneStage extends BaseSASVerificationStage { - async completeStage() { await this.log.wrap("VerifyMacStage.completeStage", async (log) => { await this.channel.send(VerificationEventTypes.Done, {}, log); this.dispose(); }); } - - get type() { - return "m.key.verification.accept"; - } } diff --git a/src/matrix/verification/SAS/stages/SendKeyStage.ts b/src/matrix/verification/SAS/stages/SendKeyStage.ts index c9455663..af2c8e49 100644 --- a/src/matrix/verification/SAS/stages/SendKeyStage.ts +++ b/src/matrix/verification/SAS/stages/SendKeyStage.ts @@ -18,7 +18,6 @@ import {VerificationEventTypes} from "../channel/types"; import {CalculateSASStage} from "./CalculateSASStage"; export class SendKeyStage extends BaseSASVerificationStage { - async completeStage() { await this.log.wrap("SendKeyStage.completeStage", async (log) => { const ourSasKey = this.olmSAS.get_pubkey(); @@ -30,12 +29,8 @@ export class SendKeyStage extends BaseSASVerificationStage { * key. */ await this.channel.waitForEvent(VerificationEventTypes.Key); - this._nextStage = new CalculateSASStage(this.options) + this.setNextStage(new CalculateSASStage(this.options)); this.dispose(); }); } - - get type() { - return "m.key.verification.accept"; - } } diff --git a/src/matrix/verification/SAS/stages/SendMacStage.ts b/src/matrix/verification/SAS/stages/SendMacStage.ts index 5ffc56a9..f3759ab6 100644 --- a/src/matrix/verification/SAS/stages/SendMacStage.ts +++ b/src/matrix/verification/SAS/stages/SendMacStage.ts @@ -37,7 +37,7 @@ export class SendMacStage extends BaseSASVerificationStage { this.calculateMAC = createCalculateMAC(this.olmSAS, macMethod); await this.sendMAC(log); await this.channel.waitForEvent(VerificationEventTypes.Mac); - this._nextStage = new VerifyMacStage(this.options); + this.setNextStage(new VerifyMacStage(this.options)); this.dispose(); }); } @@ -70,9 +70,5 @@ export class SendMacStage extends BaseSASVerificationStage { console.log("result", mac, keys); await this.channel.send(VerificationEventTypes.Mac, { mac, keys }, log); } - - get type() { - return "m.key.verification.accept"; - } } diff --git a/src/matrix/verification/SAS/stages/SendReadyStage.ts b/src/matrix/verification/SAS/stages/SendReadyStage.ts index e70d8953..b4591579 100644 --- a/src/matrix/verification/SAS/stages/SendReadyStage.ts +++ b/src/matrix/verification/SAS/stages/SendReadyStage.ts @@ -15,26 +15,18 @@ limitations under the License. */ import {BaseSASVerificationStage} from "./BaseSASVerificationStage"; import {VerificationEventTypes} from "../channel/types"; -import { SelectVerificationMethodStage } from "./SelectVerificationMethodStage"; +import {SelectVerificationMethodStage} from "./SelectVerificationMethodStage"; export class SendReadyStage extends BaseSASVerificationStage { - async completeStage() { await this.log.wrap("StartVerificationStage.completeStage", async (log) => { const content = { - // "body": `${this.ourUser.userId} is requesting to verify your device, but your client does not support verification, so you may need to use a different verification method.`, "from_device": this.ourUser.deviceId, "methods": ["m.sas.v1"], - // "msgtype": "m.key.verification.request", - // "to": this.otherUserId, }; await this.channel.send(VerificationEventTypes.Ready, content, log); - this._nextStage = new SelectVerificationMethodStage(this.options); + this.setNextStage(new SelectVerificationMethodStage(this.options)); this.dispose(); }); } - - get type() { - return "m.key.verification.request"; - } } diff --git a/src/matrix/verification/SAS/stages/VerifyMacStage.ts b/src/matrix/verification/SAS/stages/VerifyMacStage.ts index 634b8ccb..2eb37018 100644 --- a/src/matrix/verification/SAS/stages/VerifyMacStage.ts +++ b/src/matrix/verification/SAS/stages/VerifyMacStage.ts @@ -18,7 +18,7 @@ import {ILogItem} from "../../../../lib"; import {VerificationEventTypes} from "../channel/types"; import {createCalculateMAC} from "../mac"; import type * as OlmNamespace from "@matrix-org/olm"; -import { SendDoneStage } from "./SendDoneStage"; +import {SendDoneStage} from "./SendDoneStage"; type Olm = typeof OlmNamespace; export type KeyVerifier = (keyId: string, device: any, keyInfo: string) => void; @@ -39,7 +39,7 @@ export class VerifyMacStage extends BaseSASVerificationStage { this.calculateMAC = createCalculateMAC(this.olmSAS, macMethod); await this.checkMAC(log); await this.channel.waitForEvent(VerificationEventTypes.Done); - this._nextStage = new SendDoneStage(this.options); + this.setNextStage(new SendDoneStage(this.options)); this.dispose(); }); } @@ -88,8 +88,4 @@ export class VerifyMacStage extends BaseSASVerificationStage { } } } - - get type() { - return "m.key.verification.accept"; - } } diff --git a/src/matrix/verification/SAS/stages/WaitForIncomingMessageStage.ts b/src/matrix/verification/SAS/stages/WaitForIncomingMessageStage.ts deleted file mode 100644 index 087883ac..00000000 --- a/src/matrix/verification/SAS/stages/WaitForIncomingMessageStage.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2023 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -import {BaseSASVerificationStage, Options} from "./BaseSASVerificationStage"; -import {FragmentBoundaryEntry} from "../../../room/timeline/entries/FragmentBoundaryEntry.js"; - -export class WaitForIncomingMessageStage extends BaseSASVerificationStage { - constructor(private messageType: string, options: Options) { - super(options); - } - - async completeStage() { - await this.log.wrap("WaitForIncomingMessageStage.completeStage", async (log) => { - const entry = await this.fetchMessageEventsFromTimeline(); - console.log("content", entry); - this.nextStage?.setResultFromPreviousStage({ - ...this.previousResult, - [this.messageType]: entry - }); - this.dispose(); - }); - } - - private fetchMessageEventsFromTimeline() { - // todo: add timeout after 10 mins - return new Promise(resolve => { - this.track( - this.room._timeline.entries.subscribe({ - onAdd: (_, entry) => { - if (entry.eventType === this.messageType && - entry.relatedEventId === this.requestEventId) { - resolve(entry); - } - }, - onRemove: () => { }, - onUpdate: () => { }, - }) - ); - const remoteEntries = this.room._timeline.remoteEntries; - // In case we were slow and the event is already added to the timeline, - for (const entry of remoteEntries) { - if (entry instanceof FragmentBoundaryEntry) { - return; - } - if (entry.eventType === this.messageType && - entry.relatedEventId === this.requestEventId) { - resolve(entry); - } - } - }); - } - - get type() { - return this.messageType; - } -} -