Compare commits

...

1 Commits

Author SHA1 Message Date
John Molakvoæ fdfa8ebef1 fix(dav): adjust password session check on legacy dav auth
Follow-up https://github.com/nextcloud/server/pull/55955/

Signed-off-by: John Molakvoæ <skjnldsv@users.noreply.github.com>
2026-04-01 14:22:21 +02:00
2 changed files with 47 additions and 16 deletions
+44 -13
View File
@@ -16,6 +16,7 @@ use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
use Sabre\DAV\Auth\Backend\AbstractBasic;
use Sabre\DAV\Exception\NotAuthenticated;
/**
* Class PublicAuth
@@ -69,22 +70,29 @@ class LegacyPublicAuth extends AbstractBasic {
if ($share->getShareType() === IShare::TYPE_LINK
|| $share->getShareType() === IShare::TYPE_EMAIL
|| $share->getShareType() === IShare::TYPE_CIRCLE) {
// Validate password if provided
if ($this->shareManager->checkPassword($share, $password)) {
return true;
} elseif ($this->session->exists(PublicAuth::DAV_AUTHENTICATED)
&& $this->session->get(PublicAuth::DAV_AUTHENTICATED) === $share->getId()) {
return true;
} else {
if (in_array('XMLHttpRequest', explode(',', $this->request->getHeader('X-Requested-With')))) {
// do not re-authenticate over ajax, use dummy auth name to prevent browser popup
http_response_code(401);
header('WWW-Authenticate: DummyBasic realm="' . $this->realm . '"');
throw new \Sabre\DAV\Exception\NotAuthenticated('Cannot authenticate over ajax calls');
// If not set, set authenticated session cookie
if (!$this->isShareInSession($share)) {
$this->addShareToSession($share);
}
$this->throttler->registerAttempt(self::BRUTEFORCE_ACTION, $this->request->getRemoteAddress());
return false;
return true;
}
// We are already authenticated for this share in the session
if ($this->isShareInSession($share)) {
return true;
}
if (in_array('XMLHttpRequest', explode(',', $this->request->getHeader('X-Requested-With')))) {
// do not re-authenticate over ajax, use dummy auth name to prevent browser popup
http_response_code(401);
header('WWW-Authenticate: DummyBasic realm="' . $this->realm . '"');
throw new NotAuthenticated('Cannot authenticate over ajax calls');
}
$this->throttler->registerAttempt(self::BRUTEFORCE_ACTION, $this->request->getRemoteAddress());
return false;
} elseif ($share->getShareType() === IShare::TYPE_REMOTE) {
return true;
} else {
@@ -95,6 +103,29 @@ class LegacyPublicAuth extends AbstractBasic {
return true;
}
private function addShareToSession(IShare $share): void {
$allowedShareIds = $this->session->get(PublicAuth::DAV_AUTHENTICATED) ?? [];
if (!is_array($allowedShareIds)) {
$allowedShareIds = [];
}
$allowedShareIds[] = $share->getId();
$this->session->set(PublicAuth::DAV_AUTHENTICATED, $allowedShareIds);
}
private function isShareInSession(IShare $share): bool {
if (!$this->session->exists(PublicAuth::DAV_AUTHENTICATED)) {
return false;
}
$allowedShareIds = $this->session->get(PublicAuth::DAV_AUTHENTICATED);
if (!is_array($allowedShareIds)) {
return false;
}
return in_array($share->getId(), $allowedShareIds);
}
public function getShare(): IShare {
assert($this->share !== null);
return $this->share;
@@ -168,7 +168,7 @@ class LegacyPublicAuthTest extends TestCase {
)->willReturn(false);
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
$this->session->method('get')->with('public_link_authenticated')->willReturn(['42']);
$result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
@@ -192,7 +192,7 @@ class LegacyPublicAuthTest extends TestCase {
)->willReturn(false);
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
$this->session->method('get')->with('public_link_authenticated')->willReturn(['43']);
$result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
@@ -217,7 +217,7 @@ class LegacyPublicAuthTest extends TestCase {
)->willReturn(false);
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
$this->session->method('get')->with('public_link_authenticated')->willReturn(['43']);
$result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);