Skip to content
This repository has been archived by the owner on Oct 16, 2024. It is now read-only.

Commit

Permalink
Add labs option to exclude unverified devices
Browse files Browse the repository at this point in the history
Add a labs option which will, when set, switch into the "invisible crypto"
mode of refusing to send keys to, or decrypt messages from, devices that have
not been signed by their owner.
  • Loading branch information
richvdh committed Sep 27, 2024
1 parent 81192f6 commit a164d95
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/MatrixClientPeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import PlatformPeg from "./PlatformPeg";
import { formatList } from "./utils/FormattingUtils";
import SdkConfig from "./SdkConfig";
import { Features } from "./settings/Settings";
import { setDeviceIsolationMode } from "./settings/controllers/DeviceIsolationModeController.ts";

export interface IMatrixClientCreds {
homeserverUrl: string;
Expand Down Expand Up @@ -343,6 +344,9 @@ class MatrixClientPegClass implements IMatrixClientPeg {
});

StorageManager.setCryptoInitialised(true);

setDeviceIsolationMode(this.matrixClient, SettingsStore.getValue("feature_exclude_insecure_devices"));

// TODO: device dehydration and whathaveyou
return;
}
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,8 @@
"dynamic_room_predecessors": "Dynamic room predecessors",
"dynamic_room_predecessors_description": "Enable MSC3946 (to support late-arriving room archives)",
"element_call_video_rooms": "Element Call video rooms",
"exclude_insecure_devices": "Exclude insecure devices when sending/receiving messages",
"exclude_insecure_devices_description": "When this mode is enabled, encrypted messages will not be shared with unverified devices, and messages from unverified devices will be shown as an error. Note that if you enable this mode, you may be unable to communicate with users who have not verified their devices.",
"experimental_description": "Feeling experimental? Try out our latest ideas in development. These features are not finalised; they may be unstable, may change, or may be dropped altogether. <a>Learn more</a>.",
"experimental_section": "Early previews",
"extended_profiles_msc_support": "Requires your server to support MSC4133",
Expand Down
11 changes: 11 additions & 0 deletions src/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import React, { ReactNode } from "react";
import { UNSTABLE_MSC4133_EXTENDED_PROFILES } from "matrix-js-sdk/src/matrix";

import { _t, _td, TranslationKey } from "../languageHandler";
import DeviceIsolationModeController from "./controllers/DeviceIsolationModeController.ts";
import {
NotificationBodyEnabledController,
NotificationsEnabledController,
Expand Down Expand Up @@ -309,6 +310,16 @@ export const SETTINGS: { [setting: string]: ISetting } = {
supportedLevelsAreOrdered: true,
default: false,
},
"feature_exclude_insecure_devices": {
isFeature: true,
labsGroup: LabGroup.Encryption,
controller: new DeviceIsolationModeController(),
displayName: _td("labs|exclude_insecure_devices"),
description: _td("labs|exclude_insecure_devices_description"),
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED,
supportedLevelsAreOrdered: true,
default: false,
},
"useOnlyCurrentProfiles": {
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
displayName: _td("settings|disable_historical_profile"),
Expand Down
37 changes: 37 additions & 0 deletions src/settings/controllers/DeviceIsolationModeController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import { AllDevicesIsolationMode, OnlySignedDevicesIsolationMode } from "matrix-js-sdk/src/crypto-api";
import { MatrixClient } from "matrix-js-sdk/src/matrix";

import SettingController from "./SettingController";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import { SettingLevel } from "../SettingLevel";

/**
* A controller for the "exclude_insecure_devices" setting, which will
* update the crypto stack's device isolation mode on change.
*/
export default class DeviceIsolationModeController extends SettingController {
public onChange(level: SettingLevel, roomId: string, newValue: any): void {
setDeviceIsolationMode(MatrixClientPeg.safeGet(), newValue);
}
}

/**
* Set the crypto stack's device isolation mode based on the current value of the
* "exclude_insecure_devices" setting.
*
* @param client - MatrixClient to update to the new setting.
* @param settingValue - value of the "exclude_insecure_devices" setting.
*/
export function setDeviceIsolationMode(client: MatrixClient, settingValue: boolean): void {
client
.getCrypto()
?.setDeviceIsolationMode(
settingValue ? new OnlySignedDevicesIsolationMode() : new AllDevicesIsolationMode(true),
);
}
3 changes: 2 additions & 1 deletion test/components/structures/MatrixChat-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { OidcError } from "matrix-js-sdk/src/oidc/error";
import { BearerTokenResponse } from "matrix-js-sdk/src/oidc/validate";
import { defer, sleep } from "matrix-js-sdk/src/utils";
import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
import { DeviceIsolationMode, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";

Check failure on line 21 in test/components/structures/MatrixChat-test.tsx

View workflow job for this annotation

GitHub Actions / Typescript Syntax Check

'DeviceIsolationMode' is declared but its value is never read.

Check failure on line 21 in test/components/structures/MatrixChat-test.tsx

View workflow job for this annotation

GitHub Actions / ESLint

'DeviceIsolationMode' is defined but never used

import MatrixChat from "../../../src/components/structures/MatrixChat";
import * as StorageAccess from "../../../src/utils/StorageAccess";
Expand Down Expand Up @@ -1002,6 +1002,7 @@ describe("<MatrixChat />", () => {
getUserVerificationStatus: jest
.fn()
.mockResolvedValue(new UserVerificationStatus(false, false, false)),
setDeviceIsolationMode: jest.fn(),
};
loginClient.isCryptoEnabled.mockReturnValue(true);
loginClient.getCrypto.mockReturnValue(mockCrypto as any);
Expand Down
33 changes: 33 additions & 0 deletions test/settings/controllers/DeviceIsolationModeController-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import { AllDevicesIsolationMode, OnlySignedDevicesIsolationMode } from "matrix-js-sdk/src/crypto-api";

import { stubClient } from "../../test-utils";
import DeviceIsolationModeController from "../../../src/settings/controllers/DeviceIsolationModeController.ts";
import { SettingLevel } from "../../../src/settings/SettingLevel";

describe("DeviceIsolationModeController", () => {
afterEach(() => {
jest.resetAllMocks();
});

describe("tracks enabling and disabling", () => {
it("on sets signed device isolation mode", () => {
const cli = stubClient();
const controller = new DeviceIsolationModeController();
controller.onChange(SettingLevel.DEVICE, "", true);
expect(cli.getCrypto()?.setDeviceIsolationMode).toHaveBeenCalledWith(new OnlySignedDevicesIsolationMode());
});

it("off sets all device isolation mode", () => {
const cli = stubClient();
const controller = new DeviceIsolationModeController();
controller.onChange(SettingLevel.DEVICE, "", false);
expect(cli.getCrypto()?.setDeviceIsolationMode).toHaveBeenCalledWith(new AllDevicesIsolationMode(true));
});
});
});
1 change: 1 addition & 0 deletions test/test-utils/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export function createTestClient(): MatrixClient {
resetKeyBackup: jest.fn(),
isEncryptionEnabledInRoom: jest.fn(),
getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]),
setDeviceIsolationMode: jest.fn(),
}),

getPushActionsForEvent: jest.fn(),
Expand Down

0 comments on commit a164d95

Please sign in to comment.