diff --git a/lib/DAV/Auth/Backend/PDOBasicAuth.php b/lib/DAV/Auth/Backend/PDOBasicAuth.php index d142cbfbfd..a50d9a1c5b 100644 --- a/lib/DAV/Auth/Backend/PDOBasicAuth.php +++ b/lib/DAV/Auth/Backend/PDOBasicAuth.php @@ -95,6 +95,14 @@ public function validateUserPass($username, $password) $stmt->execute([$username]); $result = $stmt->fetchAll(); + // Email local/domain lookups should be case-insensitive. + // Keep exact-match behavior for non-email usernames to avoid changing existing semantics. + if (!count($result) && false !== strpos($username, '@')) { + $stmt = $this->pdo->prepare('SELECT '.$this->digestColumn.' FROM '.$this->tableName.' WHERE lower('.$this->uuidColumn.') = lower(?)'); + $stmt->execute([$username]); + $result = $stmt->fetchAll(); + } + if (!count($result)) { return false; } else { diff --git a/tests/Sabre/DAV/Auth/Backend/AbstractPDOBasicAuthTestCase.php b/tests/Sabre/DAV/Auth/Backend/AbstractPDOBasicAuthTestCase.php index 9ec8f06cab..df30b668af 100644 --- a/tests/Sabre/DAV/Auth/Backend/AbstractPDOBasicAuthTestCase.php +++ b/tests/Sabre/DAV/Auth/Backend/AbstractPDOBasicAuthTestCase.php @@ -24,6 +24,9 @@ public function setup(): void $this->getPDO()->query( "INSERT INTO users (username,digesta1) VALUES ('prefix_user','bcrypt\$\$2b\$12\$IwetRH4oj6.AWFGGVy8fpet7Pgp1TafspB6iq1/fiLDxfsGZfi2jS')" ); + $this->getPDO()->query( + "INSERT INTO users (username,digesta1) VALUES ('user@example.org','\$2b\$12\$IwetRH4oj6.AWFGGVy8fpet7Pgp1TafspB6iq1/fiLDxfsGZfi2jS')" + ); } public function testConstruct() @@ -144,6 +147,29 @@ public function testPrefixSuccess() ); } + public function testEmailCaseInsensitiveSuccess() + { + $request = HTTP\Sapi::createFromServerArray([ + 'REQUEST_METHOD' => 'GET', + 'REQUEST_URI' => '/', + 'PHP_AUTH_USER' => 'USER@EXAMPLE.ORG', + 'PHP_AUTH_PW' => 'password', + ]); + $response = new HTTP\Response(); + + $options = [ + 'tableName' => 'users', + 'digestColumn' => 'digesta1', + 'uuidColumn' => 'username', + ]; + $pdo = $this->getPDO(); + $backend = new PDOBasicAuth($pdo, $options); + self::assertEquals( + [true, 'principals/USER@EXAMPLE.ORG'], + $backend->check($request, $response) + ); + } + public function testRequireAuth() { $request = new HTTP\Request('GET', '/');