- massive code cleanup

- added md5_hmac auth type
- added support for password migration
This commit is contained in:
Cornelius Weiß 2005-05-10 19:00:55 +00:00
parent ba85974cef
commit 79c9507039
2 changed files with 131 additions and 235 deletions

View File

@ -22,11 +22,11 @@
/* $Id$ */
if(empty($GLOBALS['phpgw_info']['server']['auth_type']))
if(empty($GLOBALS['egw_info']['server']['auth_type']))
{
$GLOBALS['phpgw_info']['server']['auth_type'] = 'sql';
$GLOBALS['egw_info']['server']['auth_type'] = 'sql';
}
include(PHPGW_API_INC.'/class.auth_'.$GLOBALS['phpgw_info']['server']['auth_type'].'.inc.php');
include(PHPGW_API_INC.'/class.auth_'.$GLOBALS['egw_info']['server']['auth_type'].'.inc.php');
class auth extends auth_
{
@ -77,6 +77,38 @@
return $this->encrypt_ldap($password);
}
/*!
@function compare_password
@abstract compagres an encrypted password
@abstract encryption type set in setup and calls the appropriate encryption functions
@param $cleartext cleartext password
@param $encrypted encrypted password
@param $type type of encryption
@param $username used as optional key of encryption for md5_hmac
*/
function compare_password($cleartext,$encrypted,$type,$username='')
{
switch($type)
{
case 'smd5':
return $this->smd5_compare($cleartext,$encrypted);
case 'sha':
return $this->sha_compare($cleartext,$encrypted);
case 'ssha':
return $this->ssha_compare($cleartext,$encrypted);
case 'crypt':
case 'md5_crypt':
case 'blowfish_crypt':
case 'ext_crypt':
return $this->crypt_compare($cleartext,$encrypted,$type);
case 'md5_hmac':
return $this->md5_hmac_compare($cleartext,$encrypted,$username);
case 'md5':
default:
return strcmp(md5($cleartext),$encrypted) == 0 ? true : false;
}
}
/*!
@function encrypt_ldap
@abstract encrypt password for ldap
@ -304,5 +336,26 @@
}
return False;
}
/**
@function md5_hmac_compare
@abstract compare md5_hmac-encrypted passwords for authentication (see RFC2104)
@param $form_val user input value for comparison
@param $db_val stored value (from database)
@param $key key for md5_hmac-encryption (username for imported smf users)
@return boolean True on successful comparison
*/
function md5_hmac_compare($form_val,$db_val,$key)
{
$key = str_pad(strlen($key) <= 64 ? $key : pack('H*', md5($key)), 64, chr(0x00));
$md5_hmac = md5(($key ^ str_repeat(chr(0x5c), 64)) . pack('H*', md5(($key ^ str_repeat(chr(0x36), 64)). $form_val)));
if(strcmp($md5_hmac,$db_val) == 0)
{
return True;
}
return False;
}
}
?>

View File

@ -6,6 +6,9 @@
* Encryption types other than md5() added by *
* Miles Lott <milos@groupwhere.org> based on code from *
* http://www.thomas-alfeld.de/frank/ *
* massive code cleanup and *
* added password migration by *
* Cornelius Weiss <egw@von-und-zu-weiss.de *
* Authentication based on SQL table *
* Copyright (C) 2000, 2001 Dan Kuykendall *
* ------------------------------------------------------------------------ *
@ -31,129 +34,68 @@
function auth_()
{
copyobj($GLOBALS['phpgw']->db,$this->db);
copyobj($GLOBALS['egw']->db,$this->db);
$this->type = @$GLOBALS['egw_info']['server']['sql_encryption_type']
? strtolower($GLOBALS['egw_info']['server']['sql_encryption_type'])
: 'md5';
}
/*!
@function authenticate
@abstract password authentication against password stored in sql datababse
@param $username username of account to authenticate
@param $passwd corresponding password
@param $passwd_type 'text' for cleartext passwords
*/
function authenticate($username, $passwd, $passwd_type)
{
/* normal web form login */
if($passwd_type == 'text')
{
/* normal web form login */
$type = @$GLOBALS['phpgw_info']['server']['sql_encryption_type']
? strtolower($GLOBALS['phpgw_info']['server']['sql_encryption_type'])
: 'md5';
switch($type)
$this->db->query("SELECT account_lid,account_pwd,account_lastlogin FROM phpgw_accounts WHERE account_lid = '$username' AND "
. " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($GLOBALS['egw_info']['server']['case_sensitive_username'] == true)
{
case 'smd5':
$this->db->query("SELECT account_lid,account_pwd FROM phpgw_accounts WHERE account_lid = '$username' AND "
. " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
{
if($this->db->f('account_lid') != $username)
{
return false;
}
}
if($this->db->f('account_pwd'))
{
return $this->smd5_compare($passwd,$this->db->f('account_pwd'));
}
break;
case 'sha':
$this->db->query("SELECT account_lid,account_pwd FROM phpgw_accounts WHERE account_lid = '$username' AND "
. " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
{
if($this->db->f('account_lid') != $username)
{
return false;
}
}
if($this->db->f('account_pwd'))
{
return $this->sha_compare($passwd,$this->db->f('account_pwd'));
}
break;
case 'ssha':
$this->db->query("SELECT account_lid,account_pwd FROM phpgw_accounts WHERE account_lid = '$username' AND "
. " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
{
if($this->db->f('account_lid') != $username)
{
return false;
}
}
if($this->db->f('account_pwd'))
{
return $this->ssha_compare($passwd,$this->db->f('account_pwd'));
}
break;
case 'md5_crypt':
case 'blowfish_crypt':
case 'ext_crypt':
case 'crypt':
$this->db->query("SELECT account_lid,account_pwd FROM phpgw_accounts WHERE account_lid = '$username' AND "
. " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
{
if($this->db->f('account_lid') != $username)
{
return false;
}
}
if($this->db->f('account_pwd'))
{
return $this->crypt_compare($passwd,$this->db->f('account_pwd'),$type);
}
break;
case 'md5':
default:
$this->db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND "
. " account_type='u' AND "
. "account_pwd='" . md5($passwd) . "' AND account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
{
if($this->db->f('account_lid') != $username)
{
return false;
}
}
if($this->db->f('account_lid'))
{
$this->previous_login = $this->db->f('account_lastlogin');
return True;
}
else
{
return False;
}
break;
if($this->db->f('account_lid') != $username) return false;
}
if(!$this->db->f('account_pwd')) return false;
if(!$this->compare_password($passwd,$this->db->f('account_pwd'),$this->type,strtolower($username)))
{
// do we have to migrate an old password ?
if($GLOBALS['egw_info']['server']['passwd_migration_allowed'])
{
foreach($GLOBALS['egw_info']['server']['passwd_migration_types'] as $type)
{
if($this->compare_password($passwd,$this->db->f('account_pwd'),$type,strtolower($username)))
{
$account_id = $GLOBALS['egw_info']['user']['account_id'];
$encrypted_passwd = $this->encrypt_sql($passwd);
$this->_update_passwd($encrypted_passwd,$passwd,$account_id,false,__FILE__);
break;
}
}
}
else
{
return false;
}
}
/* if this point is reached, auth was successfull */
$this->previous_login = $this->db->f('account_lastlogin');
return true;
}
elseif($passwd_type == 'md5')
/* Auth via crypted password. NOTE: mail needs cleartext password to authenticate against mailserver! */
else
{
/* Where is this used? */
$this->db->query("SELECT * FROM phpgw_accounts WHERE account_lid = '$username' AND "
// . " account_type='u' AND "
. "account_pwd='" . $passwd . "' AND account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($GLOBALS['phpgw_info']['server']['case_sensitive_username'] == true)
if($GLOBALS['egw_info']['server']['case_sensitive_username'] == true)
{
if($this->db->f('account_lid') != $username)
{
@ -170,139 +112,40 @@
return False;
}
}
else
{
return False;
}
}
/*!
@function change_password
@abstract changes password in sql datababse
@param $old_passwd must be cleartext
@param $new_passwd must be cleartext
@param $account_id account id of user whose passwd should be changed
*/
function change_password($old_passwd, $new_passwd, $account_id = '')
{
$admin = True;
// Don't allow password changes for other accounts when using XML-RPC
if(!$account_id || $GLOBALS['phpgw_info']['flags']['currentapp'] == 'login')
if(!$account_id || $GLOBALS['egw_info']['flags']['currentapp'] == 'login')
{
$admin = False;
$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
$account_id = $GLOBALS['egw_info']['user']['account_id'];
}
$encrypted_passwd = $this->encrypt_sql($new_passwd);
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
. "' AND " // . " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if(!$this->db->f('account_pwd')) return false;
/* Grab configured type, or default to md5() (old method) */
$type = @$GLOBALS['phpgw_info']['server']['sql_encryption_type']
? strtolower($GLOBALS['phpgw_info']['server']['sql_encryption_type'])
: 'md5';
switch($type)
/* Check the old_passwd to make sure this is legal */
if(!$admin)
{
case 'smd5':
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
. "' AND " // . " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($this->db->f('account_pwd'))
{
if(!$admin)
{
/* Check the old_passwd to make sure this is legal */
if(!$this->smd5_compare($old_passwd,$this->db->f('account_pwd')))
{
return False;
}
}
/* old password ok, or admin called the function from
* the admin application (no old passwd available).
*/
return $this->_update_passwd($encrypted_passwd,$new_passwd,$account_id,$admin,__FILE__);
}
return False;
case 'sha':
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
. "' AND " // . " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($this->db->f('account_pwd'))
{
if(!$admin)
{
/* Check the old_passwd to make sure this is legal */
if(!$this->sha_compare($old_passwd,$this->db->f('account_pwd')))
{
return False;
}
}
/* old password ok, or admin called the function from
* the admin application (no old passwd available).
*/
return $this->_update_passwd($encrypted_passwd,$new_passwd,$account_id,$admin,__FILE__);
}
return False;
case 'ssha':
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
. "' AND " // . " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($this->db->f('account_pwd'))
{
if(!$admin)
{
/* Check the old_passwd to make sure this is legal */
if(!$this->ssha_compare($old_passwd,$this->db->f('account_pwd')))
{
return False;
}
}
/* old password ok, or admin called the function from
* the admin application (no old passwd available).
*/
return $this->_update_passwd($encrypted_passwd,$new_passwd,$account_id,$admin,__FILE__);
}
return False;
case 'crypt':
case 'ext_crypt':
case 'md5_crypt':
case 'blowfish_crypt':
$this->db->query("SELECT account_pwd FROM phpgw_accounts WHERE account_id = '" . (int)$account_id
. "' AND " // . " account_type='u' AND "
. " account_status ='A'",__LINE__,__FILE__);
$this->db->next_record();
if($this->db->f('account_pwd'))
{
if(!$admin)
{
/* Check the old_passwd to make sure this is legal */
if(!$this->crypt_compare($old_passwd,$this->db->f('account_pwd'),$type))
{
return False;
}
}
/* old password ok, or admin called the function from
* the admin application (no old passwd available).
*/
return $this->_update_passwd($encrypted_passwd,$new_passwd,$account_id,$admin,__FILE__);
}
return False;
case 'md5':
default:
$pwd_check = '';
if(!$admin)
{
$pwd_check = " AND account_pwd='" . $this->encrypt_sql($old_passwd) . "'";
}
$this->db->query("UPDATE phpgw_accounts SET account_pwd='" . $encrypted_passwd . "',"
. "account_lastpwd_change='" . time() . "' WHERE account_id='" . $account_id . "'" . $pwd_check,__LINE__,__FILE__);
$this->db->next_record();
if($this->db->affected_rows())
{
if(!$admin)
{
$GLOBALS['phpgw']->session->appsession('password','phpgwapi',$new_passwd);
}
return $encrypted_passwd;
}
else
{
return False;
}
if(!$this->compare_password($old_passwd,$this->db->f('account_pwd'),$this->type,strtolower($username))) return false;
}
/* old password ok, or admin called the function from the admin application (no old passwd available).*/
$encrypted_passwd = $this->encrypt_sql($new_passwd);
return $this->_update_passwd($encrypted_passwd,$new_passwd,$account_id,$admin,__FILE__);
}
function _update_passwd($encrypted_passwd,$new_passwd,$account_id,$admin=False,$file='')
@ -320,7 +163,7 @@
{
if(!$admin)
{
$GLOBALS['phpgw']->session->appsession('password','phpgwapi',$new_passwd);
$GLOBALS['egw']->session->appsession('password','phpgwapi',$new_passwd);
}
return $encrypted_passwd;
}
@ -332,7 +175,7 @@
function update_lastlogin($account_id, $ip)
{
$GLOBALS['phpgw']->db->query("UPDATE phpgw_accounts SET account_lastloginfrom='"
$GLOBALS['egw']->db->query("UPDATE phpgw_accounts SET account_lastloginfrom='"
. "$ip', account_lastlogin='" . time()
. "' WHERE account_id='$account_id'",__LINE__,__FILE__);
}