Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/e2ee use hardware token secure storage #5877

Draft
wants to merge 24 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2dc1ebc
add support to use PKCS#11 harware token to store certifice for e2ee
mgallien Jul 28, 2023
ee9c236
add support to use PKCS#11 harware token to store certifice for e2ee
mgallien Jul 28, 2023
363ebca
temporarily do not check for the certificate fingerprints
mgallien May 31, 2024
40544ae
libp11 dependency for USB token is really mandatory
mgallien Jun 11, 2024
8f94ba3
fix compilation by exporting a newly needed function
mgallien Jun 11, 2024
b50c7d5
improve logs when build with NEXTCLOUD_DEV enabled
mgallien Apr 30, 2024
a680e3b
better memory management and better logs for end-to-end encryption
mgallien Jun 12, 2024
cc51d00
fix memory issue ibetween list of token slots and the libp11 context
mgallien Jun 12, 2024
e231272
ensure sane error handling when trying to setup encryption
mgallien Jun 17, 2024
c464d7f
clearly indicate in logs which is the selected certificate
mgallien Jun 17, 2024
bcbd415
do not claim a certificate migration is needed when it is not the case
mgallien Jun 17, 2024
1a522b5
clean public API that could be misused in ClientSideEncryptionTokenSe…
mgallien Jun 17, 2024
b63e430
improve logs when checking that encryption is working reliably
mgallien Jun 17, 2024
56ca586
instead of using PKCS#11 API to get public key, read it from certificate
mgallien Jun 17, 2024
936733a
upload user certificate after end-to-end init with token storage
mgallien Jun 21, 2024
3d31899
remove duplicated confusing encryption helper methods
mgallien Jun 28, 2024
ff3758d
use the proper certificate when encrypting metadata when sharing
mgallien Jun 28, 2024
b2698b8
fix issues reported by clazy with default configuration
mgallien Jul 3, 2024
a0a51a8
prevent stack overflow when creating the systray via singleton access
mgallien Jul 4, 2024
9ec4f16
allow to start with an expired certificate: migration will be needed
mgallien Jul 4, 2024
af48f19
when discovering certificates: forget previously known ones
mgallien Jul 4, 2024
dbd38da
allow on the fly migration of encryption certificate
mgallien Jul 5, 2024
05e5510
fix live migration between certificates and improve logs
mgallien Jul 10, 2024
45bb571
for now remove this assert until we better understand
mgallien Jul 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,3 @@ trigger:
kind: signature
hmac: fbdc01c6461fcc32d9ebff4be97340cbb6da5566643b60289504ed86b2a67583

...
27 changes: 16 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,20 +227,25 @@ if(BUILD_CLIENT)
find_package(Sphinx)
find_package(PdfLatex)
find_package(OpenSSL 1.1 REQUIRED )
find_package(PkgConfig REQUIRED)
pkg_check_modules(OPENSC-LIBP11 libp11 REQUIRED IMPORTED_TARGET)

find_package(ZLIB REQUIRED)
find_package(SQLite3 3.9.0 REQUIRED)
set(ENCRYPTION_HARDWARE_TOKEN_DRIVER_PATH "c:/Windows/System32/eTPKCS11.dll" CACHE PATH "Path to the driver for end-to-end encryption token")
option(CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN "Enforce use of an hardware token for end-to-end encryption" true)

if(NOT WIN32 AND NOT APPLE)
find_package(PkgConfig REQUIRED)
pkg_check_modules(CLOUDPROVIDERS cloudproviders IMPORTED_TARGET)
find_package(ZLIB REQUIRED)
find_package(SQLite3 3.9.0 REQUIRED)

if(CLOUDPROVIDERS_FOUND)
pkg_check_modules(DBUS-1 REQUIRED dbus-1 IMPORTED_TARGET)
pkg_check_modules(GIO REQUIRED gio-2.0 IMPORTED_TARGET)
pkg_check_modules(GLIB2 REQUIRED glib-2.0 IMPORTED_TARGET)
endif()
endif()
if(NOT WIN32 AND NOT APPLE)
find_package(PkgConfig REQUIRED)
pkg_check_modules(CLOUDPROVIDERS cloudproviders IMPORTED_TARGET)

if(CLOUDPROVIDERS_FOUND)
pkg_check_modules(DBUS-1 REQUIRED dbus-1 IMPORTED_TARGET)
pkg_check_modules(GIO REQUIRED gio-2.0 IMPORTED_TARGET)
pkg_check_modules(GLIB2 REQUIRED glib-2.0 IMPORTED_TARGET)
endif()
endif()
endif()

option(BUILD_WITH_WEBENGINE "BUILD_WITH_WEBENGINE" ON)
Expand Down
1 change: 0 additions & 1 deletion NEXTCLOUD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ set( APPLICATION_WIZARD_HEADER_BACKGROUND_COLOR ${NEXTCLOUD_BACKGROUND_COLOR} CA
set( APPLICATION_WIZARD_HEADER_TITLE_COLOR "#ffffff" CACHE STRING "Hex color of the text in the wizard header")
option( APPLICATION_WIZARD_USE_CUSTOM_LOGO "Use the logo from ':/client/theme/colored/wizard_logo.(png|svg)' else the default application icon is used" ON )


#
## Windows Shell Extensions & MSI - IMPORTANT: Generate new GUIDs for custom builds with "guidgen" or "uuidgen"
#
Expand Down
6 changes: 6 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,10 @@

#cmakedefine WITH_WEBENGINE

#cmakedefine01 CLIENTSIDEENCRYPTION_ENFORCE_USB_TOKEN

#cmakedefine ENCRYPTION_HARDWARE_TOKEN_DRIVER_PATH "@ENCRYPTION_HARDWARE_TOKEN_DRIVER_PATH@"

#cmakedefine01 NEXTCLOUD_DEV

#endif
2 changes: 2 additions & 0 deletions resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<file>src/gui/PredefinedStatusButton.qml</file>
<file>src/gui/BasicComboBox.qml</file>
<file>src/gui/ErrorBox.qml</file>
<file>src/gui/EncryptionTokenSelectionWindow.qml</file>
<file>src/gui/filedetails/FileActivityView.qml</file>
<file>src/gui/filedetails/FileDetailsPage.qml</file>
<file>src/gui/filedetails/FileDetailsView.qml</file>
Expand Down Expand Up @@ -48,6 +49,7 @@
<file>src/gui/tray/TalkReplyTextField.qml</file>
<file>src/gui/tray/CallNotificationDialog.qml</file>
<file>src/gui/tray/EditFileLocallyLoadingDialog.qml</file>
<file>src/gui/tray/EncryptionTokenDiscoveryDialog.qml</file>
<file>src/gui/tray/NCBusyIndicator.qml</file>
<file>src/gui/tray/NCIconWithBackgroundImage.qml</file>
<file>src/gui/tray/NCToolTip.qml</file>
Expand Down
50 changes: 27 additions & 23 deletions src/common/syncjournaldb.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/common/syncjournaldb.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/common/syncjournaldb.cpp

File src/common/syncjournaldb.cpp does not conform to Custom style guidelines. (lines 51, 71, 992, 994)
* Copyright (C) by Klaas Freitag <[email protected]>
*
* This library is free software; you can redistribute it and/or
Expand All @@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <QCryptographicHash>

Check failure on line 19 in src/common/syncjournaldb.cpp

View workflow job for this annotation

GitHub Actions / build

src/common/syncjournaldb.cpp:19:10 [clang-diagnostic-error]

'QCryptographicHash' file not found
#include <QFile>
#include <QLoggingCategory>
#include <QStringList>
Expand Down Expand Up @@ -48,7 +48,7 @@

#define GET_FILE_RECORD_QUERY \
"SELECT path, inode, modtime, type, md5, fileid, remotePerm, filesize," \
" ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum, e2eMangledName, isE2eEncrypted, " \
" ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum, e2eMangledName, isE2eEncrypted, e2eCertificateFingerprint, " \
" lock, lockOwnerDisplayName, lockOwnerId, lockType, lockOwnerEditor, lockTime, lockTimeout, isShared, lastShareStateFetchedTimestmap, sharedByMe" \
" FROM metadata" \
" LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"
Expand All @@ -67,16 +67,18 @@
rec._checksumHeader = query.baValue(9);
rec._e2eMangledName = query.baValue(10);
rec._e2eEncryptionStatus = static_cast<SyncJournalFileRecord::EncryptionStatus>(query.intValue(11));
rec._lockstate._locked = query.intValue(12) > 0;
rec._lockstate._lockOwnerDisplayName = query.stringValue(13);
rec._lockstate._lockOwnerId = query.stringValue(14);
rec._lockstate._lockOwnerType = query.int64Value(15);
rec._lockstate._lockEditorApp = query.stringValue(16);
rec._lockstate._lockTime = query.int64Value(17);
rec._lockstate._lockTimeout = query.int64Value(18);
rec._isShared = query.intValue(19) > 0;
rec._lastShareStateFetchedTimestamp = query.int64Value(20);
rec._sharedByMe = query.intValue(21) > 0;
rec._e2eCertificateFingerprint = query.baValue(12);
//Q_ASSERT(rec._e2eEncryptionStatus == SyncJournalFileRecord::EncryptionStatus::NotEncrypted || !rec._e2eCertificateFingerprint.isEmpty());
rec._lockstate._locked = query.intValue(13) > 0;
rec._lockstate._lockOwnerDisplayName = query.stringValue(14);
rec._lockstate._lockOwnerId = query.stringValue(15);
rec._lockstate._lockOwnerType = query.int64Value(16);
rec._lockstate._lockEditorApp = query.stringValue(17);
rec._lockstate._lockTime = query.int64Value(18);
rec._lockstate._lockTimeout = query.int64Value(19);
rec._isShared = query.intValue(20) > 0;
rec._lastShareStateFetchedTimestamp = query.int64Value(21);
rec._sharedByMe = query.intValue(22) > 0;
}

static QByteArray defaultJournalMode(const QString &dbPath)
Expand Down Expand Up @@ -780,6 +782,7 @@
addColumn(QStringLiteral("contentChecksumTypeId"), QStringLiteral("INTEGER"));
addColumn(QStringLiteral("e2eMangledName"), QStringLiteral("TEXT"));
addColumn(QStringLiteral("isE2eEncrypted"), QStringLiteral("INTEGER"));
addColumn(QStringLiteral("e2eCertificateFingerprint"), QStringLiteral("TEXT"));
addColumn(QStringLiteral("isShared"), QStringLiteral("INTEGER"));
addColumn(QStringLiteral("lastShareStateFetchedTimestmap"), QStringLiteral("INTEGER"));
addColumn(QStringLiteral("sharedByMe"), QStringLiteral("INTEGER"));
Expand Down Expand Up @@ -986,9 +989,9 @@

const auto query = _queryManager.get(PreparedSqlQueryManager::SetFileRecordQuery, QByteArrayLiteral("INSERT OR REPLACE INTO metadata "
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, "
"contentChecksum, contentChecksumTypeId, e2eMangledName, isE2eEncrypted, lock, lockType, lockOwnerDisplayName, lockOwnerId, "
"contentChecksum, contentChecksumTypeId, e2eMangledName, isE2eEncrypted, e2eCertificateFingerprint, lock, lockType, lockOwnerDisplayName, lockOwnerId, "
"lockOwnerEditor, lockTime, lockTimeout, isShared, lastShareStateFetchedTimestmap, sharedByMe) "
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28);"),
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29);"),
_db);
if (!query) {
qCDebug(lcDb) << "database error:" << query->error();
Expand All @@ -1013,16 +1016,17 @@
query->bindValue(16, contentChecksumTypeId);
query->bindValue(17, record._e2eMangledName);
query->bindValue(18, static_cast<int>(record._e2eEncryptionStatus));
query->bindValue(19, record._lockstate._locked ? 1 : 0);
query->bindValue(20, record._lockstate._lockOwnerType);
query->bindValue(21, record._lockstate._lockOwnerDisplayName);
query->bindValue(22, record._lockstate._lockOwnerId);
query->bindValue(23, record._lockstate._lockEditorApp);
query->bindValue(24, record._lockstate._lockTime);
query->bindValue(25, record._lockstate._lockTimeout);
query->bindValue(26, record._isShared);
query->bindValue(27, record._lastShareStateFetchedTimestamp);
query->bindValue(28, record._sharedByMe);
query->bindValue(19, record._e2eCertificateFingerprint);
query->bindValue(20, record._lockstate._locked ? 1 : 0);
query->bindValue(21, record._lockstate._lockOwnerType);
query->bindValue(22, record._lockstate._lockOwnerDisplayName);
query->bindValue(23, record._lockstate._lockOwnerId);
query->bindValue(24, record._lockstate._lockEditorApp);
query->bindValue(25, record._lockstate._lockTime);
query->bindValue(26, record._lockstate._lockTimeout);
query->bindValue(27, record._isShared);
query->bindValue(28, record._lastShareStateFetchedTimestamp);
query->bindValue(29, record._sharedByMe);

if (!query->exec()) {
qCDebug(lcDb) << "database error:" << query->error();
Expand Down
1 change: 1 addition & 0 deletions src/common/syncjournalfilerecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#ifndef SYNCJOURNALFILERECORD_H
#define SYNCJOURNALFILERECORD_H

#include <QString>

Check failure on line 22 in src/common/syncjournalfilerecord.h

View workflow job for this annotation

GitHub Actions / build

src/common/syncjournalfilerecord.h:22:10 [clang-diagnostic-error]

'QString' file not found
#include <QDateTime>

#include "csync.h"
Expand Down Expand Up @@ -83,6 +83,7 @@
QByteArray _checksumHeader;
QByteArray _e2eMangledName;
EncryptionStatus _e2eEncryptionStatus = EncryptionStatus::NotEncrypted;
QByteArray _e2eCertificateFingerprint;
SyncJournalFileLockInfo _lockstate;
bool _isShared = false;
qint64 _lastShareStateFetchedTimestamp = 0;
Expand Down
37 changes: 19 additions & 18 deletions src/csync/csync.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/csync/csync.h

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/csync/csync.h

File src/csync/csync.h does not conform to Custom style guidelines. (lines 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 155, 157, 158)
* libcsync -- a library to sync a directory with another
*
* Copyright (c) 2008-2013 by Andreas Schneider <[email protected]>
Expand Down Expand Up @@ -138,24 +138,25 @@
* the csync state of a file.
*/
enum SyncInstructions {
CSYNC_INSTRUCTION_NONE = 0, /* Nothing to do (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_EVAL = 1 << 0, /* There was changed compared to the DB (UPDATE) */
CSYNC_INSTRUCTION_REMOVE = 1 << 1, /* The file need to be removed (RECONCILE) */
CSYNC_INSTRUCTION_RENAME = 1 << 2, /* The file need to be renamed (RECONCILE) */
CSYNC_INSTRUCTION_EVAL_RENAME = 1 << 11, /* The file is new, it is the destination of a rename (UPDATE) */
CSYNC_INSTRUCTION_NEW = 1 << 3, /* The file is new compared to the db (UPDATE) */
CSYNC_INSTRUCTION_CONFLICT = 1 << 4, /* The file need to be downloaded because it is a conflict (RECONCILE) */
CSYNC_INSTRUCTION_IGNORE = 1 << 5, /* The file is ignored (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_SYNC = 1 << 6, /* The file need to be pushed to the other remote (RECONCILE) */
CSYNC_INSTRUCTION_STAT_ERROR = 1 << 7,
CSYNC_INSTRUCTION_ERROR = 1 << 8,
CSYNC_INSTRUCTION_TYPE_CHANGE = 1 << 9, /* Like NEW, but deletes the old entity first (RECONCILE)
Used when the type of something changes from directory to file
or back. */
CSYNC_INSTRUCTION_UPDATE_METADATA = 1 << 10, /* If the etag has been updated and need to be writen to the db,
but without any propagation (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_CASE_CLASH_CONFLICT = 1 << 12, /* The file need to be downloaded because it is a case clash conflict (RECONCILE) */
CSYNC_INSTRUCTION_UPDATE_VFS_METADATA = 1 << 13, /* vfs item metadata are out of sync and we need to tell operating system about it */
CSYNC_INSTRUCTION_NONE = 0, /* Nothing to do (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_EVAL = 1 << 0, /* There was changed compared to the DB (UPDATE) */
CSYNC_INSTRUCTION_REMOVE = 1 << 1, /* The file need to be removed (RECONCILE) */
CSYNC_INSTRUCTION_RENAME = 1 << 2, /* The file need to be renamed (RECONCILE) */
CSYNC_INSTRUCTION_EVAL_RENAME = 1 << 11, /* The file is new, it is the destination of a rename (UPDATE) */
CSYNC_INSTRUCTION_NEW = 1 << 3, /* The file is new compared to the db (UPDATE) */
CSYNC_INSTRUCTION_CONFLICT = 1 << 4, /* The file need to be downloaded because it is a conflict (RECONCILE) */
CSYNC_INSTRUCTION_IGNORE = 1 << 5, /* The file is ignored (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_SYNC = 1 << 6, /* The file need to be pushed to the other remote (RECONCILE) */
CSYNC_INSTRUCTION_STAT_ERROR = 1 << 7,
CSYNC_INSTRUCTION_ERROR = 1 << 8,
CSYNC_INSTRUCTION_TYPE_CHANGE = 1 << 9, /* Like NEW, but deletes the old entity first (RECONCILE)
Used when the type of something changes from directory to file
or back. */
CSYNC_INSTRUCTION_UPDATE_METADATA = 1 << 10, /* If the etag has been updated and need to be writen to the db,
but without any propagation (UPDATE|RECONCILE) */
CSYNC_INSTRUCTION_CASE_CLASH_CONFLICT = 1 << 12, /* The file need to be downloaded because it is a case clash conflict (RECONCILE) */
CSYNC_INSTRUCTION_UPDATE_VFS_METADATA = 1 << 13, /* vfs item metadata are out of sync and we need to tell operating system about it */
CSYNC_INSTRUCTION_UPDATE_ENCRYPTION_METADATA = 1 << 14, /* encryption metadata needs update after certificate was migrated */
};

Q_ENUM_NS(SyncInstructions)
Expand Down
1 change: 1 addition & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ set(client_SRCS
syncrunfilelog.cpp
systray.h
systray.cpp
EncryptionTokenSelectionWindow.qml
thumbnailjob.h
thumbnailjob.cpp
userinfo.h
Expand Down
146 changes: 146 additions & 0 deletions src/gui/EncryptionTokenSelectionWindow.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright (C) 2023 by Matthieu Gallien <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import QtQml.Models 2.15

import com.nextcloud.desktopclient 1.0
import Style 1.0

import "./tray"

ApplicationWindow {
id: encryptionKeyChooserDialog

required property var certificatesInfo
required property ClientSideEncryptionTokenSelector certificateSelector
property string selectedSerialNumber: ''

flags: Qt.Window | Qt.Dialog
visible: true
modality: Qt.ApplicationModal

width: 400
height: 600
minimumWidth: 400
minimumHeight: 600

title: qsTr('Token Encryption Key Chooser')

// TODO: Rather than setting all these palette colours manually,
// create a custom style and do it for all components globally
palette {
text: Style.ncTextColor
windowText: Style.ncTextColor
buttonText: Style.ncTextColor
brightText: Style.ncTextBrightColor
highlight: Style.lightHover
highlightedText: Style.ncTextColor
light: Style.lightHover
midlight: Style.ncSecondaryTextColor
mid: Style.darkerHover
dark: Style.menuBorder
button: Style.buttonBackgroundColor
window: Style.backgroundColor
base: Style.backgroundColor
toolTipBase: Style.backgroundColor
toolTipText: Style.ncTextColor
}

onClosing: function(close) {
Systray.destroyDialog(self);
close.accepted = true
}

ColumnLayout {
anchors.fill: parent
anchors.leftMargin: 20
anchors.rightMargin: 20
anchors.bottomMargin: 20
anchors.topMargin: 20
spacing: 15
z: 2

EnforcedPlainTextLabel {
text: qsTr("Available Keys for end-to-end Encryption:")
font.bold: true
font.pixelSize: Style.bigFontPixelSizeResolveConflictsDialog
Layout.fillWidth: true
}

ScrollView {
Layout.fillWidth: true
Layout.fillHeight: true

clip: true

ScrollBar.horizontal.policy: ScrollBar.AlwaysOff

ListView {
id: tokensListView

currentIndex: -1

model: DelegateModel {
model: certificatesInfo

delegate: ItemDelegate {
width: tokensListView.contentItem.width

text: modelData.subject

highlighted: tokensListView.currentIndex === index

onClicked: function()
{
tokensListView.currentIndex = index
selectedSerialNumber = modelData.serialNumber
}
}
}
}
}

DialogButtonBox {
Layout.fillWidth: true

Button {
text: qsTr("Choose")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
}
Button {
text: qsTr("Cancel")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
}

onAccepted: function() {
Systray.destroyDialog(encryptionKeyChooserDialog)
certificateSelector.serialNumber = selectedSerialNumber
}

onRejected: function() {
Systray.destroyDialog(encryptionKeyChooserDialog)
certificateSelector.serialNumber = ''
}
}
}

Rectangle {
color: Style.backgroundColor
anchors.fill: parent
z: 1
}
}
5 changes: 4 additions & 1 deletion src/gui/accountmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ constexpr auto networkUploadLimitSettingC = "networkUploadLimitSetting";
constexpr auto networkDownloadLimitSettingC = "networkDownloadLimitSetting";
constexpr auto networkUploadLimitC = "networkUploadLimit";
constexpr auto networkDownloadLimitC = "networkDownloadLimit";
constexpr auto encryptionCertificateSha256FingerprintC = "encryptionCertificateSha256Fingerprint";
constexpr auto generalC = "General";

constexpr auto dummyAuthTypeC = "dummy";
Expand Down Expand Up @@ -339,7 +340,7 @@ void AccountManager::saveAccountHelper(Account *acc, QSettings &settings, bool s
settings.setValue(QLatin1String(serverColorC), acc->_serverColor);
settings.setValue(QLatin1String(serverTextColorC), acc->_serverTextColor);
settings.setValue(QLatin1String(serverHasValidSubscriptionC), acc->capabilities().serverHasValidSubscription());

settings.setValue(QLatin1String(encryptionCertificateSha256FingerprintC), acc->encryptionCertificateFingerprint());
if (!acc->_skipE2eeMetadataChecksumValidation) {
settings.remove(QLatin1String(skipE2eeMetadataChecksumValidationC));
} else {
Expand Down Expand Up @@ -537,6 +538,8 @@ AccountPtr AccountManager::loadAccountHelper(QSettings &settings)
});
job->start();

acc->setEncryptionCertificateFingerprint(settings.value(QLatin1String(encryptionCertificateSha256FingerprintC)).toByteArray());

// now the server cert, it is in the general group
settings.beginGroup(QLatin1String(generalC));
const auto certs = QSslCertificate::fromData(settings.value(caCertsKeyC).toByteArray());
Expand Down
Loading
Loading