* [ADD] New encryption schema by using Defuse/php-encryption library. WARNING: work in progress

This commit is contained in:
nuxsmin
2017-02-21 00:46:30 +01:00
parent 02a59eece2
commit 07c8a2b1f1
23 changed files with 574 additions and 440 deletions

View File

@@ -55,7 +55,7 @@ class AccountCrypt
*/
public function updateOldPass(&$currentMasterPass)
{
set_time_limit(300);
set_time_limit(0);
$accountsOk = [];
$userId = Session::getUserData()->getUserId();
@@ -87,6 +87,10 @@ class AccountCrypt
$AccountDataBase = new AccountData();
foreach ($accountsPass as $account) {
if ($LogMessage->getDetailsCounter() >= 100) {
$Log->writeLog(false, true);
}
$AccountData = clone $AccountDataBase;
$AccountData->setAccountId($account->account_id);
@@ -187,6 +191,10 @@ class AccountCrypt
$AccountDataBase = new AccountData();
foreach ($accountsPass as $account) {
if ($LogMessage->getDetailsCounter() >= 100) {
$Log->writeLog(false, true);
}
$AccountData = clone $AccountDataBase;
$AccountData->setAccountId($account->account_id);

View File

@@ -55,7 +55,7 @@ class AccountHistoryCrypt
*/
public function updateOldPass(&$currentMasterPass)
{
set_time_limit(300);
set_time_limit(0);
$accountsOk = [];
$demoEnabled = Checks::demoIsEnabled();
@@ -92,6 +92,10 @@ class AccountHistoryCrypt
$AccountDataBase->hash = Hash::hashKey($currentMasterPass);
foreach ($accountsPass as $account) {
if ($LogMessage->getDetailsCounter() >= 100) {
$Log->writeLog(false, true);
}
$AccountData = clone $AccountDataBase;
$AccountData->id = $account->acchistory_id;
@@ -200,6 +204,10 @@ class AccountHistoryCrypt
$AccountDataBase->hash = Hash::hashKey($newMasterPass);
foreach ($accountsPass as $account) {
if ($LogMessage->getDetailsCounter() >= 100) {
$Log->writeLog(false, true);
}
$AccountData = clone $AccountDataBase;
$AccountData->id = $account->acchistory_id;

View File

@@ -34,6 +34,7 @@ use SP\Core\Exceptions\SPException;
use SP\Core\Session;
use SP\Core\SessionUtil;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\Log\Log;
use SP\Mgmt\Users\User;
use SP\Mgmt\Users\UserPass;
@@ -75,7 +76,7 @@ abstract class ApiBase implements ApiInterface
*/
protected $mPass = '';
/**
* @var UserData
* @var UserLoginData
*/
protected $UserData;
/**
@@ -168,6 +169,9 @@ abstract class ApiBase implements ApiInterface
*
* @throws SPException
* @throws \SP\Core\Exceptions\InvalidClassException
* @throws \Defuse\Crypto\Exception\BadFormatException
* @throws \Defuse\Crypto\Exception\CryptoException
* @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
*/
protected function doAuth()
{
@@ -187,14 +191,11 @@ abstract class ApiBase implements ApiInterface
throw new SPException(SPException::SP_CRITICAL, __('Acceso no permitido', false));
}
$UserPass = UserPass::getItem($this->UserData);
if (!$this->UserData->isUserIsDisabled()
&& $UserPass->checkUserUpdateMPass()
&& $UserPass->loadUserMPass()
&& UserPass::loadUserMPass($this->UserData) === UserPass::MPASS_OK
) {
$this->auth = true;
$this->mPass = $UserPass->getClearUserMPass();
$this->mPass = UserPass::getClearUserMPass();
} else {
throw new SPException(SPException::SP_CRITICAL, __('Acceso no permitido', false));
}

View File

@@ -34,6 +34,7 @@ use SP\Auth\Ldap\LdapStd;
use SP\Config\Config;
use SP\Core\Exceptions\SPException;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\Util\Checks;
defined('APP_ROOT') || die();
@@ -52,17 +53,17 @@ class Auth
*/
protected $auths = [];
/**
* @var UserData
* @var UserLoginData
*/
protected $UserData;
/**
* Auth constructor.
*
* @param UserData $UserData
* @param UserLoginData $UserData
* @throws \SP\Core\Exceptions\SPException
*/
public function __construct(UserData $UserData)
public function __construct(UserLoginData $UserData)
{
$this->UserData = $UserData;
@@ -146,6 +147,8 @@ class Auth
* se ejecuta el proceso para actualizar la clave.
*
* @return DatabaseAuthData
* @throws \phpmailer\phpmailerException
* @throws \SP\Core\Exceptions\SPException
*/
public function authDatabase()
{

View File

@@ -24,7 +24,7 @@
namespace SP\Auth;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
/**
* Interface AuthInterface
@@ -35,8 +35,8 @@ interface AuthInterface
/**
* Autentificar al usuario
*
* @param UserData $UserData Datos del usuario
* @param UserLoginData $UserData Datos del usuario
* @return mixed|AuthDataBase
*/
public function authenticate(UserData $UserData);
public function authenticate(UserLoginData $UserData);
}

View File

@@ -25,7 +25,7 @@
namespace SP\Auth\Browser;
use SP\Auth\AuthInterface;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
/**
* Class Browser
@@ -39,13 +39,13 @@ class Browser implements AuthInterface
/**
* Autentificar al usuario
*
* @param UserData $UserData Datos del usuario
* @param UserLoginData $UserData Datos del usuario
* @return BrowserAuthData
*/
public function authenticate(UserData $UserData)
public function authenticate(UserLoginData $UserData)
{
$AuthData = new BrowserAuthData();
$AuthData->setAuthenticated($this->checkServerAuthUser($UserData->getUserLogin()));
$AuthData->setAuthenticated($this->checkServerAuthUser($UserData->getLogin()));
return $AuthData;
}

View File

@@ -27,9 +27,10 @@ namespace SP\Auth\Database;
use SP\Auth\AuthInterface;
use SP\Core\Crypt\Hash;
use SP\Core\Exceptions\SPException;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\DataModel\UserPassData;
use SP\Log\Log;
use SP\Mgmt\Users\User;
use SP\Mgmt\Users\UserMigrate;
use SP\Storage\DB;
use SP\Storage\QueryData;
@@ -44,19 +45,19 @@ use SP\Storage\QueryData;
class Database implements AuthInterface
{
/**
* @var UserData $UserData
* @var UserLoginData $UserData
*/
protected $UserData;
/**
* Autentificar al usuario
*
* @param UserData $UserData Datos del usuario
* @param UserLoginData $UserData Datos del usuario
* @return DatabaseAuthData
* @throws \SP\Core\Exceptions\SPException
* @throws \phpmailer\phpmailerException
*/
public function authenticate(UserData $UserData)
public function authenticate(UserLoginData $UserData)
{
$this->UserData = $UserData;
@@ -78,37 +79,23 @@ class Database implements AuthInterface
*/
protected function authUser()
{
if (UserMigrate::checkUserIsMigrate($this->UserData->getUserLogin())) {
try {
UserMigrate::migrateUserPass($this->UserData->getUserLogin(), $this->UserData->getUserPass());
} catch (SPException $e) {
$Log = new Log();
$LogMessage = $Log->getLogMessage();
$LogMessage->setAction(__FUNCTION__);
$LogMessage->addDescription($e->getMessage());
$LogMessage->addDetails(__('Login', false), $this->UserData->getUserLogin());
$Log->writeLog();
try {
User::getItem($this->UserData)->getByLogin($this->UserData->getLogin());
if ($this->UserData->isUserIsMigrate() && !UserMigrate::migrateUserPass($this->UserData)) {
return false;
}
return Hash::checkHashKey($this->UserData->getLoginPass(), $this->UserData->getUserPass());
} catch (SPException $e) {
$Log = new Log();
$LogMessage = $Log->getLogMessage();
$LogMessage->setAction(__FUNCTION__);
$LogMessage->addDescription($e->getMessage());
$LogMessage->addDetails(__('Login', false), $this->UserData->getLogin());
$Log->writeLog();
return false;
}
$query = /** @lang SQL */
'SELECT user_pass, user_hashSalt
FROM usrData
WHERE user_login = ?
AND user_isMigrate = 0 LIMIT 1';
$Data = new QueryData();
$Data->setMapClassName(UserPassData::class);
$Data->setQuery($query);
$Data->addParam($this->UserData->getUserLogin());
/** @var UserPassData $queryRes */
$queryRes = DB::getResults($Data);
return $queryRes !== false
&& $Data->getQueryNumRows() === 1
&& Hash::checkHashKey($this->UserData->getUserPass(), $queryRes->getUserPass());
}
}

View File

@@ -28,7 +28,7 @@ use SP\Auth\AuthInterface;
use SP\Config\Config;
use SP\Core\Exceptions\SPException;
use SP\Core\Messages\LogMessage;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\Log\Log;
/**
@@ -405,22 +405,22 @@ abstract class LdapBase implements LdapInterface, AuthInterface
/**
* Autentificar al usuario
*
* @param UserData $UserData Datos del usuario
* @param UserLoginData $UserData Datos del usuario
* @return bool
*/
public function authenticate(UserData $UserData)
public function authenticate(UserLoginData $UserData)
{
if (!$this->checkParams()) {
return false;
}
try {
$this->setUserLogin($UserData->getUserLogin());
$this->setUserLogin($UserData->getLogin());
$this->connect();
$this->bind();
$this->getAttributes();
$this->bind($this->LdapAuthData->getDn(), $UserData->getUserPass());
$this->bind($this->LdapAuthData->getDn(), $UserData->getLoginPass());
} catch (SPException $e) {
return false;
}
@@ -511,7 +511,7 @@ abstract class LdapBase implements LdapInterface, AuthInterface
}
}
if (!empty($res["fullname"])) {
if (!empty($res['fullname'])) {
$this->LdapAuthData->setName($res['fullname']);
} else {
$this->LdapAuthData->setName($res['name'] . ' ' . $res['sn']);

View File

@@ -281,7 +281,7 @@ class AccountController extends ControllerBase implements ActionsInterface
if (!Acl::checkUserAccess($this->getAction())) {
$this->showError(self::ERR_PAGE_NO_PERMISSION);
return false;
} elseif (!UserPass::getItem($this->UserData)->checkUserUpdateMPass()) {
} elseif (!UserPass::checkUserUpdateMPass($this->UserData->getUserId())) {
$this->showError(self::ERR_UPDATE_MPASS);
return false;
} elseif ($this->id > 0) {

View File

@@ -482,7 +482,7 @@ class ConfigActionController implements ItemControllerInterface
$confirmPassChange = Request::analyze('confirmPassChange', 0, false, 1);
$noAccountPassChange = Request::analyze('chkNoAccountChange', 0, false, 1);
if (!UserPass::getItem(Session::getUserData())->checkUserUpdateMPass()) {
if (!UserPass::checkUserUpdateMPass(Session::getUserData()->getUserId())) {
$this->JsonResponse->setDescription(__('Clave maestra actualizada', false));
$this->JsonResponse->addMessage(__('Reinicie la sesión para cambiarla', false));
$this->JsonResponse->setStatus(100);

View File

@@ -508,12 +508,9 @@ class ItemShowController extends ControllerBase implements ActionsInterface, Ite
$AccountAcl = new AccountAcl($Account, ActionsInterface::ACTION_ACC_VIEW_PASS);
$Acl = $AccountAcl->getAcl();
$UserPass = new UserPass(new UserPassData());
$UserPass->getItemData()->setUserId(Session::getUserData()->getUserId());
if (!$Acl->isShowViewPass()) {
throw new ItemException(__('No tiene permisos para acceder a esta cuenta', false));
} elseif (!$UserPass->checkUserUpdateMPass()) {
} elseif (!UserPass::checkUserUpdateMPass(Session::getUserData()->getUserId())) {
throw new ItemException(__('Clave maestra actualizada', false) . '<br>' . __('Reinicie la sesión para cambiarla', false));
}

View File

@@ -2,8 +2,8 @@
/**
* sysPass
*
* @author nuxsmin
* @link http://syspass.org
* @author nuxsmin
* @link http://syspass.org
* @copyright 2012-2017, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -41,14 +41,13 @@ use SP\Core\Language;
use SP\Core\Messages\LogMessage;
use SP\Core\Session;
use SP\Core\SessionUtil;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\DataModel\UserPassRecoverData;
use SP\Http\JsonResponse;
use SP\Http\Request;
use SP\Log\Log;
use SP\Mgmt\Groups\Group;
use SP\Mgmt\Profiles\Profile;
use SP\Mgmt\Users\User;
use SP\Mgmt\Users\UserLdap;
use SP\Mgmt\Users\UserPass;
use SP\Mgmt\Users\UserPassRecover;
@@ -76,7 +75,7 @@ class LoginController
*/
protected $jsonResponse;
/**
* @var UserData
* @var UserLoginData
*/
protected $UserData;
/**
@@ -90,7 +89,7 @@ class LoginController
public function __construct()
{
$this->jsonResponse = new JsonResponse();
$this->UserData = new UserData();
$this->UserData = new UserLoginData();
$this->LogMessage = new LogMessage();
$this->LogMessage->setAction(__('Inicio sesión', false));
}
@@ -112,8 +111,8 @@ class LoginController
Json::returnJson($this->jsonResponse);
}
$this->UserData->setUserLogin($userLogin);
$this->UserData->setUserPass($userPass);
$this->UserData->setLogin($userLogin);
$this->UserData->setLoginPass($userPass);
$Log = new Log($this->LogMessage);
@@ -134,9 +133,9 @@ class LoginController
throw new AuthException(SPException::SP_INFO, __('Login incorrecto', false), '', self::STATUS_INVALID_LOGIN);
}
$this->getUserData($userPass);
$this->checkUserDisabled();
$this->checkPasswordChange();
$this->getUserData();
$this->checkUser();
$this->loadMasterPass();
$this->setUserSession();
$this->loadUserPreferences();
} catch (SPException $e) {
@@ -166,17 +165,14 @@ class LoginController
/**
* Obtener los datos del usuario
*
* @param $userPass
* @throws SPException
* @throws \SP\Core\Exceptions\InvalidClassException
* @throws \SP\Core\Exceptions\AuthException
* @throws \InvalidArgumentException
*/
protected function getUserData($userPass)
protected function getUserData()
{
try {
$this->UserData = User::getItem($this->UserData)->getByLogin($this->UserData->getUserLogin());
$this->UserData->setUserPass($userPass);
$this->UserData->setUserPreferences(UserPreferences::getItem()->getById($this->UserData->getUserId()));
} catch (SPException $e) {
$this->LogMessage->addDescription(__('Error al obtener los datos del usuario de la BBDD', false));
@@ -186,23 +182,141 @@ class LoginController
}
/**
* omprobar si el usuario está deshabilitado
* Comprobar estado del usuario
*
* @throws \SP\Core\Exceptions\SPException
*/
protected function checkUserDisabled()
protected function checkUser()
{
// Comprobar si el usuario está deshabilitado
if ($this->UserData->isUserIsDisabled()) {
$this->LogMessage->addDescription(__('Usuario deshabilitado', false));
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getUserLogin());
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getLogin());
throw new AuthException(SPException::SP_INFO, __('Usuario deshabilitado', false), '', self::STATUS_USER_DISABLED);
} elseif ($this->UserData->isUserIsChangePass()) {
$hash = Util::generateRandomBytes();
$UserPassRecoverData = new UserPassRecoverData();
$UserPassRecoverData->setUserpassrUserId($this->UserData->getUserId());
$UserPassRecoverData->setUserpassrHash($hash);
UserPassRecover::getItem($UserPassRecoverData)->add();
$data = ['url' => Init::$WEBURI . '/index.php?a=passreset&h=' . $hash . '&t=' . time() . '&f=1'];
$this->jsonResponse->setData($data);
$this->jsonResponse->setStatus(0);
Json::returnJson($this->jsonResponse);
}
return false;
}
/**
* Cargar la clave maestra o solicitarla
*
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Core\Exceptions\AuthException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
protected function loadMasterPass()
{
$masterPass = Request::analyzeEncrypted('mpass');
$oldPass = Request::analyzeEncrypted('oldpass');
try {
if ($masterPass) {
if (CryptMasterPass::checkTempMasterPass($masterPass)) {
$this->LogMessage->addDescription(__('Usando clave temporal', false));
$masterPass = CryptMasterPass::getTempMasterPass($masterPass);
}
if (!UserPass::updateUserMPass($masterPass, $this->UserData)) {
$this->LogMessage->addDescription(__('Clave maestra incorrecta', false));
throw new AuthException(SPException::SP_INFO, __('Clave maestra incorrecta', false), '', self::STATUS_INVALID_MASTER_PASS);
} else {
CryptSession::saveSessionKey(UserPass::getClearUserMPass());
$this->LogMessage->addDescription(__('Clave maestra actualizada', false));
}
} else if ($oldPass) {
if (!UserPass::updateMasterPassFromOldPass($oldPass, $this->UserData)) {
$this->LogMessage->addDescription(__('Clave maestra incorrecta', false));
throw new AuthException(SPException::SP_INFO, __('Clave maestra incorrecta', false), '', self::STATUS_INVALID_MASTER_PASS);
} else {
CryptSession::saveSessionKey(UserPass::getClearUserMPass());
$this->LogMessage->addDescription(__('Clave maestra actualizada', false));
}
} else {
switch (UserPass::loadUserMPass($this->UserData)) {
case UserPass::MPASS_CHECKOLD:
throw new AuthException(SPException::SP_INFO, __('Es necesaria su clave anterior', false), '', self::STATUS_NEED_OLD_PASS);
break;
case UserPass::MPASS_NOTSET:
case UserPass::MPASS_CHANGED:
case UserPass::MPASS_WRONG:
throw new AuthException(SPException::SP_INFO, __('La clave maestra no ha sido guardada o es incorrecta', false), '', self::STATUS_INVALID_MASTER_PASS);
break;
}
}
} catch (CryptoException $e) {
$this->LogMessage->addDescription(__('Error interno', false));
throw new AuthException(SPException::SP_INFO, $this->LogMessage->getDescription(), $e->getMessage(), self::STATUS_INTERNAL_ERROR);
}
}
/**
* Cargar la sesión del usuario
*
* @throws \SP\Core\Exceptions\SPException
* @throws \InvalidArgumentException
* @throws \SP\Core\Exceptions\AuthException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
protected function setUserSession()
{
// Obtenemos la clave maestra del usuario
if (UserPass::getClearUserMPass() !== '') {
// Actualizar el último login del usuario
UserUtil::setUserLastLogin($this->UserData->getUserId());
// Cargar las variables de sesión del usuario
SessionUtil::loadUserSession($this->UserData);
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getLogin());
$this->LogMessage->addDetails(__('Perfil', false), Profile::getItem()->getById($this->UserData->getUserProfileId())->getUserprofileName());
$this->LogMessage->addDetails(__('Grupo', false), Group::getItem()->getById($this->UserData->getUserGroupId())->getUsergroupName());
} else {
$this->LogMessage->addDescription(__('Error al obtener la clave maestra del usuario', false));
throw new AuthException(SPException::SP_ERROR, __('Error interno', false), '', self::STATUS_INTERNAL_ERROR);
}
}
/**
* Cargar las preferencias del usuario y comprobar si usa 2FA
*
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Core\Exceptions\InvalidClassException
*/
protected function loadUserPreferences()
{
Language::setLanguage(true);
DiFactory::getTheme()->initTheme(true);
Session::setUserPreferences($this->UserData->getUserPreferences());
Session::setSessionType(Session::SESSION_INTERACTIVE);
Session::setAuthCompleted(true);
DiFactory::getEventDispatcher()->notifyEvent('login.preferences', $this);
}
/**
* Comprobar si se ha forzado un cambio de clave
*
@@ -230,116 +344,6 @@ class LoginController
return false;
}
/**
* Cargar la sesión del usuario
*
* @throws \SP\Core\Exceptions\SPException
* @throws \InvalidArgumentException
* @throws \SP\Core\Exceptions\AuthException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
protected function setUserSession()
{
$UserPass = $this->loadMasterPass();
// Obtenemos la clave maestra del usuario
if ($UserPass->getClearUserMPass() !== '') {
// Actualizar el último login del usuario
UserUtil::setUserLastLogin($this->UserData->getUserId());
// Cargar las variables de sesión del usuario
SessionUtil::loadUserSession($this->UserData);
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getUserLogin());
$this->LogMessage->addDetails(__('Perfil', false), Profile::getItem()->getById($this->UserData->getUserProfileId())->getUserprofileName());
$this->LogMessage->addDetails(__('Grupo', false), Group::getItem()->getById($this->UserData->getUserGroupId())->getUsergroupName());
} else {
$this->LogMessage->addDescription(__('Error al obtener la clave maestra del usuario', false));
throw new AuthException(SPException::SP_ERROR, __('Error interno', false), '', self::STATUS_INTERNAL_ERROR);
}
}
/**
* Cargar la clave maestra o solicitarla
*
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Core\Exceptions\AuthException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
protected function loadMasterPass()
{
$masterPass = Request::analyzeEncrypted('mpass');
$oldPass = Request::analyzeEncrypted('oldpass');
$UserPass = UserPass::getItem($this->UserData);
try {
if ($masterPass) {
if (CryptMasterPass::checkTempMasterPass($masterPass)) {
$this->LogMessage->addDescription(__('Usando clave temporal', false));
$masterPass = CryptMasterPass::getTempMasterPass($masterPass);
}
if (!$UserPass->updateUserMPass($masterPass)) {
$this->LogMessage->addDescription(__('Clave maestra incorrecta', false));
throw new AuthException(SPException::SP_INFO, __('Clave maestra incorrecta', false), '', self::STATUS_INVALID_MASTER_PASS);
} else {
CryptSession::saveSessionKey($UserPass->getClearUserMPass());
$this->LogMessage->addDescription(__('Clave maestra actualizada', false));
}
} else if ($oldPass) {
if (!$UserPass->updateMasterPass($oldPass)) {
$this->LogMessage->addDescription(__('Clave maestra incorrecta', false));
throw new AuthException(SPException::SP_INFO, __('Clave maestra incorrecta', false), '', self::STATUS_INVALID_MASTER_PASS);
} else {
CryptSession::saveSessionKey($UserPass->getClearUserMPass());
$this->LogMessage->addDescription(__('Clave maestra actualizada', false));
}
} else {
$loadMPass = $UserPass->loadUserMPass();
// Comprobar si es necesario actualizar la clave maestra
if ($loadMPass === null) {
throw new AuthException(SPException::SP_INFO, __('Es necesaria su clave anterior', false), '', self::STATUS_NEED_OLD_PASS);
// La clave no está establecida o se ha sido cambiada por el administrador
} else if ($loadMPass === false) {
throw new AuthException(SPException::SP_INFO, __('La clave maestra no ha sido guardada o es incorrecta', false), '', self::STATUS_INVALID_MASTER_PASS);
}
}
} catch (CryptoException $e) {
$this->LogMessage->addDescription(__('Error interno', false));
throw new AuthException(SPException::SP_INFO, $this->LogMessage->getDescription(), $e->getMessage(), self::STATUS_INTERNAL_ERROR);
}
return $UserPass;
}
/**
* Cargar las preferencias del usuario y comprobar si usa 2FA
*
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Core\Exceptions\InvalidClassException
*/
protected function loadUserPreferences()
{
Language::setLanguage(true);
DiFactory::getTheme()->initTheme(true);
Session::setUserPreferences($this->UserData->getUserPreferences());
Session::setSessionType(Session::SESSION_INTERACTIVE);
Session::setAuthCompleted(true);
DiFactory::getEventDispatcher()->notifyEvent('login.preferences', $this);
}
/**
* Autentificación LDAP
*
@@ -353,7 +357,7 @@ class LoginController
{
if ($LdapAuthData->getStatusCode() > 0) {
$this->LogMessage->addDetails(__('Tipo', false), __FUNCTION__);
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getUserLogin());
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getLogin());
if ($LdapAuthData->getStatusCode() === 49) {
$this->LogMessage->addDescription(__('Login incorrecto', false));
@@ -382,7 +386,7 @@ class LoginController
try {
// Verificamos si el usuario existe en la BBDD
if (UserLdap::checkLDAPUserInDB($this->UserData->getUserLogin())) {
if (UserLdap::checkLDAPUserInDB($this->UserData->getLogin())) {
// Actualizamos el usuario de LDAP en MySQL
UserLdap::getItem($this->UserData)->update();
} else {
@@ -411,7 +415,7 @@ class LoginController
// Autentificamos con la BBDD
if ($AuthData->getAuthenticated() === 0) {
$this->LogMessage->addDescription(__('Login incorrecto', false));
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getUserLogin());
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getLogin());
throw new AuthException(SPException::SP_INFO, $this->LogMessage->getDescription(), '', self::STATUS_INVALID_LOGIN);
} elseif ($AuthData->getAuthenticated() === 1) {
@@ -434,7 +438,7 @@ class LoginController
if ($AuthData->getAuthenticated() === 0) {
$this->LogMessage->addDescription(__('Login incorrecto', false));
$this->LogMessage->addDetails(__('Tipo', false), __FUNCTION__);
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getUserLogin());
$this->LogMessage->addDetails(__('Usuario', false), $this->UserData->getLogin());
$this->LogMessage->addDetails(__('Autentificación', false), sprintf('%s (%s)', AuthUtil::getServerAuthType(), $AuthData->getName()));
throw new AuthException(SPException::SP_INFO, $this->LogMessage->getDescription(), '', self::STATUS_INVALID_LOGIN);

View File

@@ -36,7 +36,7 @@ use SP\Core\Exceptions\SPException;
use SP\DataModel\GroupData;
use SP\DataModel\InstallData;
use SP\DataModel\ProfileData;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\Mgmt\Groups\Group;
use SP\Mgmt\Profiles\Profile;
use SP\Mgmt\Users\User;
@@ -462,11 +462,13 @@ class Installer
Profile::getItem($ProfileData)->add();
// Datos del usuario
$UserData = new UserData();
$UserData = new UserLoginData();
$UserData->setUserGroupId($GroupData->getUsergroupId());
$UserData->setUserProfileId($ProfileData->getUserprofileId());
$UserData->setUserLogin($this->InstallData->getAdminLogin());
$UserData->setLogin($this->InstallData->getAdminLogin());
$UserData->setUserPass($this->InstallData->getAdminPass());
$UserData->setLoginPass($this->InstallData->getAdminPass());
$UserData->setUserName('Admin');
$UserData->setUserIsAdminApp(1);
@@ -477,10 +479,9 @@ class Installer
ConfigDB::setCacheConfigValue('lastupdatempass', time());
ConfigDB::writeConfig(true);
if (!UserPass::getItem($UserData)->updateUserMPass($this->InstallData->getMasterPassword())) {
if (!UserPass::updateUserMPass($this->InstallData->getMasterPassword(), $UserData)) {
throw new SPException(SPException::SP_CRITICAL,
__('Error al actualizar la clave maestra del usuario "admin"', false),
__('Informe al desarrollador', false));
__('Error al actualizar la clave maestra del usuario "admin"', false));
}
} catch (\Exception $e) {
$this->rollback();

View File

@@ -41,6 +41,14 @@ class LogMessage extends MessageBase
* @var array Detalles de la acción en formato "detalle : descripción"
*/
protected $details = [];
/**
* @var int
*/
protected $descriptionCounter = 0;
/**
* @var int
*/
protected $detailsCounter = 0;
/**
* Devuelve la acción realizada
@@ -140,6 +148,8 @@ class LogMessage extends MessageBase
$this->details[] = [$this->formatString($key), $this->formatString($value)];
$this->detailsCounter++;
return $this;
}
@@ -175,6 +185,7 @@ class LogMessage extends MessageBase
public function addDescriptionLine()
{
$this->description[] = '';
$this->descriptionCounter++;
return $this;
}
@@ -222,7 +233,7 @@ class LogMessage extends MessageBase
* Devolver un detalle formateado
*
* @param array $detail
* @param bool $translate
* @param bool $translate
* @return string
*/
protected function formatDetail(array $detail, $translate = false)
@@ -257,6 +268,18 @@ class LogMessage extends MessageBase
public function resetDescription()
{
$this->description = [];
$this->descriptionCounter = 0;
return $this;
}
/**
* Restablecer la variable de detalles
*/
public function resetDetails()
{
$this->details = [];
$this->detailsCounter = 0;
return $this;
}
@@ -271,4 +294,20 @@ class LogMessage extends MessageBase
{
return nl2br($this->getDetails($translate));
}
/**
* @return int
*/
public function getDescriptionCounter()
{
return $this->descriptionCounter;
}
/**
* @return int
*/
public function getDetailsCounter()
{
return $this->detailsCounter;
}
}

View File

@@ -31,6 +31,7 @@ use SP\Account\AccountHistoryCrypt;
use SP\Config\ConfigDB;
use SP\Core\Crypt\Hash;
use SP\Core\Exceptions\SPException;
use SP\Core\Init;
use SP\Log\Log;
use SP\Mgmt\CustomFields\CustomFieldsUtil;
use SP\Storage\DB;
@@ -75,6 +76,10 @@ class Crypt
return false;
}
global $timeStart;
debugLog(Init::microtime_float() - $timeStart);
return true;
}

View File

@@ -52,7 +52,7 @@ defined('APP_ROOT') || die();
*/
class Upgrade
{
private static $dbUpgrade = [110, 1121, 1122, 1123, 11213, 11219, 11220, 12001, 12002, 1316011001, 1316100601, 20017011302, 20017011701, 20017012901, 20117021901];
private static $dbUpgrade = [110, 1121, 1122, 1123, 11213, 11219, 11220, 12001, 12002, 1316011001, 1316100601, 20017011302, 20017011701, 20017012901];
private static $cfgUpgrade = [1124, 1316020501, 20017011202];
private static $auxUpgrade = [12001, 12002, 20017010901, 20017011202];
private static $appUpgrade = [20117021901];

View File

@@ -25,10 +25,9 @@
namespace SP\Core\Upgrade;
use Defuse\Crypto\Exception\CryptoException;
use SP\Config\ConfigDB;
use SP\Core\Crypt\Hash;
use SP\Core\Exceptions\SPException;
use SP\Core\OldCrypt;
use SP\DataModel\UserLoginData;
use SP\Mgmt\Users\UserPass;
use SP\Storage\DB;
use SP\Storage\QueryData;
@@ -118,17 +117,16 @@ class User
/**
* Actualizar la clave maestra
*
* @param UserPass $UserPass
* @param UserLoginData $UserData
* @return bool
*/
public static function upgradeMasterKey(UserPass $UserPass)
public static function upgradeMasterKey(UserLoginData $UserData)
{
$UserData = $UserPass->getItemData();
$key = OldCrypt::generateAesKey($UserData->getUserPass() . $UserData->getUserLogin());
$key = OldCrypt::generateAesKey($UserData->getLoginPass() . $UserData->getLogin());
$mKey = OldCrypt::getDecrypt($UserData->getUserMPass(), $UserData->getUserMKey(), $key);
try {
return $mKey && $UserPass->updateUserMPass($mKey);
return $mKey && UserPass::updateUserMPass($mKey, $UserData);
} catch (SPException $e) {
} catch (CryptoException $e) {
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link http://syspass.org
* @copyright 2012-2017, 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\DataModel;
/**
* Class UserLoginData
*
* @package SP\DataModel
*/
class UserLoginData extends UserData
{
/**
* @var string
*/
protected $login;
/**
* @var string
*/
protected $loginPass;
/**
* @return string
*/
public function getLogin()
{
return $this->login;
}
/**
* @param string $login
*/
public function setLogin($login)
{
$this->login = $login;
}
/**
* @return string
*/
public function getLoginPass()
{
return $this->loginPass;
}
/**
* @param string $loginPass
*/
public function setLoginPass($loginPass)
{
$this->loginPass = $loginPass;
}
}

View File

@@ -115,13 +115,34 @@ class Log extends ActionLog
return $Log;
}
/**
* Escribir un nuevo evento en el registro de eventos
*
* @param string $action La acción realizada
* @param string $description La descripción de la acción realizada
* @param string $level
* @return Log
*/
public static function writeNewLog($action, $description = null, $level = Log::INFO)
{
$LogMessage = new LogMessage();
$LogMessage->setAction($action);
$LogMessage->addDescription($description);
$Log = new Log($LogMessage, $level);
$Log->writeLog();
return $Log;
}
/**
* Escribir un nuevo evento en el registro de eventos
*
* @param bool $resetDescription Restablecer la descripción
* @param bool $resetDetails Restablecer los detalles
* @return bool
*/
public function writeLog($resetDescription = false)
public function writeLog($resetDescription = false, $resetDetails = false)
{
if ((defined('IS_INSTALLER') && IS_INSTALLER === 1)
|| self::$logDbEnabled === 0
@@ -166,6 +187,10 @@ class Log extends ActionLog
$this->LogMessage->resetDescription();
}
if ($resetDetails === true) {
$this->LogMessage->resetDetails();
}
try {
DB::getQuery($Data);
} catch (SPException $e) {
@@ -218,24 +243,4 @@ class Log extends ActionLog
return new Log($LogMessage, $level);
}
/**
* Escribir un nuevo evento en el registro de eventos
*
* @param string $action La acción realizada
* @param string $description La descripción de la acción realizada
* @param string $level
* @return Log
*/
public static function writeNewLog($action, $description = null, $level = Log::INFO)
{
$LogMessage = new LogMessage();
$LogMessage->setAction($action);
$LogMessage->addDescription($description);
$Log = new Log($LogMessage, $level);
$Log->writeLog();
return $Log;
}
}

View File

@@ -305,6 +305,10 @@ class User extends UserBase implements ItemInterface, ItemSelectInterface
user_lastUpdate,
user_lastUpdateMPass,
user_preferences,
user_pass,
user_hashSalt,
user_mPass,
user_mKey,
BIN(user_isAdminApp) AS user_isAdminApp,
BIN(user_isAdminAcc) AS user_isAdminAcc,
BIN(user_isLdap) AS user_isLdap,
@@ -357,6 +361,10 @@ class User extends UserBase implements ItemInterface, ItemSelectInterface
user_lastUpdate,
user_lastUpdateMPass,
user_preferences,
user_pass,
user_hashSalt,
user_mPass,
user_mKey,
BIN(user_isAdminApp) AS user_isAdminApp,
BIN(user_isAdminAcc) AS user_isAdminAcc,
BIN(user_isLdap) AS user_isLdap,
@@ -369,7 +377,13 @@ class User extends UserBase implements ItemInterface, ItemSelectInterface
WHERE user_login = ? LIMIT 1';
$Data = new QueryData();
$Data->setMapClassName($this->getDataModel());
if (is_object($this->itemData)) {
$Data->setMapClass($this->itemData);
} else {
$Data->setMapClassName($this->getDataModel());
}
$Data->setQuery($query);
$Data->addParam($login);

View File

@@ -29,6 +29,8 @@ defined('APP_ROOT') || die();
use SP\Core\Crypt\Hash;
use SP\Core\Exceptions\SPException;
use SP\DataModel\GroupUsersData;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\Log\Email;
use SP\Log\Log;
use SP\Mgmt\Groups\GroupUsers;
@@ -65,48 +67,51 @@ class UserMigrate
/**
* Actualizar la clave de un usuario desde phpPMS.
*
* @param string $userLogin con el login del usuario
* @param string $userPass con la clave del usuario
* @param UserLoginData $UserData
* @return bool
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Core\Exceptions\ConstraintException
*
* Esta función actualiza la clave de un usuario que ha sido migrado desde phpPMS
* @throws \SP\Core\Exceptions\SPException
* @throws \phpmailer\phpmailerException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \SP\Core\Exceptions\QueryException
*/
public static function migrateUserPass($userLogin, $userPass)
public static function migrateUserPass(UserLoginData $UserData)
{
$query = /** @lang SQL */
'UPDATE usrData SET
$passOk = ($UserData->getUserPass() === sha1($UserData->getUserHashSalt() . $UserData->getLoginPass())
|| $UserData->getUserPass() === md5($UserData->getLoginPass())
|| hash_equals($UserData->getUserPass(), crypt($UserData->getLoginPass(), $UserData->getUserHashSalt()))
|| Hash::checkHashKey($UserData->getLoginPass(), $UserData->getUserPass()));
if ($passOk) {
$query = /** @lang SQL */
'UPDATE usrData SET
user_pass = ?,
user_hashSalt = \'\',
user_lastUpdate = NOW(),
user_isMigrate = 0
WHERE user_login = ?
AND user_isMigrate = 1
AND (user_pass = SHA1(CONCAT(user_hashSalt,?))
OR user_pass = MD5(?)
OR user_pass = ENCRYPT(?, user_hashSalt)) LIMIT 1';
WHERE user_login = ? LIMIT 1';
$Data = new QueryData();
$Data->setQuery($query);
$Data->addParam(Hash::hashKey($userPass));
$Data->addParam($userLogin);
$Data->addParam($userPass);
$Data->addParam($userPass);
$Data->addParam($userPass);
$Data->setOnErrorMessage(__('Error al migrar cuenta de usuario', false));
$Data = new QueryData();
$Data->setQuery($query);
$Data->addParam(Hash::hashKey($UserData->getLoginPass()));
$Data->addParam($UserData->getLogin());
$Data->setOnErrorMessage(__('Error al migrar cuenta de usuario', false));
DB::getQuery($Data);
DB::getQuery($Data);
$Log = new Log();
$Log->getLogMessage()
->setAction(__FUNCTION__)
->addDescription(__('Usuario actualizado', false))
->addDetails(__('Login', false), $userLogin);
$Log->writeLog();
$Log = new Log();
$Log->getLogMessage()
->setAction(__FUNCTION__)
->addDescription(__('Usuario actualizado', false))
->addDetails(__('Login', false), $UserData->getLogin());
$Log->writeLog();
Email::sendEmail($Log->getLogMessage());
Email::sendEmail($Log->getLogMessage());
return true;
}
return false;
}
/**

View File

@@ -33,7 +33,9 @@ use SP\Core\Crypt\Crypt;
use SP\Core\Crypt\Hash;
use SP\Core\Exceptions\QueryException;
use SP\Core\Exceptions\SPException;
use SP\Core\Upgrade\User;
use SP\Core\Upgrade\User as UpgradeUser;
use SP\DataModel\UserData;
use SP\DataModel\UserLoginData;
use SP\DataModel\UserPassData;
use SP\Log\Email;
use SP\Log\Log;
@@ -48,10 +50,21 @@ use SP\Core\Crypt\Session as CryptSession;
*/
class UserPass extends UserBase
{
// La clave maestra incorrecta
const MPASS_WRONG = 0;
// La clave maestra correcta
const MPASS_OK = 1;
// La clave maestra no está guardada
const MPASS_NOTSET = 2;
// La clave maestra ha cambiado
const MPASS_CHANGED = 3;
// Comprobar la clave maestra con la calve del usuario anterior
const MPASS_CHECKOLD = 4;
/**
* @var string
*/
protected $clearUserMPass = '';
private static $clearUserMPass = '';
/**
* Category constructor.
@@ -93,9 +106,10 @@ class UserPass extends UserBase
/**
* Comprobar si el usuario tiene actualizada la clave maestra actual.
*
* @param int $userId ID de usuario
* @return bool
*/
public function checkUserUpdateMPass()
public static function checkUserUpdateMPass($userId)
{
$configMPassTime = ConfigDB::getValue('lastupdatempass');
@@ -109,7 +123,7 @@ class UserPass extends UserBase
$Data = new QueryData();
$Data->setMapClassName(UserPassData::class);
$Data->setQuery($query);
$Data->addParam($this->itemData->getUserId());
$Data->addParam($userId);
/** @var UserPassData $queryRes */
$queryRes = DB::getResults($Data);
@@ -117,6 +131,152 @@ class UserPass extends UserBase
return ($queryRes !== false && $queryRes->getUserLastUpdateMPass() >= $configMPassTime);
}
/**
* Actualizar la clave maestra con la clave anterior del usuario
*
* @param string $oldUserPass
* @param UserLoginData $UserData
* @return bool
* @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
* @throws \Defuse\Crypto\Exception\BadFormatException
* @throws \SP\Core\Exceptions\SPException
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \Defuse\Crypto\Exception\CryptoException
*/
public static function updateMasterPassFromOldPass($oldUserPass, UserLoginData $UserData)
{
if (self::loadUserMPass($UserData, $oldUserPass) === UserPass::MPASS_OK) {
return self::updateUserMPass(self::$clearUserMPass, $UserData);
}
return UserPass::MPASS_WRONG;
}
/**
* Comprueba la clave maestra del usuario.
*
* @param UserLoginData $UserData
* @param string $key Clave de cifrado
* @return bool
* @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
* @throws \Defuse\Crypto\Exception\BadFormatException
* @throws \SP\Core\Exceptions\SPException
* @throws \Defuse\Crypto\Exception\CryptoException
*/
public static function loadUserMPass(UserLoginData $UserData, $key = null)
{
$configHashMPass = ConfigDB::getValue('masterPwd');
if (empty($configHashMPass)
|| empty($UserData->getUserMPass())
|| empty($UserData->getUserMKey())
) {
return self::MPASS_NOTSET;
} elseif ($UserData->getUserLastUpdateMPass() < ConfigDB::getValue('lastupdatempass')) {
return self::MPASS_CHANGED;
} elseif ($UserData->isUserIsMigrate() === 1) {
return UpgradeUser::upgradeMasterKey($UserData) ? self::MPASS_OK : self::MPASS_WRONG;
} else {
$securedKey = Crypt::unlockSecuredKey($UserData->getUserMKey(), self::getKey($UserData, $key));
$userMPass = Crypt::decrypt($UserData->getUserMPass(), $securedKey, self::getKey($UserData, $key));
// Comprobamos el hash de la clave del usuario con la guardada
if (Hash::checkHashKey($userMPass, $configHashMPass)) {
self::$clearUserMPass = $userMPass;
CryptSession::saveSessionKey($userMPass);
return self::MPASS_OK;
}
}
return self::MPASS_CHECKOLD;
}
/**
* Obtener una clave de cifrado basada en la clave del usuario y un salt.
*
* @param UserLoginData $UserData
* @param string $key Clave de cifrado
* @return string con la clave de cifrado
*/
private static function getKey(UserLoginData $UserData, $key = null)
{
$pass = $key === null ? $UserData->getLoginPass() : $key;
return $pass . $UserData->getLogin() . Config::getConfig()->getPasswordSalt();
}
/**
* Actualizar la clave maestra del usuario en la BBDD.
*
* @param string $userMPass con la clave maestra
* @param UserData|UserLoginData $UserData $UserData
* @return bool
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \Defuse\Crypto\Exception\CryptoException
* @throws \SP\Core\Exceptions\SPException
* @throws QueryException
*/
public static function updateUserMPass($userMPass, UserLoginData $UserData)
{
$configHashMPass = ConfigDB::getValue('masterPwd');
if ($configHashMPass === false) {
return self::MPASS_NOTSET;
} elseif (null === $configHashMPass) {
$configHashMPass = Hash::hashKey($userMPass);
ConfigDB::setValue('masterPwd', $configHashMPass);
}
if (Hash::checkHashKey($userMPass, $configHashMPass)
|| \SP\Core\Upgrade\Crypt::migrateHash($userMPass)
) {
$securedKey = Crypt::makeSecuredKey(self::getKey($UserData));
$cryptMPass = Crypt::encrypt($userMPass, $securedKey, self::getKey($UserData));
if (!empty($cryptMPass)) {
if (strlen($securedKey) > 1000 || strlen($cryptMPass) > 1000) {
throw new QueryException(SPException::SP_ERROR, __('Error interno', false), '', LoginController::STATUS_INTERNAL_ERROR);
}
$query = /** @lang SQL */
'UPDATE usrData SET
user_mPass = ?,
user_mKey = ?,
user_lastUpdateMPass = UNIX_TIMESTAMP(),
user_isMigrate = 0
WHERE user_id = ? LIMIT 1';
$Data = new QueryData();
$Data->setQuery($query);
$Data->addParam($cryptMPass);
$Data->addParam($securedKey);
$Data->addParam($UserData->getUserId());
self::$clearUserMPass = $userMPass;
$UserData->setUserMPass($cryptMPass);
$UserData->setUserMKey($securedKey);
DB::getQuery($Data);
return self::MPASS_OK;
}
}
return self::MPASS_WRONG;
}
/**
* @return string
*/
public static function getClearUserMPass()
{
return self::$clearUserMPass;
}
/**
* Modificar la clave de un usuario.
*
@@ -159,179 +319,4 @@ class UserPass extends UserBase
return $this;
}
/**
* Comprueba la clave maestra del usuario.
*
* @return bool
* @throws \Defuse\Crypto\Exception\CryptoException
* @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException
* @throws \Defuse\Crypto\Exception\BadFormatException
* @throws \SP\Core\Exceptions\SPException
*/
public function loadUserMPass()
{
$userMPass = $this->getUserMPass();
$configHashMPass = ConfigDB::getValue('masterPwd');
if ($userMPass === false || empty($configHashMPass)) {
return false;
// Comprobamos el hash de la clave del usuario con la guardada
} elseif (Hash::checkHashKey($userMPass, $configHashMPass)) {
$this->clearUserMPass = $userMPass;
CryptSession::saveSessionKey($userMPass);
return true;
}
return null;
}
/**
* Desencriptar la clave maestra del usuario para la sesión.
*
* @param string $key Clave de cifrado
* @return false|string Devuelve bool se hay error o string si se devuelve la clave
* @throws \Defuse\Crypto\Exception\CryptoException
*/
public function getUserMPass($key = null)
{
$query = /** @lang SQL */
'SELECT user_mPass,
user_mKey,
user_lastUpdateMPass,
BIN(user_isMigrate) AS user_isMigrate
FROM usrData WHERE user_id = ? LIMIT 1';
$Data = new QueryData();
$Data->setQuery($query);
$Data->addParam($this->itemData->getUserId());
$queryRes = DB::getResults($Data);
if ($queryRes === false
|| empty($queryRes->user_mPass)
|| empty($queryRes->user_mKey)
|| $queryRes->user_lastUpdateMPass < ConfigDB::getValue('lastupdatempass')
) {
return false;
} elseif ((int)$queryRes->user_isMigrate === 1) {
$this->itemData->setUserMPass($queryRes->user_mPass);
$this->itemData->setUserMKey($queryRes->user_mKey);
return User::upgradeMasterKey($this);
}
$this->itemData->setUserMPass($queryRes->user_mPass);
$this->itemData->setUserMKey($queryRes->user_mKey);
$securedKey = Crypt::unlockSecuredKey($queryRes->user_mKey, $this->getKey($key));
return Crypt::decrypt($queryRes->user_mPass, $securedKey, $this->getKey($key));
}
/**
* Obtener una clave de cifrado basada en la clave del usuario y un salt.
*
* @param string $key Clave de cifrado
* @return string con la clave de cifrado
* @throws \Defuse\Crypto\Exception\CryptoException
*/
private function getKey($key = null)
{
$pass = $key === null ? $this->itemData->getUserPass() : $key;
return $pass . $this->itemData->getUserLogin() . Config::getConfig()->getPasswordSalt();
}
/**
* @return string
*/
public function getClearUserMPass()
{
return $this->clearUserMPass;
}
/**
* Actualizar la clave maestra con la clave anterior del usuario
*
* @param $oldUserPass
* @return bool
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \Defuse\Crypto\Exception\CryptoException
* @throws \SP\Core\Exceptions\SPException
*/
public function updateMasterPass($oldUserPass)
{
$masterPass = $this->getUserMPass($oldUserPass);
if ($masterPass) {
return $this->updateUserMPass($masterPass);
}
return false;
}
/**
* Actualizar la clave maestra del usuario en la BBDD.
*
* @param string $masterPwd con la clave maestra
* @return bool
* @throws \SP\Core\Exceptions\QueryException
* @throws \SP\Core\Exceptions\ConstraintException
* @throws \Defuse\Crypto\Exception\CryptoException
* @throws \SP\Core\Exceptions\SPException
*/
public function updateUserMPass($masterPwd)
{
$configHashMPass = ConfigDB::getValue('masterPwd');
if ($configHashMPass === false) {
return false;
} elseif (null === $configHashMPass) {
$configHashMPass = Hash::hashKey($masterPwd);
ConfigDB::setValue('masterPwd', $configHashMPass);
}
if (Hash::checkHashKey($masterPwd, $configHashMPass)
|| \SP\Core\Upgrade\Crypt::migrateHash($masterPwd)
) {
$securedKey = Crypt::makeSecuredKey($this->getKey());
$cryptMPass = Crypt::encrypt($masterPwd, $securedKey, $this->getKey());
if (!empty($cryptMPass)) {
if (strlen($securedKey) > 1000 || strlen($cryptMPass) > 1000) {
throw new QueryException(SPException::SP_ERROR, __('Error interno', false), '', LoginController::STATUS_INTERNAL_ERROR);
}
$query = /** @lang SQL */
'UPDATE usrData SET
user_mPass = ?,
user_mKey = ?,
user_lastUpdateMPass = UNIX_TIMESTAMP(),
user_isMigrate = 0
WHERE user_id = ? LIMIT 1';
$Data = new QueryData();
$Data->setQuery($query);
$Data->addParam($cryptMPass);
$Data->addParam($securedKey);
$Data->addParam($this->itemData->getUserId());
$this->clearUserMPass = $masterPwd;
$this->itemData->setUserMPass($cryptMPass);
$this->itemData->setUserMKey($securedKey);
DB::getQuery($Data);
return true;
}
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
var $jscomp={scope:{},findInternal:function(b,d,e){b instanceof String&&(b=String(b));for(var a=b.length,c=0;c<a;c++){var f=b[c];if(d.call(e,f,c,b))return{i:c,v:f}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,d,e){if(e.get||e.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[d]=e.value)};
$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global&&null!=global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,d,e,a){if(d){e=$jscomp.global;b=b.split(".");for(a=0;a<b.length-1;a++){var c=b[a];c in e||(e[c]={});e=e[c]}b=b[b.length-1];a=e[b];d=d(a);d!=a&&null!=d&&$jscomp.defineProperty(e,b,{configurable:!0,writable:!0,value:d})}};
$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,d,e,a){if(d){e=$jscomp.global;b=b.split(".");for(a=0;a<b.length-1;a++){var c=b[a];c in e||(e[c]={});e=e[c]}b=b[b.length-1];a=e[b];d=d(a);d!=a&&null!=d&&$jscomp.defineProperty(e,b,{configurable:!0,writable:!0,value:d})}};
$jscomp.polyfill("Array.prototype.find",function(b){return b?b:function(b,e){return $jscomp.findInternal(this,b,e).v}},"es6-impl","es3");
sysPass.Triggers=function(b){var d=b.log,e=function(a){var c={valueField:"id",labelField:"name",searchField:["name"]};a.find(".select-box").each(function(a){var d=$(this);c.plugins=d.hasClass("select-box-deselect")?{clear_selection:{title:b.config().LANG[51]}}:{};if(d.data("onchange")){var f=d.data("onchange").split("/");c.onChange=function(a){if(0<a)if(2===f.length)sysPassApp.actions()[f[0]][f[1]](d);else sysPassApp.actions()[f[0]](d)}}d.selectize(c)});a.find("#allowed_exts").selectize({create:function(a){return{value:a.toUpperCase(),
text:a.toUpperCase()}},createFilter:/^[a-z0-9]{1,4}$/i,plugins:["remove_button"]});a.find("#wikifilter").selectize({create:!0,createFilter:/^[a-z0-9:._-]+$/i,plugins:["remove_button"]})};return{views:{main:function(){d.info("views:main");$(".btn-menu").click(function(){var a=$(this);"1"===a.attr("data-history-reset")&&b.appRequests().history.reset();b.appActions().doAction({actionId:a.data("action-id")},a.data("view"))});b.appActions().doAction({actionId:1},"search")},search:function(){d.info("views:search");