]> dgit.raspbian.org Git - nextcloud-desktop.git/commitdiff
E2EE. Fix freeze on metadata checksum validation.
authoralex-z <blackslayer4@gmail.com>
Fri, 5 May 2023 14:15:09 +0000 (16:15 +0200)
committeralex-z <blackslayer4@gmail.com>
Mon, 8 May 2023 09:29:16 +0000 (11:29 +0200)
Signed-off-by: alex-z <blackslayer4@gmail.com>
src/gui/accountmanager.cpp
src/libsync/account.cpp
src/libsync/account.h
src/libsync/clientsideencryption.cpp
src/libsync/clientsideencryption.h
src/libsync/owncloudpropagator.cpp
src/libsync/syncengine.cpp

index 93b5d5dba2c2ef0a2bce63b2ff11384c2eb20954..157aeb4fa8e67fba6f8d2e8d03f74278cce1c8db 100644 (file)
@@ -41,6 +41,7 @@ constexpr auto caCertsKeyC = "CaCertificates";
 constexpr auto accountsC = "Accounts";
 constexpr auto versionC = "version";
 constexpr auto serverVersionC = "serverVersion";
+constexpr auto skipE2eeMetadataChecksumValidationC = "skipE2eeMetadataChecksumValidation";
 constexpr auto generalC = "General";
 
 constexpr auto dummyAuthTypeC = "dummy";
@@ -286,6 +287,11 @@ void AccountManager::saveAccountHelper(Account *acc, QSettings &settings, bool s
     settings.setValue(QLatin1String(davUserC), acc->_davUser);
     settings.setValue(QLatin1String(displayNameC), acc->_displayName);
     settings.setValue(QLatin1String(serverVersionC), acc->_serverVersion);
+    if (!acc->_skipE2eeMetadataChecksumValidation) {
+        settings.remove(QLatin1String(skipE2eeMetadataChecksumValidationC));
+    } else {
+        settings.setValue(QLatin1String(skipE2eeMetadataChecksumValidationC), acc->_skipE2eeMetadataChecksumValidation);
+    }
 
     if (acc->_credentials) {
         if (saveCredentials) {
@@ -385,6 +391,7 @@ AccountPtr AccountManager::loadAccountHelper(QSettings &settings)
     qCInfo(lcAccountManager) << "Account for" << acc->url() << "using auth type" << authType;
 
     acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString();
+    acc->_skipE2eeMetadataChecksumValidation = settings.value(QLatin1String(skipE2eeMetadataChecksumValidationC), {}).toBool();
     acc->_davUser = settings.value(QLatin1String(davUserC), "").toString();
 
     // We want to only restore settings for that auth type and the user value
index 9cc5e11061397bbf524bdfbfc5d39ded0c6e1714..9f080fdca197564f94551868d6e637e51777038e 100644 (file)
@@ -61,6 +61,7 @@ namespace {
 constexpr int pushNotificationsReconnectInterval = 1000 * 60 * 2;
 constexpr int usernamePrefillServerVersionMinSupportedMajor = 24;
 constexpr int checksumRecalculateRequestServerVersionMinSupportedMajor = 24;
+constexpr auto isSkipE2eeMetadataChecksumValidationAllowedInClientVersion = MIRALL_VERSION_MAJOR == 3 && MIRALL_VERSION_MINOR == 8;
 }
 
 namespace OCC {
@@ -677,6 +678,17 @@ QString Account::serverVersion() const
     return _serverVersion;
 }
 
+bool Account::shouldSkipE2eeMetadataChecksumValidation() const
+{
+    return isSkipE2eeMetadataChecksumValidationAllowedInClientVersion && _skipE2eeMetadataChecksumValidation;
+}
+
+void Account::resetShouldSkipE2eeMetadataChecksumValidation()
+{
+    _skipE2eeMetadataChecksumValidation = false;
+    emit wantsAccountSaved(this);
+}
+
 int Account::serverVersionInt() const
 {
     // FIXME: Use Qt 5.5 QVersionNumber
index 87f685dfebd2b08fd6620c626b8f87f77662be2e..0546c84f170a3cab1c371839f683aefc1243a0ea 100644 (file)
@@ -233,6 +233,10 @@ public:
      */
     [[nodiscard]] QString serverVersion() const;
 
+    // check if the checksum validation of E2EE metadata is allowed to be skipped via config file, this will only work before client 3.9.0
+    [[nodiscard]] bool shouldSkipE2eeMetadataChecksumValidation() const;
+    void resetShouldSkipE2eeMetadataChecksumValidation();
+
     /** Server version for easy comparison.
      *
      * Example: serverVersionInt() >= makeServerVersion(11, 2, 3)
@@ -402,6 +406,7 @@ private:
     QSslConfiguration _sslConfiguration;
     Capabilities _capabilities;
     QString _serverVersion;
+    bool _skipE2eeMetadataChecksumValidation = false;
     QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
     QSharedPointer<QNetworkAccessManager> _am;
     QScopedPointer<AbstractCredentials> _credentials;
index d1716841a0482cc201aea66d66084f83465d8d64..ca957d34500fe7da1af725445047de3ea528c9c9 100644 (file)
@@ -1643,9 +1643,14 @@ void FolderMetadata::setupExistingMetadata(const QByteArray& metadata)
 
     if (!migratedMetadata && !checkMetadataKeyChecksum(metadataKey, metadataKeyChecksum)) {
         qCInfo(lcCseMetadata) << "checksum comparison failed" << "server value" << metadataKeyChecksum << "client value" << computeMetadataKeyChecksum(metadataKey);
-        _metadataKey.clear();
-        _files.clear();
-        return;
+        if (_account->shouldSkipE2eeMetadataChecksumValidation()) {
+            qCDebug(lcCseMetadata) << "shouldSkipE2eeMetadataChecksumValidation is set. Allowing invalid checksum until next sync.";
+            _encryptedMetadataNeedUpdate = true;
+        } else {
+            _metadataKey.clear();
+            _files.clear();
+            return;
+        }
     }
 
     // decryption finished, create new metadata key to be used for encryption
@@ -1721,13 +1726,6 @@ bool FolderMetadata::checkMetadataKeyChecksum(const QByteArray &metadataKey,
 {
     const auto referenceMetadataKeyValue = computeMetadataKeyChecksum(metadataKey);
 
-    if (referenceMetadataKeyValue != metadataKeyChecksum) {
-        if (recoverMetadataKeyChecksum(metadataKeyChecksum, metadataKey)) {
-            qCInfo(lcCseMetadata) << "Checksum recovery done";
-            return true;
-        }
-    }
-
     return referenceMetadataKeyValue == metadataKeyChecksum;
 }
 
@@ -1748,31 +1746,6 @@ QByteArray FolderMetadata::computeMetadataKeyChecksum(const QByteArray &metadata
     return hashAlgorithm.result().toHex();
 }
 
-bool FolderMetadata::recoverMetadataKeyChecksum(const QByteArray &expectedChecksum,
-                                                const QByteArray &metadataKey) const
-{
-    const auto sortLambda = [] (const auto &first, const auto &second) {
-        return first.encryptedFilename < second.encryptedFilename;
-    };
-    auto sortedFiles = _files;
-
-    std::sort(sortedFiles.begin(), sortedFiles.end(), sortLambda);
-
-    do {
-        auto hashAlgorithm = QCryptographicHash{QCryptographicHash::Sha256};
-        hashAlgorithm.addData(_account->e2e()->_mnemonic.remove(' ').toUtf8());
-        for (const auto &singleFile : sortedFiles) {
-            hashAlgorithm.addData(singleFile.encryptedFilename.toUtf8());
-        }
-        hashAlgorithm.addData(metadataKey);
-        if (hashAlgorithm.result().toHex() == expectedChecksum) {
-            return true;
-        }
-    } while (std::next_permutation(sortedFiles.begin(), sortedFiles.end(), sortLambda));
-
-    return false;
-}
-
 bool FolderMetadata::isMetadataSetup() const
 {
     return _isMetadataSetup;
index c2af28f7529a7c29c87a21fc23dc47ba4d4bf0f4..4d074c965dc8f3a1c8a3de96771804c5329c7a7d 100644 (file)
@@ -233,8 +233,6 @@ private:
     [[nodiscard]] bool checkMetadataKeyChecksum(const QByteArray &metadataKey, const QByteArray &metadataKeyChecksum) const;
 
     [[nodiscard]] QByteArray computeMetadataKeyChecksum(const QByteArray &metadataKey) const;
-    [[nodiscard]] bool recoverMetadataKeyChecksum(const QByteArray &expectedChecksum,
-                                                  const QByteArray &metadataKey) const;
 
     QByteArray _metadataKey;
 
index 061fec53ee366bc3468b357ab00e39dedc1fb532..19d5e61913c10df238043b82dc52dfd385911d75 100644 (file)
@@ -652,7 +652,11 @@ void OwncloudPropagator::startDirectoryPropagation(const SyncFileItemPtr &item,
         _anotherSyncNeeded = true;
     } else if (item->_isEncryptedMetadataNeedUpdate) {
         SyncJournalFileRecord record;
-        if (_journal->getFileRecord(item->_file, &record) && record._e2eEncryptionStatus == SyncJournalFileRecord::EncryptionStatus::EncryptedMigratedV1_2) {
+        const auto isUnexpectedMetadataFormat = _journal->getFileRecord(item->_file, &record)
+            && record._e2eEncryptionStatus == SyncJournalFileRecord::EncryptionStatus::EncryptedMigratedV1_2;
+        if (isUnexpectedMetadataFormat && _account->shouldSkipE2eeMetadataChecksumValidation()) {
+            qCDebug(lcPropagator) << "Getting unexpected metadata format, but allowing to continue as shouldSkipE2eeMetadataChecksumValidation is set.";
+        } else if (isUnexpectedMetadataFormat && !_account->shouldSkipE2eeMetadataChecksumValidation()) {
             qCDebug(lcPropagator) << "could have upgraded metadata";
             item->_instruction = CSyncEnums::CSYNC_INSTRUCTION_ERROR;
             item->_errorString = tr("Error with the metadata. Getting unexpected metadata format.");
index 23c41be9e991bd8f75d3a2027dc17ab8512d0432..f9a834d9ea42a4c93ec63f8739c15960c181c0d8 100644 (file)
@@ -956,6 +956,11 @@ void SyncEngine::finalize(bool success)
     _syncRunning = false;
     emit finished(success);
 
+    if (_account->shouldSkipE2eeMetadataChecksumValidation()) {
+        qCDebug(lcEngine) << "shouldSkipE2eeMetadataChecksumValidation was set. Sync is finished, so resetting it...";
+        _account->resetShouldSkipE2eeMetadataChecksumValidation();
+    }
+
     // Delete the propagator only after emitting the signal.
     _propagator.clear();
     _seenConflictFiles.clear();