Passed
Push — master ( 65bdac...4e88da )
by Alxarafe
32:38
created

Helpers/Security2.php (2 issues)

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