Move security function into security.lib.php

Split security.lib.php into 2 files: One always loaded, the other for
rare functions.
This commit is contained in:
Laurent Destailleur 2012-02-12 17:41:28 +01:00
parent 2a5f299ddd
commit 036e578e0f
17 changed files with 942 additions and 880 deletions

View File

@ -767,7 +767,8 @@ class Adherent extends CommonObject
// If new password not provided, we generate one
if (! $password)
{
$password=getRandomPassword('');
require_once(DOL_DOCUMENT_ROOT."/core/lib/security2.lib.php");
$password=getRandomPassword('');
}
// Cryptage mot de passe

View File

@ -706,7 +706,8 @@ if ($action == 'create')
// Password
if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED))
{
$generated_password=getRandomPassword('');
require_once(DOL_DOCUMENT_ROOT."/core/lib/security2.lib.php");
$generated_password=getRandomPassword('');
print '<tr><td><span class="fieldrequired">'.$langs->trans("Password").'</span></td><td>';
print '<input size="30" maxsize="32" type="text" name="password" value="'.$generated_password.'">';
print '</td></tr>';

View File

@ -24,6 +24,7 @@
require("../main.inc.php");
require_once(DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php");
require_once(DOL_DOCUMENT_ROOT."/core/lib/security2.lib.php");
$langs->load("users");
$langs->load("admin");

View File

@ -122,6 +122,7 @@ class Auth
if ($test && $goontestloop)
{
include_once(DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php');
$login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode);
if ($login)
{

View File

@ -42,10 +42,10 @@ abstract class ActionsContactCardCommon
//! Error array
var $errors=array();
/**
* Instantiation of DAO class
*
*
* @return void
*/
private function getInstanceDao()
@ -66,7 +66,7 @@ abstract class ActionsContactCardCommon
}
}
}
/**
* Get object
*
@ -76,7 +76,7 @@ abstract class ActionsContactCardCommon
function getObject($id)
{
$ret = $this->getInstanceDao();
if (is_object($this->object) && method_exists($this->object,'fetch'))
{
if (! empty($id)) $this->object->fetch($id);
@ -192,7 +192,7 @@ abstract class ActionsContactCardCommon
Header("Location: ".$_SERVER["PHP_SELF"]."?id=".$this->object->id);
exit;
}
if (empty($_POST["name"]))
{
$this->error=array($langs->trans("ErrorFieldRequired",$langs->transnoentities("Name").' / '.$langs->transnoentities("Label")));
@ -391,21 +391,22 @@ abstract class ActionsContactCardCommon
$this->tpl['note'] = nl2br($this->object->note);
}
if ($action == 'create_user')
{
// Full firstname and name separated with a dot : firstname.name
include_once(DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php');
require_once(DOL_DOCUMENT_ROOT."/core/lib/security2.lib.php");
$login=dol_buildlogin($this->object->nom, $this->object->prenom);
$generated_password=getRandomPassword('');
$password=$generated_password;
// Create a form array
$formquestion=array(
array('label' => $langs->trans("LoginToCreate"), 'type' => 'text', 'name' => 'login', 'value' => $login),
array('label' => $langs->trans("Password"), 'type' => 'text', 'name' => 'password', 'value' => $password));
$this->tpl['action_create_user'] = $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$this->object->id,$langs->trans("CreateDolibarrLogin"),$langs->trans("ConfirmCreateContact"),"confirm_create_user",$formquestion,'no');
}
}

View File

@ -705,7 +705,8 @@ else
$generated_password='';
if (! $ldap_sid) // TODO ldap_sid ?
{
$generated_password=getRandomPassword('');
require_once(DOL_DOCUMENT_ROOT."/core/lib/security2.lib.php");
$generated_password=getRandomPassword('');
}
$password=$generated_password;

View File

@ -43,11 +43,12 @@ top_httphead();
//print '<!-- Ajax page called with url '.$_SERVER["PHP_SELF"].'?'.$_SERVER["QUERY_STRING"].' -->'."\n";
// Registering the location of boxes
if(isset($_GET['action']) && ! empty($_GET['action']))
if (isset($_GET['action']) && ! empty($_GET['action']))
{
if ($_GET['action'] == 'getrandompassword' && $user->admin)
{
$generic = $_GET['generic'];
require_once(DOL_DOCUMENT_ROOT."/core/lib/security2.lib.php");
$generic = $_GET['generic'];
echo getRandomPassword($generic);
}
}

View File

@ -2151,407 +2151,6 @@ function info_admin($text,$infoonimgalt=0)
}
/**
* Check permissions of a user to show a page and an object. Check read permission.
* If GETPOST('action') defined, we also check write and delete permission.
*
* @param User $user User to check
* @param string $features Features to check (in most cases, it's module name)
* @param int $objectid Object ID if we want to check permission on a particular record (optionnal)
* @param string $dbtablename Table name where object is stored. Not used if objectid is null (optionnal)
* @param string $feature2 Feature to check, second level of permission (optionnal)
* @param string $dbt_keyfield Field name for socid foreign key if not fk_soc (optionnal)
* @param string $dbt_select Field name for select if not rowid (optionnal)
* @param Canvas $objcanvas Object canvas
* @return int Always 1, die process if not allowed
*/
function restrictedArea($user, $features='societe', $objectid=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null)
{
global $db, $conf;
//dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename,$feature2,$dbt_socfield,$dbt_select");
//print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid;
//print ", dbtablename=".$dbtablename.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select;
//print ", perm: ".$features."->".$feature2."=".$user->rights->$features->$feature2->lire."<br>";
// If we use canvas, we try to use function that overlod restrictarea if provided with canvas
if (is_object($objcanvas))
{
if (method_exists($objcanvas->control,'restrictedArea')) return $objcanvas->control->restrictedArea($user,$features,$objectid,$dbtablename,$feature2,$dbt_keyfield,$dbt_select);
}
if ($dbt_select != 'rowid') $objectid = "'".$objectid."'";
// More features to check
$features = explode("&",$features);
// More parameters
list($dbtablename, $sharedelement) = explode('&', $dbtablename);
// Check read permission from module
// TODO Replace "feature" param into caller by first level of permission
$readok=1;
foreach ($features as $feature)
{
if ($feature == 'societe')
{
if (! $user->rights->societe->lire && ! $user->rights->fournisseur->lire) $readok=0;
}
else if ($feature == 'contact')
{
if (! $user->rights->societe->contact->lire) $readok=0;
}
else if ($feature == 'produit|service')
{
if (! $user->rights->produit->lire && ! $user->rights->service->lire) $readok=0;
}
else if ($feature == 'prelevement')
{
if (! $user->rights->prelevement->bons->lire) $readok=0;
}
else if ($feature == 'commande_fournisseur')
{
if (! $user->rights->fournisseur->commande->lire) $readok=0;
}
else if ($feature == 'cheque')
{
if (! $user->rights->banque->cheque) $readok=0;
}
else if ($feature == 'projet')
{
if (! $user->rights->projet->lire && ! $user->rights->projet->all->lire) $readok=0;
}
else if (! empty($feature2)) // This should be used for future changes
{
if (empty($user->rights->$feature->$feature2->lire)
&& empty($user->rights->$feature->$feature2->read)) $readok=0;
}
else if (! empty($feature) && ($feature!='user' && $feature!='usergroup')) // This is for old permissions
{
if (empty($user->rights->$feature->lire)
&& empty($user->rights->$feature->read)
&& empty($user->rights->$feature->run)) $readok=0;
}
}
if (! $readok)
{
//print "Read access is down";
accessforbidden();
}
//print "Read access is ok";
// Check write permission from module
$createok=1;
if (GETPOST("action") && GETPOST("action") == 'create')
{
foreach ($features as $feature)
{
if ($feature == 'contact')
{
if (! $user->rights->societe->contact->creer) $createok=0;
}
else if ($feature == 'produit|service')
{
if (! $user->rights->produit->creer && ! $user->rights->service->creer) $createok=0;
}
else if ($feature == 'prelevement')
{
if (! $user->rights->prelevement->bons->creer) $createok=0;
}
else if ($feature == 'commande_fournisseur')
{
if (! $user->rights->fournisseur->commande->creer) $createok=0;
}
else if ($feature == 'banque')
{
if (! $user->rights->banque->modifier) $createok=0;
}
else if ($feature == 'cheque')
{
if (! $user->rights->banque->cheque) $createok=0;
}
else if (! empty($feature2)) // This should be used for future changes
{
if (empty($user->rights->$feature->$feature2->creer)
&& empty($user->rights->$feature->$feature2->write)) $createok=0;
}
else if (! empty($feature)) // This is for old permissions
{
//print '<br>feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write;
if (empty($user->rights->$feature->creer)
&& empty($user->rights->$feature->write)) $createok=0;
}
}
if (! $createok) accessforbidden();
//print "Write access is ok";
}
// Check create user permission
$createuserok=1;
if ( GETPOST("action") && (GETPOST("action") == 'confirm_create_user' && GETPOST("confirm") == 'yes') )
{
if (! $user->rights->user->user->creer) $createuserok=0;
if (! $createuserok) accessforbidden();
//print "Create user access is ok";
}
// Check delete permission from module
$deleteok=1;
if ( GETPOST("action") && ( (GETPOST("action") == 'confirm_delete' && GETPOST("confirm") && GETPOST("confirm") == 'yes') || GETPOST("action") == 'delete') )
{
foreach ($features as $feature)
{
if ($feature == 'contact')
{
if (! $user->rights->societe->contact->supprimer) $deleteok=0;
}
else if ($feature == 'produit|service')
{
if (! $user->rights->produit->supprimer && ! $user->rights->service->supprimer) $deleteok=0;
}
else if ($feature == 'commande_fournisseur')
{
if (! $user->rights->fournisseur->commande->supprimer) $deleteok=0;
}
else if ($feature == 'banque')
{
if (! $user->rights->banque->modifier) $deleteok=0;
}
else if ($feature == 'cheque')
{
if (! $user->rights->banque->cheque) $deleteok=0;
}
else if ($feature == 'ecm')
{
if (! $user->rights->ecm->upload) $deleteok=0;
}
else if ($feature == 'ftp')
{
if (! $user->rights->ftp->write) $deleteok=0;
}
else if (! empty($feature2)) // This should be used for future changes
{
if (empty($user->rights->$feature->$feature2->supprimer)
&& empty($user->rights->$feature->$feature2->delete)) $deleteok=0;
}
else if (! empty($feature)) // This is for old permissions
{
//print '<br>feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete;
if (empty($user->rights->$feature->supprimer)
&& empty($user->rights->$feature->delete)) $deleteok=0;
}
}
//print "Delete access is ko";
if (! $deleteok) accessforbidden();
//print "Delete access is ok";
}
// If we have a particular object to check permissions on, we check this object
// is linked to a company allowed to $user.
if (! empty($objectid) && $objectid > 0)
{
foreach ($features as $feature)
{
$sql='';
$check = array('banque','user','usergroup','produit','service','produit|service','categorie'); // Test on entity only (Objects with no link to company)
$checksoc = array('societe'); // Test for societe object
$checkother = array('contact'); // Test on entity and link to societe. Allowed if link is empty (Ex: contacts...).
$checkproject = array('projet'); // Test for project object
$nocheck = array('barcode','stock','fournisseur'); // No test
$checkdefault = 'all other not already defined'; // Test on entity and link to third party. Not allowed if link is empty (Ex: invoice, orders...).
// If dbtable not defined, we use same name for table than module name
if (empty($dbtablename)) $dbtablename = $feature;
// Check permission for object with entity
if (in_array($feature,$check))
{
$sql = "SELECT dbt.".$dbt_select;
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
if (($feature == 'user' || $feature == 'usergroup') && ! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
{
$sql.= " AND dbt.entity IS NOT NULL";
}
else
{
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
}
else if (in_array($feature,$checksoc))
{
// If external user: Check permission for external users
if ($user->societe_id > 0)
{
if ($user->societe_id <> $objectid) accessforbidden();
}
// If internal user: Check permission for internal users that are restricted on their objects
else if (! $user->rights->societe->client->voir)
{
$sql = "SELECT sc.fk_soc";
$sql.= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc";
$sql.= ", ".MAIN_DB_PREFIX."societe as s)";
$sql.= " WHERE sc.fk_soc = ".$objectid;
$sql.= " AND sc.fk_user = ".$user->id;
$sql.= " AND sc.fk_soc = s.rowid";
$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
}
// If multicompany and internal users with all permissions, check user is in correct entity
else if (! empty($conf->multicompany->enabled))
{
$sql = "SELECT s.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."societe as s";
$sql.= " WHERE s.rowid = ".$objectid;
$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
}
}
else if (in_array($feature,$checkother))
{
// If external user: Check permission for external users
if ($user->societe_id > 0)
{
$sql = "SELECT dbt.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND dbt.fk_soc = ".$user->societe_id;
}
// If internal user: Check permission for internal users that are restricted on their objects
else if (! $user->rights->societe->client->voir)
{
$sql = "SELECT dbt.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = '".$user->id."'";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND (dbt.fk_soc IS NULL OR sc.fk_soc IS NOT NULL)"; // Contact not linked to a company or to a company of user
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
// If multicompany and internal users with all permissions, check user is in correct entity
else if (! empty($conf->multicompany->enabled))
{
$sql = "SELECT dbt.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
}
else if (in_array($feature,$checkproject))
{
if (! $user->rights->projet->all->lire)
{
include_once(DOL_DOCUMENT_ROOT."/projet/class/project.class.php");
$projectstatic=new Project($db);
$tmps=$projectstatic->getProjectsAuthorizedForUser($user,0,1,$user->societe_id);
$tmparray=explode(',',$tmps);
if (! in_array($objectid,$tmparray)) accessforbidden();
}
}
else if (! in_array($feature,$nocheck)) // By default we check with link to third party
{
// If external user: Check permission for external users
if ($user->societe_id > 0)
{
$sql = "SELECT dbt.".$dbt_keyfield;
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND dbt.".$dbt_keyfield." = ".$user->societe_id;
}
// If internal user: Check permission for internal users that are restricted on their objects
else if (! $user->rights->societe->client->voir)
{
$sql = "SELECT sc.fk_soc";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= ", ".MAIN_DB_PREFIX."societe as s";
$sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
$sql.= " AND sc.fk_soc = dbt.".$dbt_keyfield;
$sql.= " AND dbt.".$dbt_keyfield." = s.rowid";
$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
$sql.= " AND sc.fk_user = ".$user->id;
}
// If multicompany and internal users with all permissions, check user is in correct entity
else if (! empty($conf->multicompany->enabled))
{
$sql = "SELECT dbt.".$dbt_select;
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
}
//print $sql."<br>";
if ($sql)
{
$resql=$db->query($sql);
if ($resql)
{
if ($db->num_rows($resql) == 0) accessforbidden();
}
else
{
dol_syslog("functions.lib:restrictedArea sql=".$sql, LOG_ERR);
accessforbidden();
}
}
}
}
return 1;
}
/**
* Show a message to say access is forbidden and stop program
* Calling this function terminate execution of PHP.
*
* @param string $message Force error message
* @param int $printheader Show header before
* @param int $printfooter Show footer after
* @param int $showonlymessage Show only message parameter. Otherwise add more information.
* @return void
*/
function accessforbidden($message='',$printheader=1,$printfooter=1,$showonlymessage=0)
{
global $conf, $db, $user, $langs;
if (! is_object($langs))
{
include_once(DOL_DOCUMENT_ROOT.'/core/class/translate.class.php');
$langs=new Translate('',$conf);
}
$langs->load("errors");
if ($printheader)
{
if (function_exists("llxHeader")) llxHeader('');
else if (function_exists("llxHeaderVierge")) llxHeaderVierge('');
}
print '<div class="error">';
if (! $message) print $langs->trans("ErrorForbidden");
else print $message;
print '</div>';
print '<br>';
if (empty($showonlymessage))
{
if ($user->login)
{
print $langs->trans("CurrentLogin").': <font class="error">'.$user->login.'</font><br>';
print $langs->trans("ErrorForbidden2",$langs->trans("Home"),$langs->trans("Users"));
}
else
{
print $langs->trans("ErrorForbidden3");
}
}
if ($printfooter && function_exists("llxFooter")) llxFooter();
exit(0);
}
/* For backward compatibility */
function dolibarr_print_error($db='',$error='')
{

View File

@ -20,437 +20,12 @@
/**
* \file htdocs/core/lib/security.lib.php
* \ingroup core
* \brief Set of function used for dolibarr security.
* \brief Set of function used for dolibarr security (common function included into filefunc.inc.php)
* Warning, this file must not depends on other library files, except function.lib.php
* because it is used at low code level.
*/
/**
* 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 of data we must check
* @param array $authmode Array list of selected authentication mode array('http', 'dolibarr', 'xxx'...)
* @return string Login or ''
*/
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 = '';
// Validation of login/pass/entity with a third party login module method
if (! empty($conf->login_method_modules) && is_array($conf->login_method_modules))
{
foreach($conf->login_method_modules as $dir)
{
$newdir=dol_osencode($dir);
// Check if directory exists
if (! is_dir($newdir)) continue;
$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.'/core/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
*
* @param Translate $langs Lang object (must be initialized by a new).
* @param Conf $conf Conf object
* @param Societe $mysoc Company object
* @return void
*/
function dol_loginfunction($langs,$conf,$mysoc)
{
global $dolibarr_main_demo,$db;
global $smartphone,$mc;
$langcode=(GETPOST('lang')?((is_object($langs)&&$langs->defaultlang)?$langs->defaultlang:'auto'):GETPOST('lang'));
$langs->setDefaultLang($langcode);
$langs->load("main");
$langs->load("other");
$langs->load("help");
$langs->load("admin");
$main_authentication=$conf->file->main_authentication;
$session_name=session_name();
$dol_url_root = DOL_URL_ROOT;
$php_self = $_SERVER['PHP_SELF'];
$php_self.= $_SERVER["QUERY_STRING"]?'?'.$_SERVER["QUERY_STRING"]:'';
// Title
$title='Dolibarr '.DOL_VERSION;
if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $title=$conf->global->MAIN_APPLICATION_TITLE;
// Select templates
if (preg_match('/^smartphone/',$conf->smart_menu) && isset($conf->browser->phone))
{
$template_dir = DOL_DOCUMENT_ROOT.'/theme/phones/smartphone/tpl/';
}
else
{
if (file_exists(DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/tpl/login.tpl.php"))
{
$template_dir = DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/tpl/";
}
else
{
$template_dir = DOL_DOCUMENT_ROOT."/core/tpl/";
}
}
$conf->css = "/theme/".$conf->theme."/style.css.php?lang=".$langs->defaultlang;
$conf_css = DOL_URL_ROOT.$conf->css;
// Set cookie for timeout management
$prefix=dol_getprefix();
$sessiontimeout='DOLSESSTIMEOUT_'.$prefix;
if (! empty($conf->global->MAIN_SESSION_TIMEOUT)) setcookie($sessiontimeout, $conf->global->MAIN_SESSION_TIMEOUT, 0, "/", '', 0);
if (GETPOST("urlfrom")) $_SESSION["urlfrom"]=GETPOST("urlfrom");
else unset($_SESSION["urlfrom"]);
if (! GETPOST("username")) $focus_element='username';
else $focus_element='password';
$login_background=DOL_URL_ROOT.'/theme/login_background.png';
if (file_exists(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/login_background.png'))
{
$login_background=DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/login_background.png';
}
$demologin='';
$demopassword='';
if (! empty($dolibarr_main_demo))
{
$tab=explode(',',$dolibarr_main_demo);
$demologin=$tab[0];
$demopassword=$tab[1];
}
// Entity cookie
if (! empty($conf->multicompany->enabled))
{
$lastuser = '';
$lastentity = $_POST['entity'];
if (! empty($conf->global->MULTICOMPANY_COOKIE_ENABLED))
{
$prefix=dol_getprefix();
$entityCookieName = 'DOLENTITYID_'.$prefix;
if (isset($_COOKIE[$entityCookieName]))
{
include_once(DOL_DOCUMENT_ROOT . "/core/class/cookie.class.php");
$cryptkey = (! empty($conf->file->cookie_cryptkey) ? $conf->file->cookie_cryptkey : '' );
$entityCookie = new DolCookie($cryptkey);
$cookieValue = $entityCookie->_getCookie($entityCookieName);
list($lastuser, $lastentity) = explode('|', $cookieValue);
}
}
}
// Login
$login = (!empty($lastuser)?$lastuser:(GETPOST("username","alpha",2)?GETPOST("username","alpha",2):$demologin));
$password = $demopassword;
// Show logo (search in order: small company logo, large company logo, theme logo, common logo)
$width=0;
$rowspan=2;
$urllogo=DOL_URL_ROOT.'/theme/login_logo.png';
if (! empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small))
{
$urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=companylogo&amp;file='.urlencode('thumbs/'.$mysoc->logo_small);
}
elseif (! empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo))
{
$urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=companylogo&amp;file='.urlencode($mysoc->logo);
$width=128;
}
elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png'))
{
$urllogo=DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png';
}
elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.png'))
{
$urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo.png';
}
// Entity field
$select_entity='';
if (! empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX))
{
$rowspan++;
$select_entity = $mc->select_entities($lastentity, 'entity', ' tabindex="3"', 1);
}
// Security graphical code
$captcha=0;
$captcha_refresh='';
if (function_exists("imagecreatefrompng") && ! empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA))
{
$captcha=1;
$captcha_refresh=img_picto($langs->trans("Refresh"),'refresh');
}
// Extra link
$forgetpasslink=0;
$helpcenterlink=0;
if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK) || empty($conf->global->MAIN_HELPCENTER_DISABLELINK))
{
if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK))
{
$forgetpasslink=1;
}
if (empty($conf->global->MAIN_HELPCENTER_DISABLELINK))
{
$helpcenterlink=1;
}
}
// Home message
if (! empty($conf->global->MAIN_HOME))
{
$i=0;
while (preg_match('/__\(([a-zA-Z]+)\)__/i',$conf->global->MAIN_HOME,$reg) && $i < 100)
{
$conf->global->MAIN_HOME=preg_replace('/__\('.$reg[1].'\)__/i',$langs->trans($reg[1]),$conf->global->MAIN_HOME);
$i++;
}
}
$main_home=dol_htmlcleanlastbr($conf->global->MAIN_HOME);
// Google AD
$main_google_ad_client = ((! empty($conf->global->MAIN_GOOGLE_AD_CLIENT) && ! empty($conf->global->MAIN_GOOGLE_AD_SLOT))?1:0);
$dol_loginmesg = $_SESSION["dol_loginmesg"];
include($template_dir.'login.tpl.php'); // To use native PHP
$_SESSION["dol_loginmesg"] = '';
}
/**
* Fonction pour initialiser un salt pour la fonction crypt.
*
* @param int $type 2=>renvoi un salt pour cryptage DES
* 12=>renvoi un salt pour cryptage MD5
* non defini=>renvoi un salt pour cryptage par defaut
* @return string Salt string
*/
function makesalt($type=CRYPT_SALT_LENGTH)
{
dol_syslog("security.lib.php::makesalt type=".$type);
switch($type)
{
case 12: // 8 + 4
$saltlen=8; $saltprefix='$1$'; $saltsuffix='$'; break;
case 8: // 8 (Pour compatibilite, ne devrait pas etre utilise)
$saltlen=8; $saltprefix='$1$'; $saltsuffix='$'; break;
case 2: // 2
default: // by default, fall back on Standard DES (should work everywhere)
$saltlen=2; $saltprefix=''; $saltsuffix=''; break;
}
$salt='';
while(dol_strlen($salt) < $saltlen) $salt.=chr(mt_rand(64,126));
$result=$saltprefix.$salt.$saltsuffix;
dol_syslog("security.lib.php::makesalt return=".$result);
return $result;
}
/**
* Encode or decode database password in config file
*
* @param int $level Encode level: 0 no encoding, 1 encoding
* @return int <0 if KO, >0 if OK
*/
function encodedecode_dbpassconf($level=0)
{
dol_syslog("security.lib::encodedecode_dbpassconf level=".$level, LOG_DEBUG);
$config = '';
$passwd='';
$passwd_crypted='';
if ($fp = fopen(DOL_DOCUMENT_ROOT.'/conf/conf.php','r'))
{
while(!feof($fp))
{
$buffer = fgets($fp,4096);
$lineofpass=0;
if (preg_match('/^[^#]*dolibarr_main_db_encrypted_pass[\s]*=[\s]*(.*)/i',$buffer,$reg)) // Old way to save crypted value
{
$val = trim($reg[1]); // This also remove CR/LF
$val=preg_replace('/^["\']/','',$val);
$val=preg_replace('/["\'][\s;]*$/','',$val);
if (! empty($val))
{
$passwd_crypted = $val;
$val = dol_decode($val);
$passwd = $val;
$lineofpass=1;
}
}
elseif (preg_match('/^[^#]*dolibarr_main_db_pass[\s]*=[\s]*(.*)/i',$buffer,$reg))
{
$val = trim($reg[1]); // This also remove CR/LF
$val=preg_replace('/^["\']/','',$val);
$val=preg_replace('/["\'][\s;]*$/','',$val);
if (preg_match('/crypted:/i',$buffer))
{
$val = preg_replace('/crypted:/i','',$val);
$passwd_crypted = $val;
$val = dol_decode($val);
$passwd = $val;
}
else
{
$passwd = $val;
$val = dol_encode($val);
$passwd_crypted = $val;
}
$lineofpass=1;
}
// Output line
if ($lineofpass)
{
// Add value at end of file
if ($level == 0)
{
$config .= '$dolibarr_main_db_pass=\''.$passwd.'\';'."\n";
}
if ($level == 1)
{
$config .= '$dolibarr_main_db_pass=\'crypted:'.$passwd_crypted.'\';'."\n";
}
//print 'passwd = '.$passwd.' - passwd_crypted = '.$passwd_crypted;
//exit;
}
else
{
$config .= $buffer;
}
}
fclose($fp);
// Write new conf file
$file=DOL_DOCUMENT_ROOT.'/conf/conf.php';
if ($fp = @fopen($file,'w'))
{
fputs($fp, $config);
fclose($fp);
// It's config file, so we set read permission for creator only.
// Should set permission to web user and groups for users used by batch
//@chmod($file, octdec('0600'));
return 1;
}
else
{
dol_syslog("security.lib::encodedecode_dbpassconf Failed to open conf.php file for writing", LOG_WARNING);
return -1;
}
}
else
{
dol_syslog("security.lib::encodedecode_dbpassconf Failed to read conf.php", LOG_ERR);
return -2;
}
}
/**
* Encode a string
*
@ -490,32 +65,6 @@ function dol_decode($chain)
}
/**
* Return a generated password using default module
*
* @param boolean $generic true=Create generic password (a MD5 string), false=Use the configured password generation module
* @return string New value for password
*/
function getRandomPassword($generic=false)
{
global $db,$conf,$langs,$user;
$generated_password='';
if ($generic) $generated_password=dol_hash(mt_rand());
else if ($conf->global->USER_PASSWORD_GENERATED)
{
$nomclass="modGeneratePass".ucfirst($conf->global->USER_PASSWORD_GENERATED);
$nomfichier=$nomclass.".class.php";
//print DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomclass;
require_once(DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomfichier);
$genhandler=new $nomclass($db,$conf,$langs,$user);
$generated_password=$genhandler->getNewGeneratedPassword();
unset($genhandler);
}
return $generated_password;
}
/**
* Returns a hash of a string
*
@ -530,4 +79,405 @@ function dol_hash($chain,$type=0)
else return md5($chain);
}
/**
* Check permissions of a user to show a page and an object. Check read permission.
* If GETPOST('action') defined, we also check write and delete permission.
*
* @param User $user User to check
* @param string $features Features to check (in most cases, it's module name)
* @param int $objectid Object ID if we want to check permission on a particular record (optionnal)
* @param string $dbtablename Table name where object is stored. Not used if objectid is null (optionnal)
* @param string $feature2 Feature to check, second level of permission (optionnal)
* @param string $dbt_keyfield Field name for socid foreign key if not fk_soc (optionnal)
* @param string $dbt_select Field name for select if not rowid (optionnal)
* @param Canvas $objcanvas Object canvas
* @return int Always 1, die process if not allowed
*/
function restrictedArea($user, $features='societe', $objectid=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null)
{
global $db, $conf;
//dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename,$feature2,$dbt_socfield,$dbt_select");
//print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid;
//print ", dbtablename=".$dbtablename.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select;
//print ", perm: ".$features."->".$feature2."=".$user->rights->$features->$feature2->lire."<br>";
// If we use canvas, we try to use function that overlod restrictarea if provided with canvas
if (is_object($objcanvas))
{
if (method_exists($objcanvas->control,'restrictedArea')) return $objcanvas->control->restrictedArea($user,$features,$objectid,$dbtablename,$feature2,$dbt_keyfield,$dbt_select);
}
if ($dbt_select != 'rowid') $objectid = "'".$objectid."'";
// More features to check
$features = explode("&",$features);
// More parameters
list($dbtablename, $sharedelement) = explode('&', $dbtablename);
// Check read permission from module
// TODO Replace "feature" param into caller by first level of permission
$readok=1;
foreach ($features as $feature)
{
if ($feature == 'societe')
{
if (! $user->rights->societe->lire && ! $user->rights->fournisseur->lire) $readok=0;
}
else if ($feature == 'contact')
{
if (! $user->rights->societe->contact->lire) $readok=0;
}
else if ($feature == 'produit|service')
{
if (! $user->rights->produit->lire && ! $user->rights->service->lire) $readok=0;
}
else if ($feature == 'prelevement')
{
if (! $user->rights->prelevement->bons->lire) $readok=0;
}
else if ($feature == 'commande_fournisseur')
{
if (! $user->rights->fournisseur->commande->lire) $readok=0;
}
else if ($feature == 'cheque')
{
if (! $user->rights->banque->cheque) $readok=0;
}
else if ($feature == 'projet')
{
if (! $user->rights->projet->lire && ! $user->rights->projet->all->lire) $readok=0;
}
else if (! empty($feature2)) // This should be used for future changes
{
if (empty($user->rights->$feature->$feature2->lire)
&& empty($user->rights->$feature->$feature2->read)) $readok=0;
}
else if (! empty($feature) && ($feature!='user' && $feature!='usergroup')) // This is for old permissions
{
if (empty($user->rights->$feature->lire)
&& empty($user->rights->$feature->read)
&& empty($user->rights->$feature->run)) $readok=0;
}
}
if (! $readok)
{
//print "Read access is down";
accessforbidden();
}
//print "Read access is ok";
// Check write permission from module
$createok=1;
if (GETPOST("action") && GETPOST("action") == 'create')
{
foreach ($features as $feature)
{
if ($feature == 'contact')
{
if (! $user->rights->societe->contact->creer) $createok=0;
}
else if ($feature == 'produit|service')
{
if (! $user->rights->produit->creer && ! $user->rights->service->creer) $createok=0;
}
else if ($feature == 'prelevement')
{
if (! $user->rights->prelevement->bons->creer) $createok=0;
}
else if ($feature == 'commande_fournisseur')
{
if (! $user->rights->fournisseur->commande->creer) $createok=0;
}
else if ($feature == 'banque')
{
if (! $user->rights->banque->modifier) $createok=0;
}
else if ($feature == 'cheque')
{
if (! $user->rights->banque->cheque) $createok=0;
}
else if (! empty($feature2)) // This should be used for future changes
{
if (empty($user->rights->$feature->$feature2->creer)
&& empty($user->rights->$feature->$feature2->write)) $createok=0;
}
else if (! empty($feature)) // This is for old permissions
{
//print '<br>feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write;
if (empty($user->rights->$feature->creer)
&& empty($user->rights->$feature->write)) $createok=0;
}
}
if (! $createok) accessforbidden();
//print "Write access is ok";
}
// Check create user permission
$createuserok=1;
if ( GETPOST("action") && (GETPOST("action") == 'confirm_create_user' && GETPOST("confirm") == 'yes') )
{
if (! $user->rights->user->user->creer) $createuserok=0;
if (! $createuserok) accessforbidden();
//print "Create user access is ok";
}
// Check delete permission from module
$deleteok=1;
if ( GETPOST("action") && ( (GETPOST("action") == 'confirm_delete' && GETPOST("confirm") && GETPOST("confirm") == 'yes') || GETPOST("action") == 'delete') )
{
foreach ($features as $feature)
{
if ($feature == 'contact')
{
if (! $user->rights->societe->contact->supprimer) $deleteok=0;
}
else if ($feature == 'produit|service')
{
if (! $user->rights->produit->supprimer && ! $user->rights->service->supprimer) $deleteok=0;
}
else if ($feature == 'commande_fournisseur')
{
if (! $user->rights->fournisseur->commande->supprimer) $deleteok=0;
}
else if ($feature == 'banque')
{
if (! $user->rights->banque->modifier) $deleteok=0;
}
else if ($feature == 'cheque')
{
if (! $user->rights->banque->cheque) $deleteok=0;
}
else if ($feature == 'ecm')
{
if (! $user->rights->ecm->upload) $deleteok=0;
}
else if ($feature == 'ftp')
{
if (! $user->rights->ftp->write) $deleteok=0;
}
else if (! empty($feature2)) // This should be used for future changes
{
if (empty($user->rights->$feature->$feature2->supprimer)
&& empty($user->rights->$feature->$feature2->delete)) $deleteok=0;
}
else if (! empty($feature)) // This is for old permissions
{
//print '<br>feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete;
if (empty($user->rights->$feature->supprimer)
&& empty($user->rights->$feature->delete)) $deleteok=0;
}
}
//print "Delete access is ko";
if (! $deleteok) accessforbidden();
//print "Delete access is ok";
}
// If we have a particular object to check permissions on, we check this object
// is linked to a company allowed to $user.
if (! empty($objectid) && $objectid > 0)
{
foreach ($features as $feature)
{
$sql='';
$check = array('banque','user','usergroup','produit','service','produit|service','categorie'); // Test on entity only (Objects with no link to company)
$checksoc = array('societe'); // Test for societe object
$checkother = array('contact'); // Test on entity and link to societe. Allowed if link is empty (Ex: contacts...).
$checkproject = array('projet'); // Test for project object
$nocheck = array('barcode','stock','fournisseur'); // No test
$checkdefault = 'all other not already defined'; // Test on entity and link to third party. Not allowed if link is empty (Ex: invoice, orders...).
// If dbtable not defined, we use same name for table than module name
if (empty($dbtablename)) $dbtablename = $feature;
// Check permission for object with entity
if (in_array($feature,$check))
{
$sql = "SELECT dbt.".$dbt_select;
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
if (($feature == 'user' || $feature == 'usergroup') && ! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
{
$sql.= " AND dbt.entity IS NOT NULL";
}
else
{
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
}
else if (in_array($feature,$checksoc))
{
// If external user: Check permission for external users
if ($user->societe_id > 0)
{
if ($user->societe_id <> $objectid) accessforbidden();
}
// If internal user: Check permission for internal users that are restricted on their objects
else if (! $user->rights->societe->client->voir)
{
$sql = "SELECT sc.fk_soc";
$sql.= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc";
$sql.= ", ".MAIN_DB_PREFIX."societe as s)";
$sql.= " WHERE sc.fk_soc = ".$objectid;
$sql.= " AND sc.fk_user = ".$user->id;
$sql.= " AND sc.fk_soc = s.rowid";
$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
}
// If multicompany and internal users with all permissions, check user is in correct entity
else if (! empty($conf->multicompany->enabled))
{
$sql = "SELECT s.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX."societe as s";
$sql.= " WHERE s.rowid = ".$objectid;
$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
}
}
else if (in_array($feature,$checkother))
{
// If external user: Check permission for external users
if ($user->societe_id > 0)
{
$sql = "SELECT dbt.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND dbt.fk_soc = ".$user->societe_id;
}
// If internal user: Check permission for internal users that are restricted on their objects
else if (! $user->rights->societe->client->voir)
{
$sql = "SELECT dbt.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = '".$user->id."'";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND (dbt.fk_soc IS NULL OR sc.fk_soc IS NOT NULL)"; // Contact not linked to a company or to a company of user
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
// If multicompany and internal users with all permissions, check user is in correct entity
else if (! empty($conf->multicompany->enabled))
{
$sql = "SELECT dbt.rowid";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
}
else if (in_array($feature,$checkproject))
{
if (! $user->rights->projet->all->lire)
{
include_once(DOL_DOCUMENT_ROOT."/projet/class/project.class.php");
$projectstatic=new Project($db);
$tmps=$projectstatic->getProjectsAuthorizedForUser($user,0,1,$user->societe_id);
$tmparray=explode(',',$tmps);
if (! in_array($objectid,$tmparray)) accessforbidden();
}
}
else if (! in_array($feature,$nocheck)) // By default we check with link to third party
{
// If external user: Check permission for external users
if ($user->societe_id > 0)
{
$sql = "SELECT dbt.".$dbt_keyfield;
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.rowid = ".$objectid;
$sql.= " AND dbt.".$dbt_keyfield." = ".$user->societe_id;
}
// If internal user: Check permission for internal users that are restricted on their objects
else if (! $user->rights->societe->client->voir)
{
$sql = "SELECT sc.fk_soc";
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= ", ".MAIN_DB_PREFIX."societe as s";
$sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
$sql.= " AND sc.fk_soc = dbt.".$dbt_keyfield;
$sql.= " AND dbt.".$dbt_keyfield." = s.rowid";
$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
$sql.= " AND sc.fk_user = ".$user->id;
}
// If multicompany and internal users with all permissions, check user is in correct entity
else if (! empty($conf->multicompany->enabled))
{
$sql = "SELECT dbt.".$dbt_select;
$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
}
}
//print $sql."<br>";
if ($sql)
{
$resql=$db->query($sql);
if ($resql)
{
if ($db->num_rows($resql) == 0) accessforbidden();
}
else
{
dol_syslog("security.lib:restrictedArea sql=".$sql, LOG_ERR);
accessforbidden();
}
}
}
}
return 1;
}
/**
* Show a message to say access is forbidden and stop program
* Calling this function terminate execution of PHP.
*
* @param string $message Force error message
* @param int $printheader Show header before
* @param int $printfooter Show footer after
* @param int $showonlymessage Show only message parameter. Otherwise add more information.
* @return void
*/
function accessforbidden($message='',$printheader=1,$printfooter=1,$showonlymessage=0)
{
global $conf, $db, $user, $langs;
if (! is_object($langs))
{
include_once(DOL_DOCUMENT_ROOT.'/core/class/translate.class.php');
$langs=new Translate('',$conf);
}
$langs->load("errors");
if ($printheader)
{
if (function_exists("llxHeader")) llxHeader('');
else if (function_exists("llxHeaderVierge")) llxHeaderVierge('');
}
print '<div class="error">';
if (! $message) print $langs->trans("ErrorForbidden");
else print $message;
print '</div>';
print '<br>';
if (empty($showonlymessage))
{
if ($user->login)
{
print $langs->trans("CurrentLogin").': <font class="error">'.$user->login.'</font><br>';
print $langs->trans("ErrorForbidden2",$langs->trans("Home"),$langs->trans("Users"));
}
else
{
print $langs->trans("ErrorForbidden3");
}
}
if ($printfooter && function_exists("llxFooter")) llxFooter();
exit(0);
}
?>

View File

@ -0,0 +1,480 @@
<?php
/* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2008-2012 Regis Houssin <regis@dolibarr.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* or see http://www.gnu.org/
*/
/**
* \file htdocs/core/lib/security2.lib.php
* \ingroup core
* \brief Set of function used for dolibarr security (not common functions).
* Warning, this file must not depends on other library files, except function.lib.php
* because it is used at low code level.
*/
/**
* 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 of data we must check
* @param array $authmode Array list of selected authentication mode array('http', 'dolibarr', 'xxx'...)
* @return string Login or ''
*/
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 = '';
// Validation of login/pass/entity with a third party login module method
if (! empty($conf->login_method_modules) && is_array($conf->login_method_modules))
{
foreach($conf->login_method_modules as $dir)
{
$newdir=dol_osencode($dir);
// Check if directory exists
if (! is_dir($newdir)) continue;
$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.'/core/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
*
* @param Translate $langs Lang object (must be initialized by a new).
* @param Conf $conf Conf object
* @param Societe $mysoc Company object
* @return void
*/
function dol_loginfunction($langs,$conf,$mysoc)
{
global $dolibarr_main_demo,$db;
global $smartphone,$mc;
$langcode=(GETPOST('lang')?((is_object($langs)&&$langs->defaultlang)?$langs->defaultlang:'auto'):GETPOST('lang'));
$langs->setDefaultLang($langcode);
$langs->load("main");
$langs->load("other");
$langs->load("help");
$langs->load("admin");
$main_authentication=$conf->file->main_authentication;
$session_name=session_name();
$dol_url_root = DOL_URL_ROOT;
$php_self = $_SERVER['PHP_SELF'];
$php_self.= $_SERVER["QUERY_STRING"]?'?'.$_SERVER["QUERY_STRING"]:'';
// Title
$title='Dolibarr '.DOL_VERSION;
if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $title=$conf->global->MAIN_APPLICATION_TITLE;
// Select templates
if (preg_match('/^smartphone/',$conf->smart_menu) && isset($conf->browser->phone))
{
$template_dir = DOL_DOCUMENT_ROOT.'/theme/phones/smartphone/tpl/';
}
else
{
if (file_exists(DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/tpl/login.tpl.php"))
{
$template_dir = DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/tpl/";
}
else
{
$template_dir = DOL_DOCUMENT_ROOT."/core/tpl/";
}
}
$conf->css = "/theme/".$conf->theme."/style.css.php?lang=".$langs->defaultlang;
$conf_css = DOL_URL_ROOT.$conf->css;
// Set cookie for timeout management
$prefix=dol_getprefix();
$sessiontimeout='DOLSESSTIMEOUT_'.$prefix;
if (! empty($conf->global->MAIN_SESSION_TIMEOUT)) setcookie($sessiontimeout, $conf->global->MAIN_SESSION_TIMEOUT, 0, "/", '', 0);
if (GETPOST("urlfrom")) $_SESSION["urlfrom"]=GETPOST("urlfrom");
else unset($_SESSION["urlfrom"]);
if (! GETPOST("username")) $focus_element='username';
else $focus_element='password';
$login_background=DOL_URL_ROOT.'/theme/login_background.png';
if (file_exists(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/login_background.png'))
{
$login_background=DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/login_background.png';
}
$demologin='';
$demopassword='';
if (! empty($dolibarr_main_demo))
{
$tab=explode(',',$dolibarr_main_demo);
$demologin=$tab[0];
$demopassword=$tab[1];
}
// Entity cookie
if (! empty($conf->multicompany->enabled))
{
$lastuser = '';
$lastentity = $_POST['entity'];
if (! empty($conf->global->MULTICOMPANY_COOKIE_ENABLED))
{
$prefix=dol_getprefix();
$entityCookieName = 'DOLENTITYID_'.$prefix;
if (isset($_COOKIE[$entityCookieName]))
{
include_once(DOL_DOCUMENT_ROOT . "/core/class/cookie.class.php");
$cryptkey = (! empty($conf->file->cookie_cryptkey) ? $conf->file->cookie_cryptkey : '' );
$entityCookie = new DolCookie($cryptkey);
$cookieValue = $entityCookie->_getCookie($entityCookieName);
list($lastuser, $lastentity) = explode('|', $cookieValue);
}
}
}
// Login
$login = (!empty($lastuser)?$lastuser:(GETPOST("username","alpha",2)?GETPOST("username","alpha",2):$demologin));
$password = $demopassword;
// Show logo (search in order: small company logo, large company logo, theme logo, common logo)
$width=0;
$rowspan=2;
$urllogo=DOL_URL_ROOT.'/theme/login_logo.png';
if (! empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small))
{
$urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=companylogo&amp;file='.urlencode('thumbs/'.$mysoc->logo_small);
}
elseif (! empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo))
{
$urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=companylogo&amp;file='.urlencode($mysoc->logo);
$width=128;
}
elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png'))
{
$urllogo=DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png';
}
elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.png'))
{
$urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo.png';
}
// Entity field
$select_entity='';
if (! empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX))
{
$rowspan++;
$select_entity = $mc->select_entities($lastentity, 'entity', ' tabindex="3"', 1);
}
// Security graphical code
$captcha=0;
$captcha_refresh='';
if (function_exists("imagecreatefrompng") && ! empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA))
{
$captcha=1;
$captcha_refresh=img_picto($langs->trans("Refresh"),'refresh');
}
// Extra link
$forgetpasslink=0;
$helpcenterlink=0;
if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK) || empty($conf->global->MAIN_HELPCENTER_DISABLELINK))
{
if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK))
{
$forgetpasslink=1;
}
if (empty($conf->global->MAIN_HELPCENTER_DISABLELINK))
{
$helpcenterlink=1;
}
}
// Home message
if (! empty($conf->global->MAIN_HOME))
{
$i=0;
while (preg_match('/__\(([a-zA-Z]+)\)__/i',$conf->global->MAIN_HOME,$reg) && $i < 100)
{
$conf->global->MAIN_HOME=preg_replace('/__\('.$reg[1].'\)__/i',$langs->trans($reg[1]),$conf->global->MAIN_HOME);
$i++;
}
}
$main_home=dol_htmlcleanlastbr($conf->global->MAIN_HOME);
// Google AD
$main_google_ad_client = ((! empty($conf->global->MAIN_GOOGLE_AD_CLIENT) && ! empty($conf->global->MAIN_GOOGLE_AD_SLOT))?1:0);
$dol_loginmesg = $_SESSION["dol_loginmesg"];
include($template_dir.'login.tpl.php'); // To use native PHP
$_SESSION["dol_loginmesg"] = '';
}
/**
* Fonction pour initialiser un salt pour la fonction crypt.
*
* @param int $type 2=>renvoi un salt pour cryptage DES
* 12=>renvoi un salt pour cryptage MD5
* non defini=>renvoi un salt pour cryptage par defaut
* @return string Salt string
*/
function makesalt($type=CRYPT_SALT_LENGTH)
{
dol_syslog("makesalt type=".$type);
switch($type)
{
case 12: // 8 + 4
$saltlen=8; $saltprefix='$1$'; $saltsuffix='$'; break;
case 8: // 8 (Pour compatibilite, ne devrait pas etre utilise)
$saltlen=8; $saltprefix='$1$'; $saltsuffix='$'; break;
case 2: // 2
default: // by default, fall back on Standard DES (should work everywhere)
$saltlen=2; $saltprefix=''; $saltsuffix=''; break;
}
$salt='';
while(dol_strlen($salt) < $saltlen) $salt.=chr(mt_rand(64,126));
$result=$saltprefix.$salt.$saltsuffix;
dol_syslog("makesalt return=".$result);
return $result;
}
/**
* Encode or decode database password in config file
*
* @param int $level Encode level: 0 no encoding, 1 encoding
* @return int <0 if KO, >0 if OK
*/
function encodedecode_dbpassconf($level=0)
{
dol_syslog("encodedecode_dbpassconf level=".$level, LOG_DEBUG);
$config = '';
$passwd='';
$passwd_crypted='';
if ($fp = fopen(DOL_DOCUMENT_ROOT.'/conf/conf.php','r'))
{
while(!feof($fp))
{
$buffer = fgets($fp,4096);
$lineofpass=0;
if (preg_match('/^[^#]*dolibarr_main_db_encrypted_pass[\s]*=[\s]*(.*)/i',$buffer,$reg)) // Old way to save crypted value
{
$val = trim($reg[1]); // This also remove CR/LF
$val=preg_replace('/^["\']/','',$val);
$val=preg_replace('/["\'][\s;]*$/','',$val);
if (! empty($val))
{
$passwd_crypted = $val;
$val = dol_decode($val);
$passwd = $val;
$lineofpass=1;
}
}
elseif (preg_match('/^[^#]*dolibarr_main_db_pass[\s]*=[\s]*(.*)/i',$buffer,$reg))
{
$val = trim($reg[1]); // This also remove CR/LF
$val=preg_replace('/^["\']/','',$val);
$val=preg_replace('/["\'][\s;]*$/','',$val);
if (preg_match('/crypted:/i',$buffer))
{
$val = preg_replace('/crypted:/i','',$val);
$passwd_crypted = $val;
$val = dol_decode($val);
$passwd = $val;
}
else
{
$passwd = $val;
$val = dol_encode($val);
$passwd_crypted = $val;
}
$lineofpass=1;
}
// Output line
if ($lineofpass)
{
// Add value at end of file
if ($level == 0)
{
$config .= '$dolibarr_main_db_pass=\''.$passwd.'\';'."\n";
}
if ($level == 1)
{
$config .= '$dolibarr_main_db_pass=\'crypted:'.$passwd_crypted.'\';'."\n";
}
//print 'passwd = '.$passwd.' - passwd_crypted = '.$passwd_crypted;
//exit;
}
else
{
$config .= $buffer;
}
}
fclose($fp);
// Write new conf file
$file=DOL_DOCUMENT_ROOT.'/conf/conf.php';
if ($fp = @fopen($file,'w'))
{
fputs($fp, $config);
fclose($fp);
// It's config file, so we set read permission for creator only.
// Should set permission to web user and groups for users used by batch
//@chmod($file, octdec('0600'));
return 1;
}
else
{
dol_syslog("encodedecode_dbpassconf Failed to open conf.php file for writing", LOG_WARNING);
return -1;
}
}
else
{
dol_syslog("encodedecode_dbpassconf Failed to read conf.php", LOG_ERR);
return -2;
}
}
/**
* Return a generated password using default module
*
* @param boolean $generic true=Create generic password (a MD5 string), false=Use the configured password generation module
* @return string New value for password
*/
function getRandomPassword($generic=false)
{
global $db,$conf,$langs,$user;
$generated_password='';
if ($generic) $generated_password=dol_hash(mt_rand());
else if ($conf->global->USER_PASSWORD_GENERATED)
{
$nomclass="modGeneratePass".ucfirst($conf->global->USER_PASSWORD_GENERATED);
$nomfichier=$nomclass.".class.php";
//print DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomclass;
require_once(DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomfichier);
$genhandler=new $nomclass($db,$conf,$langs,$user);
$generated_password=$genhandler->getNewGeneratedPassword();
unset($genhandler);
}
return $generated_password;
}
?>

View File

@ -75,7 +75,8 @@ function check_authentication($authentication,&$error,&$errorcode,&$errorlabel)
// Set authmode
$authmode=explode(',',$dolibarr_main_authentication);
$login = checkLoginPassEntity($authentication['login'],$authentication['password'],$authentication['entity'],$authmode);
include_once(DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php');
$login = checkLoginPassEntity($authentication['login'],$authentication['password'],$authentication['entity'],$authmode);
if (empty($login))
{
$error++;

View File

@ -145,7 +145,7 @@ foreach($paths as $tmppath)
break;
}
}
if (! $found) // If autodetect fails (Ie: when uing apache alias that point outside default DOCUMENT_ROOT.
if (! $found) // If autodetect fails (Ie: when using apache alias that point outside default DOCUMENT_ROOT.
{
$tmp=$dolibarr_main_url_root;
}
@ -213,8 +213,10 @@ if (! file_exists(DOL_DOCUMENT_ROOT ."/core/lib/functions.lib.php"))
exit;
}
include_once(DOL_DOCUMENT_ROOT ."/core/lib/functions.lib.php"); // Need 970ko memory (1.1 in 2.2)
include_once(DOL_DOCUMENT_ROOT ."/core/lib/security.lib.php"); // Include by default
// Included by default
include_once(DOL_DOCUMENT_ROOT ."/core/lib/functions.lib.php");
include_once(DOL_DOCUMENT_ROOT ."/core/lib/security.lib.php");
//print memory_get_usage();
// If password is encoded, we decode it
if (preg_match('/crypted:/i',$dolibarr_main_db_pass) || ! empty($dolibarr_main_db_encrypted_pass))
@ -227,6 +229,5 @@ if (preg_match('/crypted:/i',$dolibarr_main_db_pass) || ! empty($dolibarr_main_d
}
else $dolibarr_main_db_pass = dol_decode($dolibarr_main_db_encrypted_pass);
}
//print memory_get_usage();
?>

View File

@ -223,7 +223,6 @@ if ($user->societe_id == 0)
"bills",
"Contracts");
//print memory_get_usage()."<br>";
// Loop and displays each line of table
foreach ($keys as $key=>$val)
@ -249,8 +248,6 @@ if ($user->societe_id == 0)
print '<td>'.$title.'</td>';
print '<td align="right"><a href="'.$links[$key].'">'.$board->nb[$val].'</a></td>';
print '</tr>';
//print $includes[$key].' '.memory_get_usage()."<br>";
}
}

View File

@ -332,7 +332,8 @@ if (! defined('NOLOGIN'))
$test=true;
if (! isset($_SESSION["dol_login"]))
{
// It is not already authenticated, it requests the login / password
// It is not already authenticated and it requests the login / password
include_once(DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php');
// If in demo mode, we check we go to home page through the public/demo/index.php page
if ($dolibarr_main_demo && $_SERVER['PHP_SELF'] == DOL_URL_ROOT.'/index.php') // We ask index page
@ -384,7 +385,7 @@ if (! defined('NOLOGIN'))
if ($test && $goontestloop)
{
$login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode);
$login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode);
if ($login)
{
$dol_authmode=$conf->authmode; // This properties is defined only when logged to say what mode was successfully used

View File

@ -1236,7 +1236,7 @@ class User extends CommonObject
function setPassword($user, $password='', $changelater=0, $notrigger=0, $nosyncmember=0)
{
global $conf, $langs;
require_once(DOL_DOCUMENT_ROOT ."/core/lib/security.lib.php");
require_once(DOL_DOCUMENT_ROOT ."/core/lib/security2.lib.php");
$error=0;

View File

@ -669,8 +669,9 @@ if (($action == 'create') || ($action == 'adduserldap'))
print '</td></tr>';
$generated_password='';
if (! $ldap_sid)
if (! $ldap_sid) // ldap_sid ?
{
require_once(DOL_DOCUMENT_ROOT."/core/lib/security2.lib.php");
$generated_password=getRandomPassword('');
}
$password=$generated_password;

View File

@ -27,8 +27,8 @@ global $conf,$user,$langs,$db;
//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver
require_once 'PHPUnit/Autoload.php';
require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
require_once dirname(__FILE__).'/../../htdocs/core/lib/functions.lib.php';
require_once dirname(__FILE__).'/../../htdocs/core/lib/security.lib.php';
require_once dirname(__FILE__).'/../../htdocs/core/lib/security2.lib.php';
if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1');
if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1');
@ -113,6 +113,9 @@ class SecurityTest extends PHPUnit_Framework_TestCase
}
/**
* testGETPOST
*
* @return string
*/
public function testGETPOST()
{
@ -152,6 +155,9 @@ class SecurityTest extends PHPUnit_Framework_TestCase
}
/**
* testCheckLoginPassEntity
*
* @return void
*/
public function testCheckLoginPassEntity()
{
@ -177,6 +183,9 @@ class SecurityTest extends PHPUnit_Framework_TestCase
}
/**
* testEncodeDecode
*
* @return number
*/
public function testEncodeDecode()
{
@ -191,6 +200,9 @@ class SecurityTest extends PHPUnit_Framework_TestCase
}
/**
* testGetRandomPassword
*
* @return number
*/
public function testGetRandomPassword()
{
@ -212,5 +224,18 @@ class SecurityTest extends PHPUnit_Framework_TestCase
return 0;
}
/**
* testGetRandomPassword
*
* @return number
*/
public function testRestrictedArea()
{
}
}
?>