diff --git a/src/libsync/clientsideencryption.cpp b/src/libsync/clientsideencryption.cpp index d1716841a0482..e4ec3898b43ff 100644 --- a/src/libsync/clientsideencryption.cpp +++ b/src/libsync/clientsideencryption.cpp @@ -9,6 +9,7 @@ #include "account.h" #include "capabilities.h" +#include "configfile.h" #include "networkjobs.h" #include "clientsideencryptionjobs.h" #include "theme.h" @@ -1643,9 +1644,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 (ConfigFile().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 +1727,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 +1747,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; diff --git a/src/libsync/clientsideencryption.h b/src/libsync/clientsideencryption.h index c2af28f7529a7..4d074c965dc8f 100644 --- a/src/libsync/clientsideencryption.h +++ b/src/libsync/clientsideencryption.h @@ -233,8 +233,6 @@ class OWNCLOUDSYNC_EXPORT FolderMetadata { [[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; diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index f60a4b19bc20d..0d53fef78a5df 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -71,6 +71,7 @@ static constexpr char updateChannelC[] = "updateChannel"; static constexpr char overrideServerUrlC[] = "overrideServerUrl"; static constexpr char overrideLocalDirC[] = "overrideLocalDir"; static constexpr char isVfsEnabledC[] = "isVfsEnabled"; +static constexpr char skipE2eeMetadataChecksumValidation[] = "skipE2eeMetadataChecksumValidation"; static constexpr char geometryC[] = "geometry"; static constexpr char timeoutC[] = "timeout"; static constexpr char chunkSizeC[] = "chunkSize"; @@ -104,6 +105,7 @@ static constexpr char moveToTrashC[] = "moveToTrash"; static constexpr char certPath[] = "http_certificatePath"; static constexpr char certPasswd[] = "http_certificatePasswd"; +static constexpr auto isSkipE2eeMetadataChecksumValidationAllowedInClientVersion = MIRALL_VERSION_MAJOR == 3 && MIRALL_VERSION_MINOR == 8; } namespace OCC { @@ -731,6 +733,19 @@ bool ConfigFile::isVfsEnabled() const return settings.value({isVfsEnabledC}, {}).toBool(); } +bool ConfigFile::shouldSkipE2eeMetadataChecksumValidation() const +{ + QSettings settings(configFile(), QSettings::IniFormat); + return isSkipE2eeMetadataChecksumValidationAllowedInClientVersion + && settings.value({skipE2eeMetadataChecksumValidation}, {}).toBool(); +} + +void ConfigFile::resetShouldSkipE2eeMetadataChecksumValidation() +{ + QSettings settings(configFile(), QSettings::IniFormat); + settings.setValue({skipE2eeMetadataChecksumValidation}, false); +} + void ConfigFile::setVfsEnabled(bool enabled) { QSettings settings(configFile(), QSettings::IniFormat); diff --git a/src/libsync/configfile.h b/src/libsync/configfile.h index 9f0f76155b067..5871b862d260d 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -199,6 +199,10 @@ class OWNCLOUDSYNC_EXPORT ConfigFile [[nodiscard]] bool isVfsEnabled() const; void setVfsEnabled(bool enabled); + // 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(); + void saveGeometryHeader(QHeaderView *header); void restoreGeometryHeader(QHeaderView *header); diff --git a/src/libsync/owncloudpropagator.cpp b/src/libsync/owncloudpropagator.cpp index 061fec53ee366..301835c08a976 100644 --- a/src/libsync/owncloudpropagator.cpp +++ b/src/libsync/owncloudpropagator.cpp @@ -28,6 +28,7 @@ #include "common/utility.h" #include "account.h" #include "common/asserts.h" +#include "configfile.h" #include "discoveryphase.h" #include "syncfileitem.h" @@ -652,7 +653,12 @@ 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 && ConfigFile().shouldSkipE2eeMetadataChecksumValidation()) { + qCDebug(lcPropagator) << "Getting unexpected metadata format, but allowing to continue as shouldSkipE2eeMetadataChecksumValidation is set."; + } + if (isUnexpectedMetadataFormat && !ConfigFile().shouldSkipE2eeMetadataChecksumValidation()) { qCDebug(lcPropagator) << "could have upgraded metadata"; item->_instruction = CSyncEnums::CSYNC_INSTRUCTION_ERROR; item->_errorString = tr("Error with the metadata. Getting unexpected metadata format."); diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 23c41be9e991b..d4454f031f222 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -956,6 +956,11 @@ void SyncEngine::finalize(bool success) _syncRunning = false; emit finished(success); + if (ConfigFile().shouldSkipE2eeMetadataChecksumValidation()) { + qCDebug(lcEngine) << "shouldSkipE2eeMetadataChecksumValidation was set. Sync is finished, so resetting it..."; + ConfigFile().resetShouldSkipE2eeMetadataChecksumValidation(); + } + // Delete the propagator only after emitting the signal. _propagator.clear(); _seenConflictFiles.clear();