This commit is contained in:
Yuri Kuznetsov
2024-12-06 21:18:22 +02:00
parent d3f12e54eb
commit 4eff992b87
7 changed files with 64 additions and 32 deletions

View File

@@ -30,6 +30,7 @@
namespace Espo\Core\Authentication\AuthToken;
use RuntimeException;
use SensitiveParameter;
/**
* An auth token data. Used for auth token creation.
@@ -96,7 +97,7 @@ class Data
* createSecret?: ?bool,
* } $data
*/
public static function create(array $data): self
public static function create(#[SensitiveParameter] array $data): self
{
$obj = new self();

View File

@@ -39,18 +39,35 @@ class UserFinder
public function __construct(private EntityManager $entityManager)
{}
public function find(string $username, string $hash): ?User
public function find(string $username): ?User
{
return $this->entityManager
->getRDBRepositoryByClass(User::class)
->where([
'userName' => $username,
'password' => $hash,
'type!=' => [User::TYPE_API, User::TYPE_SYSTEM],
])
->findOne();
}
public function findByIdAndHash(string $username, string $id, ?string $hash): ?User
{
$where = [
'userName' => $username,
'id' => $id,
'type!=' => [User::TYPE_API, User::TYPE_SYSTEM],
];
if ($hash) {
$where['password'] = $hash;
}
return $this->entityManager
->getRDBRepositoryByClass(User::class)
->where($where)
->findOne();
}
public function findApiHmac(string $apiKey): ?User
{
return $this->entityManager

View File

@@ -55,6 +55,7 @@ use Espo\Entities\User;
use Exception;
use Laminas\Ldap\Exception\LdapException;
use Laminas\Ldap\Ldap;
use SensitiveParameter;
/**
* @noinspection PhpUnused
@@ -313,18 +314,25 @@ class LdapLogin implements Login
->findOne();
}
private function adminLogin(string $username, string $password): ?User
private function adminLogin(string $username, #[SensitiveParameter] string $password): ?User
{
$hash = $this->passwordHash->hash($password);
return $this->entityManager
$user = $this->entityManager
->getRDBRepository(User::ENTITY_TYPE)
->where([
'userName' => $username,
'password' => $hash,
'type' => [User::TYPE_ADMIN, User::TYPE_SUPER_ADMIN],
])
->findOne();
if (!$user) {
return null;
}
if (!$this->passwordHash->verify($password, $user->get('password'))) {
return null;
}
return $user;
}
/**

View File

@@ -30,6 +30,7 @@
namespace Espo\Core\Authentication\Login;
use Espo\Core\Authentication\AuthToken\AuthToken;
use SensitiveParameter;
/**
* Login data to be passed to the 'login' method.
@@ -40,8 +41,11 @@ class Data
private ?string $password;
private ?AuthToken $authToken;
public function __construct(?string $username, ?string $password, ?AuthToken $authToken = null)
{
public function __construct(
?string $username,
#[SensitiveParameter] ?string $password,
?AuthToken $authToken = null
) {
$this->username = $username;
$this->password = $password;
$this->authToken = $authToken;

View File

@@ -37,8 +37,6 @@ use Espo\Core\Authentication\Result;
use Espo\Core\Authentication\Result\FailReason;
use Espo\Core\Utils\PasswordHash;
use RuntimeException;
class Espo implements Login
{
public const NAME = 'Espo';
@@ -62,16 +60,16 @@ class Espo implements Login
return Result::fail(FailReason::NO_PASSWORD);
}
$hash = $authToken ?
$authToken->getHash() :
$this->passwordHash->hash($password);
if ($authToken) {
$user = $this->userFinder->findByIdAndHash($username, $authToken->getUserId(), $authToken->getHash());
} else {
$user = $this->userFinder->find($username);
if (!$hash) {
throw new RuntimeException("No hash.");
if ($user && !$this->passwordHash->verify($password, $user->get('password'))) {
$user = null;
}
}
$user = $this->userFinder->find($username, $hash);
if (!$user) {
return Result::fail(FailReason::WRONG_CREDENTIALS);
}

View File

@@ -29,13 +29,12 @@
namespace Espo\Core\Formula\Functions\PasswordGroup;
use Espo\Core\Formula\{
Functions\BaseFunction,
ArgumentList,
Processor,
};
use Espo\Core\Formula\ArgumentList;
use Espo\Core\Formula\Functions\BaseFunction;
use Espo\Core\Formula\Processor;
use Espo\Core\Utils\PasswordHash;
use SensitiveParameter;
class HashType extends BaseFunction
{
@@ -47,7 +46,7 @@ class HashType extends BaseFunction
$this->passwordHash = $passwordHash;
}
public function process(ArgumentList $args)
public function process(#[SensitiveParameter] ArgumentList $args)
{
if (count($args) < 1) {
$this->throwTooFewArguments();
@@ -59,8 +58,6 @@ class HashType extends BaseFunction
$this->throwBadArgumentType(1, 'string');
}
$hash = $this->passwordHash->hash($password);
return $hash;
return $this->passwordHash->hash($password);
}
}

View File

@@ -30,6 +30,7 @@
namespace Espo\Core\Utils;
use RuntimeException;
use SensitiveParameter;
class PasswordHash
{
@@ -44,19 +45,25 @@ class PasswordHash
/**
* Hash a password.
*/
public function hash(string $password, bool $useMd5 = true): string
public function hash(#[SensitiveParameter] string $password): string
{
$salt = $this->getSalt();
if ($useMd5) {
$password = md5($password);
}
$password = md5($password);
$hash = crypt($password, $salt);
return str_replace($salt, '', $hash);
}
public function verify(
#[SensitiveParameter] string $password,
#[SensitiveParameter] string $hash
): bool {
return $this->hash($password) === $hash;
}
/**
* Get a salt from the config and normalize it.
*/