From ddbfe4e1fadca5e74aaf82c106a04bab734b8a64 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Mar 2020 16:31:40 +0100 Subject: [PATCH 1/4] enable 4S if needed when trying to verify --- src/components/views/right_panel/UserInfo.js | 65 +----------- src/verification.js | 106 +++++++++++++++++++ 2 files changed, 109 insertions(+), 62 deletions(-) create mode 100644 src/verification.js diff --git a/src/components/views/right_panel/UserInfo.js b/src/components/views/right_panel/UserInfo.js index 24c5489c4f..4219da690e 100644 --- a/src/components/views/right_panel/UserInfo.js +++ b/src/components/views/right_panel/UserInfo.js @@ -25,7 +25,7 @@ import dis from '../../../dispatcher'; import Modal from '../../../Modal'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; -import createRoom, {findDMForUser} from '../../../createRoom'; +import createRoom from '../../../createRoom'; import DMRoomMap from '../../../utils/DMRoomMap'; import AccessibleButton from '../elements/AccessibleButton'; import SdkConfig from '../../../SdkConfig'; @@ -43,6 +43,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases"; import EncryptionPanel from "./EncryptionPanel"; import { useAsyncMemo } from '../../../hooks/useAsyncMemo'; +import { verifyUser, legacyVerifyUser, verifyDevice } from '../../../verification'; const _disambiguateDevices = (devices) => { const names = Object.create(null); @@ -153,66 +154,6 @@ function useHasCrossSigningKeys(cli, member, canVerify, setUpdating) { }, [cli, member, canVerify], false); } -async function verifyDevice(userId, device) { - const cli = MatrixClientPeg.get(); - const member = cli.getUser(userId); - const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - Modal.createTrackedDialog("Verification warning", "unverified session", QuestionDialog, { - headerImage: require("../../../../res/img/e2e/warning.svg"), - title: _t("Not Trusted"), - description:
-

{_t("%(name)s (%(userId)s) signed in to a new session without verifying it:", {name: member.displayName, userId})}

-

{device.getDisplayName()} ({device.deviceId})

-

{_t("Ask this user to verify their session, or manually verify it below.")}

-
, - onFinished: async (doneClicked) => { - const manuallyVerifyClicked = !doneClicked; - if (!manuallyVerifyClicked) { - return; - } - const cli = MatrixClientPeg.get(); - const verificationRequestPromise = cli.requestVerification( - userId, - [device.deviceId], - ); - dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: {member, verificationRequestPromise}, - }); - }, - primaryButton: _t("Done"), - cancelButton: _t("Manually Verify"), - }); -} - -async function legacyVerifyUser(member) { - const cli = MatrixClientPeg.get(); - const verificationRequestPromise = cli.requestVerification(member.userId); - dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: {member, verificationRequestPromise}, - }); -} - -function verifyUser(user) { - const cli = MatrixClientPeg.get(); - const dmRoom = findDMForUser(cli, user.userId); - let existingRequest; - if (dmRoom) { - existingRequest = cli.findVerificationRequestDMInProgress(dmRoom.roomId); - } - dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: { - member: user, - verificationRequest: existingRequest, - }, - }); -} - function DeviceItem({userId, device}) { const cli = useContext(MatrixClientContext); const isMe = userId === cli.getUserId(); @@ -239,7 +180,7 @@ function DeviceItem({userId, device}) { const onDeviceClick = () => { if (!isVerified) { - verifyDevice(userId, device); + verifyDevice(cli.getUser(userId), device); } }; diff --git a/src/verification.js b/src/verification.js new file mode 100644 index 0000000000..f110a9632a --- /dev/null +++ b/src/verification.js @@ -0,0 +1,106 @@ +/* +Copyright 2019, 2020 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 {MatrixClientPeg} from './MatrixClientPeg'; +import dis from "./dispatcher"; +import Modal from './Modal'; +import * as sdk from './index'; +import { _t } from './languageHandler'; +import {RIGHT_PANEL_PHASES} from "./stores/RightPanelStorePhases"; +import {findDMForUser} from './createRoom'; +import {accessSecretStorage} from './CrossSigningManager'; +import SettingsStore from './settings/SettingsStore'; + +async function enable4SIfNeeded() { + const cli = MatrixClientPeg.get(); + if (!cli.isCryptoEnabled() || !SettingsStore.isFeatureEnabled("feature_cross_signing")) { + return false; + } + const masterPK = cli.getCrossSigningId(); + if (!masterPK) { + await accessSecretStorage(); + return false; + } + + return true; +} + +export async function verifyDevice(user, device) { + if (!await enable4SIfNeeded()) { + return; + } + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createTrackedDialog("Verification warning", "unverified session", QuestionDialog, { + headerImage: require("../res/img/e2e/warning.svg"), + title: _t("Not Trusted"), + description:
+

{_t("%(name)s (%(userId)s) signed in to a new session without verifying it:", {name: user.displayName, userId: user.userId})}

+

{device.getDisplayName()} ({device.deviceId})

+

{_t("Ask this user to verify their session, or manually verify it below.")}

+
, + onFinished: async (doneClicked) => { + const manuallyVerifyClicked = !doneClicked; + if (!manuallyVerifyClicked) { + return; + } + const cli = MatrixClientPeg.get(); + const verificationRequestPromise = cli.requestVerification( + user.userId, + [device.deviceId], + ); + dis.dispatch({ + action: "set_right_panel_phase", + phase: RIGHT_PANEL_PHASES.EncryptionPanel, + refireParams: {member: user, verificationRequestPromise}, + }); + }, + primaryButton: _t("Done"), + cancelButton: _t("Manually Verify"), + }); +} + +export async function legacyVerifyUser(user) { + if (!await enable4SIfNeeded()) { + return; + } + const cli = MatrixClientPeg.get(); + const verificationRequestPromise = cli.requestVerification(user.userId); + dis.dispatch({ + action: "set_right_panel_phase", + phase: RIGHT_PANEL_PHASES.EncryptionPanel, + refireParams: {member: user, verificationRequestPromise}, + }); +} + +export async function verifyUser(user) { + if (!await enable4SIfNeeded()) { + return; + } + const cli = MatrixClientPeg.get(); + const dmRoom = findDMForUser(cli, user.userId); + let existingRequest; + if (dmRoom) { + existingRequest = cli.findVerificationRequestDMInProgress(dmRoom.roomId); + } + dis.dispatch({ + action: "set_right_panel_phase", + phase: RIGHT_PANEL_PHASES.EncryptionPanel, + refireParams: { + member: user, + verificationRequest: existingRequest, + }, + }); +} From ab2e3a346599a4f092d43dc8d2de94954ac34f88 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Mar 2020 16:54:49 +0100 Subject: [PATCH 2/4] also enable 4s when accepting a verification request --- src/components/views/toasts/VerificationRequestToast.js | 4 ++++ src/verification.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/views/toasts/VerificationRequestToast.js b/src/components/views/toasts/VerificationRequestToast.js index c11cefc839..f590cecc3e 100644 --- a/src/components/views/toasts/VerificationRequestToast.js +++ b/src/components/views/toasts/VerificationRequestToast.js @@ -24,6 +24,7 @@ import {userLabelForEventRoom} from "../../../utils/KeyVerificationStateObserver import dis from "../../../dispatcher"; import ToastStore from "../../../stores/ToastStore"; import Modal from "../../../Modal"; +import {enable4SIfNeeded} from "../../../verification"; export default class VerificationRequestToast extends React.PureComponent { constructor(props) { @@ -73,6 +74,9 @@ export default class VerificationRequestToast extends React.PureComponent { } accept = async () => { + if (!await enable4SIfNeeded()) { + return; + } ToastStore.sharedInstance().dismissToast(this.props.toastKey); const {request} = this.props; // no room id for to_device requests diff --git a/src/verification.js b/src/verification.js index f110a9632a..cdce9c6d32 100644 --- a/src/verification.js +++ b/src/verification.js @@ -24,7 +24,7 @@ import {findDMForUser} from './createRoom'; import {accessSecretStorage} from './CrossSigningManager'; import SettingsStore from './settings/SettingsStore'; -async function enable4SIfNeeded() { +export async function enable4SIfNeeded() { const cli = MatrixClientPeg.get(); if (!cli.isCryptoEnabled() || !SettingsStore.isFeatureEnabled("feature_cross_signing")) { return false; From e34a37102a73f49903d56fbc8c0acb9ff73c6137 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Mar 2020 16:56:20 +0100 Subject: [PATCH 3/4] move i18n strings around as script desires --- src/i18n/strings/en_EN.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 01ba458a2f..4e371cacb0 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -293,6 +293,11 @@ "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s", "Light theme": "Light theme", "Dark theme": "Dark theme", + "Not Trusted": "Not Trusted", + "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) signed in to a new session without verifying it:", + "Ask this user to verify their session, or manually verify it below.": "Ask this user to verify their session, or manually verify it below.", + "Done": "Done", + "Manually Verify": "Manually Verify", "%(displayName)s is typing …": "%(displayName)s is typing …", "%(names)s and %(count)s others are typing …|other": "%(names)s and %(count)s others are typing …", "%(names)s and %(count)s others are typing …|one": "%(names)s and one other is typing …", @@ -1184,11 +1189,6 @@ "Yours, or the other users’ session": "Yours, or the other users’ session", "Members": "Members", "Files": "Files", - "Not Trusted": "Not Trusted", - "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) signed in to a new session without verifying it:", - "Ask this user to verify their session, or manually verify it below.": "Ask this user to verify their session, or manually verify it below.", - "Done": "Done", - "Manually Verify": "Manually Verify", "Trusted": "Trusted", "Not trusted": "Not trusted", "%(count)s verified sessions|other": "%(count)s verified sessions", From 1eb5bdf847f2c5badd014e865f71e297c20869d6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 10 Mar 2020 18:40:24 +0100 Subject: [PATCH 4/4] use USK as we'll only have that around when using key sharing --- src/verification.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/verification.js b/src/verification.js index cdce9c6d32..235828dc92 100644 --- a/src/verification.js +++ b/src/verification.js @@ -29,8 +29,8 @@ export async function enable4SIfNeeded() { if (!cli.isCryptoEnabled() || !SettingsStore.isFeatureEnabled("feature_cross_signing")) { return false; } - const masterPK = cli.getCrossSigningId(); - if (!masterPK) { + const usk = cli.getCrossSigningId("user_signing"); + if (!usk) { await accessSecretStorage(); return false; }