Skip to content

Commit cd56880

Browse files
committed
allow user to check and detect its usb token for e2e encryption
Signed-off-by: Matthieu Gallien <[email protected]>
1 parent 05466f4 commit cd56880

18 files changed

+579
-15
lines changed

NEXTCLOUD.cmake

+2
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,5 @@ endif()
8080
if (APPLE)
8181
option( BUILD_FILE_PROVIDER_MODULE "Build the macOS virtual files File Provider module" OFF )
8282
endif()
83+
84+
set (CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN true)

config.h.in

+2
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@
6161

6262
#cmakedefine CFAPI_SHELL_EXTENSIONS_LIB_NAME "@CFAPI_SHELL_EXTENSIONS_LIB_NAME@"
6363

64+
#cmakedefine CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN @CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN@
65+
6466
#endif

resources.qrc

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<file>src/gui/PredefinedStatusButton.qml</file>
88
<file>src/gui/BasicComboBox.qml</file>
99
<file>src/gui/ErrorBox.qml</file>
10+
<file>src/gui/EncryptionTokenSelectionWindow.qml</file>
1011
<file>src/gui/filedetails/FileActivityView.qml</file>
1112
<file>src/gui/filedetails/FileDetailsPage.qml</file>
1213
<file>src/gui/filedetails/FileDetailsView.qml</file>

src/gui/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ set(client_SRCS
154154
syncrunfilelog.cpp
155155
systray.h
156156
systray.cpp
157+
EncryptionTokenSelectionWindow.qml
157158
thumbnailjob.h
158159
thumbnailjob.cpp
159160
userinfo.h
+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright (C) 2023 by Matthieu Gallien <[email protected]>
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* for more details.
13+
*/
14+
15+
import QtQuick 2.15
16+
import QtQuick.Layouts 1.15
17+
import QtQuick.Controls 2.15
18+
import QtQml.Models 2.15
19+
20+
import com.nextcloud.desktopclient 1.0
21+
import Style 1.0
22+
23+
import "./tray"
24+
25+
ApplicationWindow {
26+
id: root
27+
28+
required property var tokensInfo
29+
required property var keysInfo
30+
31+
flags: Qt.Window | Qt.Dialog
32+
visible: true
33+
modality: Qt.ApplicationModal
34+
35+
width: 400
36+
height: 600
37+
minimumWidth: 400
38+
minimumHeight: 600
39+
40+
title: qsTr('Token Encryption Key Chooser')
41+
42+
// TODO: Rather than setting all these palette colours manually,
43+
// create a custom style and do it for all components globally
44+
palette {
45+
text: Style.ncTextColor
46+
windowText: Style.ncTextColor
47+
buttonText: Style.ncTextColor
48+
brightText: Style.ncTextBrightColor
49+
highlight: Style.lightHover
50+
highlightedText: Style.ncTextColor
51+
light: Style.lightHover
52+
midlight: Style.ncSecondaryTextColor
53+
mid: Style.darkerHover
54+
dark: Style.menuBorder
55+
button: Style.buttonBackgroundColor
56+
window: Style.backgroundColor
57+
base: Style.backgroundColor
58+
toolTipBase: Style.backgroundColor
59+
toolTipText: Style.ncTextColor
60+
}
61+
62+
onClosing: function(close) {
63+
Systray.destroyDialog(self);
64+
close.accepted = true
65+
}
66+
67+
ColumnLayout {
68+
anchors.fill: parent
69+
anchors.leftMargin: 20
70+
anchors.rightMargin: 20
71+
anchors.bottomMargin: 20
72+
anchors.topMargin: 20
73+
spacing: 15
74+
z: 2
75+
76+
EnforcedPlainTextLabel {
77+
text: qsTr("Available Keys for end-to-end Encryption:")
78+
font.bold: true
79+
font.pixelSize: Style.bigFontPixelSizeResolveConflictsDialog
80+
Layout.fillWidth: true
81+
}
82+
83+
ScrollView {
84+
Layout.fillWidth: true
85+
Layout.fillHeight: true
86+
87+
clip: true
88+
89+
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
90+
91+
ListView {
92+
id: tokensListView
93+
94+
model: DelegateModel {
95+
model: keysInfo
96+
97+
delegate: ItemDelegate {
98+
width: tokensListView.contentItem.width
99+
100+
text: modelData.label
101+
102+
highlighted: tokensListView.currentIndex === index
103+
104+
onClicked: function() { tokensListView.currentIndex = index }
105+
}
106+
}
107+
}
108+
}
109+
110+
DialogButtonBox {
111+
Layout.fillWidth: true
112+
113+
Button {
114+
text: qsTr("Choose")
115+
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
116+
}
117+
Button {
118+
text: qsTr("Cancel")
119+
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
120+
}
121+
122+
onAccepted: function() {
123+
Systray.destroyDialog(conflictsDialog)
124+
}
125+
126+
onRejected: function() {
127+
Systray.destroyDialog(conflictsDialog)
128+
}
129+
}
130+
}
131+
132+
Rectangle {
133+
color: Style.backgroundColor
134+
anchors.fill: parent
135+
z: 1
136+
}
137+
}

src/gui/accountsettings.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ void AccountSettings::slotE2eEncryptionMnemonicReady()
283283
void AccountSettings::slotE2eEncryptionGenerateKeys()
284284
{
285285
connect(_accountState->account()->e2e(), &ClientSideEncryption::initializationFinished, this, &AccountSettings::slotE2eEncryptionInitializationFinished);
286+
connect(_accountState->account()->e2e(), &ClientSideEncryption::displayTokenInitDialog, this, &AccountSettings::slotDisplayTokenInitDialog);
286287
_accountState->account()->setE2eEncryptionKeysGenerationAllowed(true);
287288
_accountState->account()->setAskUserForMnemonic(true);
288289
_accountState->account()->e2e()->initialize(_accountState->account());
@@ -291,6 +292,7 @@ void AccountSettings::slotE2eEncryptionGenerateKeys()
291292
void AccountSettings::slotE2eEncryptionInitializationFinished(bool isNewMnemonicGenerated)
292293
{
293294
disconnect(_accountState->account()->e2e(), &ClientSideEncryption::initializationFinished, this, &AccountSettings::slotE2eEncryptionInitializationFinished);
295+
disconnect(_accountState->account()->e2e(), &ClientSideEncryption::displayTokenInitDialog, this, &AccountSettings::slotDisplayTokenInitDialog);
294296
if (_accountState->account()->e2e()->isInitialized()) {
295297
removeActionFromEncryptionMessage(e2EeUiActionEnableEncryptionId);
296298
slotE2eEncryptionMnemonicReady();
@@ -301,6 +303,14 @@ void AccountSettings::slotE2eEncryptionInitializationFinished(bool isNewMnemonic
301303
_accountState->account()->setAskUserForMnemonic(false);
302304
}
303305

306+
void AccountSettings::slotDisplayTokenInitDialog()
307+
{
308+
disconnect(_accountState->account()->e2e(), &ClientSideEncryption::initializationFinished, this, &AccountSettings::slotE2eEncryptionInitializationFinished);
309+
disconnect(_accountState->account()->e2e(), &ClientSideEncryption::displayTokenInitDialog, this, &AccountSettings::slotDisplayTokenInitDialog);
310+
Systray::instance()->createTokenInitDialog(_accountState->account()->e2e()->discoveredTokens(),
311+
_accountState->account()->e2e()->discoveredKeys());
312+
}
313+
304314
void AccountSettings::slotEncryptFolderFinished(int status)
305315
{
306316
qCInfo(lcAccountSettings) << "Current folder encryption status code:" << status;

src/gui/accountsettings.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class AccountSettings : public QWidget
5858
~AccountSettings() override;
5959
[[nodiscard]] QSize sizeHint() const override { return ownCloudGui::settingsDialogSize(); }
6060
bool canEncryptOrDecrypt(const FolderStatusModel::SubFolderInfo* folderInfo);
61+
[[nodiscard]] OCC::AccountState *accountsState() const { return _accountState; }
6162

6263
signals:
6364
void folderChanged();
@@ -72,7 +73,6 @@ public slots:
7273
void slotUpdateQuota(qint64 total, qint64 used);
7374
void slotAccountStateChanged();
7475
void slotStyleChanged();
75-
OCC::AccountState *accountsState() { return _accountState; }
7676
void slotHideSelectiveSyncWidget();
7777

7878
protected slots:
@@ -106,6 +106,7 @@ protected slots:
106106
void slotE2eEncryptionMnemonicReady();
107107
void slotE2eEncryptionGenerateKeys();
108108
void slotE2eEncryptionInitializationFinished(bool isNewMnemonicGenerated);
109+
void slotDisplayTokenInitDialog();
109110
void slotEncryptFolderFinished(int status);
110111

111112
void slotSelectiveSyncChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,

src/gui/owncloudgui.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,10 @@ void ownCloudGui::slotShowSettings()
571571
if (_settingsDialog.isNull()) {
572572
_settingsDialog = new SettingsDialog(this);
573573
_settingsDialog->setAttribute(Qt::WA_DeleteOnClose, true);
574+
575+
connect(_tray.data(), &Systray::hideSettingsDialog,
576+
_settingsDialog.data(), &SettingsDialog::close);
577+
574578
_settingsDialog->show();
575579
}
576580
raiseDialog(_settingsDialog.data());

src/gui/settingsdialog.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ SettingsDialog::SettingsDialog(ownCloudGui *gui, QWidget *parent)
137137
_actionGroupWidgets.insert(generalAction, generalSettings);
138138
_actionGroupWidgets.insert(networkAction, networkSettings);
139139

140-
foreach(auto ai, AccountManager::instance()->accounts()) {
141-
accountAdded(ai.data());
142-
}
143-
144140
QTimer::singleShot(1, this, &SettingsDialog::showFirstPage);
145141

146142
auto *showLogWindow = new QAction(this);
@@ -215,6 +211,10 @@ void SettingsDialog::slotSwitchPage(QAction *action)
215211

216212
void SettingsDialog::showFirstPage()
217213
{
214+
foreach(auto ai, AccountManager::instance()->accounts()) {
215+
accountAdded(ai.data());
216+
}
217+
218218
QList<QAction *> actions = _toolBar->actions();
219219
if (!actions.empty()) {
220220
actions.first()->trigger();

src/gui/systray.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <QScreen>
3535
#include <QMenu>
3636
#include <QGuiApplication>
37+
#include <QQuickView>
3738

3839
#ifdef USE_FDO_NOTIFICATIONS
3940
#include <QDBusConnection>
@@ -412,6 +413,50 @@ void Systray::createFileActivityDialog(const QString &localPath)
412413
Q_EMIT showFileDetailsPage(localPath, FileDetailsPage::Activity);
413414
}
414415

416+
void Systray::createTokenInitDialog(const QVariantList &tokensInfo,
417+
const QVariantList &keysInfo)
418+
{
419+
if(_tokenInitDialog) {
420+
destroyDialog(_tokenInitDialog);
421+
_tokenInitDialog = nullptr;
422+
}
423+
424+
qCDebug(lcSystray) << "Opening new token init dialog with " << tokensInfo.size() << "possible tokens";
425+
426+
if (!_trayEngine) {
427+
qCWarning(lcSystray) << "Could not open token init dialog as no tray engine was available";
428+
return;
429+
}
430+
431+
const QVariantMap initialProperties{
432+
{"tokensInfo", tokensInfo},
433+
{"keysInfo", keysInfo}
434+
};
435+
436+
QQmlComponent encryptionTokenDialog(_trayEngine, QStringLiteral("qrc:/qml/src/gui/EncryptionTokenSelectionWindow.qml"));
437+
438+
if (!encryptionTokenDialog.isError()) {
439+
const auto createdDialog = encryptionTokenDialog.createWithInitialProperties(initialProperties);
440+
const auto dialog = qobject_cast<QQuickWindow*>(createdDialog);
441+
442+
if(!dialog) {
443+
qCWarning(lcSystray) << "File details dialog window resulted in creation of object that was not a window!";
444+
return;
445+
}
446+
447+
_tokenInitDialog = dialog;
448+
449+
Q_EMIT hideSettingsDialog();
450+
451+
dialog->show();
452+
dialog->raise();
453+
dialog->requestActivate();
454+
455+
} else {
456+
qCWarning(lcSystray) << encryptionTokenDialog.errorString();
457+
}
458+
}
459+
415460
void Systray::presentShareViewInTray(const QString &localPath)
416461
{
417462
const auto folder = FolderMan::instance()->folderForPath(localPath);

src/gui/systray.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
#ifndef SYSTRAY_H
1616
#define SYSTRAY_H
1717

18-
#include <QSystemTrayIcon>
19-
2018
#include "accountmanager.h"
2119
#include "tray/usermodel.h"
2220

21+
#include <QSystemTrayIcon>
22+
#include <QQuickImageProvider>
2323
#include <QQmlNetworkAccessManagerFactory>
2424

2525
class QScreen;
@@ -112,6 +112,8 @@ class Systray
112112
void syncIsPausedChanged();
113113
void isOpenChanged();
114114

115+
void hideSettingsDialog();
116+
115117
public slots:
116118
void setTrayEngine(QQmlApplicationEngine *trayEngine);
117119
void create();
@@ -145,6 +147,8 @@ public slots:
145147

146148
void createShareDialog(const QString &localPath);
147149
void createFileActivityDialog(const QString &localPath);
150+
void createTokenInitDialog(const QVariantList &tokensInfo,
151+
const QVariantList &keysInfo);
148152

149153
void presentShareViewInTray(const QString &localPath);
150154

@@ -185,6 +189,7 @@ private slots:
185189
QSet<qlonglong> _callsAlreadyNotified;
186190
QPointer<QObject> _editFileLocallyLoadingDialog;
187191
QVector<QQuickWindow*> _fileDetailDialogs;
192+
QQuickWindow* _tokenInitDialog = nullptr;
188193
};
189194

190195
} // namespace OCC

src/libsync/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ set(libsync_SRCS
105105
clientsideencryption.cpp
106106
clientsideencryptionjobs.h
107107
clientsideencryptionjobs.cpp
108+
clientsidetokenselector.h
109+
clientsidetokenselector.cpp
108110
datetimeprovider.h
109111
datetimeprovider.cpp
110112
ocsuserstatusconnector.h

src/libsync/account.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "clientsideencryption.h"
3434
#include "ocsuserstatusconnector.h"
3535

36+
#include "config.h"
37+
3638
#include <QLoggingCategory>
3739
#include <QNetworkReply>
3840
#include <QNetworkAccessManager>
@@ -1023,9 +1025,9 @@ bool Account::askUserForMnemonic() const
10231025
return _e2eAskUserForMnemonic;
10241026
}
10251027

1026-
bool Account::useHardwareTokenEncryption() const
1028+
bool Account::enforceUseHardwareTokenEncryption() const
10271029
{
1028-
return !encryptionHardwareTokenDriverPath().isEmpty();
1030+
return CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN;
10291031
}
10301032

10311033
QString Account::encryptionHardwareTokenDriverPath() const

0 commit comments

Comments
 (0)