dolibarr  7.0.0-beta
security2.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2008-2017 Regis Houssin <regis.houssin@capnetworks.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  * or see http://www.gnu.org/
18  */
19 
35 function dol_getwebuser($mode)
36 {
37  $t='?';
38  if ($mode=='user') $t=getenv('APACHE_RUN_USER'); // $_ENV['APACHE_RUN_USER'] is empty
39  if ($mode=='group') $t=getenv('APACHE_RUN_GROUP');
40  return $t;
41 }
42 
52 function checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode)
53 {
54  global $conf,$langs;
55  //global $dolauthmode; // To return authentication finally used
56 
57  // Check parameters
58  if ($entitytotest == '') $entitytotest=1;
59 
60  dol_syslog("checkLoginPassEntity usertotest=".$usertotest." entitytotest=".$entitytotest." authmode=".join(',',$authmode));
61  $login = '';
62 
63  // Validation of login/pass/entity with standard modules
64  if (empty($login))
65  {
66  $test=true;
67  foreach($authmode as $mode)
68  {
69  if ($test && $mode && ! $login)
70  {
71  // Validation of login/pass/entity for mode $mode
72  $mode=trim($mode);
73  $authfile='functions_'.$mode.'.php';
74  $fullauthfile='';
75 
76  $dirlogin=array_merge(array("/core/login"),(array) $conf->modules_parts['login']);
77  foreach($dirlogin as $reldir)
78  {
79  $dir=dol_buildpath($reldir,0);
80  $newdir=dol_osencode($dir);
81 
82  // Check if file found (do not use dol_is_file to avoid loading files.lib.php)
83  $tmpnewauthfile = $newdir.(preg_match('/\/$/',$newdir)?'':'/').$authfile;
84  if (is_file($tmpnewauthfile)) $fullauthfile=$tmpnewauthfile;
85  }
86 
87  $result=false;
88  if ($fullauthfile) $result=include_once $fullauthfile;
89  if ($fullauthfile && $result)
90  {
91  // Call function to check user/password
92  $function='check_user_password_'.$mode;
93  $login=call_user_func($function, $usertotest, $passwordtotest, $entitytotest);
94  if ($login) // Login is successfull
95  {
96  $test=false; // To stop once at first login success
97  $conf->authmode=$mode; // This properties is defined only when logged to say what mode was successfully used
98  $dol_tz=GETPOST('tz');
99  $dol_dst=GETPOST('dst');
100  $dol_screenwidth=GETPOST('screenwidth');
101  $dol_screenheight=GETPOST('screenheight');
102  }
103  }
104  else
105  {
106  dol_syslog("Authentification ko - failed to load file '".$authfile."'",LOG_ERR);
107  sleep(1);
108  $langs->load('main');
109  $langs->load('other');
110  $langs->load('errors');
111  $_SESSION["dol_loginmesg"]=$langs->trans("ErrorFailedToLoadLoginFileForMode",$mode);
112  }
113  }
114  }
115  }
116 
117  return $login;
118 }
119 
120 
130 if (! function_exists('dol_loginfunction'))
131 {
132  function dol_loginfunction($langs,$conf,$mysoc)
133  {
134  global $dolibarr_main_demo,$db;
135  global $smartphone,$hookmanager;
136 
137  $langs->loadLangs(array("main","other","help","admin"));
138 
139  // Instantiate hooks of thirdparty module only if not already define
140  $hookmanager->initHooks(array('mainloginpage'));
141 
142  $main_authentication=$conf->file->main_authentication;
143 
144  $session_name=session_name(); // Get current session name
145 
146  $dol_url_root = DOL_URL_ROOT;
147 
148  // Title
149  $appli=constant('DOL_APPLICATION_TITLE');
150  $title=$appli.' '.constant('DOL_VERSION');
151  if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $title=$conf->global->MAIN_APPLICATION_TITLE;
152  $titletruedolibarrversion=constant('DOL_VERSION'); // $title used by login template after the @ to inform of true Dolibarr version
153 
154  // Note: $conf->css looks like '/theme/eldy/style.css.php'
155  /*
156  $conf->css = "/theme/".(GETPOST('theme','alpha')?GETPOST('theme','alpha'):$conf->theme)."/style.css.php";
157  $themepath=dol_buildpath($conf->css,1);
158  if (! empty($conf->modules_parts['theme'])) // Using this feature slow down application
159  {
160  foreach($conf->modules_parts['theme'] as $reldir)
161  {
162  if (file_exists(dol_buildpath($reldir.$conf->css, 0)))
163  {
164  $themepath=dol_buildpath($reldir.$conf->css, 1);
165  break;
166  }
167  }
168  }
169  $conf_css = $themepath."?lang=".$langs->defaultlang;
170  */
171 
172  // Select templates dir
173  if (! empty($conf->modules_parts['tpl'])) // Using this feature slow down application
174  {
175  $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl/'));
176  foreach($dirtpls as $reldir)
177  {
178  $tmp=dol_buildpath($reldir.'login.tpl.php');
179  if (file_exists($tmp)) { $template_dir=preg_replace('/login\.tpl\.php$/','',$tmp); break; }
180  }
181  }
182  else
183  {
184  $template_dir = DOL_DOCUMENT_ROOT."/core/tpl/";
185  }
186 
187  // Set cookie for timeout management
188  $prefix=dol_getprefix('');
189  $sessiontimeout='DOLSESSTIMEOUT_'.$prefix;
190  if (! empty($conf->global->MAIN_SESSION_TIMEOUT)) setcookie($sessiontimeout, $conf->global->MAIN_SESSION_TIMEOUT, 0, "/", null, false, true);
191 
192  if (GETPOST('urlfrom','alpha')) $_SESSION["urlfrom"]=GETPOST('urlfrom','alpha');
193  else unset($_SESSION["urlfrom"]);
194 
195  if (! GETPOST("username",'alpha')) $focus_element='username';
196  else $focus_element='password';
197 
198  $demologin='';
199  $demopassword='';
200  if (! empty($dolibarr_main_demo))
201  {
202  $tab=explode(',',$dolibarr_main_demo);
203  $demologin=$tab[0];
204  $demopassword=$tab[1];
205  }
206 
207  // Execute hook getLoginPageOptions (for table)
208  $parameters=array('entity' => GETPOST('entity','int'));
209  $reshook = $hookmanager->executeHooks('getLoginPageOptions',$parameters); // Note that $action and $object may have been modified by some hooks.
210  if (is_array($hookmanager->resArray) && ! empty($hookmanager->resArray)) {
211  $morelogincontent = $hookmanager->resArray; // (deprecated) For compatibility
212  } else {
213  $morelogincontent = $hookmanager->resPrint;
214  }
215 
216  // Execute hook getLoginPageExtraOptions (eg for js)
217  $parameters=array('entity' => GETPOST('entity','int'));
218  $reshook = $hookmanager->executeHooks('getLoginPageExtraOptions',$parameters); // Note that $action and $object may have been modified by some hooks.
219  $moreloginextracontent = $hookmanager->resPrint;
220 
221  // Login
222  $login = (! empty($hookmanager->resArray['username']) ? $hookmanager->resArray['username'] : (GETPOST("username","alpha") ? GETPOST("username","alpha") : $demologin));
223  $password = $demopassword;
224 
225  // Show logo (search in order: small company logo, large company logo, theme logo, common logo)
226  $width=0;
227  $urllogo=DOL_URL_ROOT.'/theme/login_logo.png';
228 
229  if (! empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small))
230  {
231  $urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('thumbs/'.$mysoc->logo_small);
232  }
233  elseif (! empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo))
234  {
235  $urllogo=DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode($mysoc->logo);
236  $width=128;
237  }
238  elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png'))
239  {
240  $urllogo=DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png';
241  }
242  elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.png'))
243  {
244  $urllogo=DOL_URL_ROOT.'/theme/dolibarr_logo.png';
245  }
246 
247  // Security graphical code
248  $captcha=0;
249  $captcha_refresh='';
250  if (function_exists("imagecreatefrompng") && ! empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA))
251  {
252  $captcha=1;
253  $captcha_refresh=img_picto($langs->trans("Refresh"),'refresh','id="captcha_refresh_img"');
254  }
255 
256  // Extra link
257  $forgetpasslink=0;
258  $helpcenterlink=0;
259  if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK) || empty($conf->global->MAIN_HELPCENTER_DISABLELINK))
260  {
261  if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK))
262  {
263  $forgetpasslink=1;
264  }
265 
266  if (empty($conf->global->MAIN_HELPCENTER_DISABLELINK))
267  {
268  $helpcenterlink=1;
269  }
270  }
271 
272  // Home message
273  $main_home='';
274  if (! empty($conf->global->MAIN_HOME))
275  {
276  $substitutionarray=getCommonSubstitutionArray($langs);
277  complete_substitutions_array($substitutionarray, $langs);
278  $texttoshow = make_substitutions($conf->global->MAIN_HOME, $substitutionarray, $langs);
279 
280  $main_home=dol_htmlcleanlastbr($texttoshow);
281  }
282 
283  // Google AD
284  $main_google_ad_client = ((! empty($conf->global->MAIN_GOOGLE_AD_CLIENT) && ! empty($conf->global->MAIN_GOOGLE_AD_SLOT))?1:0);
285 
286  // Set jquery theme
287  $dol_loginmesg = (! empty($_SESSION["dol_loginmesg"])?$_SESSION["dol_loginmesg"]:'');
288  $favicon=dol_buildpath('/theme/'.$conf->theme.'/img/favicon.ico',1);
289  if (! empty($conf->global->MAIN_FAVICON_URL)) $favicon=$conf->global->MAIN_FAVICON_URL;
290  $jquerytheme = 'base';
291  if (! empty($conf->global->MAIN_USE_JQUERY_THEME)) $jquerytheme = $conf->global->MAIN_USE_JQUERY_THEME;
292 
293  // Set dol_hide_topmenu, dol_hide_leftmenu, dol_optimize_smallscreen, dol_no_mouse_hover
294  $dol_hide_topmenu=GETPOST('dol_hide_topmenu','int');
295  $dol_hide_leftmenu=GETPOST('dol_hide_leftmenu','int');
296  $dol_optimize_smallscreen=GETPOST('dol_optimize_smallscreen','int');
297  $dol_no_mouse_hover=GETPOST('dol_no_mouse_hover','int');
298  $dol_use_jmobile=GETPOST('dol_use_jmobile','int');
299 
300  // Include login page template
301  include $template_dir.'login.tpl.php';
302 
303 
304  $_SESSION["dol_loginmesg"] = '';
305  }
306 }
307 
316 function makesalt($type=CRYPT_SALT_LENGTH)
317 {
318  dol_syslog("makesalt type=".$type);
319  switch($type)
320  {
321  case 12: // 8 + 4
322  $saltlen=8; $saltprefix='$1$'; $saltsuffix='$'; break;
323  case 8: // 8 (Pour compatibilite, ne devrait pas etre utilise)
324  $saltlen=8; $saltprefix='$1$'; $saltsuffix='$'; break;
325  case 2: // 2
326  default: // by default, fall back on Standard DES (should work everywhere)
327  $saltlen=2; $saltprefix=''; $saltsuffix=''; break;
328  }
329  $salt='';
330  while(dol_strlen($salt) < $saltlen) $salt.=chr(mt_rand(64,126));
331 
332  $result=$saltprefix.$salt.$saltsuffix;
333  dol_syslog("makesalt return=".$result);
334  return $result;
335 }
336 
343 function encodedecode_dbpassconf($level=0)
344 {
345  dol_syslog("encodedecode_dbpassconf level=".$level, LOG_DEBUG);
346  $config = '';
347  $passwd='';
348  $passwd_crypted='';
349 
350  if ($fp = fopen(DOL_DOCUMENT_ROOT.'/conf/conf.php','r'))
351  {
352  while(!feof($fp))
353  {
354  $buffer = fgets($fp,4096);
355 
356  $lineofpass=0;
357 
358  if (preg_match('/^[^#]*dolibarr_main_db_encrypted_pass[\s]*=[\s]*(.*)/i',$buffer,$reg)) // Old way to save crypted value
359  {
360  $val = trim($reg[1]); // This also remove CR/LF
361  $val=preg_replace('/^["\']/','',$val);
362  $val=preg_replace('/["\'][\s;]*$/','',$val);
363  if (! empty($val))
364  {
365  $passwd_crypted = $val;
366  $val = dol_decode($val);
367  $passwd = $val;
368  $lineofpass=1;
369  }
370  }
371  elseif (preg_match('/^[^#]*dolibarr_main_db_pass[\s]*=[\s]*(.*)/i',$buffer,$reg))
372  {
373  $val = trim($reg[1]); // This also remove CR/LF
374  $val=preg_replace('/^["\']/','',$val);
375  $val=preg_replace('/["\'][\s;]*$/','',$val);
376  if (preg_match('/crypted:/i',$buffer))
377  {
378  $val = preg_replace('/crypted:/i','',$val);
379  $passwd_crypted = $val;
380  $val = dol_decode($val);
381  $passwd = $val;
382  }
383  else
384  {
385  $passwd = $val;
386  $val = dol_encode($val);
387  $passwd_crypted = $val;
388  }
389  $lineofpass=1;
390  }
391 
392  // Output line
393  if ($lineofpass)
394  {
395  // Add value at end of file
396  if ($level == 0)
397  {
398  $config .= '$dolibarr_main_db_pass=\''.$passwd.'\';'."\n";
399  }
400  if ($level == 1)
401  {
402  $config .= '$dolibarr_main_db_pass=\'crypted:'.$passwd_crypted.'\';'."\n";
403  }
404 
405  //print 'passwd = '.$passwd.' - passwd_crypted = '.$passwd_crypted;
406  //exit;
407  }
408  else
409  {
410  $config .= $buffer;
411  }
412  }
413  fclose($fp);
414 
415  // Write new conf file
416  $file=DOL_DOCUMENT_ROOT.'/conf/conf.php';
417  if ($fp = @fopen($file,'w'))
418  {
419  fputs($fp, $config);
420  fflush($fp);
421  fclose($fp);
422  clearstatcache();
423 
424  // It's config file, so we set read permission for creator only.
425  // Should set permission to web user and groups for users used by batch
426  //@chmod($file, octdec('0600'));
427 
428  return 1;
429  }
430  else
431  {
432  dol_syslog("encodedecode_dbpassconf Failed to open conf.php file for writing", LOG_WARNING);
433  return -1;
434  }
435  }
436  else
437  {
438  dol_syslog("encodedecode_dbpassconf Failed to read conf.php", LOG_ERR);
439  return -2;
440  }
441 }
442 
449 function getRandomPassword($generic=false)
450 {
451  global $db,$conf,$langs,$user;
452 
453  $generated_password='';
454  if ($generic)
455  {
456  $length = 32;
457  $lowercase = "qwertyuiopasdfghjklzxcvbnm";
458  $uppercase = "ASDFGHJKLZXCVBNMQWERTYUIOP";
459  $numbers = "1234567890";
460  $randomCode = "";
461  $nbofchar = round($length/3);
462  $nbofcharlast = ($length - 2*$nbofchar);
463  //var_dump($nbofchar.'-'.$nbofcharlast);
464  if (function_exists('random_int')) // Cryptographic random
465  {
466  $max = strlen($lowercase) - 1;
467  for ($x = 0; $x < $nbofchar; $x++) {
468  $randomCode .= $lowercase{random_int(0, $max)};
469  }
470  $max = strlen($uppercase) - 1;
471  for ($x = 0; $x < $nbofchar; $x++) {
472  $randomCode .= $uppercase{random_int(0, $max)};
473  }
474  $max = strlen($numbers) - 1;
475  for ($x = 0; $x < $nbofcharlast; $x++) {
476  $randomCode .= $numbers{random_int(0, $max)};
477  }
478 
479  $generated_password=str_shuffle($randomCode);
480  }
481  else // Old platform, non cryptographic random
482  {
483  $max = strlen($lowercase) - 1;
484  for ($x = 0; $x < $nbofchar; $x++) {
485  $randomCode .= $lowercase{mt_rand(0, $max)};
486  }
487  $max = strlen($uppercase) - 1;
488  for ($x = 0; $x < $nbofchar; $x++) {
489  $randomCode .= $uppercase{mt_rand(0, $max)};
490  }
491  $max = strlen($numbers) - 1;
492  for ($x = 0; $x < $nbofcharlast; $x++) {
493  $randomCode .= $numbers{mt_rand(0, $max)};
494  }
495 
496  $generated_password=str_shuffle($randomCode);
497  }
498  }
499  else if (! empty($conf->global->USER_PASSWORD_GENERATED))
500  {
501  $nomclass="modGeneratePass".ucfirst($conf->global->USER_PASSWORD_GENERATED);
502  $nomfichier=$nomclass.".class.php";
503  //print DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomclass;
504  require_once DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomfichier;
505  $genhandler=new $nomclass($db,$conf,$langs,$user);
506  $generated_password=$genhandler->getNewGeneratedPassword();
507  unset($genhandler);
508  }
509 
510  return $generated_password;
511 }
512 
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='')
Show picto whatever it's its name (generic function)
conf($dolibarr_main_document_root)
Load conf file (file must exists)
Definition: inc.php:282
if(!function_exists('dol_loginfunction')) makesalt($type=CRYPT_SALT_LENGTH)
Show Dolibarr default login page.
dol_getwebuser($mode)
Return user/group account of web server.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
if($action== 'validatenewpassword'&&$username &&$passwordhash) if($action== 'buildnewpassword'&&$username) $dol_url_root
Actions.
GETPOST($paramname, $check='none', $method=0, $filter=NULL, $options=NULL, $noreplace=0)
Return value of a param into GET or POST supervariable.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null)
Return array of possible common substitutions.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
dol_decode($chain)
Decode a base 64 encoded + specific string.
if($_POST["cancel"]==$langs->trans("Cancel")&&!$id) if($action== 'setdatev'&&$user->rights->tax->charges->creer) if($action== 'add'&&$_POST["cancel"]<> $langs->trans("Cancel")) if($action== 'delete') $title
Actions.
Definition: card.php:183
dol_encode($chain)
Encode a string with base 64 algorithm + specific change Code of this function is useless and we shou...
getRandomPassword($generic=false)
Return a generated password using default module.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $authmode)
Return a login if login/pass was successfull.
encodedecode_dbpassconf($level=0)
Encode or decode database password in config file.
make_substitutions($text, $substitutionarray, $outputlangs=null)
Make substition into a text string, replacing keys with vals from $substitutionarray (oldval=>newval)...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...