Sfoglia il codice sorgente

Actually convert the token

* When getting the token
* When rotating the token

* Also store the encrypted password as base64 to avoid weird binary
stuff

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
tags/v14.0.0beta1
Roeland Jago Douma 6 anni fa
parent
commit
f168ecfa7a
Nessun account collegato all'indirizzo email del committer

+ 19
- 8
lib/private/Authentication/Token/Manager.php Vedi File

@@ -121,8 +121,19 @@ class Manager implements IProvider {
try {
return $this->publicKeyTokenProvider->getToken($tokenId);
} catch (InvalidTokenException $e) {
return $this->defaultTokenProvider->getToken($tokenId);
// No worries we try to convert it to a PublicKey Token
}

//Convert!
$token = $this->defaultTokenProvider->getToken($tokenId);

try {
$password = $this->defaultTokenProvider->getPassword($token, $tokenId);
} catch (PasswordlessTokenException $e) {
$password = null;
}

return $this->publicKeyTokenProvider->convertToken($token, $tokenId, $password);
}

/**
@@ -149,7 +160,6 @@ class Manager implements IProvider {
try {
$this->publicKeyTokenProvider->renewSessionToken($oldSessionId, $sessionId);
} catch (InvalidTokenException $e) {
//TODO: Move to new token
$this->defaultTokenProvider->renewSessionToken($oldSessionId, $sessionId);
}
}
@@ -163,7 +173,6 @@ class Manager implements IProvider {
*/
public function getPassword(IToken $savedToken, string $tokenId): string {
if ($savedToken instanceof DefaultToken) {
//TODO convert to new token type
return $this->defaultTokenProvider->getPassword($savedToken, $tokenId);
}

@@ -173,9 +182,7 @@ class Manager implements IProvider {
}

public function setPassword(IToken $token, string $tokenId, string $password) {

if ($token instanceof DefaultToken) {
//TODO conver to new token
$this->defaultTokenProvider->setPassword($token, $tokenId, $password);
}

@@ -200,10 +207,14 @@ class Manager implements IProvider {
}

public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {

if ($token instanceof DefaultToken) {
//TODO Migrate to new token
return $this->defaultTokenProvider->rotate($token, $oldTokenId, $newTokenId);
try {
$password = $this->defaultTokenProvider->getPassword($token, $oldTokenId);
} catch (PasswordlessTokenException $e) {
$password = null;
}

return $this->publicKeyTokenProvider->convertToken($token, $newTokenId, $password);
}

if ($token instanceof PublicKeyToken) {

+ 8
- 0
lib/private/Authentication/Token/PublicKeyTokenMapper.php Vedi File

@@ -159,4 +159,12 @@ class PublicKeyTokenMapper extends QBMapper {
$qb->execute();
}

public function deleteTempToken(PublicKeyToken $except) {
$qb = $this->db->getQueryBuilder();

$qb->delete('authtoken')
->where($qb->expr()->eq('type', $qb->createNamedParameter(IToken::TEMPORARY_TOKEN)))
->andWhere($qb->expr()->neq('id', $qb->createNamedParameter($except->getId())))
->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(2, IQueryBuilder::PARAM_INT)));
}
}

+ 67
- 32
lib/private/Authentication/Token/PublicKeyTokenProvider.php Vedi File

@@ -67,36 +67,7 @@ class PublicKeyTokenProvider implements IProvider {
string $name,
int $type = IToken::TEMPORARY_TOKEN,
int $remember = IToken::DO_NOT_REMEMBER): IToken {
$dbToken = new PublicKeyToken();
$dbToken->setUid($uid);
$dbToken->setLoginName($loginName);

$config = [
'digest_alg' => 'sha512',
'private_key_bits' => 2048,
];

// Generate new key
$res = openssl_pkey_new($config);
openssl_pkey_export($res, $privateKey);

// Extract the public key from $res to $pubKey
$publicKey = openssl_pkey_get_details($res);
$publicKey = $publicKey['key'];

$dbToken->setPublicKey($publicKey);
$dbToken->setPrivateKey($this->encrypt($privateKey, $token));

if (!is_null($password)) {
$dbToken->setPassword($this->encryptPassword($password, $publicKey));
}

$dbToken->setName($name);
$dbToken->setToken($this->hashToken($token));
$dbToken->setType($type);
$dbToken->setRemember($remember);
$dbToken->setLastActivity($this->time->getTime());
$dbToken->setLastCheck($this->time->getTime());
$dbToken = $this->newToken($token, $uid, $loginName, $password, $name, $type, $remember);

$this->mapper->insert($dbToken);

@@ -219,6 +190,9 @@ class PublicKeyTokenProvider implements IProvider {
throw new InvalidTokenException();
}

// When changeing passwords all temp tokens are deleted
$this->mapper->deleteTempToken($token);

// Update the password for all tokens
$tokens = $this->mapper->getTokenByUser($token->getUID());
foreach ($tokens as $t) {
@@ -226,8 +200,6 @@ class PublicKeyTokenProvider implements IProvider {
$t->setPassword($this->encryptPassword($password, $publicKey));
$this->updateToken($t);
}

//TODO: should we also do this for temp tokens?
}

public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
@@ -267,11 +239,13 @@ class PublicKeyTokenProvider implements IProvider {

private function encryptPassword(string $password, string $publicKey): string {
openssl_public_encrypt($password, $encryptedPassword, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
$encryptedPassword = base64_encode($encryptedPassword);

return $encryptedPassword;
}

private function decryptPassword(string $encryptedPassword, string $privateKey): string {
$encryptedPassword = base64_decode($encryptedPassword);
openssl_private_decrypt($encryptedPassword, $password, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);

return $password;
@@ -281,4 +255,65 @@ class PublicKeyTokenProvider implements IProvider {
$secret = $this->config->getSystemValue('secret');
return hash('sha512', $token . $secret);
}

/**
* Convert a DefaultToken to a publicKeyToken
* This will also be updated directly in the Database
*/
public function convertToken(DefaultToken $defaultToken, string $token, $password): PublicKeyToken {
$pkToken = $this->newToken(
$token,
$defaultToken->getUID(),
$defaultToken->getLoginName(),
$password,
$defaultToken->getName(),
$defaultToken->getType(),
$defaultToken->getRemember()
);

$pkToken->setId($defaultToken->getId());

return $this->mapper->update($pkToken);
}

private function newToken(string $token,
string $uid,
string $loginName,
$password,
string $name,
int $type,
int $remember): PublicKeyToken {
$dbToken = new PublicKeyToken();
$dbToken->setUid($uid);
$dbToken->setLoginName($loginName);

$config = [
'digest_alg' => 'sha512',
'private_key_bits' => 2048,
];

// Generate new key
$res = openssl_pkey_new($config);
openssl_pkey_export($res, $privateKey);

// Extract the public key from $res to $pubKey
$publicKey = openssl_pkey_get_details($res);
$publicKey = $publicKey['key'];

$dbToken->setPublicKey($publicKey);
$dbToken->setPrivateKey($this->encrypt($privateKey, $token));

if (!is_null($password)) {
$dbToken->setPassword($this->encryptPassword($password, $publicKey));
}

$dbToken->setName($name);
$dbToken->setToken($this->hashToken($token));
$dbToken->setType($type);
$dbToken->setRemember($remember);
$dbToken->setLastActivity($this->time->getTime());
$dbToken->setLastCheck($this->time->getTime());

return $dbToken;
}
}

Loading…
Annulla
Salva