mirror of
https://github.com/nextcloud/server.git
synced 2026-03-07 16:01:08 -05:00
fix(authtoken): Store only one hash for authtokens with the current password per user
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
parent
dd891e7e81
commit
580feecdbf
2 changed files with 50 additions and 1 deletions
|
|
@ -229,4 +229,31 @@ class PublicKeyTokenMapper extends QBMapper {
|
|||
);
|
||||
$update->executeStatement();
|
||||
}
|
||||
|
||||
public function updateHashesForUser(string $userId, string $passwordHash): void {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$update = $qb->update($this->getTableName())
|
||||
->set('password_hash', $qb->createNamedParameter($passwordHash))
|
||||
->where(
|
||||
$qb->expr()->eq('uid', $qb->createNamedParameter($userId))
|
||||
);
|
||||
$update->executeStatement();
|
||||
}
|
||||
|
||||
public function getFirstTokenForUser(string $userId): ?PublicKeyToken {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($qb->expr()->eq('uid', $qb->createNamedParameter($userId)))
|
||||
->setMaxResults(1)
|
||||
->orderBy('id');
|
||||
$result = $qb->executeQuery();
|
||||
|
||||
$data = $result->fetch();
|
||||
$result->closeCursor();
|
||||
if ($data === false) {
|
||||
return null;
|
||||
}
|
||||
return PublicKeyToken::fromRow($data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,9 +102,23 @@ class PublicKeyTokenProvider implements IProvider {
|
|||
$name = mb_substr($name, 0, 120) . '…';
|
||||
}
|
||||
|
||||
// We need to check against one old token to see if there is a password
|
||||
// hash that we can reuse for detecting outdated passwords
|
||||
$randomOldToken = $this->mapper->getFirstTokenForUser($uid);
|
||||
$oldTokenMatches = $randomOldToken && $this->hasher->verify(sha1($password) . $password, $randomOldToken->getPasswordHash());
|
||||
|
||||
$dbToken = $this->newToken($token, $uid, $loginName, $password, $name, $type, $remember);
|
||||
|
||||
if ($oldTokenMatches) {
|
||||
$dbToken->setPasswordHash($randomOldToken->getPasswordHash());
|
||||
}
|
||||
|
||||
$this->mapper->insert($dbToken);
|
||||
|
||||
if (!$oldTokenMatches && $password !== null) {
|
||||
$this->updatePasswords($uid, $password);
|
||||
}
|
||||
|
||||
// Add the token to the cache
|
||||
$this->cache[$dbToken->getToken()] = $dbToken;
|
||||
|
||||
|
|
@ -289,10 +303,11 @@ class PublicKeyTokenProvider implements IProvider {
|
|||
|
||||
// Update the password for all tokens
|
||||
$tokens = $this->mapper->getTokenByUser($token->getUID());
|
||||
$hashedPassword = $this->hashPassword($password);
|
||||
foreach ($tokens as $t) {
|
||||
$publicKey = $t->getPublicKey();
|
||||
$t->setPassword($this->encryptPassword($password, $publicKey));
|
||||
$t->setPasswordHash($this->hashPassword($password));
|
||||
$t->setPasswordHash($hashedPassword);
|
||||
$this->updateToken($t);
|
||||
}
|
||||
}
|
||||
|
|
@ -481,6 +496,13 @@ class PublicKeyTokenProvider implements IProvider {
|
|||
$this->updateToken($t);
|
||||
}
|
||||
}
|
||||
|
||||
// If password hashes are different we update them all to be equal so
|
||||
// that the next execution only needs to verify once
|
||||
if (count($hashNeedsUpdate) > 1) {
|
||||
$newPasswordHash = $this->hashPassword($password);
|
||||
$this->mapper->updateHashesForUser($uid, $newPasswordHash);
|
||||
}
|
||||
}
|
||||
|
||||
private function logOpensslError() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue