Skip to content

Commit

Permalink
allow user to migrate to a new certificate when needed
Browse files Browse the repository at this point in the history
Signed-off-by: Matthieu Gallien <[email protected]>
  • Loading branch information
mgallien committed Dec 11, 2023
1 parent 1e70944 commit 0f71c34
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 2 deletions.
23 changes: 23 additions & 0 deletions src/gui/accountsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ constexpr auto e2eUiActionIdKey = "id";
constexpr auto e2EeUiActionEnableEncryptionId = "enable_encryption";
constexpr auto e2EeUiActionDisableEncryptionId = "disable_encryption";
constexpr auto e2EeUiActionDisplayMnemonicId = "display_mnemonic";
constexpr auto e2EeUiActionMigrateCertificateId = "migrate_certificate";
}

namespace OCC {
Expand Down Expand Up @@ -274,6 +275,10 @@ void AccountSettings::slotE2eEncryptionMnemonicReady()
disableEncryptionForAccount(_accountState->account());
});

if (_accountState->account()->e2e()->userCertificateNeedsMigration()) {
slotE2eEncryptionCertificateNeedMigration();
}

if (!_accountState->account()->e2e()->getMnemonic().isEmpty()) {
const auto actionDisplayMnemonic = addActionToEncryptionMessage(tr("Display mnemonic"), e2EeUiActionDisplayMnemonicId);
connect(actionDisplayMnemonic, &QAction::triggered, this, [this]() {
Expand Down Expand Up @@ -1098,6 +1103,16 @@ void AccountSettings::disableEncryptionForAccount(const AccountPtr &account) con
}
}

void AccountSettings::migrateCertificateForAccount(const AccountPtr &account)
{
for (const auto action : _ui->encryptionMessage->actions()) {
_ui->encryptionMessage->removeAction(action);
}

account->e2e()->migrateCertificate(this, account);
slotE2eEncryptionGenerateKeys();
}

void AccountSettings::showConnectionLabel(const QString &message, QStringList errors)
{
const auto errStyle = QLatin1String("color:#ffffff; background-color:#bb4d4d;padding:5px;"
Expand Down Expand Up @@ -1475,6 +1490,14 @@ void AccountSettings::slotPossiblyUnblacklistE2EeFoldersAndRestartSync()
}
}

void AccountSettings::slotE2eEncryptionCertificateNeedMigration()

Check warning on line 1493 in src/gui/accountsettings.cpp

View workflow job for this annotation

GitHub Actions / build

/src/gui/accountsettings.cpp:1493:23 [readability-convert-member-functions-to-static]

method 'slotE2eEncryptionCertificateNeedMigration' can be made static
{
const auto actionMigrateCertificate = addActionToEncryptionMessage(tr("Migrate certificate to a new one"), e2EeUiActionMigrateCertificateId);
connect(actionMigrateCertificate, &QAction::triggered, this, [this] {
migrateCertificateForAccount(_accountState->account());
});
}

void AccountSettings::updateBlackListAndScheduleFolderSync(const QStringList &blackList, OCC::Folder *folder, const QStringList &foldersToRemoveFromBlacklist) const
{
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
Expand Down
3 changes: 3 additions & 0 deletions src/gui/accountsettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,16 @@ protected slots:
const QVector<int> &roles);
void slotPossiblyUnblacklistE2EeFoldersAndRestartSync();

void slotE2eEncryptionCertificateNeedMigration();

private slots:
void updateBlackListAndScheduleFolderSync(const QStringList &blackList, OCC::Folder *folder, const QStringList &foldersToRemoveFromBlacklist) const;
void folderTerminateSyncAndUpdateBlackList(const QStringList &blackList, OCC::Folder *folder, const QStringList &foldersToRemoveFromBlacklist);

private slots:
void displayMnemonic(const QString &mnemonic);
void disableEncryptionForAccount(const OCC::AccountPtr &account) const;
void migrateCertificateForAccount(const OCC::AccountPtr &account);
void showConnectionLabel(const QString &message, QStringList errors = QStringList());
void openIgnoredFilesDialog(const QString & absFolderPath);
void customizeStyle();
Expand Down
6 changes: 6 additions & 0 deletions src/gui/tray/activitylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ Q_LOGGING_CATEGORY(lcActivity, "nextcloud.gui.activity", QtInfoMsg)
ActivityListModel::ActivityListModel(QObject *parent)
: QAbstractListModel(parent)
{
connect(this, &ActivityListModel::showSettingsDialog,
Systray::instance(), &Systray::openSettings);
}

ActivityListModel::ActivityListModel(AccountState *accountState,
QObject *parent)
: QAbstractListModel(parent)
, _accountState(accountState)
{
connect(this, &ActivityListModel::showSettingsDialog,
Systray::instance(), &Systray::openSettings);
if (_accountState) {
connect(_accountState, &AccountState::stateChanged,
this, &ActivityListModel::accountStateChanged);
Expand Down Expand Up @@ -740,6 +744,8 @@ void ActivityListModel::slotTriggerDefaultAction(const int activityIndex)
_currentInvalidFilenameDialog->open();
ownCloudGui::raiseDialog(_currentInvalidFilenameDialog);
return;
} else if (activity._id == qHash(_accountState->account()->encryptionCertificateFingerprint())) {
Q_EMIT showSettingsDialog();
}

if (!path.isEmpty()) {
Expand Down
2 changes: 2 additions & 0 deletions src/gui/tray/activitylistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ public slots:

void interactiveActivityReceived();

void showSettingsDialog();

protected:
[[nodiscard]] bool currentlyFetching() const;

Expand Down
15 changes: 14 additions & 1 deletion src/gui/tray/usermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,21 @@ User::User(AccountStatePtr &account, const bool &isCurrent, QObject *parent)
connect(_account->account().data(), &Account::capabilitiesChanged, this, &User::slotAccountCapabilitiesChangedRefreshGroupFolders);

connect(_activityModel, &ActivityListModel::sendNotificationRequest, this, &User::slotSendNotificationRequest);

connect(this, &User::sendReplyMessage, this, &User::slotSendReplyMessage);

connect(_account->account().data(), &Account::userCertificateNeedsMigrationChanged, this, [this] () {
auto certificateNeedMigration = Activity{};
certificateNeedMigration._type = Activity::NotificationType;
certificateNeedMigration._subject = tr("End-to-end certificate needs to be migrated to a new one");
certificateNeedMigration._dateTime = QDateTime::fromString(QDateTime::currentDateTime().toString(), Qt::ISODate);
certificateNeedMigration._message = tr("Trigger the migration");
certificateNeedMigration._accName = _account->account()->displayName();
certificateNeedMigration._id = qHash(_account->account()->encryptionCertificateFingerprint());

_activityModel->addNotificationToActivityList(certificateNeedMigration);
showDesktopNotification(certificateNeedMigration);
});
}

void User::checkNotifiedNotifications()
Expand Down
3 changes: 3 additions & 0 deletions src/libsync/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ Account::Account(QObject *parent)

_pushNotificationsReconnectTimer.setInterval(pushNotificationsReconnectInterval);
connect(&_pushNotificationsReconnectTimer, &QTimer::timeout, this, &Account::trySetupPushNotifications);

connect(&_e2e, &ClientSideEncryption::userCertificateNeedsMigrationChanged,
this, &Account::userCertificateNeedsMigrationChanged);
}

AccountPtr Account::create()
Expand Down
1 change: 1 addition & 0 deletions src/libsync/account.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ public slots:
void lockFileError(const QString&);

void encryptionCertificateFingerprintChanged();
void userCertificateNeedsMigrationChanged();

protected Q_SLOTS:
void slotCredentialsFetched();
Expand Down
43 changes: 42 additions & 1 deletion src/libsync/clientsideencryption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,34 @@ unsigned char* unsignedData(QByteArray& array)
// data structures
//

class Pkcs11Context {
public:
Pkcs11Context()
: _pkcsS11Ctx(PKCS11_CTX_new())
{
}

~Pkcs11Context()
{
PKCS11_CTX_free(_pkcsS11Ctx);
}

operator const PKCS11_CTX*() const
{
return _pkcsS11Ctx;
}

operator PKCS11_CTX*()
{
return _pkcsS11Ctx;
}

private:
Q_DISABLE_COPY(Pkcs11Context)

PKCS11_CTX* _pkcsS11Ctx = nullptr;
};

class CipherCtx {
public:
CipherCtx()
Expand Down Expand Up @@ -1297,7 +1325,7 @@ void ClientSideEncryption::initializeHardwareTokenEncryption(QWidget *settingsDi
continue;
}

if (oneCertificateInformation.sha256Fingerprint() != _usbTokenInformation.sha256Fingerprint()) {
if (!_usbTokenInformation.sha256Fingerprint().isEmpty() && oneCertificateInformation.sha256Fingerprint() != _usbTokenInformation.sha256Fingerprint()) {
qCInfo(lcCse()) << "skipping certificate from" << "with fingerprint" << oneCertificateInformation.sha256Fingerprint() << "different from" << _usbTokenInformation.sha256Fingerprint();
continue;
}
Expand All @@ -1316,6 +1344,10 @@ void ClientSideEncryption::initializeHardwareTokenEncryption(QWidget *settingsDi
return;
}

if (!canEncrypt()) {
Q_EMIT userCertificateNeedsMigrationChanged();
}

saveCertificateIdentification(account);

emit initializationFinished();
Expand Down Expand Up @@ -1688,6 +1720,10 @@ void ClientSideEncryption::forgetSensitiveData(const AccountPtr &account)
return job;
};

if (!account->credentials()) {
return;
}

const auto user = account->credentials()->user();
const auto deletePrivateKeyJob = createDeleteJob(user + e2e_private);
const auto deleteCertJob = createDeleteJob(user + e2e_cert);
Expand All @@ -1707,6 +1743,11 @@ void ClientSideEncryption::forgetSensitiveData(const AccountPtr &account)
Q_EMIT userCertificateNeedsMigrationChanged();
}

void ClientSideEncryption::migrateCertificate(QWidget *settingsDialog, const AccountPtr &account)
{
_usbTokenInformation.clear();
}

void ClientSideEncryption::handlePrivateKeyDeleted(const QKeychain::Job* const incoming)
{
const auto error = incoming->error();
Expand Down
3 changes: 3 additions & 0 deletions src/libsync/clientsideencryption.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ public slots:
const OCC::AccountPtr &account);
void forgetSensitiveData(const OCC::AccountPtr &account);

void migrateCertificate(QWidget *settingsDialog,
const OCC::AccountPtr &account);

private slots:
void generateKeyPair(const OCC::AccountPtr &account);
void encryptPrivateKey(const OCC::AccountPtr &account);
Expand Down
6 changes: 6 additions & 0 deletions src/libsync/clientsideencryptiontokenselector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ QByteArray ClientSideEncryptionTokenSelector::sha256Fingerprint() const
return _sha256Fingerprint;
}

void ClientSideEncryptionTokenSelector::clear()
{
_discoveredCertificates.clear();
_sha256Fingerprint.clear();
}

QFuture<void> ClientSideEncryptionTokenSelector::searchForCertificates(const AccountPtr &account)
{
return QtConcurrent::run([this, account] () -> void {
Expand Down
2 changes: 2 additions & 0 deletions src/libsync/clientsideencryptiontokenselector.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class OWNCLOUDSYNC_EXPORT ClientSideEncryptionTokenSelector : public QObject

[[nodiscard]] QByteArray sha256Fingerprint() const;

void clear();

public slots:
QFuture<void> searchForCertificates(const OCC::AccountPtr &account);

Expand Down

0 comments on commit 0f71c34

Please sign in to comment.