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
2 changes: 1 addition & 1 deletion apps/dav/lib/Connector/LegacyPublicAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected function validateUserPass($username, $password) {
\OC_User::setIncognitoMode(true);

// check if the share is password protected
if ($share->getPassword() !== null) {
if ($share->isPasswordProtected()) {
if ($share->getShareType() === IShare::TYPE_LINK
|| $share->getShareType() === IShare::TYPE_EMAIL
|| $share->getShareType() === IShare::TYPE_CIRCLE) {
Expand Down
6 changes: 3 additions & 3 deletions apps/dav/lib/Connector/Sabre/PublicAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function check(RequestInterface $request, ResponseInterface $response): a
try {
$this->throttler->sleepDelayOrThrowOnMax($this->request->getRemoteAddress(), self::BRUTEFORCE_ACTION);

if (count($_COOKIE) > 0 && !$this->request->passesStrictCookieCheck() && $this->getShare()->getPassword() !== null) {
if (count($_COOKIE) > 0 && !$this->request->passesStrictCookieCheck() && $this->getShare()->isPasswordProtected()) {
throw new PreconditionFailed('Strict cookie check failed');
}

Expand Down Expand Up @@ -142,7 +142,7 @@ private function checkToken(): array {
}

// If the share is protected but user is not authenticated
if ($share->getPassword() !== null) {
if ($share->isPasswordProtected()) {
$this->throttler->registerAttempt(self::BRUTEFORCE_ACTION, $this->request->getRemoteAddress());
throw new NotAuthenticated();
}
Expand Down Expand Up @@ -176,7 +176,7 @@ protected function validateUserPass($username, $password) {
\OC_User::setIncognitoMode(true);

// check if the share is password protected
if ($share->getPassword() !== null) {
if ($share->isPasswordProtected()) {
if ($share->getShareType() === IShare::TYPE_LINK
|| $share->getShareType() === IShare::TYPE_EMAIL
|| $share->getShareType() === IShare::TYPE_CIRCLE) {
Expand Down
8 changes: 8 additions & 0 deletions apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public function testNoShare(): void {
public function testShareNoPassword(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$share->method('isPasswordProtected')->willReturn(false);

$this->shareManager->expects($this->once())
->method('getShareByToken')
Expand All @@ -86,6 +87,7 @@ public function testShareNoPassword(): void {
public function testSharePasswordFancyShareType(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(42);

$this->shareManager->expects($this->once())
Expand All @@ -100,6 +102,7 @@ public function testSharePasswordFancyShareType(): void {
public function testSharePasswordRemote(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);

$this->shareManager->expects($this->once())
Expand All @@ -114,6 +117,7 @@ public function testSharePasswordRemote(): void {
public function testSharePasswordLinkValidPassword(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);

$this->shareManager->expects($this->once())
Expand All @@ -134,6 +138,7 @@ public function testSharePasswordLinkValidPassword(): void {
public function testSharePasswordMailValidPassword(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);

$this->shareManager->expects($this->once())
Expand All @@ -154,6 +159,7 @@ public function testSharePasswordMailValidPassword(): void {
public function testInvalidSharePasswordLinkValidSession(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');

Expand All @@ -178,6 +184,7 @@ public function testInvalidSharePasswordLinkValidSession(): void {
public function testSharePasswordLinkInvalidSession(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');

Expand All @@ -202,6 +209,7 @@ public function testSharePasswordLinkInvalidSession(): void {
public function testSharePasswordMailInvalidSession(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
$share->method('getId')->willReturn('42');

Expand Down
11 changes: 11 additions & 0 deletions apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public function testCheckTokenValidShare(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$share->method('isPasswordProtected')->willReturn(false);

$this->shareManager->expects($this->once())
->method('getShareByToken')
Expand Down Expand Up @@ -146,6 +147,7 @@ public function testCheckTokenPasswordNotAuthenticated(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(42);

$this->shareManager->expects($this->once())
Expand All @@ -165,6 +167,7 @@ public function testCheckTokenPasswordAuthenticatedWrongShare(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(42);

$this->shareManager->expects($this->once())
Expand Down Expand Up @@ -199,6 +202,7 @@ public function testShareNoPassword(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$share->method('isPasswordProtected')->willReturn(false);

$this->shareManager->expects($this->once())
->method('getShareByToken')
Expand All @@ -216,6 +220,7 @@ public function testSharePasswordFancyShareType(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(42);

$this->shareManager->expects($this->once())
Expand All @@ -234,6 +239,7 @@ public function testSharePasswordRemote(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);

$this->shareManager->expects($this->once())
Expand All @@ -252,6 +258,7 @@ public function testSharePasswordLinkValidPassword(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);

$this->shareManager->expects($this->once())
Expand All @@ -276,6 +283,7 @@ public function testSharePasswordMailValidPassword(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);

$this->shareManager->expects($this->once())
Expand All @@ -300,6 +308,7 @@ public function testInvalidSharePasswordLinkValidSession(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');

Expand Down Expand Up @@ -329,6 +338,7 @@ public function testSharePasswordLinkInvalidSession(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');

Expand Down Expand Up @@ -358,6 +368,7 @@ public function testSharePasswordMailInvalidSession(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
$share->method('getId')->willReturn('42');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ public function createFederatedShare($shareWith, $token, $password = '') {
$authenticated = in_array($share->getId(), $allowedShareIds)
|| $this->shareManager->checkPassword($share, $password);

$storedPassword = $share->getPassword();
if (!empty($storedPassword) && !$authenticated) {
if ($share->isPasswordProtected() && !$authenticated) {
$response = new JSONResponse(
['message' => 'No permission to access the share'],
Http::STATUS_BAD_REQUEST
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016-2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

Expand Down Expand Up @@ -60,7 +60,7 @@ public function isValidToken(): bool {

#[\Override]
protected function isPasswordProtected(): bool {
return $this->share->getPassword() !== null;
return $this->share->isPasswordProtected();
}

/**
Expand Down Expand Up @@ -181,7 +181,7 @@ public function directLink(string $token) {
}

// Password protected shares have no direct link!
if ($share->getPassword() !== null) {
if ($share->isPasswordProtected()) {
return new DataResponse([], Http::STATUS_FORBIDDEN);
}

Expand Down
4 changes: 2 additions & 2 deletions apps/files_sharing/lib/Controller/ShareController.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016-2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
Expand Down Expand Up @@ -176,7 +176,7 @@ public function isValidToken(): bool {

#[\Override]
protected function isPasswordProtected(): bool {
return $this->share->getPassword() !== null;
return $this->share->isPasswordProtected();
}

#[\Override]
Expand Down
4 changes: 2 additions & 2 deletions apps/files_sharing/lib/Controller/ShareInfoController.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016-2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

Expand Down Expand Up @@ -70,7 +70,7 @@ public function info(string $t, ?string $password = null, ?string $dir = null, i
return $response;
}

if ($share->getPassword() && !$this->shareManager->checkPassword($share, $password)) {
if ($share->isPasswordProtected() && !$this->shareManager->checkPassword($share, $password)) {
$response = new JSONResponse([], Http::STATUS_FORBIDDEN);
$response->throttle(['token' => $t]);
return $response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ public function createShare(
$share->method('getMailSend')->willReturn($mail_send);
$share->method('getToken')->willReturn($token);
$share->method('getPassword')->willReturn($password);
$share->method('isPasswordProtected')->willReturn(!empty($password));

if ($shareType === IShare::TYPE_USER
|| $shareType === IShare::TYPE_GROUP
Expand Down
2 changes: 2 additions & 0 deletions apps/files_sharing/tests/Controller/ShareControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,7 @@ public function testShowShareInvalid(): void {
public function testDownloadShareWithCreateOnlyShare(): void {
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share
->expects($this->once())
->method('getPermissions')
Expand All @@ -728,6 +729,7 @@ public function testDownloadShareWithoutDownloadPermission(): void {

$share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('isPasswordProtected')->willReturn(true);
$share->expects(self::once())
->method('getPermissions')
->willReturn(Constants::PERMISSION_READ);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function testWrongPassword(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')
->willReturn('sharePass');
$share->method('isPasswordProtected')->willReturn(true);

$this->shareManager->method('getShareByToken')
->with('token')
Expand All @@ -68,6 +69,7 @@ public function testNoReadPermissions(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')
->willReturn('sharePass');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getPermissions')
->willReturn(Constants::PERMISSION_CREATE);

Expand Down Expand Up @@ -109,6 +111,7 @@ public function testInfoFile(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')
->willReturn('sharePass');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getPermissions')
->willReturn(Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE);
$share->method('getNode')
Expand Down Expand Up @@ -141,6 +144,7 @@ public function testInfoFileRO(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')
->willReturn('sharePass');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getPermissions')
->willReturn(Constants::PERMISSION_READ);
$share->method('getNode')
Expand Down Expand Up @@ -222,6 +226,7 @@ public function testInfoFolder(): void {
$share = $this->createMock(IShare::class);
$share->method('getPassword')
->willReturn('sharePass');
$share->method('isPasswordProtected')->willReturn(true);
$share->method('getPermissions')
->willReturn(Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE);
$share->method('getNode')
Expand Down
6 changes: 3 additions & 3 deletions lib/private/Share20/Manager.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016-2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
Expand Down Expand Up @@ -1427,8 +1427,8 @@ private function checkShare(IShare $share, int &$added = 1): void {
#[Override]
public function checkPassword(IShare $share, ?string $password): bool {

// if there is no password on the share object / passsword is null, there is nothing to check
if ($password === null || $share->getPassword() === null) {
// if the share is not password protected or the password to check is empty, there is nothing to check
if ($password === null || !$share->isPasswordProtected()) {
return false;
}

Expand Down
10 changes: 9 additions & 1 deletion lib/private/Share20/Share.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016-2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
Expand Down Expand Up @@ -507,6 +507,14 @@ public function getPassword() {
return $this->password;
}

/**
* @inheritdoc
*/
#[\Override]
public function isPasswordProtected(): bool {
return $this->password !== '' && $this->password !== null;
}

/**
* @inheritdoc
*/
Expand Down
9 changes: 8 additions & 1 deletion lib/public/Share/IShare.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016-2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
Expand Down Expand Up @@ -468,6 +468,13 @@ public function setPassword($password);
*/
public function getPassword();

/**
* Returns whether the share is password protected by any means (e.g. password or OTP)
* @return bool
* @since 35.0.0
*/
public function isPasswordProtected(): bool;

/**
* Set the password's expiration time of this share.
*
Expand Down
Loading
Loading