Sec: Fix security login mutualized function.

This commit is contained in:
Laurent Destailleur 2011-09-23 11:46:16 +00:00
parent e7565a265f
commit 540ccab025
5 changed files with 145 additions and 106 deletions

View File

@ -82,24 +82,26 @@ class Auth
} }
/** /**
* Enter description here ... * Validate login/pass
* *
* @param unknown_type $aLogin * @param string $aLogin Login
* @param unknown_type $aPasswd * @param string $aPasswd Password
*/ */
function verif($aLogin, $aPasswd) function verif($aLogin, $aPasswd)
{ {
global $conf,$dolibarr_main_authentication,$langs; global $conf,$langs;
global $dolibarr_main_authentication,$dolibarr_auto_user;
$ret=-1; $ret=-1;
$login=''; $login='';
$test=true;
// Authentication mode // Authentication mode
if (empty($dolibarr_main_authentication)) $dolibarr_main_authentication='http,dolibarr'; if (empty($dolibarr_main_authentication)) $dolibarr_main_authentication='http,dolibarr';
// Authentication mode: forceuser // Authentication mode: forceuser
if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) $dolibarr_auto_user='auto'; if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) $dolibarr_auto_user='auto';
// Set authmode // Set authmode
$authmode=explode(',',$dolibarr_main_authentication); $authmode=explode(',',$dolibarr_main_authentication);
@ -111,16 +113,9 @@ class Auth
exit; exit;
} }
$usertotest=$aLogin;
$test=true; $passwordtotest=$aPasswd;
$entitytotest=$conf->entity;
// 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;
}
// Validation tests user / password // Validation tests user / password
// If ok, the variable will be initialized login // If ok, the variable will be initialized login
@ -131,34 +126,16 @@ class Auth
if ($test && $goontestloop) if ($test && $goontestloop)
{ {
foreach($authmode as $mode) $login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode);
if ($login)
{ {
if ($test && $mode && ! $login) $this->login($aLogin);
{ $this->passwd($aPasswd);
$authfile=DOL_DOCUMENT_ROOT.'/includes/login/functions_'.$mode.'.php'; $ret=0;
$result=include_once($authfile); }
if ($result) else
{ {
$this->login($aLogin); $ret=-1;
$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;
}
}
} }
} }

View File

@ -57,7 +57,7 @@ class Conf
var $tabs_modules = array(); var $tabs_modules = array();
var $triggers_modules = array(); var $triggers_modules = array();
var $hooks_modules = array(); var $hooks_modules = array();
var $login_method_modules = array(); public $login_method_modules = array();
var $modules = array(); var $modules = array();
var $entities = array(); var $entities = array();

View File

@ -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 $usertotest Login value to test
* @param string $passwordtotest Password value to test * @param string $passwordtotest Password value to test
* @param string $entitytotest Instance to test * @param string $entitytotest Instance to test
* @param array $authmode Array list of selected authentication mode ('http', 'dolibarr', 'xxx'...)
* @return string Login or '' * @return string Login or ''
*/ */
function getLoginMethod($usertotest,$passwordtotest,$entitytotest=1) function checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode)
{ {
global $conf,$langs; 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 = ''; $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 foreach($conf->login_method_modules as $dir)
if (!is_dir($dir)) continue; {
$newdir=dol_osencode($dir);
$handle=opendir($dir); // Check if directory exists
if (is_resource($handle)) if (!is_dir($newdir)) continue;
{
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); $handle=opendir($newdir);
if ($result) if (is_resource($handle))
{ {
// Call function to check user/password while (($file = readdir($handle))!==false)
$function='check_user_password_'.$mode; {
$login=call_user_func($function,$usertotest,$passwordtotest,$entitytotest); if (is_readable($dir.'/'.$file) && preg_match('/^functions_([^_]+)\.php/',$file,$reg))
if ($login) {
{ $authfile = $dir.'/'.$file;
$conf->authmode=$mode; // This properties is defined only when logged $mode = $reg[1];
}
} $result=include_once($authfile);
else if ($result)
{ {
dol_syslog("Authentification ko - failed to load file '".$authfile."'",LOG_ERR); // Call function to check user/password
sleep(1); // To slow brut force cracking $function='check_user_password_'.$mode;
$langs->load('main'); $login=call_user_func($function,$usertotest,$passwordtotest,$entitytotest);
$langs->load('other'); if ($login)
$_SESSION["dol_loginmesg"]=$langs->trans("ErrorFailedToLoadLoginFileForMode",$mode); {
} $conf->authmode=$mode; // This properties is defined only when logged to say what mode was successfully used
} }
} }
} else
closedir($handle); {
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; return $login;
} }
/** /**
* Show Dolibarr default login page * Show Dolibarr default login page
* *

View File

@ -24,6 +24,7 @@
/** /**
* Check authentication array and set error, errorcode, errorlabel * Check authentication array and set error, errorcode, errorlabel
*
* @param authentication Array * @param authentication Array
* @param error * @param error
* @param errorcode * @param errorcode
@ -32,6 +33,7 @@
function check_authentication($authentication,&$error,&$errorcode,&$errorlabel) function check_authentication($authentication,&$error,&$errorcode,&$errorlabel)
{ {
global $db,$conf,$langs; global $db,$conf,$langs;
global $dolibarr_main_authentication,$dolibarr_auto_user;
$fuser=new User($db); $fuser=new User($db);
@ -50,26 +52,34 @@ function check_authentication($authentication,&$error,&$errorcode,&$errorlabel)
if (! $error) if (! $error)
{ {
$result=$fuser->fetch('',$authentication['login'],'',0); $result=$fuser->fetch('',$authentication['login'],'',0);
if ($result <= 0) $error++; if ($result < 0)
// 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)
{ {
$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'; $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; return $fuser;

View File

@ -17,7 +17,7 @@
*/ */
/** /**
* \file test/phpunit/DateLibTest.php * \file test/phpunit/WebservicesTest.php
* \ingroup test * \ingroup test
* \brief PHPUnit test * \brief PHPUnit test
* \remarks To run this script as CLI: phpunit filename.php * \remarks To run this script as CLI: phpunit filename.php