fix(encryption): Fix user key support with basic auth

When using basic authentication the user is not logged in yet when
 KeyManager constructor gets called, so we need to delay the check for
 the loggedin user uid.

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
This commit is contained in:
Côme Chilliet 2025-11-03 17:38:36 +01:00
parent c39f56f8a1
commit 928a45c677
No known key found for this signature in database
GPG key ID: A3E2F658B28C760A
2 changed files with 14 additions and 7 deletions

View file

@ -23,7 +23,6 @@ class KeyManager {
private string $recoveryKeyId;
private string $publicShareKeyId;
private string $masterKeyId;
private ?string $keyUid;
private string $publicKeyId = 'publicKey';
private string $privateKeyId = 'privateKey';
private string $shareKeyId = 'shareKey';
@ -33,7 +32,7 @@ class KeyManager {
private IStorage $keyStorage,
private Crypt $crypt,
private IConfig $config,
IUserSession $userSession,
private IUserSession $userSession,
private Session $session,
private LoggerInterface $logger,
private Util $util,
@ -61,8 +60,6 @@ class KeyManager {
$this->masterKeyId = 'master_' . substr(md5((string)time()), 0, 8);
$this->config->setAppValue('encryption', 'masterKeyId', $this->masterKeyId);
}
$this->keyUid = $userSession->isLoggedIn() ? $userSession->getUser()?->getUID() : null;
}
/**
@ -352,7 +349,7 @@ class KeyManager {
* @param ?bool $useLegacyFileKey null means try both
*/
public function getFileKey(string $path, ?bool $useLegacyFileKey, bool $useDecryptAll = false): string {
$publicAccess = ($this->keyUid === null);
$publicAccess = !$this->userSession->isLoggedIn();
$encryptedFileKey = '';
if ($useLegacyFileKey ?? true) {
$encryptedFileKey = $this->keyStorage->getFileKey($path, $this->fileKeyId, Encryption::ID);
@ -381,7 +378,7 @@ class KeyManager {
$privateKey = $this->keyStorage->getSystemUserKey($this->publicShareKeyId . '.' . $this->privateKeyId, Encryption::ID);
$privateKey = $this->crypt->decryptPrivateKey($privateKey);
} else {
$uid = $this->keyUid;
$uid = $this->userSession->getUser()?->getUID();
$shareKey = $this->getShareKey($path, $uid);
$privateKey = $this->session->getPrivateKey();
}

View file

@ -22,6 +22,7 @@ use OCP\Encryption\Keys\IStorage;
use OCP\Files\Cache\ICache;
use OCP\Files\Storage\IStorage as FilesIStorage;
use OCP\IConfig;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
@ -356,6 +357,9 @@ class KeyManagerTest extends TestCase {
public function testGetFileKey(?string $uid, bool $isMasterKeyEnabled, string $privateKey, string $encryptedFileKey, string $expected): void {
$path = '/foo.txt';
$this->userMock->expects(self::once())
->method('isLoggedIn')
->willReturn($uid !== null);
if ($isMasterKeyEnabled) {
$expectedUid = 'masterKeyId';
$this->configMock->expects($this->any())->method('getSystemValue')->with('secret')
@ -364,10 +368,16 @@ class KeyManagerTest extends TestCase {
$expectedUid = 'systemKeyId';
} else {
$expectedUid = $uid;
$userObjectMock = $this->createMock(IUser::class);
$userObjectMock->expects(self::once())
->method('getUID')
->willReturn($uid);
$this->userMock->expects(self::once())
->method('getUser')
->willReturn($userObjectMock);
}
$this->invokePrivate($this->instance, 'masterKeyId', ['masterKeyId']);
$this->invokePrivate($this->instance, 'keyUid', [$uid]);
$this->keyStorageMock->expects($this->exactly(2))
->method('getFileKey')