Skip to content

Commit e5d881d

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 e5d881d

17 files changed

+428
-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
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
19+
import com.nextcloud.desktopclient 1.0
20+
import Style 1.0
21+
22+
Item {
23+
id: root
24+
25+
required property var tokensInfo
26+
27+
width: 400
28+
height: 600
29+
30+
ListView {
31+
anchors.fill: parent
32+
33+
model: tokensInfo
34+
35+
delegate: ItemDelegate {
36+
width: parent.width
37+
text: 'hello'
38+
}
39+
}
40+
}

src/gui/accountsettings.cpp

+17
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,16 @@ 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+
qCInfo(lcAccountSettings()) << "trying to find the parent window" << _parentWindow;
311+
if (_parentWindow) {
312+
Systray::instance()->createTokenInitDialog(_accountState->account()->e2e()->discoveredTokens(), _parentWindow);
313+
}
314+
}
315+
304316
void AccountSettings::slotEncryptFolderFinished(int status)
305317
{
306318
qCInfo(lcAccountSettings) << "Current folder encryption status code:" << status;
@@ -1382,6 +1394,11 @@ void AccountSettings::slotHideSelectiveSyncWidget()
13821394
_ui->selectiveSyncLabel->hide();
13831395
}
13841396

1397+
void AccountSettings::setParentWindow(QWindow *parentWindow)
1398+
{
1399+
_parentWindow = parentWindow;
1400+
}
1401+
13851402
void AccountSettings::slotSelectiveSyncChanged(const QModelIndex &topLeft,
13861403
const QModelIndex &bottomRight,
13871404
const QVector<int> &roles)

src/gui/accountsettings.h

+5-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,8 +73,8 @@ public slots:
7273
void slotUpdateQuota(qint64 total, qint64 used);
7374
void slotAccountStateChanged();
7475
void slotStyleChanged();
75-
OCC::AccountState *accountsState() { return _accountState; }
7676
void slotHideSelectiveSyncWidget();
77+
void setParentWindow(QWindow *parentWindow);
7778

7879
protected slots:
7980
void slotAddFolder();
@@ -106,6 +107,7 @@ protected slots:
106107
void slotE2eEncryptionMnemonicReady();
107108
void slotE2eEncryptionGenerateKeys();
108109
void slotE2eEncryptionInitializationFinished(bool isNewMnemonicGenerated);
110+
void slotDisplayTokenInitDialog();
109111
void slotEncryptFolderFinished(int status);
110112

111113
void slotSelectiveSyncChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
@@ -150,6 +152,8 @@ private slots:
150152
bool _menuShown = false;
151153

152154
QHash<QString, QMetaObject::Connection> _folderConnections;
155+
156+
QWindow *_parentWindow = nullptr;
153157
};
154158

155159
} // namespace OCC

src/gui/settingsdialog.cpp

+5-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();
@@ -247,6 +247,7 @@ void SettingsDialog::accountAdded(AccountState *s)
247247
QString objectName = QLatin1String("accountSettings_");
248248
objectName += s->account()->displayName();
249249
accountSettings->setObjectName(objectName);
250+
accountSettings->setParentWindow(windowHandle());
250251
_ui->stack->insertWidget(0 , accountSettings);
251252

252253
_actionGroup->addAction(accountAction);

src/gui/systray.cpp

+33
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,38 @@ void Systray::createFileActivityDialog(const QString &localPath)
412413
Q_EMIT showFileDetailsPage(localPath, FileDetailsPage::Activity);
413414
}
414415

416+
void Systray::createTokenInitDialog(const QVariantList &tokensInfo, QWindow *dialogParent)
417+
{
418+
if(_tokenInitDialog) {
419+
destroyDialog(_tokenInitDialog);
420+
_tokenInitDialog = nullptr;
421+
}
422+
423+
qCDebug(lcSystray) << "Opening new token init dialog with " << tokensInfo.size() << "possible tokens";
424+
425+
if (!_trayEngine) {
426+
qCWarning(lcSystray) << "Could not open token init dialog as no tray engine was available";
427+
return;
428+
}
429+
430+
const QVariantMap initialProperties{
431+
{"tokensInfo", tokensInfo},
432+
};
433+
434+
const auto createdDialog = new QQuickView(_trayEngine.data(), dialogParent);
435+
436+
createdDialog->setInitialProperties(initialProperties);
437+
createdDialog->setSource(QStringLiteral("qrc:/qml/src/gui/EncryptionTokenSelectionWindow.qml"));
438+
createdDialog->setTitle(tr("Encryption Token Selector"));
439+
createdDialog->setModality(Qt::ApplicationModal);
440+
441+
createdDialog->show();
442+
createdDialog->raise();
443+
createdDialog->requestActivate();
444+
445+
_tokenInitDialog = createdDialog;
446+
}
447+
415448
void Systray::presentShareViewInTray(const QString &localPath)
416449
{
417450
const auto folder = FolderMan::instance()->folderForPath(localPath);

src/gui/systray.h

+4-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;
@@ -145,6 +145,7 @@ public slots:
145145

146146
void createShareDialog(const QString &localPath);
147147
void createFileActivityDialog(const QString &localPath);
148+
void createTokenInitDialog(const QVariantList &tokensInfo, QWindow *dialogParent);
148149

149150
void presentShareViewInTray(const QString &localPath);
150151

@@ -185,6 +186,7 @@ private slots:
185186
QSet<qlonglong> _callsAlreadyNotified;
186187
QPointer<QObject> _editFileLocallyLoadingDialog;
187188
QVector<QQuickWindow*> _fileDetailDialogs;
189+
QQuickWindow* _tokenInitDialog = nullptr;
188190
};
189191

190192
} // 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

src/libsync/account.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject
8888
Q_PROPERTY(QUrl url MEMBER _url)
8989
Q_PROPERTY(bool e2eEncryptionKeysGenerationAllowed MEMBER _e2eEncryptionKeysGenerationAllowed)
9090
Q_PROPERTY(bool askUserForMnemonic READ askUserForMnemonic WRITE setAskUserForMnemonic NOTIFY askUserForMnemonicChanged)
91-
Q_PROPERTY(bool useHardwareTokenEncryption READ useHardwareTokenEncryption NOTIFY useHardwareTokenEncryptionChanged)
91+
Q_PROPERTY(bool enforceUseHardwareTokenEncryption READ enforceUseHardwareTokenEncryption NOTIFY enforceUseHardwareTokenEncryptionChanged)
9292
Q_PROPERTY(QString encryptionHardwareTokenDriverPath READ encryptionHardwareTokenDriverPath NOTIFY encryptionHardwareTokenDriverPathChanged)
9393

9494
public:
@@ -328,7 +328,7 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject
328328

329329
[[nodiscard]] bool askUserForMnemonic() const;
330330

331-
[[nodiscard]] bool useHardwareTokenEncryption() const;
331+
[[nodiscard]] bool enforceUseHardwareTokenEncryption() const;
332332

333333
[[nodiscard]] QString encryptionHardwareTokenDriverPath() const;
334334

@@ -360,7 +360,7 @@ public slots:
360360
void accountChangedDisplayName();
361361
void prettyNameChanged();
362362
void askUserForMnemonicChanged();
363-
void useHardwareTokenEncryptionChanged();
363+
void enforceUseHardwareTokenEncryptionChanged();
364364
void encryptionHardwareTokenDriverPathChanged();
365365

366366
/// Used in RemoteWipe

src/libsync/clientsideencryption.cpp

+23-3
Original file line numberDiff line numberDiff line change
@@ -1012,13 +1012,22 @@ std::optional<QByteArray> decryptStringAsymmetricWithToken(ENGINE *sslEngine,
10121012
}
10131013

10141014

1015-
ClientSideEncryption::ClientSideEncryption() = default;
1015+
ClientSideEncryption::ClientSideEncryption()
1016+
{
1017+
connect(&_usbTokenInformation, &ClientSideTokenSelector::discoveredTokensChanged,
1018+
this, &ClientSideEncryption::displayTokenInitDialog);
1019+
}
10161020

10171021
bool ClientSideEncryption::isInitialized() const
10181022
{
10191023
return !getMnemonic().isEmpty();
10201024
}
10211025

1026+
QVariantList ClientSideEncryption::discoveredTokens() const
1027+
{
1028+
return _usbTokenInformation.discoveredTokens();
1029+
}
1030+
10221031
const QSslKey &ClientSideEncryption::getPublicKey() const
10231032
{
10241033
return _publicKey;
@@ -1080,8 +1089,19 @@ void ClientSideEncryption::initialize(const AccountPtr &account)
10801089
return;
10811090
}
10821091

1083-
if (account->useHardwareTokenEncryption()) {
1084-
initializeHardwareTokenEncryption(account);
1092+
if (account->enforceUseHardwareTokenEncryption()) {
1093+
if (_usbTokenInformation.isSetup()) {
1094+
initializeHardwareTokenEncryption(account);
1095+
} else if (account->e2eEncryptionKeysGenerationAllowed() && account->askUserForMnemonic()) {
1096+
_usbTokenInformation.searchForToken(account);
1097+
if (_usbTokenInformation.isSetup()) {
1098+
initializeHardwareTokenEncryption(account);
1099+
} else {
1100+
emit initializationFinished();
1101+
}
1102+
} else {
1103+
emit initializationFinished();
1104+
}
10851105
} else {
10861106
fetchCertificateFromKeyChain(account);
10871107
}

src/libsync/clientsideencryption.h

+9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
#define CLIENTSIDEENCRYPTION_H
1717

1818
#include "accountfwd.h"
19+
1920
#include "networkjobs.h"
21+
#include "clientsidetokenselector.h"
2022

2123
#include <QString>
2224
#include <QObject>
@@ -139,6 +141,10 @@ class OWNCLOUDSYNC_EXPORT ClientSideEncryption : public QObject {
139141

140142
[[nodiscard]] bool isInitialized() const;
141143

144+
[[nodiscard]] bool tokenIsSetup() const;
145+
146+
[[nodiscard]] QVariantList discoveredTokens() const;
147+
142148
[[nodiscard]] const QSslKey& getPublicKey() const;
143149

144150
void setPublicKey(const QSslKey &publicKey);
@@ -166,6 +172,7 @@ class OWNCLOUDSYNC_EXPORT ClientSideEncryption : public QObject {
166172
void certificateDeleted();
167173
void mnemonicDeleted();
168174
void publicKeyDeleted();
175+
void displayTokenInitDialog();
169176

170177
public slots:
171178
void initialize(const OCC::AccountPtr &account);
@@ -248,6 +255,8 @@ private slots:
248255
QString _mnemonic;
249256
bool _newMnemonicGenerated = false;
250257

258+
ClientSideTokenSelector _usbTokenInformation;
259+
251260
PKCS11_KEY* _tokenPublicKey = nullptr;
252261
PKCS11_KEY* _tokenPrivateKey = nullptr;
253262
};

0 commit comments

Comments
 (0)