From 540ccab0258e6f0ef6616e2ccbc26e4588252ddd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 23 Sep 2011 11:46:16 +0000 Subject: [PATCH] Sec: Fix security login mutualized function. --- htdocs/cashdesk/class/Auth.class.php | 77 ++++++---------- htdocs/core/class/conf.class.php | 2 +- htdocs/lib/security.lib.php | 126 +++++++++++++++++++-------- htdocs/lib/ws.lib.php | 44 ++++++---- test/phpunit/WebservicesTest.php | 2 +- 5 files changed, 145 insertions(+), 106 deletions(-) diff --git a/htdocs/cashdesk/class/Auth.class.php b/htdocs/cashdesk/class/Auth.class.php index 0cd6683887f..1ab7481582f 100644 --- a/htdocs/cashdesk/class/Auth.class.php +++ b/htdocs/cashdesk/class/Auth.class.php @@ -30,10 +30,10 @@ class Auth var $reponse; var $sqlQuery; - + /** * Enter description here ... - * + * * @param unknown_type $DB */ function Auth($DB) @@ -46,7 +46,7 @@ class Auth /** * Enter description here ... - * + * * @param unknown_type $aLogin */ function login($aLogin) @@ -55,10 +55,10 @@ class Auth $this->login = $aLogin; } - + /** * Enter description here ... - * + * * @param unknown_type $aPasswd */ function passwd($aPasswd) @@ -68,10 +68,10 @@ class Auth } - + /** * Enter description here ... - * + * * @param unknown_type $aReponse */ function reponse($aReponse) @@ -82,24 +82,26 @@ class Auth } /** - * Enter description here ... - * - * @param unknown_type $aLogin - * @param unknown_type $aPasswd + * Validate login/pass + * + * @param string $aLogin Login + * @param string $aPasswd Password */ function verif($aLogin, $aPasswd) { - global $conf,$dolibarr_main_authentication,$langs; + global $conf,$langs; + global $dolibarr_main_authentication,$dolibarr_auto_user; $ret=-1; $login=''; + $test=true; + // Authentication mode if (empty($dolibarr_main_authentication)) $dolibarr_main_authentication='http,dolibarr'; // Authentication mode: forceuser if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) $dolibarr_auto_user='auto'; - // Set authmode $authmode=explode(',',$dolibarr_main_authentication); @@ -111,16 +113,9 @@ class Auth exit; } - - $test=true; - - // Validation of third party module login method - if (is_array($conf->login_method_modules) && !empty($conf->login_method_modules)) - { - include_once(DOL_DOCUMENT_ROOT . "/lib/security.lib.php"); - $login = getLoginMethod($_POST["username"],$_POST["password"],$_POST["entity"]); - if ($login) $test=false; - } + $usertotest=$aLogin; + $passwordtotest=$aPasswd; + $entitytotest=$conf->entity; // Validation tests user / password // If ok, the variable will be initialized login @@ -131,34 +126,16 @@ class Auth if ($test && $goontestloop) { - foreach($authmode as $mode) + $login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode); + if ($login) { - if ($test && $mode && ! $login) - { - $authfile=DOL_DOCUMENT_ROOT.'/includes/login/functions_'.$mode.'.php'; - $result=include_once($authfile); - if ($result) - { - $this->login($aLogin); - $this->passwd($aPasswd); - $entitytotest=$conf->entity; - - $function='check_user_password_'.$mode; - $login=$function($aLogin,$aPasswd,$entitytotest); - if ($login) // Login is successfull - { - $test=false; - $dol_authmode=$mode; // This properties is defined only when logged to say what mode was successfully used - $ret=0; - } - } - else - { - dol_syslog("Authentification ko - failed to load file '".$authfile."'",LOG_ERR); - sleep(1); - $ret=-1; - } - } + $this->login($aLogin); + $this->passwd($aPasswd); + $ret=0; + } + else + { + $ret=-1; } } diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 4a9da4970a8..601d31dc199 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -57,7 +57,7 @@ class Conf var $tabs_modules = array(); var $triggers_modules = array(); var $hooks_modules = array(); - var $login_method_modules = array(); + public $login_method_modules = array(); var $modules = array(); var $entities = array(); diff --git a/htdocs/lib/security.lib.php b/htdocs/lib/security.lib.php index 1d50ad4f642..28f26c1a187 100644 --- a/htdocs/lib/security.lib.php +++ b/htdocs/lib/security.lib.php @@ -24,61 +24,113 @@ /** - * Return a login if login/pass was successfull using an external login method. + * Return a login if login/pass was successfull * * @param string $usertotest Login value to test * @param string $passwordtotest Password value to test * @param string $entitytotest Instance to test + * @param array $authmode Array list of selected authentication mode ('http', 'dolibarr', 'xxx'...) * @return string Login or '' */ -function getLoginMethod($usertotest,$passwordtotest,$entitytotest=1) +function checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode) { global $conf,$langs; + global $dolauthmode; // To return authentication finally used + // Check parameetrs + if ($entitytotest == '') $entitytotest=1; + + dol_syslog("checkLoginPassEntity usertotest=".$usertotest." entitytotest=".$entitytotest." authmode=".join(',',$authmode)); $login = ''; - foreach($conf->login_method_modules as $dir) + // Validation of login/pass/entity with a third party login module method + if (is_array($conf->login_method_modules) && !empty($conf->login_method_modules)) { - // Check if directory exists - if (!is_dir($dir)) continue; + foreach($conf->login_method_modules as $dir) + { + $newdir=dol_osencode($dir); - $handle=opendir($dir); - if (is_resource($handle)) - { - while (($file = readdir($handle))!==false) - { - if (is_readable($dir.'/'.$file) && preg_match('/^functions_([^_]+)\.php/',$file,$reg)) - { - $authfile = $dir.'/'.$file; - $mode = $reg[1]; + // Check if directory exists + if (!is_dir($newdir)) continue; - $result=include_once($authfile); - if ($result) - { - // Call function to check user/password - $function='check_user_password_'.$mode; - $login=call_user_func($function,$usertotest,$passwordtotest,$entitytotest); - if ($login) - { - $conf->authmode=$mode; // This properties is defined only when logged - } - } - else - { - dol_syslog("Authentification ko - failed to load file '".$authfile."'",LOG_ERR); - sleep(1); // To slow brut force cracking - $langs->load('main'); - $langs->load('other'); - $_SESSION["dol_loginmesg"]=$langs->trans("ErrorFailedToLoadLoginFileForMode",$mode); - } - } - } - } - closedir($handle); + $handle=opendir($newdir); + if (is_resource($handle)) + { + while (($file = readdir($handle))!==false) + { + if (is_readable($dir.'/'.$file) && preg_match('/^functions_([^_]+)\.php/',$file,$reg)) + { + $authfile = $dir.'/'.$file; + $mode = $reg[1]; + + $result=include_once($authfile); + if ($result) + { + // Call function to check user/password + $function='check_user_password_'.$mode; + $login=call_user_func($function,$usertotest,$passwordtotest,$entitytotest); + if ($login) + { + $conf->authmode=$mode; // This properties is defined only when logged to say what mode was successfully used + } + } + else + { + dol_syslog("Authentification ko - failed to load file '".$authfile."'",LOG_ERR); + sleep(1); // To slow brut force cracking + $langs->load('main'); + $langs->load('other'); + $_SESSION["dol_loginmesg"]=$langs->trans("ErrorFailedToLoadLoginFileForMode",$mode); + } + } + } + closedir($handle); + } + } } + + // Validation of login/pass/entity with standard modules + if (empty($login)) + { + $test=true; + foreach($authmode as $mode) + { + if ($test && $mode && ! $login) + { + $mode=trim($mode); + $authfile=DOL_DOCUMENT_ROOT.'/includes/login/functions_'.$mode.'.php'; + $result=include_once($authfile); + if ($result) + { + // Call function to check user/password + $function='check_user_password_'.$mode; + $login=call_user_func($function,$usertotest,$passwordtotest,$entitytotest); + if ($login) // Login is successfull + { + $test=false; // To stop once at first login success + $conf->authmode=$mode; // This properties is defined only when logged to say what mode was successfully used + $dol_tz=$_POST["tz"]; + $dol_dst=$_POST["dst"]; + $dol_screenwidth=$_POST["screenwidth"]; + $dol_screenheight=$_POST["screenheight"]; + } + } + else + { + dol_syslog("Authentification ko - failed to load file '".$authfile."'",LOG_ERR); + sleep(1); + $langs->load('main'); + $langs->load('other'); + $_SESSION["dol_loginmesg"]=$langs->trans("ErrorFailedToLoadLoginFileForMode",$mode); + } + } + } + } + return $login; } + /** * Show Dolibarr default login page * diff --git a/htdocs/lib/ws.lib.php b/htdocs/lib/ws.lib.php index 82ecf7805c6..73a538e144a 100755 --- a/htdocs/lib/ws.lib.php +++ b/htdocs/lib/ws.lib.php @@ -24,6 +24,7 @@ /** * Check authentication array and set error, errorcode, errorlabel + * * @param authentication Array * @param error * @param errorcode @@ -32,6 +33,7 @@ function check_authentication($authentication,&$error,&$errorcode,&$errorlabel) { global $db,$conf,$langs; + global $dolibarr_main_authentication,$dolibarr_auto_user; $fuser=new User($db); @@ -50,26 +52,34 @@ function check_authentication($authentication,&$error,&$errorcode,&$errorlabel) if (! $error) { $result=$fuser->fetch('',$authentication['login'],'',0); - if ($result <= 0) $error++; - - // Validation of login with a third party login module method - if (! $error) - { - if (is_array($conf->login_method_modules) && !empty($conf->login_method_modules)) - { - $login = getLoginMethod($authentication['login'],$authentication['password'],$authentication['entity']); - if (empty($login)) $error++; - } - else - { - $errorcode='BAD_LOGIN_METHOD'; $errorlabel='Bad value for login method'; - } - } - - if ($error) + if ($result < 0) { + $error++; + $errorcode='ERROR_FETCH_USER'; $errorlabel='A technical error occurs during fetch of user'; + } + else if ($result == 0) + { + $error++; $errorcode='BAD_CREDENTIALS'; $errorlabel='Bad value for login or password'; } + + // Validation of login + if (! $error) + { + // Authentication mode + if (empty($dolibarr_main_authentication)) $dolibarr_main_authentication='http,dolibarr'; + // Authentication mode: forceuser + if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) $dolibarr_auto_user='auto'; + // Set authmode + $authmode=explode(',',$dolibarr_main_authentication); + + $login = checkLoginPassEntity($authentication['login'],$authentication['password'],$authentication['entity'],$authmode); + if (empty($login)) + { + $error++; + $errorcode='BAD_CREDENTIALS'; $errorlabel='Bad value for login or password'; + } + } } return $fuser; diff --git a/test/phpunit/WebservicesTest.php b/test/phpunit/WebservicesTest.php index 8eaf1f64853..a24f4e58521 100755 --- a/test/phpunit/WebservicesTest.php +++ b/test/phpunit/WebservicesTest.php @@ -17,7 +17,7 @@ */ /** - * \file test/phpunit/DateLibTest.php + * \file test/phpunit/WebservicesTest.php * \ingroup test * \brief PHPUnit test * \remarks To run this script as CLI: phpunit filename.php