diff options
author | RaindropsSys <raindrops@equestria.dev> | 2023-11-17 23:25:29 +0100 |
---|---|---|
committer | RaindropsSys <raindrops@equestria.dev> | 2023-11-17 23:25:29 +0100 |
commit | 953ddd82e48dd206cef5ac94456549aed13b3ad5 (patch) | |
tree | 8f003106ee2e7f422e5a22d2ee04d0db302e66c0 /includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous | |
parent | 62a9199846b0c07c03218703b33e8385764f42d9 (diff) | |
download | pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.gz pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.bz2 pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.zip |
Updated 30 files and deleted 2976 files (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous')
12 files changed, 0 insertions, 978 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/MSC3906Rendezvous.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/MSC3906Rendezvous.ts deleted file mode 100644 index f431c83..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/MSC3906Rendezvous.ts +++ /dev/null @@ -1,264 +0,0 @@ -/* -Copyright 2022 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 { UnstableValue } from "matrix-events-sdk"; - -import { RendezvousChannel, RendezvousFailureListener, RendezvousFailureReason, RendezvousIntent } from "."; -import { MatrixClient } from "../client"; -import { CrossSigningInfo } from "../crypto/CrossSigning"; -import { DeviceInfo } from "../crypto/deviceinfo"; -import { buildFeatureSupportMap, Feature, ServerSupport } from "../feature"; -import { logger } from "../logger"; -import { sleep } from "../utils"; - -enum PayloadType { - Start = "m.login.start", - Finish = "m.login.finish", - Progress = "m.login.progress", -} - -enum Outcome { - Success = "success", - Failure = "failure", - Verified = "verified", - Declined = "declined", - Unsupported = "unsupported", -} - -export interface MSC3906RendezvousPayload { - type: PayloadType; - intent?: RendezvousIntent; - outcome?: Outcome; - device_id?: string; - device_key?: string; - verifying_device_id?: string; - verifying_device_key?: string; - master_key?: string; - protocols?: string[]; - protocol?: string; - login_token?: string; - homeserver?: string; -} - -const LOGIN_TOKEN_PROTOCOL = new UnstableValue("login_token", "org.matrix.msc3906.login_token"); - -/** - * Implements MSC3906 to allow a user to sign in on a new device using QR code. - * This implementation only supports generating a QR code on a device that is already signed in. - * Note that this is UNSTABLE and may have breaking changes without notice. - */ -export class MSC3906Rendezvous { - private newDeviceId?: string; - private newDeviceKey?: string; - private ourIntent: RendezvousIntent = RendezvousIntent.RECIPROCATE_LOGIN_ON_EXISTING_DEVICE; - private _code?: string; - - /** - * @param channel - The secure channel used for communication - * @param client - The Matrix client in used on the device already logged in - * @param onFailure - Callback for when the rendezvous fails - */ - public constructor( - private channel: RendezvousChannel<MSC3906RendezvousPayload>, - private client: MatrixClient, - public onFailure?: RendezvousFailureListener, - ) {} - - /** - * Returns the code representing the rendezvous suitable for rendering in a QR code or undefined if not generated yet. - */ - public get code(): string | undefined { - return this._code; - } - - /** - * Generate the code including doing partial set up of the channel where required. - */ - public async generateCode(): Promise<void> { - if (this._code) { - return; - } - - this._code = JSON.stringify(await this.channel.generateCode(this.ourIntent)); - } - - public async startAfterShowingCode(): Promise<string | undefined> { - const checksum = await this.channel.connect(); - - logger.info(`Connected to secure channel with checksum: ${checksum} our intent is ${this.ourIntent}`); - - const features = await buildFeatureSupportMap(await this.client.getVersions()); - // determine available protocols - if (features.get(Feature.LoginTokenRequest) === ServerSupport.Unsupported) { - logger.info("Server doesn't support MSC3882"); - await this.send({ type: PayloadType.Finish, outcome: Outcome.Unsupported }); - await this.cancel(RendezvousFailureReason.HomeserverLacksSupport); - return undefined; - } - - await this.send({ type: PayloadType.Progress, protocols: [LOGIN_TOKEN_PROTOCOL.name] }); - - logger.info("Waiting for other device to chose protocol"); - const { type, protocol, outcome } = await this.receive(); - - if (type === PayloadType.Finish) { - // new device decided not to complete - switch (outcome ?? "") { - case "unsupported": - await this.cancel(RendezvousFailureReason.UnsupportedAlgorithm); - break; - default: - await this.cancel(RendezvousFailureReason.Unknown); - } - return undefined; - } - - if (type !== PayloadType.Progress) { - await this.cancel(RendezvousFailureReason.Unknown); - return undefined; - } - - if (!protocol || !LOGIN_TOKEN_PROTOCOL.matches(protocol)) { - await this.cancel(RendezvousFailureReason.UnsupportedAlgorithm); - return undefined; - } - - return checksum; - } - - private async receive(): Promise<MSC3906RendezvousPayload> { - return (await this.channel.receive()) as MSC3906RendezvousPayload; - } - - private async send(payload: MSC3906RendezvousPayload): Promise<void> { - await this.channel.send(payload); - } - - public async declineLoginOnExistingDevice(): Promise<void> { - logger.info("User declined sign in"); - await this.send({ type: PayloadType.Finish, outcome: Outcome.Declined }); - } - - public async approveLoginOnExistingDevice(loginToken: string): Promise<string | undefined> { - // eslint-disable-next-line camelcase - await this.send({ type: PayloadType.Progress, login_token: loginToken, homeserver: this.client.baseUrl }); - - logger.info("Waiting for outcome"); - const res = await this.receive(); - if (!res) { - return undefined; - } - const { outcome, device_id: deviceId, device_key: deviceKey } = res; - - if (outcome !== "success") { - throw new Error("Linking failed"); - } - - this.newDeviceId = deviceId; - this.newDeviceKey = deviceKey; - - return deviceId; - } - - private async verifyAndCrossSignDevice(deviceInfo: DeviceInfo): Promise<CrossSigningInfo | DeviceInfo> { - if (!this.client.crypto) { - throw new Error("Crypto not available on client"); - } - - if (!this.newDeviceId) { - throw new Error("No new device ID set"); - } - - // check that keys received from the server for the new device match those received from the device itself - if (deviceInfo.getFingerprint() !== this.newDeviceKey) { - throw new Error( - `New device has different keys than expected: ${this.newDeviceKey} vs ${deviceInfo.getFingerprint()}`, - ); - } - - const userId = this.client.getUserId(); - - if (!userId) { - throw new Error("No user ID set"); - } - // mark the device as verified locally + cross sign - logger.info(`Marking device ${this.newDeviceId} as verified`); - const info = await this.client.crypto.setDeviceVerification(userId, this.newDeviceId, true, false, true); - - const masterPublicKey = this.client.crypto.crossSigningInfo.getId("master")!; - - await this.send({ - type: PayloadType.Finish, - outcome: Outcome.Verified, - verifying_device_id: this.client.getDeviceId()!, - verifying_device_key: this.client.getDeviceEd25519Key()!, - master_key: masterPublicKey, - }); - - return info; - } - - /** - * Verify the device and cross-sign it. - * @param timeout - time in milliseconds to wait for device to come online - * @returns the new device info if the device was verified - */ - public async verifyNewDeviceOnExistingDevice( - timeout = 10 * 1000, - ): Promise<DeviceInfo | CrossSigningInfo | undefined> { - if (!this.newDeviceId) { - throw new Error("No new device to sign"); - } - - if (!this.newDeviceKey) { - logger.info("No new device key to sign"); - return undefined; - } - - if (!this.client.crypto) { - throw new Error("Crypto not available on client"); - } - - const userId = this.client.getUserId(); - - if (!userId) { - throw new Error("No user ID set"); - } - - let deviceInfo = this.client.crypto.getStoredDevice(userId, this.newDeviceId); - - if (!deviceInfo) { - logger.info("Going to wait for new device to be online"); - await sleep(timeout); - deviceInfo = this.client.crypto.getStoredDevice(userId, this.newDeviceId); - } - - if (deviceInfo) { - return await this.verifyAndCrossSignDevice(deviceInfo); - } - - throw new Error("Device not online within timeout"); - } - - public async cancel(reason: RendezvousFailureReason): Promise<void> { - this.onFailure?.(reason); - await this.channel.cancel(reason); - } - - public async close(): Promise<void> { - await this.channel.close(); - } -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousChannel.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousChannel.ts deleted file mode 100644 index 549ebc8..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousChannel.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2022 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 { RendezvousCode, RendezvousIntent, RendezvousFailureReason } from "."; - -export interface RendezvousChannel<T> { - /** - * @returns the checksum/confirmation digits to be shown to the user - */ - connect(): Promise<string>; - - /** - * Send a payload via the channel. - * @param data - payload to send - */ - send(data: T): Promise<void>; - - /** - * Receive a payload from the channel. - * @returns the received payload - */ - receive(): Promise<Partial<T> | undefined>; - - /** - * Close the channel and clear up any resources. - */ - close(): Promise<void>; - - /** - * @returns a representation of the channel that can be encoded in a QR or similar - */ - generateCode(intent: RendezvousIntent): Promise<RendezvousCode>; - - cancel(reason: RendezvousFailureReason): Promise<void>; -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousCode.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousCode.ts deleted file mode 100644 index 86608aa..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousCode.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2022 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 { RendezvousTransportDetails, RendezvousIntent } from "."; - -export interface RendezvousCode { - intent: RendezvousIntent; - rendezvous?: { - transport: RendezvousTransportDetails; - algorithm: string; - }; -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousError.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousError.ts deleted file mode 100644 index 8b76fc1..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousError.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2022 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 { RendezvousFailureReason } from "."; - -export class RendezvousError extends Error { - public constructor(message: string, public readonly code: RendezvousFailureReason) { - super(message); - } -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousFailureReason.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousFailureReason.ts deleted file mode 100644 index b19a91c..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousFailureReason.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright 2022 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 type RendezvousFailureListener = (reason: RendezvousFailureReason) => void; - -export enum RendezvousFailureReason { - UserDeclined = "user_declined", - OtherDeviceNotSignedIn = "other_device_not_signed_in", - OtherDeviceAlreadySignedIn = "other_device_already_signed_in", - Unknown = "unknown", - Expired = "expired", - UserCancelled = "user_cancelled", - InvalidCode = "invalid_code", - UnsupportedAlgorithm = "unsupported_algorithm", - DataMismatch = "data_mismatch", - UnsupportedTransport = "unsupported_transport", - HomeserverLacksSupport = "homeserver_lacks_support", -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousIntent.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousIntent.ts deleted file mode 100644 index db53ef9..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousIntent.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2022 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 enum RendezvousIntent { - LOGIN_ON_NEW_DEVICE = "login.start", - RECIPROCATE_LOGIN_ON_EXISTING_DEVICE = "login.reciprocate", -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousTransport.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousTransport.ts deleted file mode 100644 index 08905be..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/RendezvousTransport.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2022 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 { RendezvousFailureListener, RendezvousFailureReason } from "."; - -export interface RendezvousTransportDetails { - type: string; -} - -/** - * Interface representing a generic rendezvous transport. - */ -export interface RendezvousTransport<T> { - /** - * Ready state of the transport. This is set to true when the transport is ready to be used. - */ - readonly ready: boolean; - - /** - * Listener for cancellation events. This is called when the rendezvous is cancelled or fails. - */ - onFailure?: RendezvousFailureListener; - - /** - * @returns the transport details that can be encoded in a QR or similar - */ - details(): Promise<RendezvousTransportDetails>; - - /** - * Send data via the transport. - * @param data - the data itself - */ - send(data: T): Promise<void>; - - /** - * Receive data from the transport. - */ - receive(): Promise<Partial<T> | undefined>; - - /** - * Cancel the rendezvous. This will call `onCancelled()` if it is set. - * @param reason - the reason for the cancellation/failure - */ - cancel(reason: RendezvousFailureReason): Promise<void>; -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/channels/MSC3903ECDHv2RendezvousChannel.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/channels/MSC3903ECDHv2RendezvousChannel.ts deleted file mode 100644 index be60ee5..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/channels/MSC3903ECDHv2RendezvousChannel.ts +++ /dev/null @@ -1,259 +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 { SAS } from "@matrix-org/olm"; - -import { - RendezvousError, - RendezvousCode, - RendezvousIntent, - RendezvousChannel, - RendezvousTransportDetails, - RendezvousTransport, - RendezvousFailureReason, -} from ".."; -import { encodeUnpaddedBase64, decodeBase64 } from "../../crypto/olmlib"; -import { crypto, subtleCrypto, TextEncoder } from "../../crypto/crypto"; -import { generateDecimalSas } from "../../crypto/verification/SASDecimal"; -import { UnstableValue } from "../../NamespacedValue"; - -const ECDH_V2 = new UnstableValue( - "m.rendezvous.v2.curve25519-aes-sha256", - "org.matrix.msc3903.rendezvous.v2.curve25519-aes-sha256", -); - -export interface ECDHv2RendezvousCode extends RendezvousCode { - rendezvous: { - transport: RendezvousTransportDetails; - algorithm: typeof ECDH_V2.name | typeof ECDH_V2.altName; - key: string; - }; -} - -export type MSC3903ECDHPayload = PlainTextPayload | EncryptedPayload; - -export interface PlainTextPayload { - algorithm: typeof ECDH_V2.name | typeof ECDH_V2.altName; - key?: string; -} - -export interface EncryptedPayload { - iv: string; - ciphertext: string; -} - -async function importKey(key: Uint8Array): Promise<CryptoKey> { - if (!subtleCrypto) { - throw new Error("Web Crypto is not available"); - } - - const imported = subtleCrypto.importKey("raw", key, { name: "AES-GCM" }, false, ["encrypt", "decrypt"]); - - return imported; -} - -/** - * Implementation of the unstable [MSC3903](https://github.com/matrix-org/matrix-spec-proposals/pull/3903) - * X25519/ECDH key agreement based secure rendezvous channel. - * Note that this is UNSTABLE and may have breaking changes without notice. - */ -export class MSC3903ECDHv2RendezvousChannel<T> implements RendezvousChannel<T> { - private olmSAS?: SAS; - private ourPublicKey: Uint8Array; - private aesKey?: CryptoKey; - private connected = false; - - public constructor( - private transport: RendezvousTransport<MSC3903ECDHPayload>, - private theirPublicKey?: Uint8Array, - public onFailure?: (reason: RendezvousFailureReason) => void, - ) { - this.olmSAS = new global.Olm.SAS(); - this.ourPublicKey = decodeBase64(this.olmSAS.get_pubkey()); - } - - public async generateCode(intent: RendezvousIntent): Promise<ECDHv2RendezvousCode> { - if (this.transport.ready) { - throw new Error("Code already generated"); - } - - await this.transport.send({ algorithm: ECDH_V2.name }); - - const rendezvous: ECDHv2RendezvousCode = { - rendezvous: { - algorithm: ECDH_V2.name, - key: encodeUnpaddedBase64(this.ourPublicKey), - transport: await this.transport.details(), - }, - intent, - }; - - return rendezvous; - } - - public async connect(): Promise<string> { - if (this.connected) { - throw new Error("Channel already connected"); - } - - if (!this.olmSAS) { - throw new Error("Channel closed"); - } - - const isInitiator = !this.theirPublicKey; - - if (isInitiator) { - // wait for the other side to send us their public key - const rawRes = await this.transport.receive(); - if (!rawRes) { - throw new Error("No response from other device"); - } - const res = rawRes as Partial<PlainTextPayload>; - const { key, algorithm } = res; - if (!algorithm || !ECDH_V2.matches(algorithm) || !key) { - throw new RendezvousError( - "Unsupported algorithm: " + algorithm, - RendezvousFailureReason.UnsupportedAlgorithm, - ); - } - - this.theirPublicKey = decodeBase64(key); - } else { - // send our public key unencrypted - await this.transport.send({ - algorithm: ECDH_V2.name, - key: encodeUnpaddedBase64(this.ourPublicKey), - }); - } - - this.connected = true; - - this.olmSAS.set_their_key(encodeUnpaddedBase64(this.theirPublicKey!)); - - const initiatorKey = isInitiator ? this.ourPublicKey : this.theirPublicKey!; - const recipientKey = isInitiator ? this.theirPublicKey! : this.ourPublicKey; - let aesInfo = ECDH_V2.name; - aesInfo += `|${encodeUnpaddedBase64(initiatorKey)}`; - aesInfo += `|${encodeUnpaddedBase64(recipientKey)}`; - - const aesKeyBytes = this.olmSAS.generate_bytes(aesInfo, 32); - - this.aesKey = await importKey(aesKeyBytes); - - // blank the bytes out to make sure not kept in memory - aesKeyBytes.fill(0); - - const rawChecksum = this.olmSAS.generate_bytes(aesInfo, 5); - return generateDecimalSas(Array.from(rawChecksum)).join("-"); - } - - private async encrypt(data: T): Promise<MSC3903ECDHPayload> { - if (!subtleCrypto) { - throw new Error("Web Crypto is not available"); - } - - const iv = new Uint8Array(32); - crypto.getRandomValues(iv); - - const encodedData = new TextEncoder().encode(JSON.stringify(data)); - - const ciphertext = await subtleCrypto.encrypt( - { - name: "AES-GCM", - iv, - tagLength: 128, - }, - this.aesKey as CryptoKey, - encodedData, - ); - - return { - iv: encodeUnpaddedBase64(iv), - ciphertext: encodeUnpaddedBase64(ciphertext), - }; - } - - public async send(payload: T): Promise<void> { - if (!this.olmSAS) { - throw new Error("Channel closed"); - } - - if (!this.aesKey) { - throw new Error("Shared secret not set up"); - } - - return this.transport.send(await this.encrypt(payload)); - } - - private async decrypt({ iv, ciphertext }: EncryptedPayload): Promise<Partial<T>> { - if (!ciphertext || !iv) { - throw new Error("Missing ciphertext and/or iv"); - } - - const ciphertextBytes = decodeBase64(ciphertext); - - if (!subtleCrypto) { - throw new Error("Web Crypto is not available"); - } - - const plaintext = await subtleCrypto.decrypt( - { - name: "AES-GCM", - iv: decodeBase64(iv), - tagLength: 128, - }, - this.aesKey as CryptoKey, - ciphertextBytes, - ); - - return JSON.parse(new TextDecoder().decode(new Uint8Array(plaintext))); - } - - public async receive(): Promise<Partial<T> | undefined> { - if (!this.olmSAS) { - throw new Error("Channel closed"); - } - if (!this.aesKey) { - throw new Error("Shared secret not set up"); - } - - const rawData = await this.transport.receive(); - if (!rawData) { - return undefined; - } - const data = rawData as Partial<EncryptedPayload>; - if (data.ciphertext && data.iv) { - return this.decrypt(data as EncryptedPayload); - } - - throw new Error("Data received but no ciphertext"); - } - - public async close(): Promise<void> { - if (this.olmSAS) { - this.olmSAS.free(); - this.olmSAS = undefined; - } - } - - public async cancel(reason: RendezvousFailureReason): Promise<void> { - try { - await this.transport.cancel(reason); - } finally { - await this.close(); - } - } -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/channels/index.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/channels/index.ts deleted file mode 100644 index f157bbe..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/channels/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* -Copyright 2022 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 * from "./MSC3903ECDHv2RendezvousChannel"; diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/index.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/index.ts deleted file mode 100644 index 379b133..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2022 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 * from "./MSC3906Rendezvous"; -export * from "./RendezvousChannel"; -export * from "./RendezvousCode"; -export * from "./RendezvousError"; -export * from "./RendezvousFailureReason"; -export * from "./RendezvousIntent"; -export * from "./RendezvousTransport"; diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/transports/MSC3886SimpleHttpRendezvousTransport.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/transports/MSC3886SimpleHttpRendezvousTransport.ts deleted file mode 100644 index 430ee92..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/transports/MSC3886SimpleHttpRendezvousTransport.ts +++ /dev/null @@ -1,193 +0,0 @@ -/* -Copyright 2022 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 { UnstableValue } from "matrix-events-sdk"; - -import { logger } from "../../logger"; -import { sleep } from "../../utils"; -import { - RendezvousFailureListener, - RendezvousFailureReason, - RendezvousTransport, - RendezvousTransportDetails, -} from ".."; -import { MatrixClient } from "../../matrix"; -import { ClientPrefix } from "../../http-api"; - -const TYPE = new UnstableValue("http.v1", "org.matrix.msc3886.http.v1"); - -export interface MSC3886SimpleHttpRendezvousTransportDetails extends RendezvousTransportDetails { - uri: string; -} - -/** - * Implementation of the unstable [MSC3886](https://github.com/matrix-org/matrix-spec-proposals/pull/3886) - * simple HTTP rendezvous protocol. - * Note that this is UNSTABLE and may have breaking changes without notice. - */ -export class MSC3886SimpleHttpRendezvousTransport<T extends {}> implements RendezvousTransport<T> { - private uri?: string; - private etag?: string; - private expiresAt?: Date; - private client: MatrixClient; - private fallbackRzServer?: string; - private fetchFn?: typeof global.fetch; - private cancelled = false; - private _ready = false; - public onFailure?: RendezvousFailureListener; - - public constructor({ - onFailure, - client, - fallbackRzServer, - fetchFn, - }: { - fetchFn?: typeof global.fetch; - onFailure?: RendezvousFailureListener; - client: MatrixClient; - fallbackRzServer?: string; - }) { - this.fetchFn = fetchFn; - this.onFailure = onFailure; - this.client = client; - this.fallbackRzServer = fallbackRzServer; - } - - public get ready(): boolean { - return this._ready; - } - - public async details(): Promise<MSC3886SimpleHttpRendezvousTransportDetails> { - if (!this.uri) { - throw new Error("Rendezvous not set up"); - } - - return { - type: TYPE.name, - uri: this.uri, - }; - } - - private fetch(resource: URL | string, options?: RequestInit): ReturnType<typeof global.fetch> { - if (this.fetchFn) { - return this.fetchFn(resource, options); - } - return global.fetch(resource, options); - } - - private async getPostEndpoint(): Promise<string | undefined> { - try { - if (await this.client.doesServerSupportUnstableFeature("org.matrix.msc3886")) { - return `${this.client.baseUrl}${ClientPrefix.Unstable}/org.matrix.msc3886/rendezvous`; - } - } catch (err) { - logger.warn("Failed to get unstable features", err); - } - - return this.fallbackRzServer; - } - - public async send(data: T): Promise<void> { - if (this.cancelled) { - return; - } - const method = this.uri ? "PUT" : "POST"; - const uri = this.uri ?? (await this.getPostEndpoint()); - - if (!uri) { - throw new Error("Invalid rendezvous URI"); - } - - const headers: Record<string, string> = { "content-type": "application/json" }; - if (this.etag) { - headers["if-match"] = this.etag; - } - - const res = await this.fetch(uri, { method, headers, body: JSON.stringify(data) }); - if (res.status === 404) { - return this.cancel(RendezvousFailureReason.Unknown); - } - this.etag = res.headers.get("etag") ?? undefined; - - if (method === "POST") { - const location = res.headers.get("location"); - if (!location) { - throw new Error("No rendezvous URI given"); - } - const expires = res.headers.get("expires"); - if (expires) { - this.expiresAt = new Date(expires); - } - // we would usually expect the final `url` to be set by a proper fetch implementation. - // however, if a polyfill based on XHR is used it won't be set, we we use existing URI as fallback - const baseUrl = res.url ?? uri; - // resolve location header which could be relative or absolute - this.uri = new URL(location, `${baseUrl}${baseUrl.endsWith("/") ? "" : "/"}`).href; - this._ready = true; - } - } - - public async receive(): Promise<Partial<T> | undefined> { - if (!this.uri) { - throw new Error("Rendezvous not set up"); - } - // eslint-disable-next-line no-constant-condition - while (true) { - if (this.cancelled) { - return undefined; - } - - const headers: Record<string, string> = {}; - if (this.etag) { - headers["if-none-match"] = this.etag; - } - const poll = await this.fetch(this.uri, { method: "GET", headers }); - - if (poll.status === 404) { - this.cancel(RendezvousFailureReason.Unknown); - return undefined; - } - - // rely on server expiring the channel rather than checking ourselves - - if (poll.headers.get("content-type") !== "application/json") { - this.etag = poll.headers.get("etag") ?? undefined; - } else if (poll.status === 200) { - this.etag = poll.headers.get("etag") ?? undefined; - return poll.json(); - } - await sleep(1000); - } - } - - public async cancel(reason: RendezvousFailureReason): Promise<void> { - if (reason === RendezvousFailureReason.Unknown && this.expiresAt && this.expiresAt.getTime() < Date.now()) { - reason = RendezvousFailureReason.Expired; - } - - this.cancelled = true; - this._ready = false; - this.onFailure?.(reason); - - if (this.uri && reason === RendezvousFailureReason.UserDeclined) { - try { - await this.fetch(this.uri, { method: "DELETE" }); - } catch (e) { - logger.warn(e); - } - } - } -} diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/transports/index.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/transports/index.ts deleted file mode 100644 index 6d8d642..0000000 --- a/includes/external/matrix/node_modules/matrix-js-sdk/src/rendezvous/transports/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* -Copyright 2022 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 * from "./MSC3886SimpleHttpRendezvousTransport"; |