Passed
Push — development ( ee13b6...7c2d55 )
by Nils
04:34
created

sources/identify.php (3 issues)

1
<?php
2
/**
3
 *
4
 * @file          identify.php
5
 * @author        Nils Laumaillé
6
 * @version       2.1.27
7
 * @copyright     (c) 2009-2017 Nils Laumaillé
8
 * @licensing     GNU GPL-3.0
9
 * @link          http://www.teampass.net
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 */
15
16
$debugLdap = 0; //Can be used in order to debug LDAP authentication
17
$debugDuo = 0; //Can be used in order to debug DUO authentication
18
19
require_once 'SecureHandler.php';
20
session_start();
21
if (!isset($_SESSION['CPM']) || $_SESSION['CPM'] !== 1) {
22
    die('Hacking attempt...');
23
}
24
25
// Load config
26
if (file_exists('../includes/config/tp.config.php')) {
27
    require_once '../includes/config/tp.config.php';
28
} elseif (file_exists('./includes/config/tp.config.php')) {
29
    require_once './includes/config/tp.config.php';
30
} else {
31
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
32
}
33
34
if (!isset($SETTINGS['cpassman_dir']) || empty($SETTINGS['cpassman_dir']) === true || $SETTINGS['cpassman_dir'] === ".") {
35
    $SETTINGS['cpassman_dir'] = "..";
36
}
37
38
// init
39
$dbgDuo = "";
40
$dbgLdap = "";
41
$ldap_suffix = "";
42
$result = "";
43
$adldap = "";
44
45
// Prepare POST variables
46
$post_type = filter_input(INPUT_POST, 'type', FILTER_SANITIZE_STRING);
47
$post_login = filter_input(INPUT_POST, 'login', FILTER_SANITIZE_STRING);
48
$post_sig_response = filter_input(INPUT_POST, 'sig_response', FILTER_SANITIZE_STRING);
49
$post_cardid = filter_input(INPUT_POST, 'cardid', FILTER_SANITIZE_STRING);
50
$post_data = filter_input(INPUT_POST, 'data', FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
51
$post_key = filter_input(INPUT_POST, 'key', FILTER_SANITIZE_STRING);
52
53
if ($post_type === "identify_duo_user") {
54
    //--------
55
    // DUO AUTHENTICATION
56
    //--------
57
    // This step creates the DUO request encrypted key
58
59
    include $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
60
    require_once SECUREPATH."/sk.php";
61
62
    // load library
63
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Authentication/DuoSecurity/Duo.php';
64
    $sig_request = Duo::signRequest(IKEY, SKEY, AKEY, $post_login);
65
66
    if ($debugDuo == 1) {
67
        $dbgDuo = fopen($SETTINGS['path_to_files_folder']."/duo.debug.txt", "w");
68
        fputs(
69
            $dbgDuo,
70
            "\n\n-----\n\n".
71
            "sig request : ".$post_login."\n".
72
            'resp : '.$sig_request."\n"
73
        );
74
    }
75
76
    // load csrfprotector
77
    $csrfp_config = require_once $SETTINGS['cpassman_dir'].'/includes/libraries/csrfp/libs/csrfp.config.php';
78
79
    // return result
80
    echo '[{"sig_request" : "'.$sig_request.'" , "csrfp_token" : "'.$csrfp_config['CSRFP_TOKEN'].'" , "csrfp_key" : "'.filter_var($_COOKIE[$csrfp_config['CSRFP_TOKEN']], FILTER_SANITIZE_STRING).'"}]';
81
// DUO Identification
82
} elseif ($post_type === "identify_duo_user_check") {
83
    //--------
84
    // DUO AUTHENTICATION
85
    // this step is verifying the response received from the server
86
    //--------
87
88
    include $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
89
    require_once SECUREPATH."/sk.php";
90
91
    // load library
92
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Authentication/DuoSecurity/Duo.php';
93
    $resp = Duo::verifyResponse(IKEY, SKEY, AKEY, $post_sig_response);
94
95
    if ($debugDuo == 1) {
96
        $dbgDuo = fopen($SETTINGS['path_to_files_folder']."/duo.debug.txt", "a");
97
        fputs(
98
            $dbgDuo,
99
            "\n\n-----\n\n".
100
            "sig response : ".$post_sig_response."\n".
101
            'resp : '.$resp."\n"
102
        );
103
    }
104
105
    // return the response (which should be the user name)
106
    if ($resp === $post_login) {
107
        echo '[{"resp" : "'.$resp.'"}]';
108
    } else {
109
        echo '[{"resp" : "'.$resp.'"}]';
110
    }
111
} elseif ($post_type === "identify_user_with_agses") {
112
//--------
113
//-- AUTHENTICATION WITH AGSES
114
//--------
115
116
    require_once $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
117
    require_once $SETTINGS['cpassman_dir'].'/sources/main.functions.php';
118
    // connect to the server
119
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
120
    $pass = defuse_return_decrypted($pass);
121
    DB::$host = $server;
122
    DB::$user = $user;
123
    DB::$password = $pass;
124
    DB::$dbName = $database;
125
    DB::$port = $port;
126
    DB::$encoding = $encoding;
127
    DB::$error_handler = true;
128
    $link = mysqli_connect($server, $user, $pass, $database, $port);
129
    $link->set_charset($encoding);
130
131
    // do checks
132
    if (null !== $post_cardid && empty(post_cardid) === true) {
133
        // no card id is given
134
        // check if it is DB
135
        $row = DB::queryFirstRow(
136
            "SELECT `agses-usercardid` FROM ".prefix_table("users")."
137
            WHERE login = %s",
138
            $post_login
139
        );
140
    } elseif (empty($post_cardid) === false && is_numeric($post_cardid)) {
141
        // card id is given
142
        // save it in DB
143
        DB::update(
144
            prefix_table('users'),
145
            array(
146
                'agses-usercardid' => $post_cardid
147
                ),
148
            "login = %s",
149
            $post_login
150
        );
151
        $row['agses-usercardid'] = $post_cardid;
152
    } else {
153
        // error
154
        echo '[{"error" : "something_wrong" , "agses_message" : ""}]';
155
        return false;
156
    }
157
158
    //-- get AGSES hosted information
159
    $ret_agses_url = DB::queryFirstRow(
160
        "SELECT valeur FROM ".prefix_table("misc")."
161
        WHERE type = %s AND intitule = %s",
162
        'admin',
163
        'agses_hosted_url'
164
    );
165
166
    $ret_agses_id = DB::queryFirstRow(
167
        "SELECT valeur FROM ".prefix_table("misc")."
168
        WHERE type = %s AND intitule = %s",
169
        'admin',
170
        'agses_hosted_id'
171
    );
172
173
    $ret_agses_apikey = DB::queryFirstRow(
174
        "SELECT valeur FROM ".prefix_table("misc")."
175
        WHERE type = %s AND intitule = %s",
176
        'admin',
177
        'agses_hosted_apikey'
178
    );
179
180
    // if we have a card id and all agses credentials
181
    // then we try to generate the message for agsesflicker
182
    if (isset($row['agses-usercardid']) && empty($ret_agses_url['valeur']) === false
183
        && empty($ret_agses_id['valeur']) === false && empty($ret_agses_apikey['valeur']) === false
184
    ) {
185
        // check that card id is not empty or equal to 0
186
        if ($row['agses-usercardid'] !== "0" && !empty($row['agses-usercardid'])) {
187
            include_once $SETTINGS['cpassman_dir'].'/includes/libraries/Authentication/agses/axs/AXSILPortal_V1_Auth.php';
188
            $agses = new AXSILPortal_V1_Auth();
189
            $agses->setUrl($ret_agses_url['valeur']);
190
            $agses->setAAId($ret_agses_id['valeur']);
191
            //for release there will be another api-key - this is temporary only
192
            $agses->setApiKey($ret_agses_apikey['valeur']);
193
            $agses->create();
194
            //create random salt and store it into session
195
            if (!isset($_SESSION['hedgeId']) || empty($_SESSION['hedgeId']) === true) {
196
                $_SESSION['hedgeId'] = md5(time());
197
            }
198
            $_SESSION['user_settings']['agses-usercardid'] = $row['agses-usercardid'];
199
            $agses_message = $agses->createAuthenticationMessage(
200
                (string) $row['agses-usercardid'],
201
                true,
202
                1,
203
                2,
204
                (string) $_SESSION['hedgeId']
205
            );
206
207
            echo '[{"agses_message" : "'.$agses_message.'" , "error" : ""}]';
208
        } else {
209
            echo '[{"agses_status" : "no_user_card_id" , "agses_message" : "" , "error" : ""}]';
210
        }
211
    } else {
212
        if (empty($ret_agses_apikey['valeur']) || empty($ret_agses_url['valeur']) || empty($ret_agses_id['valeur'])) {
213
            echo '[{"error" : "no_agses_info" , "agses_message" : ""}]';
214
        } else {
215
            echo '[{"error" : "something_wrong" , "agses_message" : ""}]'; // user not found but not displayed as this in the error message
216
        }
217
    }
218
} elseif ($post_type === "identify_user") {
219
//--------
220
// NORMAL IDENTICATION STEP
221
//--------
222
223
    // increment counter of login attempts
224
    if (empty($_SESSION["pwd_attempts"])) {
225
        $_SESSION["pwd_attempts"] = 1;
226
    } else {
227
        $_SESSION["pwd_attempts"]++;
228
    }
229
230
    // manage brute force
231
    if ($_SESSION["pwd_attempts"] <= 3) {
232
        // identify the user through Teampass process
233
        identifyUser(
234
            $post_data,
235
            $debugLdap,
236
            $debugDuo,
237
            $SETTINGS
238
        );
239
    } elseif (isset($_SESSION["next_possible_pwd_attempts"]) && time() > $_SESSION["next_possible_pwd_attempts"] && $_SESSION["pwd_attempts"] > 3) {
240
        $_SESSION["pwd_attempts"] = 1;
241
        // identify the user through Teampass process
242
        identifyUser(
243
            $post_data,
244
            $debugLdap,
245
            $debugDuo,
246
            $SETTINGS
247
        );
248
    } else {
249
        $_SESSION["next_possible_pwd_attempts"] = time() + 10;
250
        echo '[{"error" : "bruteforce_wait"}]';
251
        return false;
252
    }
253
} elseif ($post_type === "store_data_in_cookie") {
254
    //--------
255
    // STORE DATA IN COOKIE
256
    //--------
257
    //
258
    // not used any more (only development purpose)
259
    if ($post_key !== $_SESSION['key']) {
260
        echo '[{"error" : "something_wrong"}]';
261
        return false;
262
    }
263
    // store some connection data in cookie
264
    setcookie(
265
        "TeamPassC",
266
        $post_data,
267
        time() + 60 * 60,
268
        '/'
269
    );
270
}
271
272
/*
273
* Complete authentication of user through Teampass
274
*/
275
function identifyUser(
276
    $sentData,
277
    $debugLdap,
278
    $debugDuo,
279
    $SETTINGS
280
) {
281
    // Load config
282
    if (file_exists('../includes/config/tp.config.php')) {
283
        include_once '../includes/config/tp.config.php';
284
    } elseif (file_exists('./includes/config/tp.config.php')) {
285
        include_once './includes/config/tp.config.php';
286
    } else {
287
        throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
288
    }
289
    include $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
290
291
    header("Content-type: text/html; charset=utf-8");
292
    error_reporting(E_ERROR);
293
    include_once $SETTINGS['cpassman_dir'].'/sources/main.functions.php';
294
    include_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
295
296
    // Load AntiXSS
297
    include_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
298
    $antiXss = new protect\AntiXSS\AntiXSS();
299
300
    // Load superGlobals
301
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
302
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
303
304
    // Prepare GET variables
305
    $session_user_language = $superGlobal->get("user_language", "SESSION");
306
307
    if ($debugDuo == 1) {
308
        $dbgDuo = fopen($SETTINGS['path_to_files_folder']."/duo.debug.txt", "a");
309
310
        fputs(
311
            $dbgDuo,
312
            "Content of data sent '".filter_var($sentData, FILTER_SANITIZE_STRING)."'\n"
313
        );
314
    }
315
316
    // connect to the server
317
    include_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
318
    $pass = defuse_return_decrypted($pass);
319
    DB::$host = $server;
320
    DB::$user = $user;
321
    DB::$password = $pass;
322
    DB::$dbName = $database;
323
    DB::$port = $port;
324
    DB::$encoding = $encoding;
325
    DB::$error_handler = true;
326
    $link = mysqli_connect($server, $user, $pass, $database, $port);
327
    $link->set_charset($encoding);
328
329
    // load passwordLib library
330
    $pwdlib = new SplClassLoader('PasswordLib', $SETTINGS['cpassman_dir'].'/includes/libraries');
331
    $pwdlib->register();
332
    $pwdlib = new PasswordLib\PasswordLib();
333
334
    // User's language loading
335
    include_once $SETTINGS['cpassman_dir'].'/includes/language/'.$session_user_language.'.php';
336
337
    // decrypt and retreive data in JSON format
338
    $dataReceived = prepareExchangedData($sentData, "decode");
339
340
    // prepare variables
341
    if (isset($SETTINGS['enable_http_request_login']) === true
342
        && $SETTINGS['enable_http_request_login'] === '1'
343
        && isset($_SERVER['PHP_AUTH_USER']) === true
344
        && isset($SETTINGS['maintenance_mode']) === true
345
        && $SETTINGS['maintenance_mode'] === '1'
346
    ) {
347
        if (strpos($_SERVER['PHP_AUTH_USER'], '@') !== false) {
348
            $username = explode("@", $_SERVER['PHP_AUTH_USER'])[0];
349
        } elseif (strpos($_SERVER['PHP_AUTH_USER'], '\\') !== false) {
350
            $username = explode("\\", $_SERVER['PHP_AUTH_USER'])[1];
351
        } else {
352
            $username = $_SERVER['PHP_AUTH_USER'];
353
        }
354
        $passwordClear = $_SERVER['PHP_AUTH_PW'];
355
    } else {
356
        $passwordClear = htmlspecialchars_decode($dataReceived['pw']);
357
        $username = $antiXss->xss_clean(htmlspecialchars_decode($dataReceived['login']));
358
    }
359
    $logError = "";
360
    $userPasswordVerified = false;
361
362
    if ($debugDuo == 1) {
363
        fputs(
364
            $dbgDuo,
365
            "Starting authentication of '".$username."'\n"
0 ignored issues
show
Security File Manipulation introduced by
'Starting authentication of '' . $username . '' ' can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read tainted data from array, and $_SERVER['PHP_AUTH_USER'] is assigned to $username in sources/identify.php on line 352
  1. Read tainted data from array, and $_SERVER['PHP_AUTH_USER'] is assigned to $username
    in sources/identify.php on line 352
  2. Path: Read tainted data from array, and Data is passed through explode(), and explode('@', $_SERVER['PHP_AUTH_USER'])[0] is assigned to $username in sources/identify.php on line 348
  1. Read tainted data from array, and Data is passed through explode(), and explode('@', $_SERVER['PHP_AUTH_USER'])[0] is assigned to $username
    in sources/identify.php on line 348
  3. Path: Read tainted data from array, and Data is passed through explode(), and explode('\', $_SERVER['PHP_AUTH_USER'])[1] is assigned to $username in sources/identify.php on line 350
  1. Read tainted data from array, and Data is passed through explode(), and explode('\', $_SERVER['PHP_AUTH_USER'])[1] is assigned to $username
    in sources/identify.php on line 350

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
366
        );
367
    }
368
369
    $ldapConnection = false;
370
371
    /* LDAP connection */
372
    if ($debugLdap == 1) {
373
        // create temp file
374
        $dbgLdap = fopen($SETTINGS['path_to_files_folder']."/ldap.debug.txt", "w");
375
        fputs(
376
            $dbgLdap,
377
            "Get all LDAP params : \n".
378
            'mode : '.$SETTINGS['ldap_mode']."\n".
379
            'type : '.$SETTINGS['ldap_type']."\n".
380
            'base_dn : '.$SETTINGS['ldap_domain_dn']."\n".
381
            'search_base : '.$SETTINGS['ldap_search_base']."\n".
382
            'bind_dn : '.$SETTINGS['ldap_bind_dn']."\n".
383
            'bind_passwd : '.$SETTINGS['ldap_bind_passwd']."\n".
384
            'user_attribute : '.$SETTINGS['ldap_user_attribute']."\n".
385
            'account_suffix : '.$SETTINGS['ldap_suffix']."\n".
386
            'domain_controllers : '.$SETTINGS['ldap_domain_controler']."\n".
387
            'ad_port : '.$SETTINGS['ldap_port']."\n".
388
            'use_ssl : '.$SETTINGS['ldap_ssl']."\n".
389
            'use_tls : '.$SETTINGS['ldap_tls']."\n*********\n\n"
390
        );
391
    }
392
393
    if ($debugDuo == 1) {
394
        fputs(
395
            $dbgDuo,
396
            "LDAP status: ".$SETTINGS['ldap_mode']."\n"
397
        );
398
    }
399
400
    // Check if user exists
401
    $data = DB::queryFirstRow(
402
        "SELECT * FROM ".prefix_table("users")." WHERE login=%s_login",
403
        array(
404
            'login' => $username
405
        )
406
    );
407
    $counter = DB::count();
408
    $user_initial_creation_through_ldap = false;
409
    $proceedIdentification = false;
410
411
    // Prepare LDAP connection if set up
412
    if (isset($SETTINGS['ldap_mode'])
413
        && $SETTINGS['ldap_mode'] === '1'
414
        && $username !== "admin"
415
    ) {
416
        //Multiple Domain Names
417
        if (strpos(html_entity_decode($username), '\\') === true) {
418
            $ldap_suffix = "@".substr(html_entity_decode($username), 0, strpos(html_entity_decode($username), '\\'));
419
            $username = substr(html_entity_decode($username), strpos(html_entity_decode($username), '\\') + 1);
420
        }
421
        if ($SETTINGS['ldap_type'] === 'posix-search') {
422
            $ldapURIs = "";
423
            foreach (explode(",", $SETTINGS['ldap_domain_controler']) as $domainControler) {
424
                if ($SETTINGS['ldap_ssl'] == 1) {
425
                    $ldapURIs .= "ldaps://".$domainControler.":".$SETTINGS['ldap_port']." ";
426
                } else {
427
                    $ldapURIs .= "ldap://".$domainControler.":".$SETTINGS['ldap_port']." ";
428
                }
429
            }
430
            if ($debugLdap == 1) {
431
                fputs($dbgLdap, "LDAP URIs : ".$ldapURIs."\n");
432
            }
433
            $ldapconn = ldap_connect($ldapURIs);
434
435
            if ($SETTINGS['ldap_tls']) {
436
                ldap_start_tls($ldapconn);
437
            }
438
            if ($debugLdap == 1) {
439
                fputs($dbgLdap, "LDAP connection : ".($ldapconn ? "Connected" : "Failed")."\n");
440
            }
441
            ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
442
            ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
443
444
            // Is LDAP connection ready?
445
            if ($ldapconn !== false) {
446
                // Should we bind the connection?
447
                if ($SETTINGS['ldap_bind_dn'] !== "" && $SETTINGS['ldap_bind_passwd'] !== "") {
448
                    $ldapbind = ldap_bind($ldapconn, $SETTINGS['ldap_bind_dn'], $SETTINGS['ldap_bind_passwd']);
449
                    if ($debugLdap == 1) {
450
                        fputs($dbgLdap, "LDAP bind : ".($ldapbind ? "Bound" : "Failed")."\n");
451
                    }
452
                }
453
                if (($SETTINGS['ldap_bind_dn'] === "" && $SETTINGS['ldap_bind_passwd'] === "") || $ldapbind === true) {
454
                    $filter = "(&(".$SETTINGS['ldap_user_attribute']."=".$username.")(objectClass=".$SETTINGS['ldap_object_class']."))";
455
                    $result = ldap_search(
456
                      $ldapconn,
457
                      $SETTINGS['ldap_search_base'],
458
                      $filter,
0 ignored issues
show
Security LDAP Injection introduced by
$filter can contain request data and is used in ldap context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read tainted data from array, and $_SERVER['PHP_AUTH_USER'] is assigned to $username in sources/identify.php on line 352
  1. Read tainted data from array, and $_SERVER['PHP_AUTH_USER'] is assigned to $username
    in sources/identify.php on line 352
  2. '(&(' . $SETTINGS['ldap_user_attribute'] . '=' . $username . ')(objectClass=' . $SETTINGS['ldap_object_class'] . '))' is assigned to $filter
    in sources/identify.php on line 454
  2. Path: Read tainted data from array, and Data is passed through explode(), and explode('@', $_SERVER['PHP_AUTH_USER'])[0] is assigned to $username in sources/identify.php on line 348
  1. Read tainted data from array, and Data is passed through explode(), and explode('@', $_SERVER['PHP_AUTH_USER'])[0] is assigned to $username
    in sources/identify.php on line 348
  2. '(&(' . $SETTINGS['ldap_user_attribute'] . '=' . $username . ')(objectClass=' . $SETTINGS['ldap_object_class'] . '))' is assigned to $filter
    in sources/identify.php on line 454
  3. Path: Read tainted data from array, and Data is passed through explode(), and explode('\', $_SERVER['PHP_AUTH_USER'])[1] is assigned to $username in sources/identify.php on line 350
  1. Read tainted data from array, and Data is passed through explode(), and explode('\', $_SERVER['PHP_AUTH_USER'])[1] is assigned to $username
    in sources/identify.php on line 350
  2. '(&(' . $SETTINGS['ldap_user_attribute'] . '=' . $username . ')(objectClass=' . $SETTINGS['ldap_object_class'] . '))' is assigned to $filter
    in sources/identify.php on line 454

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
459
                      array('dn', 'mail', 'givenname', 'sn')
460
                    );
461
                    if ($debugLdap == 1) {
462
                        fputs(
463
                            $dbgLdap,
464
                            'Search filter : '.$filter."\n".
465
                            'Results : '.print_r(ldap_get_entries($ldapconn, $result), true)."\n"
466
                        );
467
                    }
468
469
                    // Check if user was found in AD
470
                    if (ldap_count_entries($ldapconn, $result) > 0) {
471
                        // Get user's info and especially the DN
472
                        $result = ldap_get_entries($ldapconn, $result);
473
                        $user_dn = $result[0]['dn'];
474
475
                        fputs(
476
                            $dbgLdap,
477
                            'User was found. '.$user_dn.'\n'
478
                        );
479
480
                        // Should we restrain the search in specified user groups
481
                        $GroupRestrictionEnabled = false;
482
                        if (isset($SETTINGS['ldap_usergroup']) === true && empty($SETTINGS['ldap_usergroup']) === false) {
483
                            // New way to check User's group membership
484
                            $filter_group = "memberUid=".$username;
485
                            $result_group = ldap_search(
486
                                $ldapconn,
487
                                $SETTINGS['ldap_search_base'],
488
                                $filter_group,
0 ignored issues
show
Security LDAP Injection introduced by
$filter_group can contain request data and is used in ldap context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read tainted data from array, and $_SERVER['PHP_AUTH_USER'] is assigned to $username in sources/identify.php on line 352
  1. Read tainted data from array, and $_SERVER['PHP_AUTH_USER'] is assigned to $username
    in sources/identify.php on line 352
  2. 'memberUid=' . $username is assigned to $filter_group
    in sources/identify.php on line 484
  2. Path: Read tainted data from array, and Data is passed through explode(), and explode('@', $_SERVER['PHP_AUTH_USER'])[0] is assigned to $username in sources/identify.php on line 348
  1. Read tainted data from array, and Data is passed through explode(), and explode('@', $_SERVER['PHP_AUTH_USER'])[0] is assigned to $username
    in sources/identify.php on line 348
  2. 'memberUid=' . $username is assigned to $filter_group
    in sources/identify.php on line 484
  3. Path: Read tainted data from array, and Data is passed through explode(), and explode('\', $_SERVER['PHP_AUTH_USER'])[1] is assigned to $username in sources/identify.php on line 350
  1. Read tainted data from array, and Data is passed through explode(), and explode('\', $_SERVER['PHP_AUTH_USER'])[1] is assigned to $username
    in sources/identify.php on line 350
  2. 'memberUid=' . $username is assigned to $filter_group
    in sources/identify.php on line 484

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
489
                                array('dn')
490
                            );
491
492
                            if ($result_group) {
493
                                $entries = ldap_get_entries($ldapconn, $result_group);
494
495
                                if ($debugLdap == 1) {
496
                                    fputs(
497
                                        $dbgLdap,
498
                                        'Search groups appartenance : '.$SETTINGS['ldap_search_base']."\n".
499
                                        'Results : '.print_r($entries, true)."\n"
500
                                    );
501
                                }
502
503
                                if ($entries['count'] > 0) {
504
                                    // Now check if group fits
505
                                    for ($i=0; $i<$entries['count']; $i++) {
506
                                      $parsr=ldap_explode_dn($entries[$i]['dn'], 0);
507
                                      if (str_replace(array('CN=','cn='), '', $parsr[0]) === $SETTINGS['ldap_usergroup']) {
508
                                        $GroupRestrictionEnabled = true;
509
                                        break;
510
                                      }
511
                                    }
512
513
                                }
514
                            }
515
516
                            if ($debugLdap == 1) {
517
                                fputs(
518
                                    $dbgLdap,
519
                                    'Group was found : '.$GroupRestrictionEnabled."\n"
520
                                );
521
                            }
522
                        }
523
524
                        // Is user in the LDAP?
525
                        if ($GroupRestrictionEnabled === true
526
                            || (
527
                                $GroupRestrictionEnabled === false
528
                                && (isset($SETTINGS['ldap_usergroup']) === false
529
                                    || (isset($SETTINGS['ldap_usergroup']) === true && empty($SETTINGS['ldap_usergroup']) === true)
530
                                )
531
                            )
532
                        ) {
533
                            // Try to auth inside LDAP
534
                            $ldapbind = ldap_bind($ldapconn, $user_dn, $passwordClear);
535
                            if ($ldapbind === true) {
536
                                $ldapConnection = true;
537
538
                                // Update user's password
539
                                $data['pw'] = $pwdlib->createPasswordHash($passwordClear);
540
541
                                // Do things if user exists in TP
542
                                if ($counter > 0) {
543
                                    // Update pwd in TP database
544
                                    DB::update(
545
                                        prefix_table('users'),
546
                                        array(
547
                                            'pw' => $data['pw']
548
                                        ),
549
                                        "login=%s",
550
                                        $username
551
                                    );
552
553
                                    // No user creation is requested
554
                                    $proceedIdentification = true;
555
                                }
556
                            } else {
557
                                $ldapConnection = false;
558
                            }
559
                        }
560
                    } else {
561
                        $ldapConnection = false;
562
                    }
563
                } else {
564
                    $ldapConnection = false;
565
                }
566
            } else {
567
                $ldapConnection = false;
568
            }
569
        } else {
570
            if ($debugLdap == 1) {
571
                fputs(
572
                    $dbgLdap,
573
                    "Get all ldap params : \n".
574
                    'base_dn : '.$SETTINGS['ldap_domain_dn']."\n".
575
                    'account_suffix : '.$SETTINGS['ldap_suffix']."\n".
576
                    'domain_controllers : '.$SETTINGS['ldap_domain_controler']."\n".
577
                    'ad_port : '.$SETTINGS['ldap_port']."\n".
578
                    'use_ssl : '.$SETTINGS['ldap_ssl']."\n".
579
                    'use_tls : '.$SETTINGS['ldap_tls']."\n*********\n\n"
580
                );
581
            }
582
            $adldap = new SplClassLoader('adLDAP', '../includes/libraries/LDAP');
583
            $adldap->register();
584
585
            // Posix style LDAP handles user searches a bit differently
586
            if ($SETTINGS['ldap_type'] === 'posix') {
587
                $ldap_suffix = ','.$SETTINGS['ldap_suffix'].','.$SETTINGS['ldap_domain_dn'];
588
            } elseif ($SETTINGS['ldap_type'] === 'windows' && empty($ldap_suffix) === true) {
589
                //Multiple Domain Names
590
                $ldap_suffix = $SETTINGS['ldap_suffix'];
591
            }
592
593
            // Ensure no double commas exist in ldap_suffix
594
            $ldap_suffix = str_replace(',,', ',', $ldap_suffix);
595
596
            // Create LDAP connection
597
            $adldap = new adLDAP\adLDAP(
598
                array(
599
                    'base_dn' => $SETTINGS['ldap_domain_dn'],
600
                    'account_suffix' => $ldap_suffix,
601
                    'domain_controllers' => explode(",", $SETTINGS['ldap_domain_controler']),
602
                    'ad_port' => $SETTINGS['ldap_port'],
603
                    'use_ssl' => $SETTINGS['ldap_ssl'],
604
                    'use_tls' => $SETTINGS['ldap_tls']
605
                )
606
            );
607
608
            if ($debugLdap == 1) {
609
                fputs($dbgLdap, "Create new adldap object : ".$adldap->getLastError()."\n\n\n"); //Debug
610
            }
611
612
            // OpenLDAP expects an attribute=value pair
613
            if ($SETTINGS['ldap_type'] === 'posix') {
614
                $auth_username = $SETTINGS['ldap_user_attribute'].'='.$username;
615
            } else {
616
                $auth_username = $username;
617
            }
618
619
            // Authenticate the user
620
            if ($adldap->authenticate($auth_username, html_entity_decode($passwordClear))) {
621
                // Is user in allowed group
622
                if (isset($SETTINGS['ldap_allowed_usergroup']) === true
623
                    && empty($SETTINGS['ldap_allowed_usergroup']) === false
624
                ) {
625
                    if ($adldap->user()->inGroup($auth_username, $SETTINGS['ldap_allowed_usergroup']) === true) {
626
                        $ldapConnection = true;
627
                    } else {
628
                        $ldapConnection = false;
629
                    }
630
                } else {
631
                    $ldapConnection = true;
632
                }
633
634
                // Update user's password
635
                if ($ldapConnection === true) {
636
                    $data['pw'] = $pwdlib->createPasswordHash($passwordClear);
637
638
                    // Do things if user exists in TP
639
                    if ($counter > 0) {
640
                        // Update pwd in TP database
641
                        DB::update(
642
                            prefix_table('users'),
643
                            array(
644
                                'pw' => $data['pw']
645
                            ),
646
                            "login=%s",
647
                            $username
648
                        );
649
650
                        // No user creation is requested
651
                        $proceedIdentification = true;
652
                    }
653
                }
654
            } else {
655
                $ldapConnection = false;
656
            }
657
            if ($debugLdap == 1) {
658
                fputs(
659
                    $dbgLdap,
660
                    "After authenticate : ".$adldap->getLastError()."\n\n\n".
661
                    "ldap status : ".$ldapConnection."\n\n\n"
662
                ); //Debug
663
            }
664
        }
665
    } elseif (isset($SETTINGS['ldap_mode']) && $SETTINGS['ldap_mode'] == 2) {
666
        // nothing
667
    }
668
    if ($debugDuo == 1) {
669
        fputs(
670
            $dbgDuo,
671
            "USer exists: ".$counter."\n"
672
        );
673
    }
674
675
676
    // Check PSK
677
    if (isset($SETTINGS['psk_authentication'])
678
        && $SETTINGS['psk_authentication'] === "1"
679
        && $data['admin'] !== "1"
680
    ) {
681
        $psk = htmlspecialchars_decode($dataReceived['psk']);
682
        $pskConfirm = htmlspecialchars_decode($dataReceived['psk_confirm']);
683
        if (empty($psk)) {
684
            echo '[{"value" : "psk_required"}]';
685
            exit();
686
        } elseif (empty($data['psk'])) {
687
            if (empty($pskConfirm)) {
688
                echo '[{"value" : "bad_psk_confirmation"}]';
689
                exit();
690
            } else {
691
                $_SESSION['user_settings']['clear_psk'] = $psk;
692
            }
693
        } elseif ($pwdlib->verifyPasswordHash($psk, $data['psk']) === true) {
694
            echo '[{"value" : "bad_psk"}]';
695
            exit();
696
        }
697
    }
698
699
700
    // Create new LDAP user if not existing in Teampass
701
    // Don't create it if option "only localy declared users" is enabled
702
    if ($counter == 0 && $ldapConnection === true && isset($SETTINGS['ldap_elusers'])
703
        && ($SETTINGS['ldap_elusers'] == 0)
704
    ) {
705
        // If LDAP enabled, create user in TEAMPASS if doesn't exist
706
707
        // Get user info from LDAP
708
        if ($SETTINGS['ldap_type'] === 'posix-search') {
709
            //Because we didn't use adLDAP, we need to set the user info from the ldap_get_entries result
710
            $user_info_from_ad = $result;
711
        } else {
712
            $user_info_from_ad = $adldap->user()->info($auth_username, array("mail", "givenname", "sn"));
713
        }
714
715
        DB::insert(
716
            prefix_table('users'),
717
            array(
718
                'login' => $username,
719
                'pw' => $data['pw'],
720
                'email' => (isset($user_info_from_ad[0]['mail'][0]) === false) ? '' : $user_info_from_ad[0]['mail'][0],
721
                'name' => $user_info_from_ad[0]['givenname'][0],
722
                'lastname' => $user_info_from_ad[0]['sn'][0],
723
                'admin' => '0',
724
                'gestionnaire' => '0',
725
                'can_manage_all_users' => '0',
726
                'personal_folder' => $SETTINGS['enable_pf_feature'] === "1" ? '1' : '0',
727
                'fonction_id' => isset($SETTINGS['ldap_new_user_role']) === true ? $SETTINGS['ldap_new_user_role'] : '0',
728
                'groupes_interdits' => '',
729
                'groupes_visibles' => '',
730
                'last_pw_change' => time(),
731
                'user_language' => $SETTINGS['default_language'],
732
                'encrypted_psk' => '',
733
                '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
734
            )
735
        );
736
        $newUserId = DB::insertId();
737
        // Create personnal folder
738
        if (isset($SETTINGS['enable_pf_feature']) === true && $SETTINGS['enable_pf_feature'] === "1") {
739
            DB::insert(
740
                prefix_table("nested_tree"),
741
                array(
742
                    'parent_id' => '0',
743
                    'title' => $newUserId,
744
                    'bloquer_creation' => '0',
745
                    'bloquer_modification' => '0',
746
                    'personal_folder' => '1'
747
                )
748
            );
749
        }
750
        $proceedIdentification = true;
751
        $user_initial_creation_through_ldap = true;
752
    }
753
754
    // Check if user exists (and has been created in case of new LDAP user)
755
    $data = DB::queryFirstRow(
756
        "SELECT * FROM ".prefix_table("users")." WHERE login=%s_login",
757
        array(
758
            'login' => $username
759
        )
760
    );
761
    $counter = DB::count();
762
    if ($counter === 0) {
763
        logEvents('failed_auth', 'user_not_exists', "", stripslashes($username));
764
        echo '[{"value" : "user_not_exists '.$username.'", "text":""}]';
765
        exit();
766
    }
767
768
    // check GA code
769
    if (isset($SETTINGS['google_authentication']) && $SETTINGS['google_authentication'] == 1 && $username !== "admin") {
770
        if (isset($dataReceived['GACode']) && empty($dataReceived['GACode']) === false) {
771
            // load library
772
            include_once($SETTINGS['cpassman_dir']."/includes/libraries/Authentication/TwoFactorAuth/TwoFactorAuth.php");
773
774
            // create new instance
775
            $tfa = new Authentication\TwoFactorAuth\TwoFactorAuth($SETTINGS['ga_website_name']);
776
777
            // now check if it is the 1st time the user is using 2FA
778
            if ($data['ga_temporary_code'] !== "none" && $data['ga_temporary_code'] !== "done") {
779
                if ($data['ga_temporary_code'] !== $dataReceived['GACode']) {
780
                    $proceedIdentification = false;
781
                    $logError = "ga_temporary_code_wrong";
782
                } else {
783
                    $proceedIdentification = false;
784
                    $logError = "ga_temporary_code_correct";
785
786
                    // generate new QR
787
                    $new_2fa_qr = $tfa->getQRCodeImageAsDataUri("Teampass - ".$username, $data['ga']);
788
789
                    // clear temporary code from DB
790
                    DB::update(
791
                        prefix_table('users'),
792
                        array(
793
                            'ga_temporary_code' => 'done'
794
                        ),
795
                        "id=%i",
796
                        $data['id']
797
                    );
798
799
                    echo '[{"value" : "<img src=\"'.$new_2fa_qr.'\">", "user_admin":"', isset($_SESSION['user_admin']) ? $antiXss->xss_clean($_SESSION['user_admin']) : "", '", "initial_url" : "'.@$_SESSION['initial_url'].'", "error" : "'.$logError.'"}]';
800
801
                    exit();
802
                }
803
            } else {
804
                // verify the user GA code
805
                if ($tfa->verifyCode($data['ga'], $dataReceived['GACode'])) {
806
                    $proceedIdentification = true;
807
                } else {
808
                    $proceedIdentification = false;
809
                    $logError = "ga_code_wrong";
810
                }
811
            }
812
        } else {
813
            $proceedIdentification = false;
814
            $logError = "ga_code_wrong";
815
        }
816
    } elseif ($counter > 0) {
817
        $proceedIdentification = true;
818
    }
819
820
    if ($debugDuo == 1) {
821
        fputs(
822
            $dbgDuo,
823
            "Proceed with Ident: ".$proceedIdentification."\n"
824
        );
825
    }
826
827
828
    // check AGSES code
829
    if (isset($SETTINGS['agses_authentication_enabled']) && $SETTINGS['agses_authentication_enabled'] == 1 && $username != "admin") {
830
        // load AGSES
831
        include_once $SETTINGS['cpassman_dir'].'/includes/libraries/Authentication/agses/axs/AXSILPortal_V1_Auth.php';
832
        $agses = new AXSILPortal_V1_Auth();
833
        $agses->setUrl($SETTINGS['agses_hosted_url']);
834
        $agses->setAAId($SETTINGS['agses_hosted_id']);
835
        //for release there will be another api-key - this is temporary only
836
        $agses->setApiKey($SETTINGS['agses_hosted_apikey']);
837
        $agses->create();
838
        //create random salt and store it into session
839
        if (!isset($_SESSION['hedgeId']) || $_SESSION['hedgeId'] == "") {
840
            $_SESSION['hedgeId'] = md5(time());
841
        }
842
843
        $responseCode = $passwordClear;
844
        if ($responseCode != "" && strlen($responseCode) >= 4) {
845
            // Verify response code, store result in session
846
            $result = $agses->verifyResponse(
847
                (string) $_SESSION['user_settings']['agses-usercardid'],
848
                $responseCode,
849
                (string) $_SESSION['hedgeId']
850
            );
851
852
            if ($result == 1) {
853
                $return = "";
854
                $logError = "";
855
                $proceedIdentification = true;
856
                $userPasswordVerified = true;
857
                unset($_SESSION['hedgeId']);
858
                unset($_SESSION['flickercode']);
859
            } else {
860
                if ($result < -10) {
861
                    $logError = "ERROR: ".$result;
862
                } elseif ($result == -4) {
863
                    $logError = "Wrong response code, no more tries left.";
864
                } elseif ($result == -3) {
865
                    $logError = "Wrong response code, try to reenter.";
866
                } elseif ($result == -2) {
867
                    $logError = "Timeout. The response code is not valid anymore.";
868
                } elseif ($result == -1) {
869
                    $logError = "Security Error. Did you try to verify the response from a different computer?";
870
                } elseif ($result == 1) {
871
                    $logError = "Authentication successful, response code correct.
872
                          <br /><br />Authentification Method for SecureBrowser updated!";
873
                    // Add necessary code here for accessing your Business Application
874
                }
875
                $return = "agses_error";
876
                echo '[{"value" : "'.$return.'", "user_admin":"',
877
                isset($_SESSION['user_admin']) ? $_SESSION['user_admin'] : "",
878
                '", "initial_url" : "'.@$_SESSION['initial_url'].'",
879
                "error" : "'.$logError.'"}]';
880
881
                exit();
882
            }
883
        } else {
884
            // We have an error here
885
            $return = "agses_error";
886
            $logError = "No response code given";
887
888
            echo '[{"value" : "'.$return.'", "user_admin":"',
889
            isset($_SESSION['user_admin']) ? $_SESSION['user_admin'] : "",
890
            '", "initial_url" : "'.@$_SESSION['initial_url'].'",
891
            "error" : "'.$logError.'"}]';
892
893
            exit();
894
        }
895
    }
896
897
    // If admin user then check if folder install exists
898
    // if yes then refuse connection
899
    if ($data['admin'] === "1" && is_dir("../install")) {
900
        $return = "install_error";
901
        $logError = "Install folder has to be removed!";
902
903
        echo '[{"value" : "'.$return.'", "user_admin":"',
904
        isset($_SESSION['user_admin']) ? $antiXss->xss_clean($_SESSION['user_admin']) : "",
905
        '", "initial_url" : "'.@$_SESSION['initial_url'].'",
906
        "error" : "'.$logError.'"}]';
907
908
        exit();
909
    }
910
911
    if ($proceedIdentification === true) {
912
        // User exists in the DB
913
        if (crypt($passwordClear, $data['pw']) == $data['pw'] && !empty($data['pw'])) {
914
            //update user's password
915
            $data['pw'] = $pwdlib->createPasswordHash($passwordClear);
916
            DB::update(
917
                prefix_table('users'),
918
                array(
919
                    'pw' => $data['pw']
920
                ),
921
                "id=%i",
922
                $data['id']
923
            );
924
        }
925
926
        // check the given password
927
        if ($userPasswordVerified !== true) {
928
            if ($pwdlib->verifyPasswordHash($passwordClear, $data['pw']) === true) {
929
                $userPasswordVerified = true;
930
            } else {
931
                $userPasswordVerified = false;
932
                logEvents('failed_auth', 'user_password_not_correct', "", stripslashes($username));
933
            }
934
        }
935
936
        if ($debugDuo == 1) {
937
            fputs(
938
                $dbgDuo,
939
                "User's password verified: ".$userPasswordVerified."\n"
940
            );
941
        }
942
943
        // Can connect if
944
        // 1- no LDAP mode + user enabled + pw ok
945
        // 2- LDAP mode + user enabled + ldap connection ok + user is not admin
946
        // 3-  LDAP mode + user enabled + pw ok + usre is admin
947
        // This in order to allow admin by default to connect even if LDAP is activated
948
        if ((
949
                isset($SETTINGS['ldap_mode']) && $SETTINGS['ldap_mode'] === '0'
950
                && $userPasswordVerified === true && $data['disabled'] == 0
951
            )
952
            ||
953
            (
954
                isset($SETTINGS['ldap_mode']) && $SETTINGS['ldap_mode'] === '1'
955
                && $ldapConnection === true && $data['disabled'] === '0' && $username != "admin"
956
            )
957
            ||
958
            (
959
                isset($SETTINGS['ldap_mode']) && $SETTINGS['ldap_mode'] === '2'
960
                && $ldapConnection === true && $data['disabled'] === '0' && $username != "admin"
961
            )
962
            ||
963
            (
964
                isset($SETTINGS['ldap_mode']) && $SETTINGS['ldap_mode'] === '1'
965
                && $username == "admin" && $userPasswordVerified === true && $data['disabled'] === '0'
966
            )
967
            ||
968
            (
969
                isset($SETTINGS['ldap_and_local_authentication']) && $SETTINGS['ldap_and_local_authentication'] === '1'
970
                && isset($SETTINGS['ldap_mode']) && in_array($SETTINGS['ldap_mode'], array('1', '2')) === true
971
                && $userPasswordVerified === true && $data['disabled'] == 0
972
            )
973
        ) {
974
            $_SESSION['autoriser'] = true;
975
            $_SESSION["pwd_attempts"] = 0;
976
977
            // Generate a ramdom ID
978
            $key = GenerateCryptKey(50);
979
980
            if ($debugDuo == 1) {
981
                fputs(
982
                    $dbgDuo,
983
                    "User's token: ".$key."\n"
984
                );
985
            }
986
987
            // Log into DB the user's connection
988
            if (isset($SETTINGS['log_connections']) && $SETTINGS['log_connections'] === '1') {
989
                logEvents('user_connection', 'connection', $data['id'], stripslashes($username));
990
            }
991
            // Save account in SESSION
992
            $_SESSION['login'] = stripslashes($username);
993
            $_SESSION['name'] = stripslashes($data['name']);
994
            $_SESSION['lastname'] = stripslashes($data['lastname']);
995
            $_SESSION['user_id'] = $data['id'];
996
            $_SESSION['user_admin'] = $data['admin'];
997
            $_SESSION['user_manager'] = $data['gestionnaire'];
998
            $_SESSION['user_can_manage_all_users'] = $data['can_manage_all_users'];
999
            $_SESSION['user_read_only'] = $data['read_only'];
1000
            $_SESSION['last_pw_change'] = $data['last_pw_change'];
1001
            $_SESSION['last_pw'] = $data['last_pw'];
1002
            $_SESSION['can_create_root_folder'] = $data['can_create_root_folder'];
1003
            $_SESSION['key'] = $key;
1004
            $_SESSION['personal_folder'] = $data['personal_folder'];
1005
            $_SESSION['user_language'] = $data['user_language'];
1006
            $_SESSION['user_email'] = $data['email'];
1007
            $_SESSION['user_ga'] = $data['ga'];
1008
            $_SESSION['user_avatar'] = $data['avatar'];
1009
            $_SESSION['user_avatar_thumb'] = $data['avatar_thumb'];
1010
            $_SESSION['user_upgrade_needed'] = $data['upgrade_needed'];
1011
            $_SESSION['user_force_relog'] = $data['force-relog'];
1012
            // get personal settings
1013
            if (!isset($data['treeloadstrategy']) || empty($data['treeloadstrategy'])) {
1014
                $data['treeloadstrategy'] = "full";
1015
            }
1016
            $_SESSION['user_settings']['treeloadstrategy'] = $data['treeloadstrategy'];
1017
            $_SESSION['user_settings']['agses-usercardid'] = $data['agses-usercardid'];
1018
            $_SESSION['user_settings']['user_language'] = $data['user_language'];
1019
            $_SESSION['user_settings']['encrypted_psk'] = $data['encrypted_psk'];
1020
            $_SESSION['user_settings']['usertimezone'] = $data['usertimezone'];
1021
            $_SESSION['user_settings']['session_duration'] = $dataReceived['duree_session'] * 60;
1022
            $_SESSION['user_settings']['api-key'] = $data['user_api_key'];
1023
1024
1025
            // manage session expiration
1026
            $_SESSION['fin_session'] = (integer) (time() + $_SESSION['user_settings']['session_duration']);
1027
1028
            /* If this option is set user password MD5 is used as personal SALTKey */
1029
            if (isset($SETTINGS['use_md5_password_as_salt']) &&
1030
                $SETTINGS['use_md5_password_as_salt'] == 1
1031
            ) {
1032
                $_SESSION['user_settings']['clear_psk'] = md5($passwordClear);
1033
                setcookie(
1034
                    "TeamPass_PFSK_".md5($_SESSION['user_id']),
1035
                    encrypt($_SESSION['user_settings']['clear_psk'], ""),
1036
                    time() + 60 * 60 * 24 * $SETTINGS['personal_saltkey_cookie_duration'],
1037
                    '/'
1038
                );
1039
            }
1040
1041
            if (empty($data['last_connexion'])) {
1042
                $_SESSION['derniere_connexion'] = time();
1043
            } else {
1044
                $_SESSION['derniere_connexion'] = $data['last_connexion'];
1045
            }
1046
1047
            if (!empty($data['latest_items'])) {
1048
                $_SESSION['latest_items'] = explode(';', $data['latest_items']);
1049
            } else {
1050
                $_SESSION['latest_items'] = array();
1051
            }
1052
            if (!empty($data['favourites'])) {
1053
                $_SESSION['favourites'] = explode(';', $data['favourites']);
1054
            } else {
1055
                $_SESSION['favourites'] = array();
1056
            }
1057
1058
            if (!empty($data['groupes_visibles'])) {
1059
                $_SESSION['groupes_visibles'] = @implode(';', $data['groupes_visibles']);
1060
            } else {
1061
                $_SESSION['groupes_visibles'] = array();
1062
            }
1063
            if (!empty($data['groupes_interdits'])) {
1064
                $_SESSION['groupes_interdits'] = @implode(';', $data['groupes_interdits']);
1065
            } else {
1066
                $_SESSION['groupes_interdits'] = array();
1067
            }
1068
            // User's roles
1069
            $_SESSION['fonction_id'] = $data['fonction_id'];
1070
            $_SESSION['user_roles'] = explode(";", $data['fonction_id']);
1071
            // build array of roles
1072
            $_SESSION['user_pw_complexity'] = 0;
1073
            $_SESSION['arr_roles'] = array();
1074
            foreach (array_filter(explode(';', $_SESSION['fonction_id'])) as $role) {
1075
                $resRoles = DB::queryFirstRow("SELECT title, complexity FROM ".prefix_table("roles_title")." WHERE id=%i", $role);
1076
                $_SESSION['arr_roles'][$role] = array(
1077
                        'id' => $role,
1078
                        'title' => $resRoles['title']
1079
                );
1080
                // get highest complexity
1081
                if ($_SESSION['user_pw_complexity'] < $resRoles['complexity']) {
1082
                    $_SESSION['user_pw_complexity'] = $resRoles['complexity'];
1083
                }
1084
            }
1085
            // build complete array of roles
1086
            $_SESSION['arr_roles_full'] = array();
1087
            $rows = DB::query("SELECT id, title FROM ".prefix_table("roles_title")." ORDER BY title ASC");
1088
            foreach ($rows as $record) {
1089
                $_SESSION['arr_roles_full'][$record['id']] = array(
1090
                        'id' => $record['id'],
1091
                        'title' => $record['title']
1092
                );
1093
            }
1094
            // Set some settings
1095
            $_SESSION['user']['find_cookie'] = false;
1096
            $SETTINGS['update_needed'] = "";
1097
            // Update table
1098
            DB::update(
1099
                prefix_table('users'),
1100
                array(
1101
                    'key_tempo' => $_SESSION['key'],
1102
                    'last_connexion' => time(),
1103
                    'timestamp' => time(),
1104
                    'disabled' => 0,
1105
                    'no_bad_attempts' => 0,
1106
                    'session_end' => $_SESSION['fin_session'],
1107
                    'psk' => isset($psk) ? $pwdlib->createPasswordHash(htmlspecialchars_decode($psk)) : '',
1108
                    'user_ip' =>  $dataReceived['client']
1109
                ),
1110
                "id=%i",
1111
                $data['id']
1112
            );
1113
1114
            if ($debugDuo == 1) {
1115
                fputs(
1116
                    $dbgDuo,
1117
                    "Preparing to identify the user rights\n"
1118
                );
1119
            }
1120
1121
            // Get user's rights
1122
            if ($user_initial_creation_through_ldap === false) {
1123
                identifyUserRights(
1124
                    $data['groupes_visibles'],
1125
                    $_SESSION['groupes_interdits'],
1126
                    $data['admin'],
1127
                    $data['fonction_id'],
1128
                    $server,
1129
                    $user,
1130
                    $pass,
1131
                    $database,
1132
                    $port,
1133
                    $encoding,
1134
                    $SETTINGS
1135
                );
1136
            } else {
1137
                // is new LDAP user. Show only his personal folder
1138
                if ($SETTINGS['enable_pf_feature'] === '1') {
1139
                    $_SESSION['personal_visible_groups'] = array($data['id']);
1140
                    $_SESSION['personal_folders'] = array($data['id']);
1141
                } else {
1142
                    $_SESSION['personal_visible_groups'] = array();
1143
                    $_SESSION['personal_folders'] = array();
1144
                }
1145
                $_SESSION['all_non_personal_folders'] = array();
1146
                $_SESSION['groupes_visibles'] = array();
1147
                $_SESSION['groupes_visibles_list'] = "";
1148
                $_SESSION['read_only_folders'] = array();
1149
                $_SESSION['list_folders_limited'] = "";
1150
                $_SESSION['list_folders_editable_by_role'] = array();
1151
                $_SESSION['list_restricted_folders_for_items'] = array();
1152
                $_SESSION['nb_folders'] = 1;
1153
                $_SESSION['nb_roles'] = 0;
1154
            }
1155
            // Get some more elements
1156
            $_SESSION['screenHeight'] = $dataReceived['screenHeight'];
1157
            // Get last seen items
1158
            $_SESSION['latest_items_tab'][] = "";
1159
            foreach ($_SESSION['latest_items'] as $item) {
1160
                if (!empty($item)) {
1161
                    $data = DB::queryFirstRow("SELECT id,label,id_tree FROM ".prefix_table("items")." WHERE id=%i", $item);
1162
                    $_SESSION['latest_items_tab'][$item] = array(
1163
                        'id' => $item,
1164
                        'label' => $data['label'],
1165
                        'url' => 'index.php?page=items&amp;group='.$data['id_tree'].'&amp;id='.$item
1166
                    );
1167
                }
1168
            }
1169
            // send back the random key
1170
            $return = $dataReceived['randomstring'];
1171
            // Send email
1172
            if (isset($SETTINGS['enable_send_email_on_user_login'])
1173
                    && $SETTINGS['enable_send_email_on_user_login'] === '1'
1174
                    && $_SESSION['user_admin'] != 1
1175
            ) {
1176
                // get all Admin users
1177
                $receivers = "";
1178
                $rows = DB::query("SELECT email FROM ".prefix_table("users")." WHERE admin = %i and email != ''", 1);
1179
                foreach ($rows as $record) {
1180
                    if (empty($receivers)) {
1181
                        $receivers = $record['email'];
1182
                    } else {
1183
                        $receivers = ",".$record['email'];
1184
                    }
1185
                }
1186
                // Add email to table
1187
                DB::insert(
1188
                    prefix_table("emails"),
1189
                    array(
1190
                        'timestamp' => time(),
1191
                        'subject' => $LANG['email_subject_on_user_login'],
1192
                        'body' => str_replace(
1193
                            array(
1194
                                '#tp_user#',
1195
                                '#tp_date#',
1196
                                '#tp_time#'
1197
                            ),
1198
                            array(
1199
                                " ".$_SESSION['login']." (IP: ".get_client_ip_server().")",
1200
                                date($SETTINGS['date_format'], $_SESSION['derniere_connexion']),
1201
                                date($SETTINGS['time_format'], $_SESSION['derniere_connexion'])
1202
                            ),
1203
                            $LANG['email_body_on_user_login']
1204
                        ),
1205
                        'receivers' => $receivers,
1206
                        'status' => "not_sent"
1207
                    )
1208
                );
1209
            }
1210
        } elseif ($data['disabled'] == 1) {
1211
            // User and password is okay but account is locked
1212
            $return = "user_is_locked";
1213
        } else {
1214
            // User exists in the DB but Password is false
1215
            // check if user is locked
1216
            $userIsLocked = 0;
1217
            $nbAttempts = intval($data['no_bad_attempts'] + 1);
1218
            if ($SETTINGS['nb_bad_authentication'] > 0
1219
                    && intval($SETTINGS['nb_bad_authentication']) < $nbAttempts
1220
            ) {
1221
                $userIsLocked = 1;
1222
                // log it
1223
                if (isset($SETTINGS['log_connections'])
1224
                        && $SETTINGS['log_connections'] === '1'
1225
                ) {
1226
                    logEvents('user_locked', 'connection', $data['id'], stripslashes($username));
1227
                }
1228
            }
1229
            DB::update(
1230
                prefix_table('users'),
1231
                array(
1232
                    'key_tempo' => $_SESSION['key'],
1233
                    'last_connexion' => time(),
1234
                    'disabled' => $userIsLocked,
1235
                    'no_bad_attempts' => $nbAttempts
1236
                ),
1237
                "id=%i",
1238
                $data['id']
1239
            );
1240
            // What return shoulb we do
1241
            if ($userIsLocked == 1) {
1242
                $return = "user_is_locked";
1243
            } elseif ($SETTINGS['nb_bad_authentication'] === '0') {
1244
                $return = "false";
1245
            } else {
1246
                $return = $nbAttempts;
1247
            }
1248
        }
1249
    } else {
1250
        if ($user_initial_creation_through_ldap === true) {
1251
            $return = "new_ldap_account_created";
1252
        } else {
1253
            $return = "false";
1254
        }
1255
    }
1256
1257
    if ($debugDuo == 1) {
1258
        fputs(
1259
            $dbgDuo,
1260
            "\n\n----\n".
1261
            "Identified : ".filter_var($return, FILTER_SANITIZE_STRING)."\n\n"
1262
        );
1263
    }
1264
1265
    // manage bruteforce
1266
    if ($_SESSION["pwd_attempts"] > 2) {
1267
        $_SESSION["next_possible_pwd_attempts"] = time() + 10;
1268
    }
1269
1270
    echo '[{"value" : "'.$return.'", "user_admin":"', isset($_SESSION['user_admin']) ? $antiXss->xss_clean($_SESSION['user_admin']) : "", '", "initial_url" : "'.@$_SESSION['initial_url'].'", "error" : "'.$logError.'", "pwd_attempts" : "'.$antiXss->xss_clean($_SESSION["pwd_attempts"]).'"}]';
1271
1272
    $_SESSION['initial_url'] = "";
1273
    if ($SETTINGS['cpassman_dir'] === '..') {
1274
        $SETTINGS['cpassman_dir'] = '.';
1275
    }
1276
}
1277