mirror of
https://github.com/nuxsmin/sysPass.git
synced 2026-03-03 07:04:07 +01:00
* [ADD] Unit testing. Work in progress
* [MOD] Code refactoring
This commit is contained in:
@@ -182,4 +182,11 @@ interface ContextInterface
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTrasientKey(string $key, $default = null);
|
||||
|
||||
/**
|
||||
* Sets a temporary master password
|
||||
*
|
||||
* @param string $password
|
||||
*/
|
||||
public function setTemporaryMasterPass(string $password);
|
||||
}
|
||||
@@ -268,11 +268,11 @@ class SessionContext extends ContextBase
|
||||
}
|
||||
|
||||
/**
|
||||
* Establece la clave maestra temporal
|
||||
* Sets a temporary master password
|
||||
*
|
||||
* @param string $password
|
||||
*/
|
||||
public function setTemporaryMasterPass($password)
|
||||
public function setTemporaryMasterPass(string $password)
|
||||
{
|
||||
$this->setContextKey('tempmasterpass', $password);
|
||||
}
|
||||
|
||||
@@ -257,4 +257,16 @@ class StatelessContext extends ContextBase
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a temporary master password
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @throws ContextException
|
||||
*/
|
||||
public function setTemporaryMasterPass(string $password)
|
||||
{
|
||||
$this->setTrasientKey('_tempmasterpass', $password);
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,7 @@ use Defuse\Crypto\Exception\CryptoException;
|
||||
use SP\Account\AccountRequest;
|
||||
use SP\Account\AccountSearchFilter;
|
||||
use SP\Account\AccountUtil;
|
||||
use SP\Core\Context\SessionContext;
|
||||
use SP\Core\Crypt\Crypt;
|
||||
use SP\Core\Crypt\Session as CryptSession;
|
||||
use SP\Core\Exceptions\QueryException;
|
||||
use SP\Core\Exceptions\SPException;
|
||||
use SP\DataModel\AccountData;
|
||||
@@ -220,11 +218,7 @@ class AccountService extends Service implements AccountServiceInterface
|
||||
{
|
||||
try {
|
||||
if ($masterPass === null) {
|
||||
if ($this->context instanceof SessionContext) {
|
||||
$masterPass = CryptSession::getSessionKey($this->context);
|
||||
} else {
|
||||
$masterPass = $this->context->getTrasientKey('_masterpass');
|
||||
}
|
||||
$masterPass = $this->getMasterKeyFromContext();
|
||||
}
|
||||
|
||||
if (empty($masterPass)) {
|
||||
|
||||
@@ -393,10 +393,11 @@ class ApiService extends Service
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function getMasterPass()
|
||||
{
|
||||
return $this->context->getTrasientKey('_masterpass');
|
||||
return $this->getMasterKeyFromContext();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace SP\Services\AuthToken;
|
||||
use SP\Core\Acl\Acl;
|
||||
use SP\Core\Acl\ActionsInterface;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\Core\Crypt\Session as CryptSession;
|
||||
use SP\Core\Crypt\Vault;
|
||||
use SP\Core\Exceptions\SPException;
|
||||
use SP\DataModel\AuthTokenData;
|
||||
@@ -217,17 +216,12 @@ class AuthTokenService extends Service
|
||||
* @param string $key
|
||||
*
|
||||
* @return Vault
|
||||
* @throws ServiceException
|
||||
* @throws \Defuse\Crypto\Exception\CryptoException
|
||||
*/
|
||||
private function getSecureData($token, $key)
|
||||
{
|
||||
if (($mKey = $this->context->getTrasientKey('_masterpass')) !== null) {
|
||||
return (new Vault())
|
||||
->saveData($mKey, $key . $token);
|
||||
}
|
||||
|
||||
return (new Vault())
|
||||
->saveData(CryptSession::getSessionKey($this->context), $key . $token);
|
||||
return (new Vault())->saveData($this->getMasterKeyFromContext(), $key . $token);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace SP\Services\Crypt;
|
||||
|
||||
use SP\Core\Crypt\Crypt;
|
||||
use SP\Core\Crypt\Hash;
|
||||
use SP\Core\Crypt\Session;
|
||||
use SP\Core\Events\Event;
|
||||
use SP\Core\Events\EventMessage;
|
||||
use SP\Core\Messages\MailMessage;
|
||||
@@ -86,7 +85,7 @@ class TemporaryMasterPassService extends Service
|
||||
$secureKey = Crypt::makeSecuredKey($randomKey);
|
||||
|
||||
$configRequest = new ConfigRequest();
|
||||
$configRequest->add(self::PARAM_PASS, Crypt::encrypt(Session::getSessionKey($this->context), $secureKey, $randomKey));
|
||||
$configRequest->add(self::PARAM_PASS, Crypt::encrypt($this->getMasterKeyFromContext(), $secureKey, $randomKey));
|
||||
$configRequest->add(self::PARAM_KEY, $secureKey);
|
||||
$configRequest->add(self::PARAM_HASH, Hash::hashKey($randomKey));
|
||||
$configRequest->add(self::PARAM_TIME, time());
|
||||
@@ -123,9 +122,7 @@ class TemporaryMasterPassService extends Service
|
||||
{
|
||||
try {
|
||||
$isValid = false;
|
||||
$passTime = (int)$this->configService->getByParam(self::PARAM_TIME);
|
||||
$passMaxTime = (int)$this->configService->getByParam(self::PARAM_MAX_TIME);
|
||||
$attempts = (int)$this->configService->getByParam(self::PARAM_ATTEMPTS);
|
||||
|
||||
// Comprobar si el tiempo de validez o los intentos se han superado
|
||||
if ($passMaxTime === 0) {
|
||||
@@ -136,6 +133,9 @@ class TemporaryMasterPassService extends Service
|
||||
return $isValid;
|
||||
}
|
||||
|
||||
$passTime = (int)$this->configService->getByParam(self::PARAM_TIME);
|
||||
$attempts = (int)$this->configService->getByParam(self::PARAM_ATTEMPTS);
|
||||
|
||||
if ((!empty($passTime) && time() > $passMaxTime)
|
||||
|| $attempts >= self::MAX_ATTEMPTS
|
||||
) {
|
||||
@@ -197,7 +197,8 @@ class TemporaryMasterPassService extends Service
|
||||
return $value->email;
|
||||
}, $this->dic->get(UserService::class)->getUserEmailForGroup($groupId));
|
||||
|
||||
$this->dic->get(MailService::class)->sendBatch($mailMessage->getTitle(), $emails, $mailMessage);
|
||||
$this->dic->get(MailService::class)
|
||||
->sendBatch($mailMessage->getTitle(), $emails, $mailMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,6 +56,7 @@ class MailService extends Service
|
||||
*
|
||||
* @param MailParams $mailParams
|
||||
* @param string $to
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function check(MailParams $mailParams, $to)
|
||||
@@ -104,6 +105,7 @@ class MailService extends Service
|
||||
|
||||
/**
|
||||
* @param $action
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getSubjectForAction($action)
|
||||
@@ -115,6 +117,7 @@ class MailService extends Service
|
||||
* @param string $subject
|
||||
* @param string $to
|
||||
* @param MailMessage $mailMessage
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function send($subject, $to, MailMessage $mailMessage)
|
||||
@@ -134,7 +137,7 @@ class MailService extends Service
|
||||
{
|
||||
try {
|
||||
$this->mailer->send();
|
||||
|
||||
|
||||
$this->eventDispatcher->notifyEvent('send.mail',
|
||||
new Event($this, EventMessage::factory()
|
||||
->addDescription(__u('Correo enviado'))
|
||||
@@ -155,6 +158,7 @@ class MailService extends Service
|
||||
* @param string $subject
|
||||
* @param array $to
|
||||
* @param MailMessage $mailMessage
|
||||
*
|
||||
* @throws ServiceException
|
||||
*/
|
||||
public function sendBatch($subject, array $to, MailMessage $mailMessage)
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
|
||||
namespace SP\Services;
|
||||
|
||||
use Defuse\Crypto\Exception\CryptoException;
|
||||
use DI\Container;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use SP\Config\Config;
|
||||
use SP\Core\Context\ContextInterface;
|
||||
use SP\Core\Context\SessionContext;
|
||||
use SP\Core\Crypt\Session;
|
||||
use SP\Core\Events\Event;
|
||||
use SP\Core\Events\EventDispatcher;
|
||||
use SP\Core\Events\EventMessage;
|
||||
@@ -115,4 +118,29 @@ abstract class Service
|
||||
throw new ServiceException(__u('No es posible iniciar una transacción'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws ServiceException
|
||||
*/
|
||||
protected final function getMasterKeyFromContext(): String
|
||||
{
|
||||
try {
|
||||
if ($this->context instanceof SessionContext) {
|
||||
$key = Session::getSessionKey($this->context);
|
||||
} else {
|
||||
$key = $this->context->getTrasientKey('_masterpass');
|
||||
}
|
||||
|
||||
if (empty($key)) {
|
||||
throw new ServiceException(__u('Error ol obtener la clave maestra del contexto'));
|
||||
}
|
||||
|
||||
return $key;
|
||||
} catch (CryptoException $e) {
|
||||
debugLog($e->getMessage());
|
||||
|
||||
throw new ServiceException(__u('Error ol obtener la clave maestra del contexto'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,6 @@ class MasterPassServiceTest extends DatabaseTestCase
|
||||
self::$service = $dic->get(MasterPassService::class);
|
||||
self::$accountService = $dic->get(AccountService::class);
|
||||
self::$customFieldService = $dic->get(CustomFieldService::class);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
127
tests/Services/Crypt/TemporaryMasterPassServiceTest.php
Normal file
127
tests/Services/Crypt/TemporaryMasterPassServiceTest.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* sysPass
|
||||
*
|
||||
* @author nuxsmin
|
||||
* @link https://syspass.org
|
||||
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
|
||||
*
|
||||
* This file is part of sysPass.
|
||||
*
|
||||
* sysPass is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* sysPass is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace SP\Tests\Services\Crypt;
|
||||
|
||||
use Defuse\Crypto\Exception\CryptoException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use SP\Core\Context\ContextInterface;
|
||||
use SP\Services\Crypt\TemporaryMasterPassService;
|
||||
use function SP\Tests\setupContext;
|
||||
|
||||
/**
|
||||
* Class TemporaryMasterPassServiceTest
|
||||
*
|
||||
* @package SP\Tests\Services\Crypt
|
||||
*/
|
||||
class TemporaryMasterPassServiceTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ContextInterface
|
||||
*/
|
||||
private $context;
|
||||
/**
|
||||
* @var TemporaryMasterPassService
|
||||
*/
|
||||
private $service;
|
||||
|
||||
/**
|
||||
* @throws \DI\NotFoundException
|
||||
* @throws \SP\Core\Context\ContextException
|
||||
* @throws \DI\DependencyException
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$dic = setupContext();
|
||||
|
||||
// Inicializar el repositorio
|
||||
$this->service = $dic->get(TemporaryMasterPassService::class);
|
||||
|
||||
$this->context = $dic->get(ContextInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \SP\Services\ServiceException
|
||||
*/
|
||||
public function testCreate()
|
||||
{
|
||||
$key = $this->service->create();
|
||||
|
||||
$this->assertNotEmpty($key);
|
||||
$this->assertEquals($this->context->getTrasientKey('_tempmasterpass'), $key);
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreate
|
||||
*
|
||||
* @param $key
|
||||
*
|
||||
* @throws \Defuse\Crypto\Exception\CryptoException
|
||||
* @throws \SP\Repositories\NoSuchItemException
|
||||
* @throws \SP\Services\ServiceException
|
||||
*/
|
||||
public function testGetUsingKey($key)
|
||||
{
|
||||
$this->assertEquals('12345678900', $this->service->getUsingKey($key));
|
||||
|
||||
$this->expectException(CryptoException::class);
|
||||
|
||||
$this->service->getUsingKey('test123');
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testCreate
|
||||
*
|
||||
* @param $key
|
||||
*
|
||||
* @throws \SP\Services\ServiceException
|
||||
*/
|
||||
public function testCheckTempMasterPass($key)
|
||||
{
|
||||
$this->assertTrue($this->service->checkTempMasterPass($key));
|
||||
|
||||
for ($i = 1; $i <= 50; $i++) {
|
||||
$this->assertFalse($this->service->checkTempMasterPass('test123'));
|
||||
}
|
||||
|
||||
// The 50's attempt should fails
|
||||
$this->assertFalse($this->service->checkTempMasterPass($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \SP\Services\ServiceException
|
||||
*/
|
||||
public function testExpiredKey()
|
||||
{
|
||||
$key = $this->service->create(10);
|
||||
|
||||
print 'Sleeping for 12 seconds';
|
||||
|
||||
sleep(12);
|
||||
|
||||
$this->assertFalse($this->service->checkTempMasterPass($key));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user