* Mail: automatic migrate old mcrypt tripledes passwords to openssl AES on successful login

This commit is contained in:
Ralf Becker 2016-07-07 16:08:08 +02:00
parent ea200604fb
commit 26ccede602
3 changed files with 97 additions and 2 deletions

View File

@ -235,6 +235,13 @@ class Account implements \ArrayAccess
'accountStatus', 'deliveryMode', 'quotaLimit', 'quotaUsed',
);
/**
* Callable to run on successful login to eg. run Credentials::migrate
*
* @var array with callable and further arguments
*/
protected $on_login;
/**
* Constructor
*
@ -248,7 +255,7 @@ class Account implements \ArrayAccess
/*protected*/ function __construct(array $params, $called_for=null)
{
// read credentials from database
$params += Credentials::read($params['acc_id'], null, $called_for ? array(0, $called_for) : $called_for);
$params += Credentials::read($params['acc_id'], null, $called_for ? array(0, $called_for) : $called_for, $this->on_login);
if (!isset($params['notify_folders']))
{
@ -365,6 +372,14 @@ class Account implements \ArrayAccess
$class = $this->params['acc_imap_type'];
$this->imapServer = new $class($this->params, $_adminConnection, $_timeout);
// if Credentials class told us to run something on successful login, tell it to Imap class
if ($this->on_login)
{
$func = array_shift($this->on_login);
$this->imapServer->runOnLogin($func, $this->on_login);
unset($this->on_login);
}
}
return $this->imapServer;
}

View File

@ -144,9 +144,11 @@ class Credentials
* @param int $acc_id
* @param int $type =null default return all credentials
* @param int|array $account_id =null default use current user or all (in that order)
* @param array& $on_login =null on return array with callable and further arguments
* to run on successful login to trigger password migration
* @return array with values for (imap|smtp|admin)_(username|password|cred_id)
*/
public static function read($acc_id, $type=null, $account_id=null)
public static function read($acc_id, $type=null, $account_id=null, &$on_login=null)
{
if (is_null($type)) $type = self::ALL;
if (is_null($account_id))
@ -176,6 +178,7 @@ class Credentials
$rows = call_user_func_array('array_merge', $rows);
//error_log(__METHOD__."($acc_id, $type, ".array2string($account_id).") read from cache ".array2string($rows));
}
$on_login = null;
$results = array();
foreach($rows as $row)
{
@ -184,6 +187,11 @@ class Credentials
{
self::$cache[$acc_id][$row['account_id']][$row['cred_type']] = $row;
//error_log(__METHOD__."($acc_id, $type, ".array2string($account_id).") stored to cache ".array2string($row));
if (!isset($on_login) && self::needMigration($row['cred_pw_enc']))
{
$on_login = array(__CLASS__.'::migrate', $acc_id);
}
}
$password = self::decrypt($row);
@ -632,6 +640,43 @@ class Credentials
self::AES_METHOD, $aes_key, OPENSSL_RAW_DATA, $salt), "\0");
}
/**
* Check if credentials need migration to AES
*
* @param string $pw_enc
* @return boolean
*/
static public function needMigration($pw_enc)
{
return $pw_enc == self::USER || $pw_enc == self::SYSTEM || $pw_enc == self::CLEARTEXT;
}
/**
* Run password migration for credentials of given account
*
* @param int $acc_id
*/
static function migrate($acc_id)
{
try {
foreach((array)self::$cache[$acc_id] as $account_id => &$rows)
{
foreach($rows as $cred_type => &$row)
{
if (self::needMigration($row['cred_pw_enc']) && ($row['cred_pw_enc'] != self::USER ||
$row['cred_pw_enc'] == self::USER && $account_id == $GLOBALS['egw_info']['user']['account_id']))
{
self::write($acc_id, $row['cred_username'], self::decrypt($row), $cred_type, $account_id, $row['cred_id']);
}
}
}
}
catch(Exception $e) {
// do not stall regular use, if password migration fails
_egw_log_exception($e);
}
}
/**
* Hook called when user changes his password, to re-encode his credentials with his new password
*

View File

@ -238,6 +238,41 @@ class Imap extends Horde_Imap_Client_Socket implements Imap\Iface
}
}
/**
* Methods to run on successful login
*
* @var array
*/
protected $run_on_login=array();
/**
* Run given function on successful login
*
* @param callable $func
* @param array $params =array()
*/
public function runOnLogin($func, array $params=array())
{
$this->run_on_login[] = array($func, $params);
}
/**
* Login to the IMAP server.
*
* @throws Horde_Imap_Client_Exception
*/
public function login()
{
parent::login();
foreach($this->run_on_login as $key => $data)
{
call_user_func_array($data[0], $data[1]);
unset($this->run_on_login[$key]);
}
}
/**
* Allow read access to former public attributes
*