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 committed by backportbot[bot]
parent 554dce6bc7
commit cc397d5ca4
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')