Properly handle sensitive data deletion in ClientSideEncryption
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 11 Nov 2022 14:54:13 +0000 (15:54 +0100)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Tue, 24 Jan 2023 16:00:14 +0000 (17:00 +0100)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
src/libsync/clientsideencryption.cpp
src/libsync/clientsideencryption.h

index 762dd5b2a79e994e909d9d334dc3a0efbf4fdb2f..49b528dc66fedaf18d5d33f95f6f6b43a1586c59 100644 (file)
@@ -1064,22 +1064,78 @@ void ClientSideEncryption::writeMnemonic(const AccountPtr &account)
 
 void ClientSideEncryption::forgetSensitiveData(const AccountPtr &account)
 {
-    _privateKey = QByteArray();
-    _certificate = QSslCertificate();
     _publicKey = QSslKey();
-    _mnemonic = QString();
 
-    auto startDeleteJob = [account](QString user) {
+    const auto createDeleteJob = [account](QString user) {
         auto *job = new DeletePasswordJob(Theme::instance()->appName());
         job->setInsecureFallback(false);
         job->setKey(AbstractCredentials::keychainKey(account->url().toString(), user, account->id()));
-        job->start();
+        return job;
     };
 
-    auto user = account->credentials()->user();
-    startDeleteJob(user + e2e_private);
-    startDeleteJob(user + e2e_cert);
-    startDeleteJob(user + e2e_mnemonic);
+    const auto user = account->credentials()->user();
+    const auto deletePrivateKeyJob = createDeleteJob(user + e2e_private);
+    const auto deleteCertJob = createDeleteJob(user + e2e_cert);
+    const auto deleteMnemonicJob = createDeleteJob(user + e2e_mnemonic);
+
+    connect(deletePrivateKeyJob, &DeletePasswordJob::finished, this, &ClientSideEncryption::handlePrivateKeyDeleted);
+    connect(deleteCertJob, &DeletePasswordJob::finished, this, &ClientSideEncryption::handleCertificateDeleted);
+    connect(deleteMnemonicJob, &DeletePasswordJob::finished, this, &ClientSideEncryption::handleMnemonicDeleted);
+    deletePrivateKeyJob->start();
+    deleteCertJob->start();
+    deleteMnemonicJob->start();
+}
+
+void ClientSideEncryption::handlePrivateKeyDeleted(QKeychain::Job *incoming)
+{
+    if (incoming->error() != QKeychain::NoError) {
+        qCWarning(lcCse) << "Private key could not be deleted:" << incoming->errorString();
+        return;
+    }
+
+    qCDebug(lcCse) << "Private key successfully deleted from keychain. Clearing.";
+    _privateKey = QByteArray();
+    Q_EMIT privateKeyDeleted();
+    checkAllSensitiveDataDeleted();
+}
+
+void ClientSideEncryption::handleCertificateDeleted(QKeychain::Job *incoming)
+{
+    if (incoming->error() != QKeychain::NoError) {
+        qCWarning(lcCse) << "Certificate could not be deleted:" << incoming->errorString();
+        return;
+    }
+
+    qCDebug(lcCse) << "Certificate successfully deleted from keychain. Clearing.";
+    _certificate = QSslCertificate();
+    Q_EMIT certificateDeleted();
+    checkAllSensitiveDataDeleted();
+}
+
+void ClientSideEncryption::handleMnemonicDeleted(QKeychain::Job *incoming)
+{
+    if (incoming->error() != QKeychain::NoError) {
+        qCWarning(lcCse) << "Mnemonic could not be deleted:" << incoming->errorString();
+        return;
+    }
+
+    qCDebug(lcCse) << "Mnemonic successfully deleted from keychain. Clearing.";
+    _mnemonic = QString();
+    Q_EMIT mnemonicDeleted();
+    checkAllSensitiveDataDeleted();
+}
+
+void ClientSideEncryption::checkAllSensitiveDataDeleted()
+{
+    if (_privateKey.isEmpty() && _certificate.isNull() && _mnemonic.isEmpty()) {
+        qCDebug(lcCse) << "All sensitive encryption data has been deleted.";
+        Q_EMIT sensitiveDataForgotten();
+    }
+
+    qCDebug(lcCse) << "Some sensitive data emaining:"
+                   << "Private key:" << _privateKey
+                   << "Certificate is null:" << _certificate.isNull()
+                   << "Mnemonic:" << _mnemonic;
 }
 
 void ClientSideEncryption::generateKeyPair(const AccountPtr &account)
index 1783ebba5ce432b37dc9b9022dd778442740bf82..037d231ea02f0eafc7a2b80902d663937088ff30 100644 (file)
@@ -128,6 +128,10 @@ public:
 
 signals:
     void initializationFinished(bool isNewMnemonicGenerated = false);
+    void sensitiveDataForgotten();
+    void privateKeyDeleted();
+    void certificateDeleted();
+    void mnemonicDeleted();
 
 public slots:
     void initialize(const AccountPtr &account);
@@ -141,6 +145,11 @@ private slots:
     void privateKeyFetched(QKeychain::Job *incoming);
     void mnemonicKeyFetched(QKeychain::Job *incoming);
 
+    void handlePrivateKeyDeleted(QKeychain::Job *incoming);
+    void handleCertificateDeleted(QKeychain::Job *incoming);
+    void handleMnemonicDeleted(QKeychain::Job *incoming);
+    void checkAllSensitiveDataDeleted();
+
     void getPrivateKeyFromServer(const AccountPtr &account);
     void getPublicKeyFromServer(const AccountPtr &account);
     void fetchAndValidatePublicKeyFromServer(const AccountPtr &account);