Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorallexzander <blackslayer4@gmail.com>2022-10-14 18:47:46 +0300
committerallexzander <allexzander@users.noreply.github.com>2022-11-01 11:18:28 +0300
commit9ab89daedd867465e6c86fd420994f54a03fbee4 (patch)
tree9249855bbd41fd895111590a5a6d5cf05fc3e429
parent2839c958877a46fafb447640e56a660ab678a446 (diff)
E2EE. Do not generate keypair without user request.
Signed-off-by: allexzander <blackslayer4@gmail.com>
-rw-r--r--src/gui/accountmanager.cpp18
-rw-r--r--src/gui/accountmanager.h3
-rw-r--r--src/gui/accountsettings.cpp123
-rw-r--r--src/gui/accountsettings.h10
-rw-r--r--src/gui/mnemonicdialog.ui18
-rw-r--r--src/libsync/account.cpp10
-rw-r--r--src/libsync/account.h6
-rw-r--r--src/libsync/clientsideencryption.cpp20
-rw-r--r--src/libsync/clientsideencryption.h9
9 files changed, 136 insertions, 81 deletions
diff --git a/src/gui/accountmanager.cpp b/src/gui/accountmanager.cpp
index 331db6297..0474021c9 100644
--- a/src/gui/accountmanager.cpp
+++ b/src/gui/accountmanager.cpp
@@ -26,7 +26,6 @@
#include <QNetworkAccessManager>
#include <QMessageBox>
#include "clientsideencryption.h"
-#include "ui_mnemonicdialog.h"
namespace {
constexpr auto urlC = "url";
@@ -434,23 +433,6 @@ AccountPtr AccountManager::createAccount()
return acc;
}
-void AccountManager::displayMnemonic(const QString& mnemonic)
-{
- const auto widget = new QDialog;
- Ui_Dialog ui;
- ui.setupUi(widget);
- widget->setWindowTitle(tr("End-to-End encryption mnemonic"));
- ui.label->setText(tr("To protect your Cryptographic Identity, we encrypt it with a mnemonic of 12 dictionary words. "
- "Please note these down and keep them safe. "
- "They will be needed to add other devices to your account (like your mobile phone or laptop)."));
- ui.textEdit->setText(mnemonic);
- ui.textEdit->focusWidget();
- ui.textEdit->selectAll();
- ui.textEdit->setAlignment(Qt::AlignCenter);
- widget->exec();
- widget->resize(widget->sizeHint());
-}
-
void AccountManager::shutdown()
{
const auto accountsCopy = _accounts;
diff --git a/src/gui/accountmanager.h b/src/gui/accountmanager.h
index 04ce8e57b..948e1de4a 100644
--- a/src/gui/accountmanager.h
+++ b/src/gui/accountmanager.h
@@ -113,9 +113,6 @@ public slots:
/// Saves account state data, not including the account
void saveAccountState(AccountState *a);
- /// Display a Box with the mnemonic so the user can copy it to a safe place.
- static void displayMnemonic(const QString& mnemonic);
-
Q_SIGNALS:
void accountAdded(AccountState *account);
diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp
index 169162a5c..82520d1c5 100644
--- a/src/gui/accountsettings.cpp
+++ b/src/gui/accountsettings.cpp
@@ -41,6 +41,7 @@
#include "syncresult.h"
#include "ignorelisttablewidget.h"
#include "wizard/owncloudwizard.h"
+#include "ui_mnemonicdialog.h"
#include <cmath>
@@ -63,6 +64,9 @@
namespace {
constexpr auto propertyFolder = "folder";
constexpr auto propertyPath = "path";
+constexpr auto e2eUiActionIdKey = "id";
+constexpr auto e2EeUiActionEnableEncryptionId = "enable_encryption";
+constexpr auto e2EeUiActionDisplayMnemonicId = "display_mnemonic";
}
namespace OCC {
@@ -223,20 +227,7 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
_ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));*/
// Connect E2E stuff
- connect(this, &AccountSettings::requestMnemonic, _accountState->account()->e2e(), &ClientSideEncryption::slotRequestMnemonic);
- connect(_accountState->account()->e2e(), &ClientSideEncryption::showMnemonic, this, &AccountSettings::slotShowMnemonic);
-
- connect(_accountState->account()->e2e(), &ClientSideEncryption::mnemonicGenerated, this, &AccountSettings::slotNewMnemonicGenerated);
- if (_accountState->account()->e2e()->newMnemonicGenerated()) {
- slotNewMnemonicGenerated();
- } else {
- _ui->encryptionMessage->setText(tr("This account supports End-to-End encryption"));
-
- auto *mnemonic = new QAction(tr("Display mnemonic"), this);
- connect(mnemonic, &QAction::triggered, this, &AccountSettings::requestMnemonic);
- _ui->encryptionMessage->addAction(mnemonic);
- _ui->encryptionMessage->hide();
- }
+ initializeE2eEncryption();
_ui->connectLabel->setText(tr("No account configured."));
@@ -249,16 +240,34 @@ AccountSettings::AccountSettings(AccountState *accountState, QWidget *parent)
customizeStyle();
}
-void AccountSettings::slotNewMnemonicGenerated()
+void AccountSettings::slotE2eEncryptionMnemonicReady()
{
+ auto *const actionDisplayMnemonic = addActionToEncryptionMessage(tr("Display mnemonic"), e2EeUiActionDisplayMnemonicId);
+ connect(actionDisplayMnemonic, &QAction::triggered, this, [this]() {
+ displayMnemonic(_accountState->account()->e2e()->_mnemonic);
+ });
_ui->encryptionMessage->setText(tr("This account supports End-to-End encryption"));
+ _ui->encryptionMessage->show();
+
+}
- auto *mnemonic = new QAction(tr("Enable encryption"), this);
- connect(mnemonic, &QAction::triggered, this, &AccountSettings::requestMnemonic);
- connect(mnemonic, &QAction::triggered, _ui->encryptionMessage, &KMessageWidget::hide);
+void AccountSettings::slotE2eEncryptionGenerateKeys()
+{
+ connect(_accountState->account()->e2e(), &ClientSideEncryption::initializationFinished, this, &AccountSettings::slotE2eEncryptionInitializationFinished);
+ _accountState->account()->setE2eEncryptionKeysGenerationAllowed(true);
+ _accountState->account()->e2e()->initialize(_accountState->account());
+}
- _ui->encryptionMessage->addAction(mnemonic);
- _ui->encryptionMessage->show();
+void AccountSettings::slotE2eEncryptionInitializationFinished(bool isNewMnemonicGenerated)
+{
+ disconnect(_accountState->account()->e2e(), &ClientSideEncryption::initializationFinished, this, &AccountSettings::slotE2eEncryptionInitializationFinished);
+ if (!_accountState->account()->e2e()->_mnemonic.isEmpty()) {
+ removeActionFromEncryptionMessage(e2EeUiActionEnableEncryptionId);
+ slotE2eEncryptionMnemonicReady();
+ if (isNewMnemonicGenerated) {
+ displayMnemonic(_accountState->account()->e2e()->_mnemonic);
+ }
+ }
}
void AccountSettings::slotEncryptFolderFinished(int status)
@@ -310,11 +319,6 @@ void AccountSettings::doExpand()
}
}
-void AccountSettings::slotShowMnemonic(const QString &mnemonic)
-{
- AccountManager::instance()->displayMnemonic(mnemonic);
-}
-
bool AccountSettings::canEncryptOrDecrypt (const FolderStatusModel::SubFolderInfo* info) {
if (info->_folder->syncResult().status() != SyncResult::Status::Success) {
QMessageBox msgBox;
@@ -965,6 +969,35 @@ void AccountSettings::slotSetSubFolderAvailability(Folder *folder, const QString
folder->scheduleThisFolderSoon();
}
+void AccountSettings::displayMnemonic(const QString &mnemonic)
+{
+ auto widget = QDialog(this);
+ Ui_Dialog ui;
+ ui.setupUi(&widget);
+ widget.setWindowTitle(tr("End-to-End encryption mnemonic"));
+ ui.label->setText(
+ tr("To protect your Cryptographic Identity, we encrypt it with a mnemonic of 12 dictionary words. "
+ "Please note these down and keep them safe. "
+ "They will be needed to add other devices to your account (like your mobile phone or laptop)."));
+ QFont monoFont(QStringLiteral("Monospace"));
+ monoFont.setStyleHint(QFont::TypeWriter);
+ ui.lineEdit->setFont(monoFont);
+ ui.lineEdit->setText(mnemonic);
+ ui.lineEdit->setReadOnly(true);
+
+ ui.lineEdit->setStyleSheet(QStringLiteral("QLineEdit{ color: black; background: lightgrey; border-style: inset;}"));
+
+ ui.lineEdit->focusWidget();
+ ui.lineEdit->selectAll();
+ ui.lineEdit->setAlignment(Qt::AlignCenter);
+
+ const QFont font(QStringLiteral(""), 0);
+ QFontMetrics fm(font);
+ ui.lineEdit->setFixedWidth(fm.horizontalAdvance(mnemonic));
+ widget.resize(widget.sizeHint());
+ widget.exec();
+}
+
void AccountSettings::showConnectionLabel(const QString &message, QStringList errors)
{
const auto errStyle = QLatin1String("color:#ffffff; background-color:#bb4d4d;padding:5px;"
@@ -1417,6 +1450,46 @@ void AccountSettings::customizeStyle()
_ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));
}
+void AccountSettings::initializeE2eEncryption()
+{
+ if (!_accountState->account()->e2e()->_mnemonic.isEmpty()) {
+ slotE2eEncryptionMnemonicReady();
+ } else {
+ _ui->encryptionMessage->setText(tr("This account supports End-to-End encryption"));
+ _ui->encryptionMessage->hide();
+
+ auto *const actionEnableE2e = addActionToEncryptionMessage(tr("Enable encryption"), e2EeUiActionEnableEncryptionId);
+ connect(actionEnableE2e, &QAction::triggered, this, &AccountSettings::slotE2eEncryptionGenerateKeys);
+ }
+}
+
+void AccountSettings::removeActionFromEncryptionMessage(const QString &actionId)
+{
+ const auto foundEnableEncryptionActionIt = std::find_if(std::cbegin(_ui->encryptionMessage->actions()), std::cend(_ui->encryptionMessage->actions()), [&actionId](const QAction *action) {
+ return action->property(e2eUiActionIdKey).toString() == actionId;
+ });
+ if (foundEnableEncryptionActionIt != std::cend(_ui->encryptionMessage->actions())) {
+ _ui->encryptionMessage->removeAction(*foundEnableEncryptionActionIt);
+ (*foundEnableEncryptionActionIt)->deleteLater();
+ }
+}
+
+QAction *AccountSettings::addActionToEncryptionMessage(const QString &actionTitle, const QString &actionId)
+{
+ for (const auto &action : _ui->encryptionMessage->actions()) {
+ if (action->property(e2eUiActionIdKey) == actionId) {
+ return action;
+ }
+ }
+
+ auto *const action = new QAction(actionTitle, this);
+ if (!actionId.isEmpty()) {
+ action->setProperty(e2eUiActionIdKey, actionId);
+ }
+ _ui->encryptionMessage->addAction(action);
+ return action;
+}
+
} // namespace OCC
#include "accountsettings.moc"
diff --git a/src/gui/accountsettings.h b/src/gui/accountsettings.h
index 8a2db31ef..f875be0d1 100644
--- a/src/gui/accountsettings.h
+++ b/src/gui/accountsettings.h
@@ -104,14 +104,16 @@ protected slots:
void slotLinkActivated(const QString &link);
// Encryption Related Stuff.
- void slotShowMnemonic(const QString &mnemonic);
- void slotNewMnemonicGenerated();
+ void slotE2eEncryptionMnemonicReady();
+ void slotE2eEncryptionGenerateKeys();
+ void slotE2eEncryptionInitializationFinished(bool isNewMnemonicGenerated);
void slotEncryptFolderFinished(int status);
void slotSelectiveSyncChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
const QVector<int> &roles);
private:
+ void displayMnemonic(const QString &mnemonic);
void showConnectionLabel(const QString &message,
QStringList errors = QStringList());
bool event(QEvent *) override;
@@ -119,6 +121,10 @@ private:
void openIgnoredFilesDialog(const QString & absFolderPath);
void customizeStyle();
+ void initializeE2eEncryption();
+ void removeActionFromEncryptionMessage(const QString &actionId);
+ QAction *addActionToEncryptionMessage(const QString &actionTitle, const QString &actionId);
+
/// Returns the alias of the selected folder, empty string if none
[[nodiscard]] QString selectedFolderAlias() const;
diff --git a/src/gui/mnemonicdialog.ui b/src/gui/mnemonicdialog.ui
index a482b0f34..7a18b6ce2 100644
--- a/src/gui/mnemonicdialog.ui
+++ b/src/gui/mnemonicdialog.ui
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>588</width>
- <height>214</height>
+ <height>131</height>
</rect>
</property>
<property name="sizePolicy">
@@ -31,6 +31,9 @@
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>7</number>
+ </property>
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
@@ -39,7 +42,7 @@
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
- <verstretch>50</verstretch>
+ <verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
@@ -73,20 +76,13 @@
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
- <height>40</height>
+ <height>20</height>
</size>
</property>
</spacer>
</item>
<item>
- <widget class="QTextEdit" name="textEdit">
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>80</height>
- </size>
- </property>
- </widget>
+ <widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp
index 7f640416d..6d9f2a4d5 100644
--- a/src/libsync/account.cpp
+++ b/src/libsync/account.cpp
@@ -933,4 +933,14 @@ bool Account::trustCertificates() const
return _trustCertificates;
}
+void Account::setE2eEncryptionKeysGenerationAllowed(bool allowed)
+{
+ _e2eEncryptionKeysGenerationAllowed = allowed;
+}
+
+[[nodiscard]] bool Account::e2eEncryptionKeysGenerationAllowed() const
+{
+ return _e2eEncryptionKeysGenerationAllowed;
+}
+
} // namespace OCC
diff --git a/src/libsync/account.h b/src/libsync/account.h
index d96597dee..42af77f56 100644
--- a/src/libsync/account.h
+++ b/src/libsync/account.h
@@ -85,6 +85,7 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject
Q_PROPERTY(QString displayName MEMBER _displayName)
Q_PROPERTY(QString prettyName READ prettyName NOTIFY prettyNameChanged)
Q_PROPERTY(QUrl url MEMBER _url)
+ Q_PROPERTY(bool e2eEncryptionKeysGenerationAllowed MEMBER _e2eEncryptionKeysGenerationAllowed)
public:
static AccountPtr create();
@@ -300,6 +301,9 @@ public:
void setTrustCertificates(bool trustCertificates);
[[nodiscard]] bool trustCertificates() const;
+ void setE2eEncryptionKeysGenerationAllowed(bool allowed);
+ [[nodiscard]] bool e2eEncryptionKeysGenerationAllowed() const;
+
public slots:
/// Used when forgetting credentials
void clearQNAMCache();
@@ -355,6 +359,8 @@ private:
bool _trustCertificates = false;
+ bool _e2eEncryptionKeysGenerationAllowed = false;
+
QWeakPointer<Account> _sharedThis;
QString _id;
QString _davUser;
diff --git a/src/libsync/clientsideencryption.cpp b/src/libsync/clientsideencryption.cpp
index 2408b6ade..51ca66a7f 100644
--- a/src/libsync/clientsideencryption.cpp
+++ b/src/libsync/clientsideencryption.cpp
@@ -1082,11 +1082,6 @@ void ClientSideEncryption::forgetSensitiveData(const AccountPtr &account)
startDeleteJob(user + e2e_mnemonic);
}
-void ClientSideEncryption::slotRequestMnemonic()
-{
- emit showMnemonic(_mnemonic);
-}
-
void ClientSideEncryption::generateKeyPair(const AccountPtr &account)
{
// AES/GCM/NoPadding,
@@ -1223,11 +1218,8 @@ void ClientSideEncryption::encryptPrivateKey(const AccountPtr &account)
{
QStringList list = WordList::getRandomWords(12);
_mnemonic = list.join(' ');
- _newMnemonicGenerated = true;
qCInfo(lcCse()) << "mnemonic Generated:" << _mnemonic;
- emit mnemonicGenerated(_mnemonic);
-
QString passPhrase = list.join(QString()).toLower();
qCInfo(lcCse()) << "Passphrase Generated:" << passPhrase;
@@ -1246,7 +1238,7 @@ void ClientSideEncryption::encryptPrivateKey(const AccountPtr &account)
writePrivateKey(account);
writeCertificate(account);
writeMnemonic(account);
- emit initializationFinished();
+ emit initializationFinished(true);
break;
default:
qCInfo(lcCse()) << "Store private key failed, return code:" << retCode;
@@ -1255,11 +1247,6 @@ void ClientSideEncryption::encryptPrivateKey(const AccountPtr &account)
job->start();
}
-bool ClientSideEncryption::newMnemonicGenerated() const
-{
- return _newMnemonicGenerated;
-}
-
void ClientSideEncryption::decryptPrivateKey(const AccountPtr &account, const QByteArray &key) {
QString msg = tr("Please enter your End-to-End encryption passphrase:<br>"
"<br>"
@@ -1349,6 +1336,11 @@ void ClientSideEncryption::getPublicKeyFromServer(const AccountPtr &account)
fetchAndValidatePublicKeyFromServer(account);
} else if (retCode == 404) {
qCInfo(lcCse()) << "No public key on the server";
+ if (!account->e2eEncryptionKeysGenerationAllowed()) {
+ qCInfo(lcCse()) << "User did not allow E2E keys generation.";
+ emit initializationFinished();
+ return;
+ }
generateKeyPair(account);
} else {
qCInfo(lcCse()) << "Error while requesting public key: " << retCode;
diff --git a/src/libsync/clientsideencryption.h b/src/libsync/clientsideencryption.h
index ec51de61b..552282e38 100644
--- a/src/libsync/clientsideencryption.h
+++ b/src/libsync/clientsideencryption.h
@@ -130,20 +130,13 @@ private:
public:
void forgetSensitiveData(const AccountPtr &account);
- [[nodiscard]] bool newMnemonicGenerated() const;
-
-public slots:
- void slotRequestMnemonic();
-
private slots:
void publicKeyFetched(QKeychain::Job *incoming);
void privateKeyFetched(QKeychain::Job *incoming);
void mnemonicKeyFetched(QKeychain::Job *incoming);
signals:
- void initializationFinished();
- void mnemonicGenerated(const QString& mnemonic);
- void showMnemonic(const QString& mnemonic);
+ void initializationFinished(bool isNewMnemonicGenerated = false);
private:
void getPrivateKeyFromServer(const AccountPtr &account);