* Setup: making SSHA (salted sha1) hashes the default password hash for SQL and LDAP

- fixing not working ssha hashes if mb_string.func_overload > 0 set
This commit is contained in:
Ralf Becker 2011-05-04 07:52:45 +00:00
parent 03cd666e8b
commit 457e79454d
3 changed files with 40 additions and 15 deletions

View File

@ -57,9 +57,9 @@ class auth
/** /**
* check_password_age * check_password_age
* check if users are supposed to change their password every x sdays, then check if password is of old age * check if users are supposed to change their password every x sdays, then check if password is of old age
* or the devil-admin reset the users password and forced the user to change his password on next login. * or the devil-admin reset the users password and forced the user to change his password on next login.
* *
* @param string $app to know where you are/ or where you want to go * @param string $app to know where you are/ or where you want to go
* @param string $class to know where you are/ or where you want to go * @param string $class to know where you are/ or where you want to go
* @param string $method to know where you are/ or where you want to go * @param string $method to know where you are/ or where you want to go
@ -87,7 +87,7 @@ class auth
//echo egw_time::to('now','ts')-($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400).'<br>'; //echo egw_time::to('now','ts')-($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400).'<br>';
// if neither timestamp isset return true, nothing to do (exept this means the password is too old) // if neither timestamp isset return true, nothing to do (exept this means the password is too old)
if (!isset($GLOBALS['egw_info']['user']['account_lastpasswd_change']) && if (!isset($GLOBALS['egw_info']['user']['account_lastpasswd_change']) &&
!isset($GLOBALS['egw_info']['user'][$alpwchange]) && !isset($GLOBALS['egw_info']['user'][$alpwchange]) &&
empty($GLOBALS['egw_info']['server']['change_pwd_every_x_days']) empty($GLOBALS['egw_info']['server']['change_pwd_every_x_days'])
) return true; ) return true;
@ -106,7 +106,7 @@ class auth
if (method_exists($backend,'getLastPwdChange')) $alpwchange_val = $backend->getLastPwdChange($GLOBALS['egw_info']['user']['account_lid']); if (method_exists($backend,'getLastPwdChange')) $alpwchange_val = $backend->getLastPwdChange($GLOBALS['egw_info']['user']['account_lid']);
if (is_null($alpwchange_val) || $alpwchange_val === false) $alpwchange_val = $GLOBALS['egw_info']['user'][$alpwchange]; if (is_null($alpwchange_val) || $alpwchange_val === false) $alpwchange_val = $GLOBALS['egw_info']['user'][$alpwchange];
} }
if (is_null($passwordAgeBorder) && $GLOBALS['egw_info']['server']['change_pwd_every_x_days']) if (is_null($passwordAgeBorder) && $GLOBALS['egw_info']['server']['change_pwd_every_x_days'])
{ {
$passwordAgeBorder = (egw_time::to('now','ts')-($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400)); $passwordAgeBorder = (egw_time::to('now','ts')-($GLOBALS['egw_info']['server']['change_pwd_every_x_days']*86400));
} }
@ -125,17 +125,17 @@ class auth
( (
($passwordAgeBorder > $alpwchange_val) || ($passwordAgeBorder > $alpwchange_val) ||
( (
$GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change'] && $GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change'] &&
$GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change'] > $daysLeftUntilChangeReq $GLOBALS['egw_info']['server']['warn_about_upcoming_pwd_change'] > $daysLeftUntilChangeReq
) )
) )
) || $alpwchange_val==0 ) || $alpwchange_val==0
) )
) )
{ {
if ($GLOBALS['egw']->acl->check('nopasswordchange', 1, 'preferences')) return true; // user has no rights to change password if ($GLOBALS['egw']->acl->check('nopasswordchange', 1, 'preferences')) return true; // user has no rights to change password
if ($UserKnowsAboutPwdChange === true && !($passwordAgeBorder > $alpwchange_val || $alpwchange_val==0)) return true; // user has already been informed about the upcomming password expiration if ($UserKnowsAboutPwdChange === true && !($passwordAgeBorder > $alpwchange_val || $alpwchange_val==0)) return true; // user has already been informed about the upcomming password expiration
if ($alpwchange_val == 0) if ($alpwchange_val == 0)
{ {
$message = lang('an admin required that you must change your password upon login.'); $message = lang('an admin required that you must change your password upon login.');
} }
@ -167,7 +167,7 @@ class auth
* fetch the last pwd change for the user * fetch the last pwd change for the user
* *
* @param string $username username of account to authenticate * @param string $username username of account to authenticate
* @return mixed false or shadowlastchange*24*3600 * @return mixed false or shadowlastchange*24*3600
*/ */
function getLastPwdChange($username) function getLastPwdChange($username)
{ {
@ -566,8 +566,8 @@ class auth
$hash = base64_decode(substr($db_val,6)); $hash = base64_decode(substr($db_val,6));
/* SMD5 hashes are 16 bytes long */ /* SMD5 hashes are 16 bytes long */
$orig_hash = substr($hash, 0, 16); $orig_hash = cut_bytes($hash, 0, 16); // binary string need to use cut_bytes, not mb_substr(,,'utf-8')!
$salt = substr($hash, 16); $salt = cut_bytes($hash, 16);
$new_hash = md5($form_val . $salt,true); $new_hash = md5($form_val . $salt,true);
//echo '<br> DB: ' . base64_encode($orig_hash) . '<br>FORM: ' . base64_encode($new_hash); //echo '<br> DB: ' . base64_encode($orig_hash) . '<br>FORM: ' . base64_encode($new_hash);
@ -605,10 +605,11 @@ class auth
$hash = base64_decode(substr($db_val, 6)); $hash = base64_decode(substr($db_val, 6));
// SHA-1 hashes are 160 bits long // SHA-1 hashes are 160 bits long
$orig_hash = substr($hash, 0, 20); $orig_hash = cut_bytes($hash, 0, 20); // binary string need to use cut_bytes, not mb_substr(,,'utf-8')!
$salt = substr($hash, 20); $salt = cut_bytes($hash, 20);
$new_hash = sha1($form_val . $salt,true); $new_hash = sha1($form_val . $salt,true);
//error_log(__METHOD__."('$form_val', '$db_val') hash='$hash', orig_hash='$orig_hash', salt='$salt', new_hash='$new_hash' returning ".array2string(strcmp($orig_hash,$new_hash) == 0));
return strcmp($orig_hash,$new_hash) == 0; return strcmp($orig_hash,$new_hash) == 0;
} }

View File

@ -49,6 +49,27 @@ function bytes($str)
return $func_overload & 2 ? mb_strlen($str,'ascii') : strlen($str); return $func_overload & 2 ? mb_strlen($str,'ascii') : strlen($str);
} }
/**
* mbstring.func_overload safe substr
*
* @param string $data
* @param int $offset
* @param int $len
* @return string
*/
function cut_bytes(&$data,$offset,$len=null)
{
static $func_overload;
if (is_null($func_overload)) $func_overload = extension_loaded('mbstring') ? ini_get('mbstring.func_overload') : 0;
if (is_null($len))
{
return $func_overload ? mb_substr($data,$offset,bytes($data),'ascii') : substr($data,$offset);
}
return $func_overload ? mb_substr($data,$offset,$len,'ascii') : substr($data,$offset,$len);
}
/** /**
* Format array or other types as (one-line) string, eg. for error_log statements * Format array or other types as (one-line) string, eg. for error_log statements
* *

View File

@ -259,7 +259,7 @@ class setup_process
} }
// always enable spellchecker, ckeditor now uses spell-as-you-type via a public webservice // always enable spellchecker, ckeditor now uses spell-as-you-type via a public webservice
$current_config['enabled_spellcheck'] = 'True'; $current_config['enabled_spellcheck'] = 'True';
// always enable history logging for calendar, addressbook and infolog // always enable history logging for calendar, addressbook and infolog
$current_config['history'] = 'history'; // addressbook: only admin $current_config['history'] = 'history'; // addressbook: only admin
$current_config['calendar_delete_history'] = 'history'; // only admins $current_config['calendar_delete_history'] = 'history'; // only admins
@ -270,7 +270,7 @@ class setup_process
'config_app' => 'infolog', 'config_app' => 'infolog',
'config_name' => 'history', 'config_name' => 'history',
),__FILE__,__LINE__); ),__FILE__,__LINE__);
// RalfBecker: php.net recommend this for security reasons, it should be our default too // RalfBecker: php.net recommend this for security reasons, it should be our default too
$current_config['usecookies'] = 'True'; $current_config['usecookies'] = 'True';
@ -294,6 +294,9 @@ class setup_process
$current_config['postpone_statistics_submit'] = time() + 2 * 30 * 3600; // ask user in 2 month from now, when he has something to report $current_config['postpone_statistics_submit'] = time() + 2 * 30 * 3600; // ask user in 2 month from now, when he has something to report
// use ssha (salted sha1) password hashes by default
$current_config['sql_encryption_type'] = $current_config['ldap_encryption_type'] = 'ssha';
if ($preset_config) if ($preset_config)
{ {
$current_config = array_merge($current_config,$preset_config); $current_config = array_merge($current_config,$preset_config);