Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 1 addition & 28 deletions src/gui/folderman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1789,27 +1789,7 @@ void FolderMan::leaveShare(const QString &localFile)
SyncJournalFileRecord rec;
if (folder->journalDb()->getFileRecord(filePathRelative, &rec)
&& rec.isValid() && rec.isE2eEncrypted()) {

if (_removeE2eeShareJob) {
_removeE2eeShareJob->deleteLater();
}

_removeE2eeShareJob = new UpdateE2eeFolderUsersMetadataJob(folder->accountState()->account(),
folder->journalDb(),
folder->remotePath(),
UpdateE2eeFolderUsersMetadataJob::Remove,
folder->remotePathTrailingSlash() + filePathRelative,
folder->accountState()->account()->davUser());
_removeE2eeShareJob->setParent(this);
_removeE2eeShareJob->start(true);
connect(_removeE2eeShareJob, &UpdateE2eeFolderUsersMetadataJob::finished, this, [localFileNoTrailingSlash, this](int code, const QString &message) {
if (code != 200) {
qCWarning(lcFolderMan) << "Could not remove share from E2EE folder's metadata!" << code << message;
return;
}
slotLeaveShare(localFileNoTrailingSlash, _removeE2eeShareJob->folderToken());
});

qCWarning(lcFolderMan) << "You cannot remove yourself from an encrypted share";
return;
}
slotLeaveShare(localFileNoTrailingSlash);
Expand All @@ -1832,13 +1812,6 @@ void FolderMan::slotLeaveShare(const QString &localFile, const QByteArray &folde
connect(leaveShareJob, &SimpleApiJob::resultReceived, this, [this, folder, localFile](int statusCode) {
qCDebug(lcFolderMan) << "slotLeaveShare callback statusCode" << statusCode;
Q_UNUSED(statusCode);
if (_removeE2eeShareJob) {
_removeE2eeShareJob->unlockFolder(EncryptedFolderMetadataHandler::UnlockFolderWithResult::Success);
connect(_removeE2eeShareJob.data(), &UpdateE2eeFolderUsersMetadataJob::folderUnlocked, this, [this, folder] {
scheduleFolder(folder);
});
return;
}
scheduleFolder(folder);
});
leaveShareJob->start();
Expand Down
2 changes: 0 additions & 2 deletions src/gui/folderman.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,6 @@ private slots:
NavigationPaneHelper _navigationPaneHelper;
#endif

QPointer<UpdateE2eeFolderUsersMetadataJob> _removeE2eeShareJob;

bool _appRestartRequired = false;

static FolderMan *_instance;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/socketapi/socketapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,7 @@ void SocketApi::sendSharingContextMenuOptions(const FileData &fileData, SocketLi
if (!capabilities.shareAPI() || !(theme->userGroupSharing() || (theme->linkSharing() && capabilities.sharePublicLink())))
return;

if (record._isShared && !record._sharedByMe) {
if (record._isShared && !record._sharedByMe && itemEncryptionFlag == SharingContextItemEncryptedFlag::NotEncryptedItem) {
listener->sendMessage(QLatin1String("MENU_ITEM:LEAVESHARE") + flagString + tr("Leave this share"));
}

Expand Down
10 changes: 8 additions & 2 deletions src/libsync/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,16 +743,22 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(const SyncFileItemPtr &it
Q_ASSERT(item->_e2eEncryptionStatus != SyncFileItem::EncryptionStatus::NotEncrypted);
}
item->_encryptedFileName = [=, this] {
auto result = QString{};

if (item->_e2eEncryptionStatus == SyncFileItem::EncryptionStatus::NotEncrypted) {
return result;
}
if (serverEntry.e2eMangledName.isEmpty()) {
return QString();
return result;
}

Q_ASSERT(_discoveryData->_remoteFolder.startsWith('/'));
Q_ASSERT(_discoveryData->_remoteFolder.endsWith('/'));

const auto rootPath = _discoveryData->_remoteFolder.mid(1);
Q_ASSERT(serverEntry.e2eMangledName.startsWith(rootPath));
return serverEntry.e2eMangledName.mid(rootPath.length());
result = serverEntry.e2eMangledName.mid(rootPath.length());
return result;
}();
item->_locked = serverEntry.locked;
item->_lockOwnerDisplayName = serverEntry.lockOwnerDisplayName;
Expand Down
10 changes: 8 additions & 2 deletions src/libsync/discoveryphase.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2014 ownCloud GmbH
Expand Down Expand Up @@ -671,11 +671,17 @@
break;
}

const auto rootEncryptedFolderInfo = RootEncryptedFolderInfo{Utility::fullRemotePathToRemoteSyncRootRelative(topLevelFolderPath, _remoteRootFolderPath)};

const auto folderType = _topLevelE2eeFolderPaths.contains(_subPath) ? FolderMetadata::FolderType::Root : FolderMetadata::FolderType::Nested;
Q_ASSERT((folderType == FolderMetadata::FolderType::Root) == (rootEncryptedFolderInfo.path == QStringLiteral("/")));

const auto e2EeFolderMetadata = new FolderMetadata(_account,
_remoteRootFolderPath,
jsonMetadata,
RootEncryptedFolderInfo(Utility::fullRemotePathToRemoteSyncRootRelative(topLevelFolderPath, _remoteRootFolderPath)),
job->signature());
rootEncryptedFolderInfo,
job->signature(),
folderType);
connect(e2EeFolderMetadata, &FolderMetadata::setupComplete, this, [this, e2EeFolderMetadata] {
e2EeFolderMetadata->deleteLater();
if (!e2EeFolderMetadata->isValid()) {
Expand Down Expand Up @@ -718,7 +724,7 @@
emit finished(_results);
deleteLater();
});
}

Check failure on line 727 in src/libsync/discoveryphase.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Potential leak of memory pointed to by 'e2EeFolderMetadata'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ76qAiE2GTpmvHyOk1u&open=AZ76qAiE2GTpmvHyOk1u&pullRequest=10248

void DiscoverySingleDirectoryJob::metadataError(const QByteArray &fileId, int httpReturnCode)
{
Expand Down
9 changes: 8 additions & 1 deletion src/libsync/encryptedfoldermetadatahandler.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
Expand All @@ -14,6 +14,8 @@
#include <QLoggingCategory>
#include <QNetworkReply>

using namespace Qt::StringLiterals;

namespace OCC {

Q_LOGGING_CATEGORY(lcFetchAndUploadE2eeFolderMetadataJob, "nextcloud.sync.propagator.encryptedfoldermetadatahandler", QtInfoMsg)
Expand Down Expand Up @@ -183,7 +185,12 @@

const auto rawMetadata = statusCode == 404
? QByteArray{} : json.toJson(QJsonDocument::Compact);
const auto metadata(QSharedPointer<FolderMetadata>::create(_account, _remoteFolderRoot, rawMetadata, _rootEncryptedFolderInfo, job->signature()));
const auto metadata(QSharedPointer<FolderMetadata>::create(_account,
_remoteFolderRoot,
rawMetadata,
_rootEncryptedFolderInfo,
job->signature(),
(_rootEncryptedFolderInfo.path == u"/"_s ? FolderMetadata::FolderType::Root : FolderMetadata::FolderType::Nested)));
connect(metadata.data(), &FolderMetadata::setupComplete, this, [this, metadata] {
if (!metadata->isValid()) {
qCWarning(lcFetchAndUploadE2eeFolderMetadataJob) << "Error parsing or decrypting metadata for folder" << _folderFullRemotePath;
Expand Down
9 changes: 7 additions & 2 deletions src/libsync/encryptfolderjob.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
Expand All @@ -10,6 +10,8 @@
#include "foldermetadata.h"
#include <QLoggingCategory>

using namespace Qt::StringLiterals;

namespace OCC {

Q_LOGGING_CATEGORY(lcEncryptFolderJob, "nextcloud.sync.propagator.encryptfolder", QtInfoMsg)
Expand Down Expand Up @@ -103,12 +105,15 @@
return;
}

const auto rootEncryptedFolderInfo = RootEncryptedFolderInfo{RootEncryptedFolderInfo::createRootPath(currentPathRelative, rec.path())};

const auto emptyMetadata(QSharedPointer<FolderMetadata>::create(
_account,
_remoteSyncRootPath,
QByteArray{},
RootEncryptedFolderInfo(RootEncryptedFolderInfo::createRootPath(currentPathRelative, rec.path())),
QByteArray{}));
rootEncryptedFolderInfo,
QByteArray{},
rootEncryptedFolderInfo.path == u"/"_s ? FolderMetadata::FolderType::Root : FolderMetadata::FolderType::Nested));

connect(emptyMetadata.data(), &FolderMetadata::setupComplete, this, [this, emptyMetadata] {
const auto encryptedMetadata = !emptyMetadata->isValid() ? QByteArray{} : emptyMetadata->encryptedMetadata();
Expand Down
7 changes: 6 additions & 1 deletion src/libsync/foldermetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,19 @@
const QByteArray &metadata,
const RootEncryptedFolderInfo &rootEncryptedFolderInfo,
const QByteArray &signature,
FolderType folderType,

Check warning on line 71 in src/libsync/foldermetadata.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "folderType" of type "enum OCC::FolderMetadata::FolderType" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ76qAmu2GTpmvHyOk1v&open=AZ76qAmu2GTpmvHyOk1v&pullRequest=10248
QObject *parent)
: QObject(parent)
, _account(account)
, _remoteFolderRoot(Utility::noLeadingSlashPath(Utility::noTrailingSlashPath(remoteFolderRoot)))
, _initialMetadata(metadata)
, _isRootEncryptedFolder(rootEncryptedFolderInfo.path == QStringLiteral("/"))
, _isRootEncryptedFolder(folderType == FolderType::Root)
, _binaryMetadataKeyForEncryption(rootEncryptedFolderInfo.binaryKeyForEncryption)
, _binaryMetadataKeyForDecryption(rootEncryptedFolderInfo.binaryKeyForDecryption)
, _keyChecksums(rootEncryptedFolderInfo.keyChecksums)
, _initialSignature(signature)
{
Q_ASSERT(_isRootEncryptedFolder == (rootEncryptedFolderInfo.path == QStringLiteral("/")));
Q_ASSERT(!_remoteFolderRoot.isEmpty());
_existingMetadataVersion = setupVersionFromExistingMetadata(metadata);

Expand Down Expand Up @@ -109,7 +111,7 @@
emitSetupComplete();
}

void FolderMetadata::setupExistingMetadata(const QByteArray &metadata)

Check failure on line 114 in src/libsync/foldermetadata.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 36 to the 25 allowed.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ76qAmu2GTpmvHyOk1w&open=AZ76qAmu2GTpmvHyOk1w&pullRequest=10248
{
const auto doc = QJsonDocument::fromJson(metadata);
qCDebug(lcCseMetadata()) << "Got existing metadata:" << doc.toJson(QJsonDocument::Compact);
Expand All @@ -131,6 +133,9 @@
const auto folderUsers = metaDataDoc[usersKey].toArray();

const auto isUsersArrayValid = (!_isRootEncryptedFolder && folderUsers.isEmpty()) || (_isRootEncryptedFolder && !folderUsers.isEmpty());
if (!isUsersArrayValid) {
qCCritical(lcCseMetadata()) << (_isRootEncryptedFolder ? "is root encrypted folder" : "is child encrypted folder") << folderUsers;
}
Q_ASSERT(isUsersArrayValid);

if (!isUsersArrayValid) {
Expand Down
3 changes: 2 additions & 1 deletion src/libsync/foldermetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class OWNCLOUDSYNC_EXPORT FolderMetadata : public QObject
};
Q_ENUM(MetadataVersion)

FolderMetadata(AccountPtr account, const QString &remoteFolderRoot, FolderType folderType = FolderType::Nested);
FolderMetadata(AccountPtr account, const QString &remoteFolderRoot, FolderType folderType);
/*
* construct metadata based on RootEncryptedFolderInfo
* as per E2EE V2, the encryption key and users that have access are only stored in root(top-level) encrypted folder's metadata
Expand All @@ -103,6 +103,7 @@ class OWNCLOUDSYNC_EXPORT FolderMetadata : public QObject
const QByteArray &metadata,
const RootEncryptedFolderInfo &rootEncryptedFolderInfo,
const QByteArray &signature,
FolderType folderType,
QObject *parent = nullptr);

[[nodiscard]] QVector<EncryptedFile> files() const;
Expand Down
13 changes: 8 additions & 5 deletions test/testclientsideencryptionv2.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
Expand Down Expand Up @@ -176,7 +176,7 @@

QScopedPointer<FolderMetadata> metadataFromJson(new FolderMetadata(_account, "/",
ocsDoc.toJson(),
RootEncryptedFolderInfo::makeDefault(), signature));
RootEncryptedFolderInfo::makeDefault(), signature, FolderMetadata::FolderType::Root));
QSignalSpy metadataSetupExistingCompleteSpy(metadataFromJson.data(), &FolderMetadata::setupComplete);
metadataSetupExistingCompleteSpy.wait();
QCOMPARE(metadataSetupExistingCompleteSpy.count(), 1);
Expand Down Expand Up @@ -208,7 +208,8 @@
QScopedPointer<FolderMetadata> metadataFromJson(new FolderMetadata(_account, "/",
ocsDoc.toJson(),
RootEncryptedFolderInfo::makeDefault(),
emptySignature));
emptySignature,
FolderMetadata::FolderType::Root));

QSignalSpy metadataSetupExistingCompleteSpy(metadataFromJson.data(), &FolderMetadata::setupComplete);
metadataSetupExistingCompleteSpy.wait();
Expand Down Expand Up @@ -314,7 +315,7 @@
QJsonDocument ocsDoc =
QJsonDocument::fromJson(QStringLiteral("{\"ocs\": {\"data\": {\"meta-data\": \"%1\"}}}").arg(QString::fromUtf8(encryptedMetadataCopy)).toUtf8());

QScopedPointer<FolderMetadata> metadataFromJsonForSecondUser(new FolderMetadata(_secondAccount, "/", ocsDoc.toJson(), RootEncryptedFolderInfo::makeDefault(), signature));
QScopedPointer<FolderMetadata> metadataFromJsonForSecondUser(new FolderMetadata(_secondAccount, "/", ocsDoc.toJson(), RootEncryptedFolderInfo::makeDefault(), signature, FolderMetadata::FolderType::Root));
QSignalSpy metadataSetupExistingCompleteSpy(metadataFromJsonForSecondUser.data(), &FolderMetadata::setupComplete);
metadataSetupExistingCompleteSpy.wait();
QCOMPARE(metadataSetupExistingCompleteSpy.count(), 1);
Expand All @@ -338,10 +339,12 @@
QJsonDocument ocsDocFromSecondUser = QJsonDocument::fromJson(
QStringLiteral("{\"ocs\": {\"data\": {\"meta-data\": \"%1\"}}}").arg(QString::fromUtf8(encryptedMetadataFromSecondUser)).toUtf8());

QScopedPointer<FolderMetadata> metadataFromJsonForFirstUserToCheckCrossSharing(new FolderMetadata(_account, "/",
QScopedPointer<FolderMetadata> metadataFromJsonForFirstUserToCheckCrossSharing(new FolderMetadata(_account,
"/",
ocsDocFromSecondUser.toJson(),
RootEncryptedFolderInfo::makeDefault(),
signatureAfterSecondUserModification));
signatureAfterSecondUserModification,
FolderMetadata::FolderType::Root));
QSignalSpy metadataSetupForCrossSharingCompleteSpy(metadataFromJsonForFirstUserToCheckCrossSharing.data(), &FolderMetadata::setupComplete);
metadataSetupForCrossSharingCompleteSpy.wait();
QCOMPARE(metadataSetupForCrossSharingCompleteSpy.count(), 1);
Expand Down
4 changes: 2 additions & 2 deletions test/testsecurefiledrop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private slots:
const auto signature = metadata->metadataSignature();
QJsonDocument ocsDoc =
QJsonDocument::fromJson(QStringLiteral("{\"ocs\": {\"data\": {\"meta-data\": \"%1\"}}}").arg(QString::fromUtf8(encryptedMetadata)).toUtf8());
_parsedMetadataWithFileDrop.reset(new FolderMetadata(_account, "/", ocsDoc.toJson(), RootEncryptedFolderInfo::makeDefault(), signature));
_parsedMetadataWithFileDrop.reset(new FolderMetadata(_account, "/", ocsDoc.toJson(), RootEncryptedFolderInfo::makeDefault(), signature, FolderMetadata::FolderType::Root));

QSignalSpy metadataWithFileDropSetupCompleteSpy(_parsedMetadataWithFileDrop.data(), &FolderMetadata::setupComplete);
metadataWithFileDropSetupCompleteSpy.wait();
Expand All @@ -164,7 +164,7 @@ private slots:
QJsonDocument ocsDoc =
QJsonDocument::fromJson(QStringLiteral("{\"ocs\": {\"data\": {\"meta-data\": \"%1\"}}}").arg(QString::fromUtf8(encryptedMetadata)).toUtf8());

_parsedMetadataAfterProcessingFileDrop.reset(new FolderMetadata(_account, "/", ocsDoc.toJson(), RootEncryptedFolderInfo::makeDefault(), signature));
_parsedMetadataAfterProcessingFileDrop.reset(new FolderMetadata(_account, "/", ocsDoc.toJson(), RootEncryptedFolderInfo::makeDefault(), signature, FolderMetadata::FolderType::Root));

QSignalSpy metadataAfterProcessingFileDropSetupCompleteSpy(_parsedMetadataAfterProcessingFileDrop.data(), &FolderMetadata::setupComplete);
metadataAfterProcessingFileDropSetupCompleteSpy.wait();
Expand Down
Loading