mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-03-13 15:48:17 +01:00
store user-password encrypted in the session, managed by session-class via $GLOBALS['egw']->session->passwd
This commit is contained in:
parent
7000326f40
commit
424ce562a7
@ -397,8 +397,7 @@ class Auth
|
||||
if ($account_id == $GLOBALS['egw']->session->account_id)
|
||||
{
|
||||
// need to change current users password in session
|
||||
Cache::setSession('phpgwapi', 'password', base64_encode($new_passwd));
|
||||
$GLOBALS['egw_info']['user']['passwd'] = $new_passwd;
|
||||
$GLOBALS['egw']->session->passwd = $new_passwd;
|
||||
$GLOBALS['egw_info']['user']['account_lastpwd_change'] = DateTime::to('now','ts');
|
||||
// invalidate EGroupware session, as password is stored in egw_info in session
|
||||
Egw::invalidate_session_cache();
|
||||
|
@ -499,6 +499,11 @@ class Cache
|
||||
if (Session::ERROR_LOG_DEBUG) error_log(__METHOD__.' called after session was encrypted --> ignored!');
|
||||
return false; // can no longer store something in the session, eg. because commit_session() was called
|
||||
}
|
||||
// user password is no longer stored (unencrypted) in session, but encrypted by session-class
|
||||
if ($app === 'phpgwapi' && $location === 'password')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$_SESSION[Session::EGW_APPSESSION_VAR][$app][$location] = $data;
|
||||
|
||||
if ($expiration > 0)
|
||||
@ -529,6 +534,13 @@ class Cache
|
||||
$ret = null; // can no longer store something in the session, eg. because commit_session() was called
|
||||
return $ret;
|
||||
}
|
||||
// user password is no longer stored (unencrypted) in session, but encrypted by session-class
|
||||
if ($app === 'phpgwapi' && $location === 'password')
|
||||
{
|
||||
$passwd = isset($GLOBALS['egw']->session) && $GLOBALS['egw']->session->__isset('passwd') ?
|
||||
base64_encode($GLOBALS['egw']->session->__get('passwd')) : null;
|
||||
return $passwd;
|
||||
}
|
||||
// check if entry is expired and clean it up in that case
|
||||
if (isset($_SESSION[Session::EGW_APPSESSION_VAR][self::SESSION_EXPIRATION_PREFIX.$app][$location]) &&
|
||||
$_SESSION[Session::EGW_APPSESSION_VAR][self::SESSION_EXPIRATION_PREFIX.$app][$location] < time())
|
||||
@ -897,4 +909,4 @@ if (is_null(Cache::$default_provider))
|
||||
'EGroupware\Api\Cache\Files'));
|
||||
}
|
||||
|
||||
//error_log('Cache::$default_provider='.array2string(Cache::$default_provider));
|
||||
//error_log('Cache::$default_provider='.array2string(Cache::$default_provider));
|
@ -425,7 +425,7 @@ class Ldap
|
||||
$this->ds = Api\Ldap::factory(true,
|
||||
$this->ldap_config['ldap_contact_host'],
|
||||
$GLOBALS['egw_info']['user']['account_dn'],
|
||||
$GLOBALS['egw_info']['user']['passwd'],
|
||||
$GLOBALS['egw']->session->passwd,
|
||||
$reconnect
|
||||
);
|
||||
}
|
||||
|
@ -297,8 +297,7 @@ class Credentials
|
||||
|
||||
if (isset($data[self::$type2prefix[self::SSO_PASSWORD].'password']))
|
||||
{
|
||||
Api\Cache::setSession('phpgwapi', 'password',
|
||||
base64_encode($GLOBALS['egw']->session->passwd = $data[self::$type2prefix[self::SSO_PASSWORD].'password']));
|
||||
$GLOBALS['egw']->session->passwd = $data[self::$type2prefix[self::SSO_PASSWORD].'password'];
|
||||
|
||||
return $data[self::$type2prefix[self::SSO_PASSWORD].'password'];
|
||||
}
|
||||
@ -391,7 +390,7 @@ class Credentials
|
||||
default:
|
||||
throw new Api\Exception\WrongParameter("Unknown data[acc_imap_logintype]=".array2string($data['acc_imap_logintype']).'!');
|
||||
}
|
||||
$password = base64_decode(Api\Cache::getSession('phpgwapi', 'password'));
|
||||
$password = $GLOBALS['egw']->session->passwd;
|
||||
// if session password is a token, do NOT use it, but also do NOT throw, just return NULL for the password(s)
|
||||
if (Api\Auth\Token::isToken($password))
|
||||
{
|
||||
@ -580,7 +579,7 @@ class Credentials
|
||||
if (empty($key))
|
||||
{
|
||||
if ($use_system !== true && $account_id > 0 && $account_id == $GLOBALS['egw_info']['user']['account_id'] &&
|
||||
($key = Api\Cache::getSession('phpgwapi', 'password')) &&
|
||||
($key = $GLOBALS['egw']->session->passwd) &&
|
||||
// do NOT encrypt password if (optional) SAML or OpenIdConnect auth is enabled
|
||||
!array_filter(array_keys(Api\Config::read('phpgwapi')), static function($name)
|
||||
{
|
||||
@ -736,7 +735,7 @@ class Credentials
|
||||
{
|
||||
if (self::isUser($pw_enc))
|
||||
{
|
||||
$session_key = Api\Cache::getSession('phpgwapi', 'password');
|
||||
$session_key = $GLOBALS['egw']->session->passwd;
|
||||
if (empty($session_key))
|
||||
{
|
||||
throw new NoSessionPassword();
|
||||
@ -868,7 +867,7 @@ class Credentials
|
||||
if (empty($data['old_passwd'])) return;
|
||||
|
||||
// as self::encrypt will use password in session, check it is identical to given new password
|
||||
if ($data['new_passwd'] !== base64_decode(Api\Cache::getSession('phpgwapi', 'password')))
|
||||
if ($data['new_passwd'] !== $GLOBALS['egw']->session->passwd)
|
||||
{
|
||||
throw new Api\Exception\AssertionFailed('Password in session !== password given in $data[new_password]!');
|
||||
}
|
||||
@ -915,7 +914,7 @@ class Credentials
|
||||
}
|
||||
elseif ($user)
|
||||
{
|
||||
$session_key = Api\Cache::getSession('phpgwapi', 'password');
|
||||
$session_key = $GLOBALS['egw']->session->passwd;
|
||||
if (empty($session_key))
|
||||
{
|
||||
error_log(__METHOD__."() no session password available!");
|
||||
|
@ -35,6 +35,8 @@ use League\OAuth2\Server\Exception\OAuthServerException;
|
||||
* {
|
||||
* // switch that on to analyse memory usage in the session
|
||||
* //self::log_session_usage($_SESSION[self::EGW_APPSESSION_VAR],'_SESSION['.self::EGW_APPSESSION_VAR.']',true,5000);
|
||||
*
|
||||
* @var passwd user-password from session (it's stored encrypted in the session)
|
||||
*/
|
||||
class Session
|
||||
{
|
||||
@ -83,11 +85,17 @@ class Session
|
||||
var $login;
|
||||
|
||||
/**
|
||||
* current user password
|
||||
* current encrypted user password
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $passwd;
|
||||
public $password_encrypted;
|
||||
/**
|
||||
* @var string decrypted password, do NOT use direct, set or read $this->passwd (__sleep() method ensures it never gets serialized into session)
|
||||
*/
|
||||
private $_password;
|
||||
|
||||
public $passwd_type;
|
||||
|
||||
/**
|
||||
* current user db/ldap account id
|
||||
@ -151,7 +159,7 @@ class Session
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $egw_domains;
|
||||
public $egw_domains;
|
||||
|
||||
/**
|
||||
* Nummeric code why session creation failed
|
||||
@ -279,6 +287,62 @@ class Session
|
||||
$this->action = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure to NOT serialize unencrypted user password ($this->_password) to session
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
function __sleep()
|
||||
{
|
||||
unset($this->_password); // not really necessary, as get_object_vars() only returns public attributes
|
||||
|
||||
return array_keys(get_object_vars($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter: currently used to decrypt encrypted user password from session ($this->password_encrypted)
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name === 'passwd')
|
||||
{
|
||||
if (!isset($this->_password) && isset($this->password_encrypted))
|
||||
{
|
||||
$this->_password = Mail\Credentials::decrypt([
|
||||
'cred_password' => $this->password_encrypted,
|
||||
'cred_pw_enc' => Mail\Credentials::SYSTEM_AES, // use system secret aka. DB password
|
||||
]);
|
||||
}
|
||||
return $this->_password;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic setter: currently only used to store user password encrypted in the session
|
||||
*
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if ($name === 'passwd')
|
||||
{
|
||||
$this->password_encrypted = Mail\Credentials::encrypt($value, $this->account_id, $pw_enc, true);
|
||||
$this->_password = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function __isset($name)
|
||||
{
|
||||
if ($name === 'passwd')
|
||||
{
|
||||
return isset($this->password_encrypted);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor: update access-log and encrypt session
|
||||
*/
|
||||
@ -578,8 +642,6 @@ class Session
|
||||
return false;
|
||||
}
|
||||
|
||||
Cache::setSession('phpgwapi', 'password', base64_encode($this->passwd));
|
||||
|
||||
// if we have a second factor, check it before forced password change
|
||||
if ($check_2fa !== false)
|
||||
{
|
||||
@ -758,7 +820,7 @@ class Session
|
||||
}
|
||||
|
||||
/**
|
||||
* Check multifcator authemtication
|
||||
* Check multifactor authentication
|
||||
*
|
||||
* @param string $code 2fa-code
|
||||
* @param string $token remember me token
|
||||
@ -980,6 +1042,7 @@ class Session
|
||||
// we need to preserve the limits and if authenticated via token
|
||||
'session_limits' => $this->limits,
|
||||
'session_token_auth' => $this->token_auth,
|
||||
'session_password' => $this->password_encrypted,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1375,11 +1438,10 @@ class Session
|
||||
if (self::ERROR_LOG_DEBUG) error_log("*** Session::verify($sessionid) accounts is expired");
|
||||
return false;
|
||||
}
|
||||
$this->passwd = base64_decode(Cache::getSession('phpgwapi', 'password'));
|
||||
$this->password_encrypted = $session['session_password'];
|
||||
if ($fill_egw_info_and_repositories)
|
||||
{
|
||||
$GLOBALS['egw_info']['user']['session_ip'] = $session['session_ip'];
|
||||
$GLOBALS['egw_info']['user']['passwd'] = $this->passwd;
|
||||
}
|
||||
if ($this->account_domain != $GLOBALS['egw_info']['user']['domain'])
|
||||
{
|
||||
@ -2017,7 +2079,7 @@ class Session
|
||||
{
|
||||
$probable_domain = array_pop($parts);
|
||||
//Last part of login string, when separated by @, is a domain name
|
||||
if (in_array($probable_domain,$this->egw_domains))
|
||||
if ($this->egw_domains && in_array($probable_domain, $this->egw_domains))
|
||||
{
|
||||
$got_login = true;
|
||||
$domain = $probable_domain;
|
||||
@ -2230,4 +2292,4 @@ class Session
|
||||
'notification_heartbeat > '.self::heartbeat_limit(),
|
||||
), __LINE__, __FILE__)->fetchColumn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ class Base
|
||||
{
|
||||
$check_url = strtr($url, [
|
||||
'$user' => $GLOBALS['egw_info']['user']['account_lid'],
|
||||
'$pass' => urlencode($GLOBALS['egw_info']['user']['passwd']),
|
||||
'$pass' => urlencode($GLOBALS['egw']->session->passwd),
|
||||
'$host' => $GLOBALS['egw_info']['user']['domain'],
|
||||
'$home' => str_replace(array('\\\\', '\\'), array('', '/'), $GLOBALS['egw_info']['user']['homedirectory']),
|
||||
]);
|
||||
@ -291,12 +291,12 @@ class Base
|
||||
// setting default user, passwd and domain, if it's not contained int the url
|
||||
$defaults = array(
|
||||
'user' => $GLOBALS['egw_info']['user']['account_lid'],
|
||||
'pass' => urlencode($GLOBALS['egw_info']['user']['passwd'] ?? ''),
|
||||
'pass' => urlencode($GLOBALS['egw']->session->passwd ?? ''),
|
||||
'host' => $GLOBALS['egw_info']['user']['domain'],
|
||||
'home' => str_replace(array('\\\\', '\\'), array('', '/'), $GLOBALS['egw_info']['user']['homedirectory'] ?? ''),
|
||||
);
|
||||
// check if we have a (base64 encoded) fallback-auth GET parameter and need to use it
|
||||
if (empty($GLOBALS['egw_info']['user']['passwd']) && ($query=Vfs::parse_url($_path, PHP_URL_QUERY)) &&
|
||||
if (empty($GLOBALS['egw']->session->passwd) && ($query=Vfs::parse_url($_path, PHP_URL_QUERY)) &&
|
||||
strpos($query, 'fallback-auth=') !== false)
|
||||
{
|
||||
parse_str($query, $query_params);
|
||||
|
@ -2180,7 +2180,7 @@ class calendar_bo
|
||||
elseif ($GLOBALS['egw_info']['user']['preferences']['calendar']['freebusy'] == 2)
|
||||
{
|
||||
$credentials = $GLOBALS['egw_info']['user']['account_lid']
|
||||
. ':' . $GLOBALS['egw_info']['user']['passwd'];
|
||||
. ':' . $GLOBALS['egw']->session->passwd;
|
||||
$credentials = '&cred=' . base64_encode($credentials);
|
||||
}
|
||||
return Api\Framework::getUrl($GLOBALS['egw_info']['server']['webserver_url']).
|
||||
|
@ -311,8 +311,8 @@ class preferences_password
|
||||
}
|
||||
$errors = array();
|
||||
|
||||
if (isset($GLOBALS['egw_info']['user']['passwd']) &&
|
||||
$old_passwd !== $GLOBALS['egw_info']['user']['passwd'])
|
||||
if (isset($GLOBALS['egw']->session->passwd) &&
|
||||
$old_passwd !== $GLOBALS['egw']->session->passwd)
|
||||
{
|
||||
$errors[] = lang('The old password is not correct');
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user