constexpr auto accountsC = "Accounts";
constexpr auto versionC = "version";
constexpr auto serverVersionC = "serverVersion";
+constexpr auto skipE2eeMetadataChecksumValidationC = "skipE2eeMetadataChecksumValidation";
constexpr auto generalC = "General";
constexpr auto dummyAuthTypeC = "dummy";
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) {
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
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 {
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
*/
[[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)
QSslConfiguration _sslConfiguration;
Capabilities _capabilities;
QString _serverVersion;
+ bool _skipE2eeMetadataChecksumValidation = false;
QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
QSharedPointer<QNetworkAccessManager> _am;
QScopedPointer<AbstractCredentials> _credentials;
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
{
const auto referenceMetadataKeyValue = computeMetadataKeyChecksum(metadataKey);
- if (referenceMetadataKeyValue != metadataKeyChecksum) {
- if (recoverMetadataKeyChecksum(metadataKeyChecksum, metadataKey)) {
- qCInfo(lcCseMetadata) << "Checksum recovery done";
- return true;
- }
- }
-
return referenceMetadataKeyValue == metadataKeyChecksum;
}
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;
[[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;
_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.");
_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();