Passed
Push — teampass_3.0 ( 23c792...d6f83d )
by Nils
04:32
created

identifyViaLDAPPosix()   C

Complexity

Conditions 13
Paths 132

Size

Total Lines 159
Code Lines 99

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 13
eloc 99
c 6
b 0
f 0
nc 132
nop 5
dl 0
loc 159
rs 5.1018

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Teampass - a collaborative passwords manager.
5
 * ---
6
 * This library is distributed in the hope that it will be useful,
7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
 * ---
10
 * @project   Teampass
11
 * @file      identify.php
12
 * ---
13
 * @author    Nils Laumaillé ([email protected])
14
 * @copyright 2009-2019 Teampass.net
15
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
16
 * ---
17
 * @see       https://www.teampass.net
18
 */
19
20
use LdapRecord\Models\Model;
21
use LdapRecord\Models\Entry;
22
use LdapRecord\Container; 
23
use LdapRecord\Connection;
24
25
require_once 'SecureHandler.php';
26
session_name('teampass_session');
27
session_start();
28
if (isset($_SESSION['CPM']) === false || (int) $_SESSION['CPM'] !== 1) {
29
    die('Hacking attempt...');
30
}
31
32
// Load config
33
if (file_exists('../includes/config/tp.config.php')) {
34
    include_once '../includes/config/tp.config.php';
35
} elseif (file_exists('./includes/config/tp.config.php')) {
36
    include_once './includes/config/tp.config.php';
37
} else {
38
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
39
}
40
41
if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir']) === true || $SETTINGS['cpassman_dir'] === '.') {
42
    $SETTINGS['cpassman_dir'] = '..';
43
}
44
45
// Load AntiXSS
46
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/voku/helper/AntiXSS.php';
47
$antiXss = new voku\helper\AntiXSS();
48
49
require_once $SETTINGS['cpassman_dir'] . '/sources/main.functions.php';
50
require_once $SETTINGS['cpassman_dir'] . '/includes/config/include.php';
51
require_once $SETTINGS['cpassman_dir'] . '/includes/config/settings.php';
52
53
// init
54
$ldap_suffix = '';
55
$result = '';
56
$adldap = '';
57
58
// If Debug then clean the files
59
if (DEBUGLDAP === true) {
60
    define('DEBUGLDAPFILE', $SETTINGS['path_to_files_folder'] . '/ldap.debug.txt');
61
    $fp = fopen(DEBUGLDAPFILE, 'w');
62
    fclose($fp);
63
}
64
if (DEBUGDUO === true) {
65
    define('DEBUGDUOFILE', $SETTINGS['path_to_files_folder'] . '/duo.debug.txt');
66
    $fp = fopen(DEBUGDUOFILE, 'w');
67
    fclose($fp);
68
}
69
70
// Prepare POST variables
71
$post_type = filter_input(INPUT_POST, 'type', FILTER_SANITIZE_STRING);
72
$post_login = filter_input(INPUT_POST, 'login', FILTER_SANITIZE_STRING);
73
$post_pwd = filter_input(INPUT_POST, 'pwd', FILTER_SANITIZE_STRING);
74
$post_sig_response = filter_input(INPUT_POST, 'sig_response', FILTER_SANITIZE_STRING);
75
$post_cardid = filter_input(INPUT_POST, 'cardid', FILTER_SANITIZE_STRING);
76
$post_data = filter_input(INPUT_POST, 'data', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
77
78
// connect to the server
79
if (defined('DB_PASSWD_CLEAR') === false) {
80
    define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
81
}
82
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Database/Meekrodb/db.class.php';
83
if (defined('DB_PASSWD_CLEAR') === false) {
84
    define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
85
}
86
DB::$host = DB_HOST;
87
DB::$user = DB_USER;
88
DB::$password = DB_PASSWD_CLEAR;
89
DB::$dbName = DB_NAME;
90
DB::$port = DB_PORT;
91
DB::$encoding = DB_ENCODING;
92
93
if ($post_type === 'identify_duo_user') {
94
    //--------
95
    // DUO AUTHENTICATION
96
    //--------
97
    // This step creates the DUO request encrypted key
98
99
    // Get DUO keys
100
    $duoData = DB::query(
101
        'SELECT intitule, valeur
102
        FROM ' . prefixTable('misc') . '
103
        WHERE type = %s',
104
        'duoSecurity'
105
    );
106
    foreach ($duoData as $value) {
107
        $_GLOBALS[strtoupper($value['intitule'])] = $value['valeur'];
108
    }
109
110
    // load library
111
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Authentication/DuoSecurity/Duo.php';
112
    $sig_request = Duo::signRequest(
113
        $_GLOBALS['IKEY'],
114
        $_GLOBALS['SKEY'],
115
        $_GLOBALS['AKEY'],
116
        $post_login
117
    );
118
119
    if (DEBUGDUO === true) {
120
        debugIdentify(
121
            DEBUGDUO,
122
            DEBUGDUOFILE,
123
            "\n\n-----\n\n" .
124
                'sig request : ' . $post_login . "\n" .
125
                'resp : ' . $sig_request . "\n"
126
        );
127
    }
128
129
    // load csrfprotector
130
    $csrfp_config = include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/csrfp/libs/csrfp.config.php';
131
132
    // return result
133
    echo '[{"sig_request" : "' . $sig_request . '" , "csrfp_token" : "' . $csrfp_config['CSRFP_TOKEN'] . '" , "csrfp_key" : "' . filter_var($_COOKIE[$csrfp_config['CSRFP_TOKEN']], FILTER_SANITIZE_STRING) . '"}]';
134
    // ---
135
    // ---
136
} elseif ($post_type === 'identify_duo_user_check') {
137
    //--------
138
    // DUO AUTHENTICATION
139
    // this step is verifying the response received from the server
140
    //--------
141
142
    // load library
143
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Authentication/DuoSecurity/Duo.php';
144
    $authenticated_username = Duo::verifyResponse(
145
        $SETTINGS['duo_ikey'],
146
        $SETTINGS['duo_skey'],
147
        $SETTINGS['duo_akey'],
148
        $post_sig_response
149
    );
150
151
    if (DEBUGDUO === true) {
152
        debugIdentify(
153
            DEBUGDUO,
154
            DEBUGDUOFILE,
155
            "\n\n-----\n\n" .
156
                'sig response : ' . $post_sig_response . "\n" .
157
                'resp : ' . $authenticated_username . "\n"
158
        );
159
    }
160
161
    // return the response (which should be the user name)
162
    if ($authenticated_username === $post_login) {
163
        // Check if this account exists in Teampass or only in LDAP
164
        if (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 1) {
165
            // is user in Teampass?
166
            $userInfo = DB::queryfirstrow(
167
                'SELECT id
168
                FROM ' . prefixTable('users') . '
169
                WHERE login = %s',
170
                $post_login
171
            );
172
173
            if (DB::count() === 0) {
174
                // Ask your administrator to create your account in Teampass
175
                // TODO
176
            }
177
        }
178
179
        echo '[{"authenticated_username" : "' . $authenticated_username . '"}]';
180
    } else {
181
        echo '[{"authenticated_username" : "' . $authenticated_username . '"}]';
182
    }
183
    // ---
184
    // ---
185
} elseif ($post_type === 'identify_user') {
186
    //--------
187
    // NORMAL IDENTICATION STEP
188
    //--------
189
190
191
    // Load superGlobals
192
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
193
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
194
195
    // Prepare GET variables
196
    $sessionPwdAttempts = $superGlobal->get('pwd_attempts', 'SESSION');
197
198
    // increment counter of login attempts
199
    if (empty($sessionPwdAttempts) === true) {
200
        $sessionPwdAttempts = 1;
201
    } else {
202
        ++$sessionPwdAttempts;
203
    }
204
205
    $superGlobal->put('pwd_attempts', $sessionPwdAttempts, 'SESSION');
206
207
    // manage brute force
208
    if ($sessionPwdAttempts <= 3) {
209
        $sessionPwdAttempts = 0;
210
        // identify the user through Teampass process
211
        identifyUser(
212
            $post_data,
213
            $SETTINGS
214
        );
215
    } elseif (isset($_SESSION['next_possible_pwd_attempts']) && time() > $_SESSION['next_possible_pwd_attempts'] && $sessionPwdAttempts > 3) {
216
        $sessionPwdAttempts = 0;
217
        // identify the user through Teampass process
218
        identifyUser(
219
            $post_data,
220
            $SETTINGS
221
        );
222
    } else {
223
        $_SESSION['next_possible_pwd_attempts'] = time() + 10;
224
225
        // Encrypt data to return
226
        echo prepareExchangedData(
227
            array(
228
                'value' => 'bruteforce_wait',
229
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : 0,
230
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
231
                'pwd_attempts' => (int) $sessionPwdAttempts,
232
                'error' => true,
233
                'message' => langHdl('error_bad_credentials_more_than_3_times'),
234
            ),
235
            'encode'
236
        );
237
238
        return false;
239
    }
240
    // ---
241
    // ---
242
    // ---
243
} elseif ($post_type === 'get2FAMethods') {
244
    //--------
245
    // Get MFA methods
246
    //--------
247
    //
248
249
    // Encrypt data to return
250
    echo prepareExchangedData(
251
        array(
252
            'agses' => (isset($SETTINGS['agses_authentication_enabled']) === true
253
                && (int) $SETTINGS['agses_authentication_enabled'] === 1) ? true : false,
254
            'google' => (isset($SETTINGS['google_authentication']) === true
255
                && (int) $SETTINGS['google_authentication'] === 1) ? true : false,
256
            'yubico' => (isset($SETTINGS['yubico_authentication']) === true
257
                && (int) $SETTINGS['yubico_authentication'] === 1) ? true : false,
258
            'duo' => (isset($SETTINGS['duo']) === true
259
                && (int) $SETTINGS['duo'] === 1) ? true : false,
260
        ),
261
        'encode'
262
    );
263
264
    return false;
265
}
266
267
/**
268
 * Complete authentication of user through Teampass.
269
 *
270
 * @param string $sentData Credentials
271
 * @param array  $SETTINGS Teamapss settings
272
 *
273
 * @return boolean
274
 */
275
function identifyUser($sentData, $SETTINGS)
276
{
277
    // Load config
278
    if (file_exists('../includes/config/tp.config.php')) {
279
        include_once '../includes/config/tp.config.php';
280
    } elseif (file_exists('./includes/config/tp.config.php')) {
281
        include_once './includes/config/tp.config.php';
282
    } else {
283
        throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
284
    }
285
    include_once $SETTINGS['cpassman_dir'] . '/includes/config/settings.php';
286
287
    header('Content-type: text/html; charset=utf-8');
288
    error_reporting(E_ERROR);
289
    include_once $SETTINGS['cpassman_dir'] . '/sources/main.functions.php';
290
    include_once $SETTINGS['cpassman_dir'] . '/sources/SplClassLoader.php';
291
292
    // Load AntiXSS
293
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/voku/helper/AntiXSS.php';
294
    $antiXss = new voku\helper\AntiXSS();
295
296
    // Load superGlobals
297
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
298
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
299
300
    // Prepare GET variables
301
    $sessionUserLanguage = $superGlobal->get('user_language', 'SESSION');
302
    $sessionKey = $superGlobal->get('key', 'SESSION');
303
    $sessionAdmin = $superGlobal->get('user_admin', 'SESSION');
304
    $sessionPwdAttempts = $superGlobal->get('pwd_attempts', 'SESSION');
305
    $sessionUrl = $superGlobal->get('initial_url', 'SESSION');
306
307
    // Debug
308
    debugIdentify(
309
        DEBUGDUO,
310
        DEBUGDUOFILE,
311
        "Content of data sent '" . filter_var($sentData, FILTER_SANITIZE_STRING) . "'\n"
312
    );
313
314
    // connect to the server
315
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Database/Meekrodb/db.class.php';
316
    if (defined('DB_PASSWD_CLEAR') === false) {
317
        define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
318
    }
319
    DB::$host = DB_HOST;
320
    DB::$user = DB_USER;
321
    DB::$password = DB_PASSWD_CLEAR;
322
    DB::$dbName = DB_NAME;
323
    DB::$port = DB_PORT;
324
    DB::$encoding = DB_ENCODING;
325
326
    // User's language loading
327
    include_once $SETTINGS['cpassman_dir'] . '/includes/language/' . $sessionUserLanguage . '.php';
328
    //echo $dataReceived." -->".empty($sessionKey)."<-- ".$sessionKey." ** " ;
329
    // decrypt and retreive data in JSON format
330
    if (empty($sessionKey) === true) {
331
        $dataReceived = $sentData;
332
    } else {
333
        $dataReceived = prepareExchangedData($sentData, 'decode', $sessionKey);
334
        $superGlobal->put('key', $sessionKey, 'SESSION');
335
    }
336
337
    // prepare variables
338
    if (
339
        isset($SETTINGS['enable_http_request_login']) === true
340
        && (int) $SETTINGS['enable_http_request_login'] === 1
341
        && isset($_SERVER['PHP_AUTH_USER']) === true
342
        && isset($SETTINGS['maintenance_mode']) === true
343
        && (int) $SETTINGS['maintenance_mode'] === 1
344
    ) {
345
        if (strpos($_SERVER['PHP_AUTH_USER'], '@') !== false) {
346
            $username = explode('@', filter_var($_SERVER['PHP_AUTH_USER'], FILTER_SANITIZE_STRING))[0];
347
        } elseif (strpos($_SERVER['PHP_AUTH_USER'], '\\') !== false) {
348
            $username = explode('\\', filter_var($_SERVER['PHP_AUTH_USER'], FILTER_SANITIZE_STRING))[1];
349
        } else {
350
            $username = filter_var($_SERVER['PHP_AUTH_USER'], FILTER_SANITIZE_STRING);
351
        }
352
        $passwordClear = $_SERVER['PHP_AUTH_PW'];
353
    } else {
354
        $passwordClear = filter_var($dataReceived['pw'], FILTER_SANITIZE_STRING);
355
        $username = filter_var($dataReceived['login'], FILTER_SANITIZE_STRING);
356
    }
357
358
    // Brute force management
359
    if ($sessionPwdAttempts > 3) {
360
        $superGlobal->put('next_possible_pwd_attempts', (time() + 10), 'SESSION');
361
        $superGlobal->put('pwd_attempts', 0, 'SESSION');
362
363
        logEvents($SETTINGS, 'failed_auth', 'user_not_exists', '', stripslashes($username), stripslashes($username));
364
        echo prepareExchangedData(
365
            array(
366
                'value' => 'bruteforce_wait',
367
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : 0,
368
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
369
                'pwd_attempts' => 0,
370
                'error' => true,
371
                'message' => langHdl('error_bad_credentials_more_than_3_times'),
372
            ),
373
            'encode'
374
        );
375
376
        return false;
377
    }
378
379
    // User's 2FA method
380
    $user_2fa_selection = filter_var($dataReceived['user_2fa_selection'], FILTER_SANITIZE_STRING);
381
382
    // Check 2FA
383
    if ((((int) $SETTINGS['yubico_authentication'] === 1 && empty($user_2fa_selection) === true)
384
            || ((int) $SETTINGS['google_authentication'] === 1 && empty($user_2fa_selection) === true)
385
            || ((int) $SETTINGS['duo'] === 1 && empty($user_2fa_selection) === true))
386
        && ($username !== 'admin' || ((int) $SETTINGS['admin_2fa_required'] === 1 && $username === 'admin'))
387
    ) {
388
        echo prepareExchangedData(
389
            array(
390
                'value' => '2fa_not_set',
391
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : 0,
392
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
393
                'pwd_attempts' => (int) $sessionPwdAttempts,
394
                'error' => '2fa_not_set',
395
                'message' => langHdl('2fa_credential_not_correct'),
396
            ),
397
            'encode'
398
        );
399
400
        return false;
401
    }
402
403
    // Debug
404
    debugIdentify(
405
        DEBUGDUO,
406
        DEBUGDUOFILE,
407
        "Starting authentication of '" . $username . "'\n" .
408
            'LDAP status: ' . $SETTINGS['ldap_mode'] . "\n"
409
    );
410
    debugIdentify(
411
        DEBUGLDAP,
412
        DEBUGLDAPFILE,
413
        "Get all LDAP params : \n" .
414
            'mode : ' . $SETTINGS['ldap_mode'] . "\n" .
415
            'type : ' . $SETTINGS['ldap_type'] . "\n" .
416
            'base_dn : ' . $SETTINGS['ldap_domain_dn'] . "\n" .
417
            'search_base : ' . $SETTINGS['ldap_search_base'] . "\n" .
418
            'bind_dn : ' . $SETTINGS['ldap_bind_dn'] . "\n" .
419
            'bind_passwd : ' . $SETTINGS['ldap_bind_passwd'] . "\n" .
420
            'user_attribute : ' . $SETTINGS['ldap_user_attribute'] . "\n" .
421
            'account_suffix : ' . $SETTINGS['ldap_suffix'] . "\n" .
422
            'domain_controllers : ' . $SETTINGS['ldap_domain_controler'] . "\n" .
423
            'ad_port : ' . $SETTINGS['ldap_port'] . "\n" .
424
            'use_ssl : ' . $SETTINGS['ldap_ssl'] . "\n" .
425
            'use_tls : ' . $SETTINGS['ldap_tls'] . "\n*********\n\n"
426
    );
427
428
    // Check if user exists
429
    $userInfo = DB::queryFirstRow(
430
        'SELECT *
431
        FROM ' . prefixTable('users') . '
432
        WHERE login=%s',
433
        $username
434
    );
435
    $counter = DB::count();
436
437
    // User doesn't exist then stop
438
    if ($counter === 0) {
439
        logEvents($SETTINGS, 'failed_auth', 'user_not_exists', '', stripslashes($username), stripslashes($username));
440
        echo prepareExchangedData(
441
            array(
442
                'error' => 'user_not_exists',
443
                'message' => langHdl('error_bad_credentials'),
444
                'pwd_attempts' => (int) $sessionPwdAttempts,
445
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : 0,
446
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
447
            ),
448
            'encode'
449
        );
450
        return false;
451
    }
452
453
    // Debug
454
    debugIdentify(
455
        DEBUGDUO,
456
        DEBUGDUOFILE,
457
        'USer exists: ' . $counter . "\n"
458
    );
459
460
    
461
462
    // Manage Maintenance mode
463
    if (
464
        isset($SETTINGS['maintenance_mode']) === true && (int) $SETTINGS['maintenance_mode'] === 1
465
        && (int) $userInfo['admin'] === 0
466
    ) {
467
        echo prepareExchangedData(
468
            array(
469
                'value' => '',
470
                'user_admin' => (int) $userInfo['admin'],
471
                'initial_url' => '',
472
                'pwd_attempts' => '',
473
                'error' => 'maintenance_mode_enabled',
474
                'message' => '',
475
            ),
476
            'encode'
477
        );
478
        return false;
479
    }
480
481
482
    $user_initial_creation_through_ldap = false;
483
    $userPasswordVerified = '';
484
    $ldapConnection = false;
485
    $return = '';
486
    $proceedIdentification = '';
487
488
    // Prepare LDAP connection if set up
489
    if (
490
        isset($SETTINGS['ldap_mode']) === true
491
        && (int) $SETTINGS['ldap_mode'] === 1
492
        && $username !== 'admin'
493
        && $userInfo['auth_type'] !== 'local'
494
    ) {
495
        $ldapConnection = true;
496
497
        $retLDAP = authenticateThroughAD(
498
            $username,
499
            $userInfo,
500
            $passwordClear,
501
            $SETTINGS
502
        );
503
504
        if ($retLDAP['error'] === true) {
505
            echo prepareExchangedData(
506
                array(
507
                    'value' => '',
508
                    'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : 0,
509
                    'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
510
                    'pwd_attempts' => (int) $sessionPwdAttempts,
511
                    'error' => true,
512
                    'message' => $retLDAP['message'],
513
                ),
514
                'encode'
515
            );
516
            return false;
517
        }
518
    }
519
520
    // Check Yubico
521
    if (
522
        isset($SETTINGS['yubico_authentication']) === true
523
        && (int) $SETTINGS['yubico_authentication'] === 1
524
        && ((int) $userInfo['admin'] !== 1 || ((int) $SETTINGS['admin_2fa_required'] === 1 && (int) $userInfo['admin'] === 1))
525
        && $user_2fa_selection === 'yubico'
526
    ) {
527
        $ret = yubicoMFACheck(
528
            $dataReceived,
529
            $userInfo,
530
            $SETTINGS
531
        );
532
533
        if ($ret['error'] !== "") {
534
            echo prepareExchangedData(
535
                $ret,
536
                'encode'
537
            );
538
            return false;
539
        }
540
    }
541
542
    // check GA code
543
    if (
544
        isset($SETTINGS['google_authentication']) === true
545
        && (int) $SETTINGS['google_authentication'] === 1
546
        && ($username !== 'admin' || ((int) $SETTINGS['admin_2fa_required'] === 1 && $username === 'admin'))
547
        && $user_2fa_selection === 'otp'
548
    ) {
549
        $ret = googleMFACheck(
550
            $username,
551
            $userInfo,
552
            $dataReceived,
553
            $SETTINGS
554
        );
555
556
        if ($ret['error'] !== false) {
557
            logEvents($SETTINGS, 'failed_auth', 'wrong_mfa_code', '', stripslashes($username), stripslashes($username));
558
            echo prepareExchangedData(
559
                $ret,
560
                'encode'
561
            );
562
            return false;
563
            // ---
564
        } else {
565
            $proceedIdentification = $ret['proceedIdentification'];
566
            $user_initial_creation_through_ldap = $ret['user_initial_creation_through_ldap'];
567
568
            // Manage 1st usage of Google MFA
569
            if (count($ret['firstTime']) > 0) {
570
                echo prepareExchangedData(
571
                    $ret['firstTime'],
572
                    'encode'
573
                );
574
                return false;
575
            }
576
        }
577
    }
578
579
    // Debug
580
    debugIdentify(
581
        DEBUGDUO,
582
        DEBUGDUOFILE,
583
        'Proceed with Ident: ' . $proceedIdentification . "\n"
584
    );
585
586
    // If admin user then check if folder install exists
587
    // if yes then refuse connection
588
    if ((int) $userInfo['admin'] === 1 && is_dir('../install') === true) {
589
        echo prepareExchangedData(
590
            array(
591
                'value' => '',
592
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : 0,
593
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
594
                'pwd_attempts' => (int) $sessionPwdAttempts,
595
                'error' => true,
596
                'message' => langHdl('remove_install_folder'),
597
            ),
598
            'encode'
599
        );
600
        return false;
601
    }
602
603
604
    // Check user and password
605
    if (checkCredentials($passwordClear, $userInfo, $dataReceived, $username, $SETTINGS) !== true) {
606
        echo prepareExchangedData(
607
            array(
608
                'value' => '',
609
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : 0,
610
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
611
                'pwd_attempts' => (int) $sessionPwdAttempts,
612
                'error' => 'user_not_exists2',
613
                'message' => langHdl('error_bad_credentials'),
614
            ),
615
            'encode'
616
        );
617
        return false;
618
    }
619
620
    // Debug
621
    debugIdentify(
622
        DEBUGDUO,
623
        DEBUGDUOFILE,
624
        "User's password verified: " . $userPasswordVerified . "\n"
625
    );
626
627
    // Can connect if
628
    // 1- no LDAP mode + user enabled + pw ok
629
    // 2- LDAP mode + user enabled + ldap connection ok + user is not admin
630
    // 3-  LDAP mode + user enabled + pw ok + usre is admin
631
    // This in order to allow admin by default to connect even if LDAP is activated
632
    if ((isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 0
633
            && (int) $userInfo['disabled'] === 0)
634
        || (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 1
635
            && $ldapConnection === true && (int) $userInfo['disabled'] === 0 && $username !== 'admin')
636
        || (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 2
637
            && $ldapConnection === true && (int) $userInfo['disabled'] === 0 && $username !== 'admin')
638
        || (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 1
639
            && $username == 'admin' && (int) $userInfo['disabled'] === 0)
640
        || (isset($SETTINGS['ldap_and_local_authentication']) === true && (int) $SETTINGS['ldap_and_local_authentication'] === 1
641
            && isset($SETTINGS['ldap_mode']) === true && in_array($SETTINGS['ldap_mode'], array('1', '2')) === true
642
            && (int) $userInfo['disabled'] === 0)
643
    ) {
644
        $superGlobal->put('autoriser', true, 'SESSION');
645
        $superGlobal->put('pwd_attempts', 0, 'SESSION');
646
647
        /*// Debug
648
        debugIdentify(
649
            DEBUGDUO,
650
            DEBUGDUOFILE,
651
            "User's token: " . $key . "\n"
652
        );*/
653
654
        // Check if any unsuccessfull login tries exist
655
        //$arrAttempts = array();
656
        $rows = DB::query(
657
            'SELECT date
658
            FROM ' . prefixTable('log_system') . "
659
            WHERE field_1 = %s
660
            AND type = 'failed_auth'
661
            AND label = 'user_password_not_correct'
662
            AND date >= %s AND date < %s",
663
            $userInfo['login'],
664
            $userInfo['last_connexion'],
665
            time()
666
        );
667
        //$arrAttempts['nb'] = DB::count();
668
        //$arrAttempts['shown'] = DB::count() === 0 ? true : false;
669
        $arrAttempts = array();
670
        if (DB::count() > 0) {
671
            foreach ($rows as $record) {
672
                array_push(
673
                    $arrAttempts,
674
                    date($SETTINGS['date_format'] . ' ' . $SETTINGS['time_format'], $record['date'])
675
                );
676
            }
677
        }
678
        $superGlobal->put('unsuccessfull_login_attempts_list', $arrAttempts, 'SESSION', 'user');
679
        $superGlobal->put('unsuccessfull_login_attempts_shown', DB::count() === 0 ? true : false, 'SESSION', 'user');
680
        $superGlobal->put('unsuccessfull_login_attempts_nb', DB::count(), 'SESSION', 'user');
681
682
        // Log into DB the user's connection
683
        if (
684
            isset($SETTINGS['log_connections']) === true
685
            && (int) $SETTINGS['log_connections'] === 1
686
        ) {
687
            logEvents($SETTINGS, 'user_connection', 'connection', $userInfo['id'], stripslashes($username));
688
        }
689
        // Save account in SESSION
690
        $superGlobal->put('login', stripslashes($username), 'SESSION');
691
        $superGlobal->put('name', stripslashes($userInfo['name']), 'SESSION');
692
        $superGlobal->put('lastname', stripslashes($userInfo['lastname']), 'SESSION');
693
        $superGlobal->put('user_id', $userInfo['id'], 'SESSION');
694
        $superGlobal->put('user_pwd', $passwordClear, 'SESSION');
695
        $superGlobal->put('admin', $userInfo['admin'], 'SESSION');
696
        $superGlobal->put('user_manager', $userInfo['gestionnaire'], 'SESSION');
697
        $superGlobal->put('user_can_manage_all_users', $userInfo['can_manage_all_users'], 'SESSION');
698
        $superGlobal->put('user_read_only', $userInfo['read_only'], 'SESSION');
699
        $superGlobal->put('last_pw_change', $userInfo['last_pw_change'], 'SESSION');
700
        $superGlobal->put('last_pw', $userInfo['last_pw'], 'SESSION');
701
        $superGlobal->put('can_create_root_folder', $userInfo['can_create_root_folder'], 'SESSION');
702
        $superGlobal->put('personal_folder', $userInfo['personal_folder'], 'SESSION');
703
        $superGlobal->put('user_language', $userInfo['user_language'], 'SESSION');
704
        $superGlobal->put('user_email', $userInfo['email'], 'SESSION');
705
        $superGlobal->put('user_ga', $userInfo['ga'], 'SESSION');
706
        $superGlobal->put('user_avatar', $userInfo['avatar'], 'SESSION');
707
        $superGlobal->put('user_avatar_thumb', $userInfo['avatar_thumb'], 'SESSION');
708
        $superGlobal->put('user_upgrade_needed', $userInfo['upgrade_needed'], 'SESSION');
709
        $superGlobal->put('user_force_relog', $userInfo['force-relog'], 'SESSION');
710
        // get personal settings
711
        if (!isset($userInfo['treeloadstrategy']) || empty($userInfo['treeloadstrategy'])) {
712
            $userInfo['treeloadstrategy'] = 'full';
713
        }
714
        $superGlobal->put('treeloadstrategy', $userInfo['treeloadstrategy'], 'SESSION', 'user');
715
        $superGlobal->put('agses-usercardid', $userInfo['agses-usercardid'], 'SESSION', 'user');
716
        $superGlobal->put('user_language', $userInfo['user_language'], 'SESSION', 'user');
717
        $superGlobal->put('usertimezone', $userInfo['usertimezone'], 'SESSION', 'user');
718
        $superGlobal->put('session_duration', $dataReceived['duree_session'] * 60, 'SESSION', 'user');
719
        $superGlobal->put('api-key', $userInfo['user_api_key'], 'SESSION', 'user');
720
        $superGlobal->put('special', $userInfo['special'], 'SESSION', 'user');
721
722
        // manage session expiration
723
        $superGlobal->put('sessionDuration', (int) (time() + ($dataReceived['duree_session'] * 60)), 'SESSION');
724
725
        /*
726
        * CHECK PASSWORD VALIDITY
727
        * Don't take into consideration if LDAP in use
728
        */
729
        if (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 1) {
730
            $superGlobal->put('validite_pw', true, 'SESSION');
731
            $superGlobal->put('last_pw_change', true, 'SESSION');
732
        } else {
733
            if (isset($userInfo['last_pw_change']) === true) {
734
                if ((int) $SETTINGS['pw_life_duration'] === 0) {
735
                    $superGlobal->put('user_force_relog', 'infinite', 'SESSION');
736
                    $superGlobal->put('validite_pw', true, 'SESSION');
737
                } else {
738
                    $superGlobal->put(
739
                        'numDaysBeforePwExpiration',
740
                        $SETTINGS['pw_life_duration'] - round(
741
                            (mktime(0, 0, 0, (int) date('m'), (int) date('d'), (int) date('y')) - $superGlobal->get('last_pw_change', 'SESSION')) / (24 * 60 * 60)
742
                        ),
743
                        'SESSION'
744
                    );
745
                    if ($superGlobal->get('numDaysBeforePwExpiration', 'SESSION') <= 0) {
746
                        $superGlobal->put('validite_pw', false, 'SESSION');
747
                    } else {
748
                        $superGlobal->put('validite_pw', true, 'SESSION');
749
                    }
750
                }
751
            } else {
752
                $superGlobal->put('validite_pw', false, 'SESSION');
753
            }
754
        }
755
756
        if (empty($userInfo['last_connexion'])) {
757
            $superGlobal->put('last_connection', time(), 'SESSION');
758
        } else {
759
            $superGlobal->put('last_connection', $userInfo['last_connexion'], 'SESSION');
760
        }
761
762
        if (empty($userInfo['latest_items']) === false) {
763
            $superGlobal->put('latest_items', explode(';', $userInfo['latest_items']), 'SESSION');
764
        } else {
765
            $superGlobal->put('latest_items', array(), 'SESSION');
766
        }
767
        if (empty($userInfo['favourites']) === false) {
768
            $superGlobal->put('favourites', explode(';', $userInfo['favourites']), 'SESSION');
769
        } else {
770
            $superGlobal->put('favourites', array(), 'SESSION');
771
        }
772
773
        if (empty($userInfo['groupes_visibles']) === false) {
774
            $superGlobal->put(
775
                'groupes_visibles',
776
                implode(';', $userInfo['groupes_visibles']),
777
                'SESSION'
778
            );
779
        } else {
780
            $superGlobal->put('groupes_visibles', array(), 'SESSION');
781
        }
782
        if (empty($userInfo['groupes_interdits']) === false) {
783
            $superGlobal->put(
784
                'no_access_folders',
785
                implode(';', $userInfo['groupes_visibles']),
786
                'SESSION'
787
            );
788
        } else {
789
            $superGlobal->put('no_access_folders', array(), 'SESSION');
790
        }
791
        // User's roles
792
        if (strpos($userInfo['fonction_id'], ',') !== -1) {
793
            // Convert , to ;
794
            $userInfo['fonction_id'] = str_replace(',', ';', $userInfo['fonction_id']);
795
            DB::update(
796
                prefixTable('users'),
797
                array(
798
                    'fonction_id' => $userInfo['fonction_id'],
799
                ),
800
                'id = %i',
801
                $superGlobal->get('user_id', 'SESSION')
802
            );
803
        }
804
        $superGlobal->put('fonction_id', $userInfo['fonction_id'], 'SESSION');
805
        $superGlobal->put('user_roles', array_filter(explode(';', $userInfo['fonction_id'])), 'SESSION');
806
807
        // build array of roles
808
        $superGlobal->put('user_pw_complexity', 0, 'SESSION');
809
        $superGlobal->put('arr_roles', array(), 'SESSION');
810
        foreach ($superGlobal->get('user_roles', 'SESSION') as $role) {
811
            $resRoles = DB::queryFirstRow(
812
                'SELECT title, complexity
813
                FROM ' . prefixTable('roles_title') . '
814
                WHERE id=%i',
815
                $role
816
            );
817
            $superGlobal->put(
818
                $role,
819
                array(
820
                    'id' => $role,
821
                    'title' => $resRoles['title'],
822
                ),
823
                'SESSION',
824
                'arr_roles'
825
            );
826
            // get highest complexity
827
            if (intval($superGlobal->get('user_pw_complexity', 'SESSION')) < intval($resRoles['complexity'])) {
828
                $superGlobal->put('user_pw_complexity', $resRoles['complexity'], 'SESSION');
829
            }
830
        }
831
832
        // build complete array of roles
833
        $superGlobal->put('arr_roles_full', array(), 'SESSION');
834
        $rows = DB::query('SELECT id, title FROM ' . prefixTable('roles_title') . ' ORDER BY title ASC');
835
        foreach ($rows as $record) {
836
            $superGlobal->put(
837
                $record['id'],
838
                array(
839
                    'id' => $record['id'],
840
                    'title' => $record['title'],
841
                ),
842
                'SESSION',
843
                'arr_roles_full'
844
            );
845
        }
846
        // Set some settings
847
        $SETTINGS['update_needed'] = '';
848
849
        // User signature keys
850
        $superGlobal->put('public_key', $userInfo['public_key'], 'SESSION', 'user');
851
        if (is_null($userInfo['private_key']) === true || empty($userInfo['private_key']) === true || $userInfo['private_key'] === 'none') {
852
            // No keys have been generated yet
853
            // Create them
854
            $userKeys = generateUserKeys($passwordClear);
855
            $superGlobal->put('private_key', $userKeys['private_key_clear'], 'SESSION', 'user');
856
            $arrayUserKeys = array(
857
                'public_key' => $userKeys['public_key'],
858
                'private_key' => $userKeys['private_key'],
859
            );
860
        } else {
861
            // Uncrypt private key
862
            $superGlobal->put('private_key', decryptPrivateKey($passwordClear, $userInfo['private_key']), 'SESSION', 'user');
863
            $arrayUserKeys = [];
864
        }
865
866
        // Update table
867
        DB::update(
868
            prefixTable('users'),
869
            array_merge(
870
                array(
871
                    'key_tempo' => $superGlobal->get('key', 'SESSION'),
872
                    'last_connexion' => time(),
873
                    'timestamp' => time(),
874
                    'disabled' => 0,
875
                    'no_bad_attempts' => 0,
876
                    'session_end' => $superGlobal->get('sessionDuration', 'SESSION'),
877
                    'user_ip' => $dataReceived['client'],
878
                ),
879
                $arrayUserKeys
880
            ),
881
            'id=%i',
882
            $userInfo['id']
883
        );
884
885
        // Debug
886
        debugIdentify(
887
            DEBUGDUO,
888
            DEBUGDUOFILE,
889
            "Preparing to identify the user rights\n"
890
        );
891
892
        // Get user's rights
893
        if ($user_initial_creation_through_ldap === false) {
894
            identifyUserRights(
895
                implode(';', $userInfo['groupes_visibles']),
896
                $superGlobal->get('no_access_folders', 'SESSION'),
897
                $userInfo['admin'],
898
                $userInfo['fonction_id'],
899
                $SETTINGS
900
            );
901
        } else {
902
            // is new LDAP user. Show only his personal folder
903
            if ($SETTINGS['enable_pf_feature'] === '1') {
904
                $superGlobal->put('personal_visible_groups', array($userInfo['id']), 'SESSION');
905
                $superGlobal->put('personal_folders', array($userInfo['id']), 'SESSION');
906
            } else {
907
                $superGlobal->put('personal_visible_groups', array(), 'SESSION');
908
                $superGlobal->put('personal_folders', array(), 'SESSION');
909
            }
910
            $superGlobal->put('all_non_personal_folders', array(), 'SESSION');
911
            $superGlobal->put('groupes_visibles', array(), 'SESSION');
912
            $superGlobal->put('read_only_folders', array(), 'SESSION');
913
            $superGlobal->put('list_folders_limited', '', 'SESSION');
914
            $superGlobal->put('list_folders_editable_by_role', array(), 'SESSION');
915
            $superGlobal->put('list_restricted_folders_for_items', array(), 'SESSION');
916
            $superGlobal->put('nb_folders', 1, 'SESSION');
917
            $superGlobal->put('nb_roles', 0, 'SESSION');
918
        }
919
        // Get some more elements
920
        $superGlobal->put('screenHeight', $dataReceived['screenHeight'], 'SESSION');
921
        // Get last seen items
922
        $superGlobal->put('latest_items_tab', array(), 'SESSION');
923
        $superGlobal->put('nb_roles', 0, 'SESSION');
924
        foreach ($superGlobal->get('latest_items', 'SESSION') as $item) {
925
            if (!empty($item)) {
926
                $dataLastItems = DB::queryFirstRow(
927
                    'SELECT id,label,id_tree
928
                    FROM ' . prefixTable('items') . '
929
                    WHERE id=%i',
930
                    $item
931
                );
932
                $superGlobal->put(
933
                    $item,
934
                    array(
935
                        'id' => $item,
936
                        'label' => $dataLastItems['label'],
937
                        'url' => 'index.php?page=items&amp;group=' . $dataLastItems['id_tree'] . '&amp;id=' . $item,
938
                    ),
939
                    'SESSION',
940
                    'latest_items_tab'
941
                );
942
            }
943
        }
944
        // send back the random key
945
        $return = $dataReceived['randomstring'];
946
        // Send email
947
        if (
948
            isset($SETTINGS['enable_send_email_on_user_login'])
949
            && (int) $SETTINGS['enable_send_email_on_user_login'] === 1
950
            && (int) $sessionAdmin !== 1
951
        ) {
952
            // get all Admin users
953
            $receivers = '';
954
            $rows = DB::query('SELECT email FROM ' . prefixTable('users') . " WHERE admin = %i and email != ''", 1);
955
            foreach ($rows as $record) {
956
                if (empty($receivers)) {
957
                    $receivers = $record['email'];
958
                } else {
959
                    $receivers = ',' . $record['email'];
960
                }
961
            }
962
            // Add email to table
963
            DB::insert(
964
                prefixTable('emails'),
965
                array(
966
                    'timestamp' => time(),
967
                    'subject' => langHdl('email_subject_on_user_login'),
968
                    'body' => str_replace(
969
                        array(
970
                            '#tp_user#',
971
                            '#tp_date#',
972
                            '#tp_time#',
973
                        ),
974
                        array(
975
                            ' ' . $superGlobal->get('login', 'SESSION') . ' (IP: ' . getClientIpServer() . ')',
976
                            date($SETTINGS['date_format'], $superGlobal->get('last_connection', 'SESSION')),
977
                            date($SETTINGS['time_format'], $superGlobal->get('last_connection', 'SESSION')),
978
                        ),
979
                        langHdl('email_body_on_user_login')
980
                    ),
981
                    'receivers' => $receivers,
982
                    'status' => 'not_sent',
983
                )
984
            );
985
        }
986
987
        // Ensure Complexity levels are translated
988
        if (defined('TP_PW_COMPLEXITY') === false) {
989
            define(
990
                'TP_PW_COMPLEXITY',
991
                array(
992
                    0 => array(0, langHdl('complex_level0'), 'fas fa-bolt text-danger'),
993
                    25 => array(25, langHdl('complex_level1'), 'fas fa-thermometer-empty text-danger'),
994
                    50 => array(50, langHdl('complex_level2'), 'fas fa-thermometer-quarter text-warning'),
995
                    60 => array(60, langHdl('complex_level3'), 'fas fa-thermometer-half text-warning'),
996
                    70 => array(70, langHdl('complex_level4'), 'fas fa-thermometer-three-quarters text-success'),
997
                    80 => array(80, langHdl('complex_level5'), 'fas fa-thermometer-full text-success'),
998
                    90 => array(90, langHdl('complex_level6'), 'far fa-gem text-success'),
999
                )
1000
            );
1001
        }
1002
1003
        /*
1004
        $sessionUrl = '';
1005
        if ($SETTINGS['cpassman_dir'] === '..') {
1006
            $SETTINGS['cpassman_dir'] = '.';
1007
        }
1008
        */
1009
    } elseif ((int) $userInfo['disabled'] === 1) {
1010
        // User and password is okay but account is locked
1011
        echo prepareExchangedData(
1012
            array(
1013
                'value' => $return,
1014
                'user_id' => null !== $superGlobal->get('user_id', 'SESSION') ? (int) $superGlobal->get('user_id', 'SESSION') : '',
1015
                'user_admin' => null !== $superGlobal->get('admin', 'SESSION') ? (int) $superGlobal->get('admin', 'SESSION') : 0,
1016
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
1017
                'pwd_attempts' => 0,
1018
                'error' => 'user_is_locked',
1019
                'message' => langHdl('account_is_locked'),
1020
                'first_connection' => $superGlobal->get('validite_pw', 'SESSION') === false ? true : false,
1021
                'password_complexity' => TP_PW_COMPLEXITY[$superGlobal->get('user_pw_complexity', 'SESSION')][1],
1022
                'password_change_expected' => $userInfo['special'] === 'password_change_expected' ? true : false,
1023
                'private_key_conform' => null !== $superGlobal->get('private_key', 'SESSION', 'user')
1024
                    && empty($superGlobal->get('private_key', 'SESSION', 'user')) === false
1025
                    && $superGlobal->get('private_key', 'SESSION', 'user') !== 'none' ? true : false,
1026
                'session_key' => $superGlobal->get('key', 'SESSION'),
1027
                //'has_psk' => empty($superGlobal->get('encrypted_psk', 'SESSION', 'user')) === false ? true : false,
1028
                'can_create_root_folder' => null !== $superGlobal->get('can_create_root_folder', 'SESSION') ? (int) $superGlobal->get('can_create_root_folder', 'SESSION') : '',
1029
                'shown_warning_unsuccessful_login' => $superGlobal->get('unsuccessfull_login_attempts_shown', 'SESSION', 'user'),
1030
                'nb_unsuccessful_logins' => $superGlobal->get('unsuccessfull_login_attempts_nb', 'SESSION', 'user'),
1031
            ),
1032
            'encode'
1033
        );
1034
1035
        return false;
1036
    } else {
1037
        // User exists in the DB but Password is false
1038
        // check if user is locked
1039
        $userIsLocked = false;
1040
        $nbAttempts = intval($userInfo['no_bad_attempts'] + 1);
1041
        if (
1042
            $SETTINGS['nb_bad_authentication'] > 0
1043
            && intval($SETTINGS['nb_bad_authentication']) < $nbAttempts
1044
        ) {
1045
            $userIsLocked = true;
1046
            // log it
1047
            if (
1048
                isset($SETTINGS['log_connections']) === true
1049
                && (int) $SETTINGS['log_connections'] === 1
1050
            ) {
1051
                logEvents($SETTINGS, 'user_locked', 'connection', $userInfo['id'], stripslashes($username));
1052
            }
1053
        }
1054
        DB::update(
1055
            prefixTable('users'),
1056
            array(
1057
                'key_tempo' => $superGlobal->get('key', 'SESSION'),
1058
                'disabled' => $userIsLocked,
1059
                'no_bad_attempts' => $nbAttempts,
1060
            ),
1061
            'id=%i',
1062
            $userInfo['id']
1063
        );
1064
        // What return shoulb we do
1065
        if ($userIsLocked === true) {
1066
            echo prepareExchangedData(
1067
                array(
1068
                    'value' => $return,
1069
                    'user_id' => null !== $superGlobal->get('user_id', 'SESSION') ? (int) $superGlobal->get('user_id', 'SESSION') : '',
1070
                    'user_admin' => null !== $superGlobal->get('admin', 'SESSION') ? (int) $superGlobal->get('admin', 'SESSION') : 0,
1071
                    'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
1072
                    'pwd_attempts' => 0,
1073
                    'error' => 'user_is_locked',
1074
                    'message' => langHdl('account_is_locked'),
1075
                    'first_connection' => $superGlobal->get('validite_pw', 'SESSION') === false ? true : false,
1076
                    'password_complexity' => TP_PW_COMPLEXITY[$superGlobal->get('user_pw_complexity', 'SESSION')][1],
1077
                    'password_change_expected' => $userInfo['special'] === 'password_change_expected' ? true : false,
1078
                    'private_key_conform' => (null !== $superGlobal->get('user_id', 'SESSION')
1079
                        && empty($superGlobal->get('private_key', 'SESSION', 'user')) === false
1080
                        && $superGlobal->get('private_key', 'SESSION', 'user') !== 'none') ? true : false,
1081
                    'session_key' => $superGlobal->get('key', 'SESSION'),
1082
                    //'has_psk' => empty($superGlobal->get('encrypted_psk', 'SESSION', 'user')) === false ? true : false,
1083
                    'can_create_root_folder' => null !== $superGlobal->get('can_create_root_folder', 'SESSION') ? (int) $superGlobal->get('can_create_root_folder', 'SESSION') : '',
1084
                    'shown_warning_unsuccessful_login' => $superGlobal->get('unsuccessfull_login_attempts_shown', 'SESSION', 'user'),
1085
                    'nb_unsuccessful_logins' => $superGlobal->get('unsuccessfull_login_attempts_nb', 'SESSION', 'user'),
1086
                ),
1087
                'encode'
1088
            );
1089
1090
            return false;
1091
        } else {
1092
            echo prepareExchangedData(
1093
                array(
1094
                    'value' => $return,
1095
                    'user_id' => null !== $superGlobal->get('user_id', 'SESSION') ? (int) $superGlobal->get('user_id', 'SESSION') : '',
1096
                    'user_admin' => null !== $superGlobal->get('admin', 'SESSION') ? (int) $superGlobal->get('admin', 'SESSION') : 0,
1097
                    'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
1098
                    'pwd_attempts' => (int) $sessionPwdAttempts,
1099
                    'error' => 'user_not_exists3',
1100
                    'message' => langHdl('error_bad_credentials'),
1101
                    'first_connection' => $superGlobal->get('validite_pw', 'SESSION') === false ? true : false,
1102
                    'password_complexity' => TP_PW_COMPLEXITY[$superGlobal->get('user_pw_complexity', 'SESSION')][1],
1103
                    'password_change_expected' => $userInfo['special'] === 'password_change_expected' ? true : false,
1104
                    'private_key_conform' => (null !== $superGlobal->get('user_id', 'SESSION')
1105
                        && empty($superGlobal->get('private_key', 'SESSION', 'user')) === false
1106
                        && $superGlobal->get('private_key', 'SESSION', 'user') !== 'none') ? true : false,
1107
                    'session_key' => $superGlobal->get('key', 'SESSION'),
1108
                    //'has_psk' => empty($superGlobal->get('encrypted_psk', 'SESSION', 'user')) === false ? true : false,
1109
                    'can_create_root_folder' => null !== $superGlobal->get('can_create_root_folder', 'SESSION') ? (int) $superGlobal->get('can_create_root_folder', 'SESSION') : '',
1110
                    'shown_warning_unsuccessful_login' => $superGlobal->get('unsuccessfull_login_attempts_shown', 'SESSION', 'user'),
1111
                    'nb_unsuccessful_logins' => $superGlobal->get('unsuccessfull_login_attempts_nb', 'SESSION', 'user'),
1112
                ),
1113
                'encode'
1114
            );
1115
1116
            return false;
1117
        }
1118
    }
1119
1120
    // Debug
1121
    debugIdentify(
1122
        DEBUGDUO,
1123
        DEBUGDUOFILE,
1124
        "\n\n----\n" .
1125
            'Identified : ' . filter_var($return, FILTER_SANITIZE_STRING) . "\n\n"
1126
    );
1127
1128
    echo prepareExchangedData(
1129
        array(
1130
            'value' => $return,
1131
            'user_id' => null !== $superGlobal->get('user_id', 'SESSION') ? (int) $superGlobal->get('user_id', 'SESSION') : '',
1132
            'user_admin' => null !== $superGlobal->get('admin', 'SESSION') ? (int) $superGlobal->get('admin', 'SESSION') : 0,
1133
            'initial_url' => $antiXss->xss_clean($sessionUrl),
1134
            'pwd_attempts' => 0,
1135
            'error' => false,
1136
            'message' => (null !== $superGlobal->get('user_upgrade_needed', 'SESSION', 'user') && (int) $superGlobal->get('user_upgrade_needed', 'SESSION', 'user') === 1) ? 'ask_for_otc' : '',
1137
            'first_connection' => $superGlobal->get('validite_pw', 'SESSION') === false ? true : false,
1138
            'password_complexity' => TP_PW_COMPLEXITY[$superGlobal->get('user_pw_complexity', 'SESSION')][1],
1139
            'password_change_expected' => $userInfo['special'] === 'password_change_expected' ? true : false,
1140
            'private_key_conform' => (null !== $superGlobal->get('user_id', 'SESSION')
1141
                && empty($superGlobal->get('private_key', 'SESSION', 'user')) === false
1142
                && $superGlobal->get('private_key', 'SESSION', 'user') !== 'none') ? true : false,
1143
            'session_key' => $superGlobal->get('key', 'SESSION'),
1144
            //'has_psk' => empty($superGlobal->get('encrypted_psk', 'SESSION', 'user')) === false ? true : false,
1145
            'can_create_root_folder' => null !== $superGlobal->get('can_create_root_folder', 'SESSION') ? (int) $superGlobal->get('can_create_root_folder', 'SESSION') : '',
1146
            'shown_warning_unsuccessful_login' => $superGlobal->get('unsuccessfull_login_attempts_shown', 'SESSION', 'user'),
1147
            'nb_unsuccessful_logins' => $superGlobal->get('unsuccessfull_login_attempts_nb', 'SESSION', 'user'),
1148
            'upgrade_needed' => isset($userInfo['upgrade_needed']) === true ? (int) $userInfo['upgrade_needed'] : 0,
1149
            'special' => isset($userInfo['special']) === true ? (int) $userInfo['special'] : 0,
1150
        ),
1151
        'encode'
1152
    );
1153
}
1154
1155
/**
1156
 * Authenticate a user through AD.
1157
 *
1158
 * @param string $username      Username
1159
 * @param array  $userInfo      User account information
1160
 * @param string $passwordClear Password
1161
 * @param array  $SETTINGS      Teampass settings
1162
 *
1163
 * @return array
1164
 */
1165
function authenticateThroughAD($username, $userInfo, $passwordClear, $SETTINGS)
1166
{
1167
    // Build ldap configuration array
1168
    $config = [
1169
        // Mandatory Configuration Options
1170
        'hosts'            => [$SETTINGS['ldap_domain_controler']],
1171
        'base_dn'          => $SETTINGS['ldap_search_base'],
1172
        'username'         => $SETTINGS['ldap_user_attribute']."=".$username.",cn=users,".$SETTINGS['ldap_bdn'],
1173
        'password'         => $passwordClear,
1174
    
1175
        // Optional Configuration Options
1176
        'port'             => $SETTINGS['ldap_port'],
1177
        'use_ssl'          => $SETTINGS['ldap_ssl'] === 1 ? true : false,
1178
        'use_tls'          => $SETTINGS['ldap_tls'] === 1 ? true : false,
1179
        'version'          => 3,
1180
        'timeout'          => 5,
1181
        'follow_referrals' => false,
1182
    
1183
        // Custom LDAP Options
1184
        'options' => [
1185
            // See: http://php.net/ldap_set_option
1186
            LDAP_OPT_X_TLS_REQUIRE_CERT => LDAP_OPT_X_TLS_HARD
1187
        ]
1188
    ];
1189
1190
    // Load expected libraries
1191
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/illuminate/Contracts/Auth/Authenticatable.php';
1192
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Support/Traits/EnumeratesValues.php';
1193
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Support/Traits/Macroable.php';
1194
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Support/helpers.php';
1195
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Support/Arr.php';
1196
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Contracts/Support/Jsonable.php';
1197
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Contracts/Support/Arrayable.php';
1198
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Support/Enumerable.php';
1199
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tightenco/Collect/Support/Collection.php';
1200
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/LdapRecord/DetectsErrors.php';
1201
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/LdapRecord/Connection.php';
1202
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/LdapRecord/Ldap.php';
1203
1204
    $ad = new SplClassLoader('LdapRecord', '../includes/libraries');
1205
    $ad->register();
1206
    $connection = new Connection($config);
1207
1208
    // COnnect to LDAP
1209
    try {
1210
        $connection->connect();
1211
        Container::addConnection($connection);
1212
    } catch (\LdapRecord\Auth\BindException $e) {
1213
        $error = $e->getDetailedError();
1214
1215
        return array(
1216
            'error' => true,
1217
            'message' => langHdl('error').' : '.$error->getErrorCode()." - ".$error->getErrorMessage(). "<br>".$error->getDiagnosticMessage(),
1218
             
1219
        );
1220
    }
1221
1222
    $query = $connection->query();
1223
1224
    
1225
    try {
1226
        $entry = $query->findBy('uid', 'nils');
1227
    } catch (\LdapRecord\Models\ModelNotFoundException $ex) {
1228
        // Not found.
1229
        return array(
1230
            'error' => true,
1231
            'message' => langHdl('error_no_user_in_ad'),             
1232
        );
1233
    }
1234
    
1235
    // Check shadowexpire attribute - if === 1 then user disabled
1236
    if (isset($entry['shadowexpire'][0]) === true && (int) $entry['shadowexpire'][0] === 1) {
1237
        return array(
1238
            'error' => true,
1239
            'message' => langHdl('error_ad_user_expired'),
1240
        );
1241
    }
1242
1243
    
1244
    // Should we restrain the search in specified user groups
1245
    if (isset($SETTINGS['ldap_usergroup']) === true && empty($SETTINGS['ldap_usergroup']) === false) {
1246
        // Get immediate groups the user is apart of:
1247
        $arrayTmp = array();
1248
        foreach ($entry['memberof'] as $group) {
1249
            $group = substr($group, strpos($group, '=')+1, (strpos($group,',') - strpos($group, '=') - 1));
1250
            if (empty($group) === false) {
1251
                array_push($arrayTmp, $group);
1252
            }
1253
        }
1254
1255
        if (in_array($SETTINGS['ldap_usergroup'], $arrayTmp) === false) {
1256
            return array(
1257
                'error' => true,
1258
                'message' => langHdl('error_user_not_allowed_group'),
1259
            );
1260
        }
1261
    }
1262
1263
    
1264
    // Check if password is still the same with the one in Teampass
1265
    // load passwordLib library
1266
    $pwdlib = new SplClassLoader('PasswordLib', $SETTINGS['cpassman_dir'] . '/includes/libraries');
1267
    $pwdlib->register();
1268
    $pwdlib = new PasswordLib\PasswordLib();
1269
    
1270
    // If user has never been connected then erase current pwd with the ldap's one
1271
    if (empty($userInfo['last_connexion']) === true) {
1272
        $hashedPassword = $pwdlib->createPasswordHash($passwordClear);
1273
        if ($pwdlib->verifyPasswordHash(htmlspecialchars_decode($passwordClear), $hashedPassword) === true) {
1274
            DB::update(
1275
                prefixTable('users'),
1276
                array(
1277
                    'pw' => $hashedPassword,
1278
                ),
1279
                'id = %i',
1280
                $userInfo['id']
1281
            );
1282
            $userInfo['pw'] = $hashedPassword;
1283
        } else {
1284
            return array(
1285
                'error' => true,
1286
                'message' => langHdl('error_something_wrong'),
1287
            );
1288
        }
1289
    } else {
1290
        DB::update(
1291
            prefixTable('users'),
1292
            array(
1293
                'upgrade_needed' => 1,
1294
            ),
1295
            'id = %i',
1296
            $userInfo['id']
1297
        );
1298
    }
1299
1300
    return array(
1301
        'error' => false,
1302
        'message' => '',
1303
    );
1304
}
1305
1306
1307
1308
/**
1309
 * Undocumented function.
1310
 *
1311
 * @param string|array|resource $dataReceived Received data
1312
 * @param string                $userInfo     Result of query
1313
 * @param array                 $SETTINGS     Teampass settings
1314
 *
1315
 * @return array
1316
 */
1317
function yubicoMFACheck($dataReceived, $userInfo, $SETTINGS)
1318
{
1319
    // Load superGlobals
1320
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
1321
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
1322
    $sessionAdmin = $superGlobal->get('user_admin', 'SESSION');
1323
    $sessionUrl = $superGlobal->get('initial_url', 'SESSION');
1324
    $sessionPwdAttempts = $superGlobal->get('pwd_attempts', 'SESSION');
1325
1326
    // Init
1327
    $proceedIdentification = false;
1328
1329
    $yubico_key = htmlspecialchars_decode($dataReceived['yubico_key']);
1330
    $yubico_user_key = htmlspecialchars_decode($dataReceived['yubico_user_key']);
1331
    $yubico_user_id = htmlspecialchars_decode($dataReceived['yubico_user_id']);
1332
1333
    if (empty($yubico_user_key) === false && empty($yubico_user_id) === false) {
1334
        // save the new yubico in user's account
1335
        DB::update(
1336
            prefixTable('users'),
1337
            array(
1338
                'yubico_user_key' => $yubico_user_key,
1339
                'yubico_user_id' => $yubico_user_id,
1340
            ),
1341
            'id=%i',
1342
            $userInfo['id']
1343
        );
1344
    } else {
1345
        // Check existing yubico credentials
1346
        if ($userInfo['yubico_user_key'] === 'none' || $userInfo['yubico_user_id'] === 'none') {
1347
            return array(
1348
                'error' => true,
1349
                'value' => '',
1350
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : '',
1351
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
1352
                'pwd_attempts' => (int) $sessionPwdAttempts,
1353
                'error' => 'no_user_yubico_credentials',
1354
                'message' => '',
1355
            );
1356
        } else {
1357
            $yubico_user_key = $userInfo['yubico_user_key'];
1358
            $yubico_user_id = $userInfo['yubico_user_id'];
1359
        }
1360
    }
1361
1362
    // Now check yubico validity
1363
    include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Authentication/Yubico/Yubico.php';
1364
    $yubi = new Auth_Yubico($yubico_user_id, $yubico_user_key);
1365
    $auth = $yubi->verify($yubico_key); //, null, null, null, 60
1366
1367
    if (PEAR::isError($auth)) {
1368
        $proceedIdentification = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $proceedIdentification is dead and can be removed.
Loading history...
1369
1370
        return array(
1371
            'error' => true,
1372
            'value' => '',
1373
            'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : '',
1374
            'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
1375
            'pwd_attempts' => (int) $sessionPwdAttempts,
1376
            'error' => 'bad_user_yubico_credentials',
1377
            'message' => langHdl('yubico_bad_code'),
1378
        );
1379
    } else {
1380
        $proceedIdentification = true;
1381
    }
1382
1383
    return array(
1384
        'error' => false,
1385
        'message' => '',
1386
        'proceedIdentification' => $proceedIdentification,
1387
    );
1388
}
1389
1390
/**
1391
 * Undocumented function.
1392
 *
1393
 * @param string $username      User name
1394
 * @param string $passwordClear User password in clear
1395
 * @param string $retLDAP       Received data from LDAP
1396
 * @param array  $SETTINGS      Teampass settings
1397
 *
1398
 * @return array
1399
 */
1400
function ldapCreateUser($username, $passwordClear, $retLDAP, $SETTINGS)
1401
{
1402
    // Generate user keys pair
1403
    $userKeys = generateUserKeys($passwordClear);
1404
1405
    // Insert user in DB
1406
    DB::insert(
1407
        prefixTable('users'),
1408
        array(
1409
            'login' => $username,
1410
            'pw' => $retLDAP['hashedPassword'],
1411
            'email' => (isset($retLDAP['user_info_from_ad'][0]['mail'][0]) === false) ? '' : $retLDAP['user_info_from_ad'][0]['mail'][0],
1412
            'name' => $retLDAP['user_info_from_ad'][0]['givenname'][0],
1413
            'lastname' => $retLDAP['user_info_from_ad'][0]['sn'][0],
1414
            'admin' => '0',
1415
            'gestionnaire' => '0',
1416
            'can_manage_all_users' => '0',
1417
            'personal_folder' => $SETTINGS['enable_pf_feature'] === '1' ? '1' : '0',
1418
            'fonction_id' => (empty($retLDAP['user_info_from_ad'][0]['commonGroupsLdapVsTeampass']) === false ? $retLDAP['user_info_from_ad'][0]['commonGroupsLdapVsTeampass'] . ';' : '') . (isset($SETTINGS['ldap_new_user_role']) === true ? $SETTINGS['ldap_new_user_role'] : '0'),
1419
            'groupes_interdits' => '',
1420
            'groupes_visibles' => '',
1421
            'last_pw_change' => time(),
1422
            'user_language' => $SETTINGS['default_language'],
1423
            'encrypted_psk' => '',
1424
            'isAdministratedByRole' => (isset($SETTINGS['ldap_new_user_is_administrated_by']) === true && empty($SETTINGS['ldap_new_user_is_administrated_by']) === false) ? $SETTINGS['ldap_new_user_is_administrated_by'] : 0,
1425
            'public_key' => $userKeys['public_key'],
1426
            'private_key' => $userKeys['private_key'],
1427
        )
1428
    );
1429
    $newUserId = DB::insertId();
1430
    // Create personnal folder
1431
    if (isset($SETTINGS['enable_pf_feature']) === true && $SETTINGS['enable_pf_feature'] === '1') {
1432
        DB::insert(
1433
            prefixTable('nested_tree'),
1434
            array(
1435
                'parent_id' => '0',
1436
                'title' => $newUserId,
1437
                'bloquer_creation' => '0',
1438
                'bloquer_modification' => '0',
1439
                'personal_folder' => '1',
1440
            )
1441
        );
1442
1443
        // Rebuild tree
1444
        $tree = new SplClassLoader('Tree\NestedTree', $SETTINGS['cpassman_dir'] . '/includes/libraries');
1445
        $tree->register();
1446
        $tree = new Tree\NestedTree\NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
1447
        $tree->rebuild();
1448
    }
1449
1450
    return array(
1451
        'error' => false,
1452
        'message' => '',
1453
        'proceedIdentification' => true,
1454
        'user_initial_creation_through_ldap' => true,
1455
    );
1456
}
1457
1458
/**
1459
 * Undocumented function.
1460
 *
1461
 * @param string                $username     Username
1462
 * @param string                $userInfo     Result of query
1463
 * @param string|array|resource $dataReceived DataReceived
1464
 * @param array                 $SETTINGS     Teampass settings
1465
 *
1466
 * @return array
1467
 */
1468
function googleMFACheck($username, $userInfo, $dataReceived, $SETTINGS)
1469
{
1470
    if (
1471
        isset($dataReceived['GACode']) === true
1472
        && empty($dataReceived['GACode']) === false
1473
    ) {
1474
        // Load superGlobals
1475
        include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
1476
        $superGlobal = new protect\SuperGlobal\SuperGlobal();
1477
        $sessionAdmin = $superGlobal->get('user_admin', 'SESSION');
1478
        $sessionUrl = $superGlobal->get('initial_url', 'SESSION');
1479
        $sessionPwdAttempts = $superGlobal->get('pwd_attempts', 'SESSION');
1480
1481
        // Init
1482
        $proceedIdentification = false;
1483
        
1484
        // load library
1485
        include_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Authentication/TwoFactorAuth/TwoFactorAuth.php';
1486
1487
        // create new instance
1488
        $tfa = new Authentication\TwoFactorAuth\TwoFactorAuth($SETTINGS['ga_website_name']);
1489
1490
        // Init
1491
        $firstTime = array();
1492
1493
        // now check if it is the 1st time the user is using 2FA
1494
        if ($userInfo['ga_temporary_code'] !== 'none' && $userInfo['ga_temporary_code'] !== 'done') {
1495
            if ($userInfo['ga_temporary_code'] !== $dataReceived['GACode']) {
1496
                return array(
1497
                    'error' => true,
1498
                    'message' => langHdl('ga_bad_code'),
1499
                    'proceedIdentification' => false,
1500
                    'mfaStatus' => '',
1501
                );
1502
            }
1503
1504
            // If first time with MFA code
1505
            $proceedIdentification = false;
1506
            $mfaStatus = 'ga_temporary_code_correct';
1507
            $mfaMessage = langHdl('ga_flash_qr_and_login');
1508
1509
            // generate new QR
1510
            $new_2fa_qr = $tfa->getQRCodeImageAsDataUri(
1511
                'Teampass - ' . $username,
1512
                $userInfo['ga']
1513
            );
1514
1515
            // clear temporary code from DB
1516
            DB::update(
1517
                prefixTable('users'),
1518
                array(
1519
                    'ga_temporary_code' => 'done',
1520
                ),
1521
                'id=%i',
1522
                $userInfo['id']
1523
            );
1524
1525
            $firstTime = array(
1526
                'value' => '<img src="' . $new_2fa_qr . '">',
1527
                'user_admin' => isset($sessionAdmin) ? (int) $sessionAdmin : '',
1528
                'initial_url' => isset($sessionUrl) === true ? $sessionUrl : '',
1529
                'pwd_attempts' => (int) $sessionPwdAttempts,
1530
                'error' => false,
1531
                'message' => $mfaMessage,
1532
                'mfaStatus' => $mfaStatus,
1533
            );
1534
        } else {
1535
            // verify the user GA code
1536
            if ($tfa->verifyCode($userInfo['ga'], $dataReceived['GACode'])) {
1537
                $proceedIdentification = true;
1538
            } else {
1539
                return array(
1540
                    'error' => true,
1541
                    'message' => langHdl('ga_bad_code'),
1542
                    'proceedIdentification' => false,
1543
                );
1544
            }
1545
        }
1546
    } else {
1547
        return array(
1548
            'error' => true,
1549
            'message' => langHdl('ga_bad_code'),
1550
            'proceedIdentification' => false,
1551
        );
1552
    }
1553
1554
    return array(
1555
        'error' => false,
1556
        'message' => '',
1557
        'proceedIdentification' => $proceedIdentification,
1558
        'firstTime' => $firstTime,
1559
    );
1560
}
1561
1562
/**
1563
 * Undocumented function.
1564
 *
1565
 * @param string                $passwordClear Password in clear
1566
 * @param array|string          $userInfo      Array of user data
1567
 * @param array|string|resource $dataReceived  Received data
1568
 * @param string                $username      User name
1569
 * @param array                 $SETTINGS      Teampass settings
1570
 *
1571
 * @return bool
1572
 */
1573
function checkCredentials($passwordClear, $userInfo, $dataReceived, $username, $SETTINGS)
1574
{
1575
    // Set to false
1576
    $userPasswordVerified = false;
1577
1578
    // load passwordLib library
1579
    include_once $SETTINGS['cpassman_dir'] . '/sources/SplClassLoader.php';
1580
    $pwdlib = new SplClassLoader('PasswordLib', $SETTINGS['cpassman_dir'] . '/includes/libraries');
1581
    $pwdlib->register();
1582
    $pwdlib = new PasswordLib\PasswordLib();
1583
1584
    // Check if old encryption used
1585
    if (
1586
        crypt($passwordClear, $userInfo['pw']) === $userInfo['pw']
1587
        && empty($userInfo['pw']) === false
1588
    ) {
1589
        $userPasswordVerified = true;
1590
1591
        //update user's password
1592
        $userInfo['pw'] = $pwdlib->createPasswordHash($passwordClear);
1593
        DB::update(
1594
            prefixTable('users'),
1595
            array(
1596
                'pw' => $userInfo['pw'],
1597
            ),
1598
            'id=%i',
1599
            $userInfo['id']
1600
        );
1601
    }
1602
    //echo $passwordClear." - ".$userInfo['pw']." - ".$pwdlib->verifyPasswordHash($passwordClear, $userInfo['pw'])." ;; ";
1603
    // check the given password
1604
    if ($userPasswordVerified !== true) {
1605
        if ($pwdlib->verifyPasswordHash($passwordClear, $userInfo['pw']) === true) {
1606
            $userPasswordVerified = true;
1607
        } else {
1608
            // 2.1.27.24 - manage passwords
1609
            if ($pwdlib->verifyPasswordHash(htmlspecialchars_decode($dataReceived['pw']), $userInfo['pw']) === true) {
1610
                // then the auth is correct but needs to be adapted in DB since change of encoding
1611
                $userInfo['pw'] = $pwdlib->createPasswordHash($passwordClear);
1612
                DB::update(
1613
                    prefixTable('users'),
1614
                    array(
1615
                        'pw' => $userInfo['pw'],
1616
                    ),
1617
                    'id=%i',
1618
                    $userInfo['id']
1619
                );
1620
                $userPasswordVerified = true;
1621
            } else {
1622
                $userPasswordVerified = false;
1623
1624
                logEvents(
1625
                    $SETTINGS,
1626
                    'failed_auth',
1627
                    'user_password_not_correct',
1628
                    '',
1629
                    '',
1630
                    stripslashes($username)
1631
                );
1632
            }
1633
        }
1634
    }
1635
1636
    return $userPasswordVerified;
1637
}
1638
1639
/**
1640
 * Undocumented function.
1641
 *
1642
 * @param bool   $enabled text1
1643
 * @param string $dbgFile text2
1644
 * @param string $text    text3
1645
 *
1646
 * @return void
1647
 */
1648
function debugIdentify($enabled, $dbgFile, $text)
1649
{
1650
    if ($enabled === true) {
1651
        $fp = fopen($dbgFile, 'a');
1652
        if ($fp !== false) {
1653
            fwrite(
1654
                $fp,
1655
                $text
1656
            );
1657
        }
1658
    }
1659
}
1660