From 510b71b0e5c63cbef5c92f8cd490e38426266db6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 19 Mar 2020 16:30:49 +0100 Subject: [PATCH 1/5] extract manual device verification out of device verify dialog as the plan is to remove the latter --- .../ManualDeviceKeyVerificationDialog.js | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js new file mode 100644 index 0000000000..35cd0ea20d --- /dev/null +++ b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js @@ -0,0 +1,91 @@ +/* +Copyright 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd +Copyright 2019 New Vector Ltd +Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> + +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 React from 'react'; +import PropTypes from 'prop-types'; +import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import * as sdk from '../../../index'; +import * as FormattingUtils from '../../../utils/FormattingUtils'; +import { _t } from '../../../languageHandler'; + +export default class ManualDeviceKeyVerificationDialog extends React.Component { + static propTypes = { + userId: PropTypes.string.isRequired, + device: PropTypes.object.isRequired, + onFinished: PropTypes.func.isRequired, + }; + + _onCancelClick = () => { + this.props.onFinished(false); + } + + _onLegacyFinished = (confirm) => { + if (confirm) { + MatrixClientPeg.get().setDeviceVerified( + this.props.userId, this.props.device.deviceId, true, + ); + } + this.props.onFinished(confirm); + } + + render() { + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton'); + + let text; + if (MatrixClientPeg.get().getUserId() === this.props.userId) { + text = _t("To verify that this session can be trusted, please check that the key you see " + + "in User Settings on that device matches the key below:"); + } else { + text = _t("To verify that this session can be trusted, please contact its owner using some other " + + "means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings " + + "for this session matches the key below:"); + } + + const key = FormattingUtils.formatCryptoKey(this.props.device.getFingerprint()); + const body = ( +
+

+ { text } +

+
+
    +
  • { this.props.device.getDisplayName() }
  • +
  • { this.props.device.deviceId }
  • +
  • { key }
  • +
+
+

+ { _t("If it matches, press the verify button below. " + + "If it doesn't, then someone else is intercepting this session " + + "and you probably want to press the blacklist button instead.") } +

+
+ ); + + return ( + + ); + } +} From 073c2c525f6a9270b9666b573a7d28ba8510f9b8 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 19 Mar 2020 16:31:23 +0100 Subject: [PATCH 2/5] Add "legacy verify" button to untrusted session dialog --- src/i18n/strings/en_EN.json | 3 +- src/verification.js | 69 +++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c3befa2298..e04946b5a3 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -294,8 +294,9 @@ "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.", + "Legacy Verify Device": "Legacy Verify Device", + "Verify Device by Emoji": "Verify Device by Emoji", "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 …", diff --git a/src/verification.js b/src/verification.js index 4443079b95..00905acf8e 100644 --- a/src/verification.js +++ b/src/verification.js @@ -39,38 +39,55 @@ async function enable4SIfNeeded() { return true; } +function UntrustedDeviceDialog(props) { + const {device, user, onFinished} = props; + const BaseDialog = sdk.getComponent("dialogs.BaseDialog"); + const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); + return +
+

{_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("legacy")}>{_t("Legacy Verify Device")} + onFinished("sas")}>{_t("Verify Device by Emoji")} + onFinished()}>{_t("Done")} +
+
; +} + 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; + Modal.createTrackedDialog("Verification warning", "unverified session", UntrustedDeviceDialog, { + user, + device, + onFinished: async (action) => { + if (action === "sas") { + const cli = MatrixClientPeg.get(); + const verificationRequestPromise = cli.legacyDeviceVerification( + user.userId, + device.deviceId, + verificationMethods.SAS, + ); + dis.dispatch({ + action: "set_right_panel_phase", + phase: RIGHT_PANEL_PHASES.EncryptionPanel, + refireParams: {member: user, verificationRequestPromise}, + }); + } else if (action === "legacy") { + const ManualDeviceKeyVerificationDialog = sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); + Modal.createTrackedDialog("Legacy verify session", "legacy verify session", ManualDeviceKeyVerificationDialog, { + userId: user.userId, + device, + }); } - const cli = MatrixClientPeg.get(); - const verificationRequestPromise = cli.legacyDeviceVerification( - user.userId, - device.deviceId, - verificationMethods.SAS, - ); - dis.dispatch({ - action: "set_right_panel_phase", - phase: RIGHT_PANEL_PHASES.EncryptionPanel, - refireParams: {member: user, verificationRequestPromise}, - }); }, - primaryButton: _t("Done"), - cancelButton: _t("Manually Verify"), }); } From b97b8873054491476735fbc6080f0974da0797c5 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 19 Mar 2020 16:35:41 +0100 Subject: [PATCH 3/5] fix lint --- .../dialogs/ManualDeviceKeyVerificationDialog.js | 1 - src/verification.js | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js index 35cd0ea20d..3d944d279f 100644 --- a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js +++ b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js @@ -46,7 +46,6 @@ export default class ManualDeviceKeyVerificationDialog extends React.Component { render() { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - const AccessibleButton = sdk.getComponent('views.elements.AccessibleButton'); let text; if (MatrixClientPeg.get().getUserId() === this.props.userId) { diff --git a/src/verification.js b/src/verification.js index 00905acf8e..e33a569a73 100644 --- a/src/verification.js +++ b/src/verification.js @@ -82,10 +82,13 @@ export async function verifyDevice(user, device) { }); } else if (action === "legacy") { const ManualDeviceKeyVerificationDialog = sdk.getComponent("dialogs.ManualDeviceKeyVerificationDialog"); - Modal.createTrackedDialog("Legacy verify session", "legacy verify session", ManualDeviceKeyVerificationDialog, { - userId: user.userId, - device, - }); + Modal.createTrackedDialog("Legacy verify session", "legacy verify session", + ManualDeviceKeyVerificationDialog, + { + userId: user.userId, + device, + }, + ); } }, }); From 1620f2159bbf03bbaffce77e5ec2e4e25b6a37b2 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 20 Mar 2020 14:45:22 +0100 Subject: [PATCH 4/5] add 2020 foundation copyright --- .../views/dialogs/ManualDeviceKeyVerificationDialog.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js index 3d944d279f..2db090a901 100644 --- a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js +++ b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js @@ -3,6 +3,7 @@ Copyright 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd Copyright 2019 New Vector Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> +Copyright 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. From 39bd1da1d0b2d1c23554c8cb3a55cc7fcfda4f54 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 20 Mar 2020 15:30:17 +0100 Subject: [PATCH 5/5] update copy --- .../dialogs/ManualDeviceKeyVerificationDialog.js | 13 ++++--------- src/i18n/strings/en_EN.json | 7 +++++-- src/verification.js | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js index 2db090a901..4b9d7239e6 100644 --- a/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js +++ b/src/components/views/dialogs/ManualDeviceKeyVerificationDialog.js @@ -50,12 +50,9 @@ export default class ManualDeviceKeyVerificationDialog extends React.Component { let text; if (MatrixClientPeg.get().getUserId() === this.props.userId) { - text = _t("To verify that this session can be trusted, please check that the key you see " + - "in User Settings on that device matches the key below:"); + text = _t("Confirm by comparing the following with the User Settings in your other session:"); } else { - text = _t("To verify that this session can be trusted, please contact its owner using some other " + - "means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings " + - "for this session matches the key below:"); + text = _t("Confirm this user's session by comparing the following with their User Settings:"); } const key = FormattingUtils.formatCryptoKey(this.props.device.getFingerprint()); @@ -72,9 +69,7 @@ export default class ManualDeviceKeyVerificationDialog extends React.Component {

- { _t("If it matches, press the verify button below. " + - "If it doesn't, then someone else is intercepting this session " + - "and you probably want to press the blacklist button instead.") } + { _t("If they don't match, the security of your communication may be compromised.") }

); @@ -83,7 +78,7 @@ export default class ManualDeviceKeyVerificationDialog extends React.Component { ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e04946b5a3..4ff7ebc9c1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -294,8 +294,8 @@ "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.", - "Legacy Verify Device": "Legacy Verify Device", - "Verify Device by Emoji": "Verify Device by Emoji", + "Manually Verify by Text": "Manually Verify by Text", + "Interactively verify by Emoji": "Interactively verify by Emoji", "Done": "Done", "%(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 …", @@ -1614,6 +1614,9 @@ "Manually export keys": "Manually export keys", "You'll lose access to your encrypted messages": "You'll lose access to your encrypted messages", "Are you sure you want to sign out?": "Are you sure you want to sign out?", + "Confirm by comparing the following with the User Settings in your other session:": "Confirm by comparing the following with the User Settings in your other session:", + "Confirm this user's session by comparing the following with their User Settings:": "Confirm this user's session by comparing the following with their User Settings:", + "If they don't match, the security of your communication may be compromised.": "If they don't match, the security of your communication may be compromised.", "Your homeserver doesn't seem to support this feature.": "Your homeserver doesn't seem to support this feature.", "Message edits": "Message edits", "Your account is not secure": "Your account is not secure", diff --git a/src/verification.js b/src/verification.js index e33a569a73..d0f6fd7806 100644 --- a/src/verification.js +++ b/src/verification.js @@ -53,8 +53,8 @@ function UntrustedDeviceDialog(props) {

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

- onFinished("legacy")}>{_t("Legacy Verify Device")} - onFinished("sas")}>{_t("Verify Device by Emoji")} + onFinished("legacy")}>{_t("Manually Verify by Text")} + onFinished("sas")}>{_t("Interactively verify by Emoji")} onFinished()}>{_t("Done")}
;