security2.lib.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. <?php
  2. /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2008-2017 Regis Houssin <regis.houssin@inodbox.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 <https://www.gnu.org/licenses/>.
  17. * or see https://www.gnu.org/
  18. */
  19. /**
  20. * \file htdocs/core/lib/security2.lib.php
  21. * \ingroup core
  22. * \brief Set of function used for dolibarr security (not common functions).
  23. * Warning, this file must not depends on other library files, except function.lib.php
  24. * because it is used at low code level.
  25. */
  26. /**
  27. * Return user/group account of web server
  28. *
  29. * @param string $mode 'user' or 'group'
  30. * @return string Return user or group of web server
  31. */
  32. function dol_getwebuser($mode)
  33. {
  34. $t = '?';
  35. if ($mode == 'user') {
  36. $t = getenv('APACHE_RUN_USER'); // $_ENV['APACHE_RUN_USER'] is empty
  37. }
  38. if ($mode == 'group') {
  39. $t = getenv('APACHE_RUN_GROUP');
  40. }
  41. return $t;
  42. }
  43. /**
  44. * Return a login if login/pass was successfull
  45. *
  46. * @param string $usertotest Login value to test
  47. * @param string $passwordtotest Password value to test
  48. * @param string $entitytotest Instance of data we must check
  49. * @param array $authmode Array list of selected authentication mode array('http', 'dolibarr', 'xxx'...)
  50. * @param string $context Context checkLoginPassEntity was created for ('api', 'dav', 'ws', '')
  51. * @return string Login or ''
  52. */
  53. function checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $authmode, $context = '')
  54. {
  55. global $conf, $langs;
  56. //global $dolauthmode; // To return authentication finally used
  57. // Check parameters
  58. if ($entitytotest == '') {
  59. $entitytotest = 1;
  60. }
  61. dol_syslog("checkLoginPassEntity usertotest=".$usertotest." entitytotest=".$entitytotest." authmode=".join(',', $authmode));
  62. $login = '';
  63. // Validation of login/pass/entity with standard modules
  64. if (empty($login)) {
  65. $test = true;
  66. foreach ($authmode as $mode) {
  67. if ($test && $mode && !$login) {
  68. // Validation of login/pass/entity for mode $mode
  69. $mode = trim($mode);
  70. $authfile = 'functions_'.$mode.'.php';
  71. $fullauthfile = '';
  72. $dirlogin = array_merge(array("/core/login"), (array) $conf->modules_parts['login']);
  73. foreach ($dirlogin as $reldir) {
  74. $dir = dol_buildpath($reldir, 0);
  75. $newdir = dol_osencode($dir);
  76. // Check if file found (do not use dol_is_file to avoid loading files.lib.php)
  77. $tmpnewauthfile = $newdir.(preg_match('/\/$/', $newdir) ? '' : '/').$authfile;
  78. if (is_file($tmpnewauthfile)) {
  79. $fullauthfile = $tmpnewauthfile;
  80. }
  81. }
  82. $result = false;
  83. if ($fullauthfile) {
  84. $result = include_once $fullauthfile;
  85. }
  86. if ($fullauthfile && $result) {
  87. // Call function to check user/password
  88. $function = 'check_user_password_'.$mode;
  89. $login = call_user_func($function, $usertotest, $passwordtotest, $entitytotest, $context);
  90. if ($login && $login != '--bad-login-validity--') { // Login is successfull
  91. $test = false; // To stop once at first login success
  92. $conf->authmode = $mode; // This properties is defined only when logged to say what mode was successfully used
  93. $dol_tz = GETPOST('tz');
  94. $dol_dst = GETPOST('dst');
  95. $dol_screenwidth = GETPOST('screenwidth');
  96. $dol_screenheight = GETPOST('screenheight');
  97. }
  98. } else {
  99. dol_syslog("Authentication KO - failed to load file '".$authfile."'", LOG_ERR);
  100. sleep(1);
  101. // Load translation files required by the page
  102. $langs->loadLangs(array('other', 'main', 'errors'));
  103. $_SESSION["dol_loginmesg"] = (empty($_SESSION["dol_loginmesg"]) ? '' : $_SESSION["dol_loginmesg"].', ').$langs->transnoentitiesnoconv("ErrorFailedToLoadLoginFileForMode", $mode);
  104. }
  105. }
  106. }
  107. }
  108. return $login;
  109. }
  110. if (!function_exists('dol_loginfunction')) {
  111. /**
  112. * Show Dolibarr default login page.
  113. * Part of this code is also duplicated into main.inc.php::top_htmlhead
  114. *
  115. * @param Translate $langs Lang object (must be initialized by a new).
  116. * @param Conf $conf Conf object
  117. * @param Societe $mysoc Company object
  118. * @return void
  119. */
  120. function dol_loginfunction($langs, $conf, $mysoc)
  121. {
  122. global $dolibarr_main_demo, $dolibarr_main_force_https;
  123. global $db, $hookmanager;
  124. $langs->loadLangs(array("main", "other", "help", "admin"));
  125. // Instantiate hooks of thirdparty module only if not already define
  126. $hookmanager->initHooks(array('mainloginpage'));
  127. $main_authentication = $conf->file->main_authentication;
  128. $session_name = session_name(); // Get current session name
  129. $dol_url_root = DOL_URL_ROOT;
  130. // Title
  131. $appli = constant('DOL_APPLICATION_TITLE');
  132. $title = $appli.' '.constant('DOL_VERSION');
  133. if (!empty($conf->global->MAIN_APPLICATION_TITLE)) {
  134. $title = $conf->global->MAIN_APPLICATION_TITLE;
  135. }
  136. $titletruedolibarrversion = constant('DOL_VERSION'); // $title used by login template after the @ to inform of true Dolibarr version
  137. // Note: $conf->css looks like '/theme/eldy/style.css.php'
  138. /*
  139. $conf->css = "/theme/".(GETPOST('theme','aZ09')?GETPOST('theme','aZ09'):$conf->theme)."/style.css.php";
  140. $themepath=dol_buildpath($conf->css,1);
  141. if (!empty($conf->modules_parts['theme'])) // Using this feature slow down application
  142. {
  143. foreach($conf->modules_parts['theme'] as $reldir)
  144. {
  145. if (file_exists(dol_buildpath($reldir.$conf->css, 0)))
  146. {
  147. $themepath=dol_buildpath($reldir.$conf->css, 1);
  148. break;
  149. }
  150. }
  151. }
  152. $conf_css = $themepath."?lang=".$langs->defaultlang;
  153. */
  154. // Select templates dir
  155. if (!empty($conf->modules_parts['tpl'])) { // Using this feature slow down application
  156. $dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl/'));
  157. foreach ($dirtpls as $reldir) {
  158. $tmp = dol_buildpath($reldir.'login.tpl.php');
  159. if (file_exists($tmp)) {
  160. $template_dir = preg_replace('/login\.tpl\.php$/', '', $tmp);
  161. break;
  162. }
  163. }
  164. } else {
  165. $template_dir = DOL_DOCUMENT_ROOT."/core/tpl/";
  166. }
  167. // Set cookie for timeout management. We set it as a cookie so we will be able to use it to set timeout on next page before the session start
  168. // and the conf file is loaded.
  169. $prefix = dol_getprefix('');
  170. $sessiontimeout = 'DOLSESSTIMEOUT_'.$prefix;
  171. if (!empty($conf->global->MAIN_SESSION_TIMEOUT)) {
  172. if (session_status() != PHP_SESSION_ACTIVE) {
  173. if (PHP_VERSION_ID < 70300) {
  174. session_set_cookie_params(0, '/', null, ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start.
  175. } else {
  176. // Only available for php >= 7.3
  177. $sessioncookieparams = array(
  178. 'lifetime' => 0,
  179. 'path' => '/',
  180. //'domain' => '.mywebsite.com', // the dot at the beginning allows compatibility with subdomains
  181. 'secure' => ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true),
  182. 'httponly' => true,
  183. 'samesite' => 'Lax' // None || Lax || Strict
  184. );
  185. session_set_cookie_params($sessioncookieparams);
  186. }
  187. setcookie($sessiontimeout, $conf->global->MAIN_SESSION_TIMEOUT, 0, "/", null, (empty($dolibarr_main_force_https) ? false : true), true);
  188. }
  189. }
  190. if (GETPOST('urlfrom', 'alpha')) {
  191. $_SESSION["urlfrom"] = GETPOST('urlfrom', 'alpha');
  192. } else {
  193. unset($_SESSION["urlfrom"]);
  194. }
  195. if (!GETPOST("username", 'alpha')) {
  196. $focus_element = 'username';
  197. } else {
  198. $focus_element = 'password';
  199. }
  200. $demologin = '';
  201. $demopassword = '';
  202. if (!empty($dolibarr_main_demo)) {
  203. $tab = explode(',', $dolibarr_main_demo);
  204. $demologin = $tab[0];
  205. $demopassword = $tab[1];
  206. }
  207. // Execute hook getLoginPageOptions (for table)
  208. $parameters = array('entity' => GETPOST('entity', 'int'), 'switchentity' => GETPOST('switchentity', 'int'));
  209. $reshook = $hookmanager->executeHooks('getLoginPageOptions', $parameters); // Note that $action and $object may have been modified by some hooks.
  210. $morelogincontent = $hookmanager->resPrint;
  211. // Execute hook getLoginPageExtraOptions (eg for js)
  212. $parameters = array('entity' => GETPOST('entity', 'int'), 'switchentity' => GETPOST('switchentity', 'int'));
  213. $reshook = $hookmanager->executeHooks('getLoginPageExtraOptions', $parameters); // Note that $action and $object may have been modified by some hooks.
  214. $moreloginextracontent = $hookmanager->resPrint;
  215. //Redirect after connection
  216. $parameters = array('entity' => GETPOST('entity', 'int'), 'switchentity' => GETPOST('switchentity', 'int'));
  217. $reshook = $hookmanager->executeHooks('redirectAfterConnection', $parameters); // Note that $action and $object may have been modified by some hooks.
  218. $php_self = $hookmanager->resPrint;
  219. // Login
  220. $login = (!empty($hookmanager->resArray['username']) ? $hookmanager->resArray['username'] : (GETPOST("username", "alpha") ? GETPOST("username", "alpha") : $demologin));
  221. $password = $demopassword;
  222. // Show logo (search in order: small company logo, large company logo, theme logo, common logo)
  223. $width = 0;
  224. $urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png';
  225. if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) {
  226. $urllogo = DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_small);
  227. } elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) {
  228. $urllogo = DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/'.$mysoc->logo);
  229. $width = 128;
  230. } elseif (!empty($mysoc->logo_squarred_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_squarred_small)) {
  231. $urllogo = DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_squarred_small);
  232. } elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) {
  233. $urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg';
  234. }
  235. // Security graphical code
  236. $captcha = 0;
  237. $captcha_refresh = '';
  238. if (function_exists("imagecreatefrompng") && !empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA)) {
  239. $captcha = 1;
  240. $captcha_refresh = img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"');
  241. }
  242. // Extra link
  243. $forgetpasslink = 0;
  244. $helpcenterlink = 0;
  245. if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK) || empty($conf->global->MAIN_HELPCENTER_DISABLELINK)) {
  246. if (empty($conf->global->MAIN_SECURITY_DISABLEFORGETPASSLINK)) {
  247. $forgetpasslink = 1;
  248. }
  249. if (empty($conf->global->MAIN_HELPCENTER_DISABLELINK)) {
  250. $helpcenterlink = 1;
  251. }
  252. }
  253. // Home message
  254. $main_home = '';
  255. if (!empty($conf->global->MAIN_HOME)) {
  256. $substitutionarray = getCommonSubstitutionArray($langs);
  257. complete_substitutions_array($substitutionarray, $langs);
  258. $texttoshow = make_substitutions($conf->global->MAIN_HOME, $substitutionarray, $langs);
  259. $main_home = dol_htmlcleanlastbr($texttoshow);
  260. }
  261. // Google AD
  262. $main_google_ad_client = ((!empty($conf->global->MAIN_GOOGLE_AD_CLIENT) && !empty($conf->global->MAIN_GOOGLE_AD_SLOT)) ? 1 : 0);
  263. // Set jquery theme
  264. $dol_loginmesg = (!empty($_SESSION["dol_loginmesg"]) ? $_SESSION["dol_loginmesg"] : '');
  265. $favicon = DOL_URL_ROOT.'/theme/dolibarr_256x256_color.png';
  266. if (!empty($mysoc->logo_squarred_mini)) {
  267. $favicon = DOL_URL_ROOT.'/viewimage.php?cache=1&modulepart=mycompany&file='.urlencode('logos/thumbs/'.$mysoc->logo_squarred_mini);
  268. }
  269. if (!empty($conf->global->MAIN_FAVICON_URL)) {
  270. $favicon = $conf->global->MAIN_FAVICON_URL;
  271. }
  272. $jquerytheme = 'base';
  273. if (!empty($conf->global->MAIN_USE_JQUERY_THEME)) {
  274. $jquerytheme = $conf->global->MAIN_USE_JQUERY_THEME;
  275. }
  276. // Set dol_hide_topmenu, dol_hide_leftmenu, dol_optimize_smallscreen, dol_no_mouse_hover
  277. $dol_hide_topmenu = GETPOST('dol_hide_topmenu', 'int');
  278. $dol_hide_leftmenu = GETPOST('dol_hide_leftmenu', 'int');
  279. $dol_optimize_smallscreen = GETPOST('dol_optimize_smallscreen', 'int');
  280. $dol_no_mouse_hover = GETPOST('dol_no_mouse_hover', 'int');
  281. $dol_use_jmobile = GETPOST('dol_use_jmobile', 'int');
  282. // Include login page template
  283. include $template_dir.'login.tpl.php';
  284. // Global html output events ($mesgs, $errors, $warnings)
  285. dol_htmloutput_events(0);
  286. $_SESSION["dol_loginmesg"] = '';
  287. }
  288. }
  289. /**
  290. * Fonction pour initialiser un salt pour la fonction crypt.
  291. *
  292. * @param int $type 2=>renvoi un salt pour cryptage DES
  293. * 12=>renvoi un salt pour cryptage MD5
  294. * non defini=>renvoi un salt pour cryptage par defaut
  295. * @return string Salt string
  296. */
  297. function makesalt($type = CRYPT_SALT_LENGTH)
  298. {
  299. dol_syslog("makesalt type=".$type);
  300. switch ($type) {
  301. case 12: // 8 + 4
  302. $saltlen = 8;
  303. $saltprefix = '$1$';
  304. $saltsuffix = '$';
  305. break;
  306. case 8: // 8 (Pour compatibilite, ne devrait pas etre utilise)
  307. $saltlen = 8;
  308. $saltprefix = '$1$';
  309. $saltsuffix = '$';
  310. break;
  311. case 2: // 2
  312. default: // by default, fall back on Standard DES (should work everywhere)
  313. $saltlen = 2;
  314. $saltprefix = '';
  315. $saltsuffix = '';
  316. break;
  317. }
  318. $salt = '';
  319. while (dol_strlen($salt) < $saltlen) {
  320. $salt .= chr(mt_rand(64, 126));
  321. }
  322. $result = $saltprefix.$salt.$saltsuffix;
  323. dol_syslog("makesalt return=".$result);
  324. return $result;
  325. }
  326. /**
  327. * Encode or decode database password in config file
  328. *
  329. * @param int $level Encode level: 0 no encoding, 1 encoding
  330. * @return int <0 if KO, >0 if OK
  331. */
  332. function encodedecode_dbpassconf($level = 0)
  333. {
  334. dol_syslog("encodedecode_dbpassconf level=".$level, LOG_DEBUG);
  335. $config = '';
  336. $passwd = '';
  337. $passwd_crypted = '';
  338. if ($fp = fopen(DOL_DOCUMENT_ROOT.'/conf/conf.php', 'r')) {
  339. while (!feof($fp)) {
  340. $buffer = fgets($fp, 4096);
  341. $lineofpass = 0;
  342. $reg = array();
  343. if (preg_match('/^[^#]*dolibarr_main_db_encrypted_pass[\s]*=[\s]*(.*)/i', $buffer, $reg)) { // Old way to save crypted value
  344. $val = trim($reg[1]); // This also remove CR/LF
  345. $val = preg_replace('/^["\']/', '', $val);
  346. $val = preg_replace('/["\'][\s;]*$/', '', $val);
  347. if (!empty($val)) {
  348. $passwd_crypted = $val;
  349. // method dol_encode/dol_decode
  350. $val = dol_decode($val);
  351. //$val = dolEncrypt($val);
  352. $passwd = $val;
  353. $lineofpass = 1;
  354. }
  355. } elseif (preg_match('/^[^#]*dolibarr_main_db_pass[\s]*=[\s]*(.*)/i', $buffer, $reg)) {
  356. $val = trim($reg[1]); // This also remove CR/LF
  357. $val = preg_replace('/^["\']/', '', $val);
  358. $val = preg_replace('/["\'][\s;]*$/', '', $val);
  359. if (preg_match('/crypted:/i', $buffer)) {
  360. // method dol_encode/dol_decode
  361. $val = preg_replace('/crypted:/i', '', $val);
  362. $passwd_crypted = $val;
  363. $val = dol_decode($val);
  364. $passwd = $val;
  365. } elseif (preg_match('/^dolcrypt:([^:]+):(.*)$/i', $buffer, $reg)) {
  366. // method dolEncrypt/dolDecrypt
  367. $val = preg_replace('/crypted:([^:]+):/i', '', $val);
  368. $passwd_crypted = $val;
  369. $val = dolDecrypt($buffer);
  370. $passwd = $val;
  371. } else {
  372. $passwd = $val;
  373. $val = dol_encode($val);
  374. $passwd_crypted = $val;
  375. }
  376. $lineofpass = 1;
  377. }
  378. // Output line
  379. if ($lineofpass) {
  380. // Add value at end of file
  381. if ($level == 0) {
  382. $config .= '$dolibarr_main_db_pass=\''.$passwd.'\';'."\n";
  383. }
  384. if ($level == 1) {
  385. $config .= '$dolibarr_main_db_pass=\'crypted:'.$passwd_crypted.'\';'."\n";
  386. }
  387. //print 'passwd = '.$passwd.' - passwd_crypted = '.$passwd_crypted;
  388. //exit;
  389. } else {
  390. $config .= $buffer;
  391. }
  392. }
  393. fclose($fp);
  394. // Write new conf file
  395. $file = DOL_DOCUMENT_ROOT.'/conf/conf.php';
  396. if ($fp = @fopen($file, 'w')) {
  397. fputs($fp, $config);
  398. fflush($fp);
  399. fclose($fp);
  400. clearstatcache();
  401. // It's config file, so we set read permission for creator only.
  402. // Should set permission to web user and groups for users used by batch
  403. //@chmod($file, octdec('0600'));
  404. return 1;
  405. } else {
  406. dol_syslog("encodedecode_dbpassconf Failed to open conf.php file for writing", LOG_WARNING);
  407. return -1;
  408. }
  409. } else {
  410. dol_syslog("encodedecode_dbpassconf Failed to read conf.php", LOG_ERR);
  411. return -2;
  412. }
  413. }
  414. /**
  415. * Return a generated password using default module
  416. *
  417. * @param boolean $generic true=Create generic password (32 chars/numbers), false=Use the configured password generation module
  418. * @param array $replaceambiguouschars Discard ambigous characters. For example array('I').
  419. * @param int $length Length of random string (Used only if $generic is true)
  420. * @return string New value for password
  421. * @see dol_hash(), dolJSToSetRandomPassword()
  422. */
  423. function getRandomPassword($generic = false, $replaceambiguouschars = null, $length = 32)
  424. {
  425. global $db, $conf, $langs, $user;
  426. $generated_password = '';
  427. if ($generic) {
  428. $lowercase = "qwertyuiopasdfghjklzxcvbnm";
  429. $uppercase = "ASDFGHJKLZXCVBNMQWERTYUIOP";
  430. $numbers = "1234567890";
  431. $randomCode = "";
  432. $nbofchar = round($length / 3);
  433. $nbofcharlast = ($length - 2 * $nbofchar);
  434. //var_dump($nbofchar.'-'.$nbofcharlast);
  435. if (function_exists('random_int')) { // Cryptographic random
  436. $max = strlen($lowercase) - 1;
  437. for ($x = 0; $x < $nbofchar; $x++) {
  438. $tmp = random_int(0, $max);
  439. $randomCode .= $lowercase[$tmp];
  440. }
  441. $max = strlen($uppercase) - 1;
  442. for ($x = 0; $x < $nbofchar; $x++) {
  443. $tmp = random_int(0, $max);
  444. $randomCode .= $uppercase[$tmp];
  445. }
  446. $max = strlen($numbers) - 1;
  447. for ($x = 0; $x < $nbofcharlast; $x++) {
  448. $tmp = random_int(0, $max);
  449. $randomCode .= $numbers[$tmp];
  450. }
  451. $generated_password = str_shuffle($randomCode);
  452. } else {
  453. // Old platform, non cryptographic random
  454. $max = strlen($lowercase) - 1;
  455. for ($x = 0; $x < $nbofchar; $x++) {
  456. $tmp = mt_rand(0, $max);
  457. $randomCode .= $lowercase[$tmp];
  458. }
  459. $max = strlen($uppercase) - 1;
  460. for ($x = 0; $x < $nbofchar; $x++) {
  461. $tmp = mt_rand(0, $max);
  462. $randomCode .= $uppercase[$tmp];
  463. }
  464. $max = strlen($numbers) - 1;
  465. for ($x = 0; $x < $nbofcharlast; $x++) {
  466. $tmp = mt_rand(0, $max);
  467. $randomCode .= $numbers[$tmp];
  468. }
  469. $generated_password = str_shuffle($randomCode);
  470. }
  471. } elseif (!empty($conf->global->USER_PASSWORD_GENERATED)) {
  472. $nomclass = "modGeneratePass".ucfirst($conf->global->USER_PASSWORD_GENERATED);
  473. $nomfichier = $nomclass.".class.php";
  474. //print DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomclass;
  475. require_once DOL_DOCUMENT_ROOT."/core/modules/security/generate/".$nomfichier;
  476. $genhandler = new $nomclass($db, $conf, $langs, $user);
  477. $generated_password = $genhandler->getNewGeneratedPassword();
  478. unset($genhandler);
  479. }
  480. // Do we have to discard some alphabetic characters ?
  481. if (is_array($replaceambiguouschars) && count($replaceambiguouschars) > 0) {
  482. $numbers = "ABCDEF";
  483. $max = strlen($numbers) - 1;
  484. if (function_exists('random_int')) { // Cryptographic random
  485. $tmp = random_int(0, $max);
  486. $generated_password = str_replace($replaceambiguouschars, $numbers[$tmp], $generated_password);
  487. } else {
  488. $tmp = mt_rand(0, $max);
  489. $generated_password = str_replace($replaceambiguouschars, $numbers[$tmp], $generated_password);
  490. }
  491. }
  492. return $generated_password;
  493. }
  494. /**
  495. * Ouput javacript to autoset a generated password using default module into a HTML element.
  496. *
  497. * @param string $htmlname HTML name of element to insert key into
  498. * @param string $htmlnameofbutton HTML name of button
  499. * @param int $generic 1=Return a generic pass, 0=Return a pass following setup rules
  500. * @return string HTML javascript code to set a password
  501. * @see getRandomPassword()
  502. */
  503. function dolJSToSetRandomPassword($htmlname, $htmlnameofbutton = 'generate_token', $generic = 1)
  504. {
  505. global $conf;
  506. if (!empty($conf->use_javascript_ajax)) {
  507. print "\n".'<!-- Js code to suggest a security key --><script type="text/javascript">';
  508. print '$(document).ready(function () {
  509. $("#'.dol_escape_js($htmlnameofbutton).'").click(function() {
  510. console.log("We click on the button '.dol_escape_js($htmlnameofbutton).' to suggest a key. We will fill '.dol_escape_js($htmlname).'");
  511. $.get( "'.DOL_URL_ROOT.'/core/ajax/security.php", {
  512. action: \'getrandompassword\',
  513. generic: '.($generic ? '1' : '0').',
  514. token: \''.dol_escape_js(newToken()).'\'
  515. },
  516. function(result) {
  517. $("#'.dol_escape_js($htmlname).'").val(result);
  518. });
  519. });
  520. });'."\n";
  521. print '</script>';
  522. }
  523. }