mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-27 09:30:13 +03:00
E2EE. Fix freeze on metadata checksum validation.
Signed-off-by: alex-z <blackslayer4@gmail.com>
This commit is contained in:
parent
c1bfd8b133
commit
90e3a37a20
7 changed files with 42 additions and 38 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue