Passed
Push — master ( 9ed3e0...ab4baa )
by Nils
06:04
created

teampassRedirect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 1
dl 0
loc 15
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Teampass - a collaborative passwords manager.
7
 * ---
8
 * This library is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 * ---
12
 *
13
 * @project   Teampass
14
 * @file      core.php
15
 * ---
16
 *
17
 * @author    Nils Laumaillé ([email protected])
18
 *
19
 * @copyright 2009-2023 Teampass.net
20
 *
21
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
22
 * ---
23
 *
24
 * @see       https://www.teampass.net
25
 */
26
27
28
use voku\helper\AntiXSS;
29
use TeampassClasses\SuperGlobal\SuperGlobal;
30
use EZimuel\PHPSecureSession;
31
32
// Load functions
33
require_once 'main.functions.php';
34
$superGlobal = new SuperGlobal();
35
36
// Load config if $SETTINGS not defined
37
try {
38
    include_once __DIR__.'/../includes/config/tp.config.php';
39
} catch (Exception $e) {
40
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
41
}
42
43
44
/**
45
 * Redirection management.
46
 *
47
 * @param string $url new url
48
 *
49
 * @return string refresh page to url
50
 */
51
function teampassRedirect($url)
52
{
53
    // Load AntiXSS
54
    $antiXss = new AntiXSS();
55
    if (! headers_sent()) {    //If headers not sent yet... then do php redirect
56
        header('Location: ' . $antiXss->xss_clean($url));
57
    }
58
59
    //If headers are sent... do java redirect... if java disabled, do html redirect.
60
    echo '<script type="text/javascript">';
61
    echo 'window.location.href="' . $antiXss->xss_clean($url) . '";';
62
    echo '</script>';
63
    echo '<noscript>';
64
    echo '<meta http-equiv="refresh" content="0;url=' . $antiXss->xss_clean($url) . '" />';
65
    echo '</noscript>';
66
}
67
68
69
// Prepare GET variables
70
$server = [];
71
$server['https'] = $superGlobal->get('HTTPS', 'SERVER');
72
$server['request_uri'] = $superGlobal->get('REQUEST_URI', 'SERVER');
73
$server['http_host'] = $superGlobal->get('HTTP_HOST', 'SERVER');
74
$server['ssl_server_cert'] = $superGlobal->get('ssl_server_cert', 'SERVER');
75
$server['remote_addr'] = $superGlobal->get('remote_addr', 'SERVER');
76
$server['http_user_agent'] = $superGlobal->get('http_user_agent', 'SERVER');
77
78
$get = [];
79
$get['session'] = $superGlobal->get('session', 'GET');
80
$get['action'] = $superGlobal->get('action', 'GET');
81
$get['type'] = $superGlobal->get('type', 'GET');
82
$get['page'] = $superGlobal->get('page', 'GET');
83
84
// Redirect needed?
85
if (isset($server['https']) === true
86
    && $server['https'] !== 'on'
87
    && isset($SETTINGS['enable_sts']) === true
88
    && (int) $SETTINGS['enable_sts'] === 1
89
) {
90
    teampassRedirect('https://' . $server['http_host'] . $server['request_uri']);
91
}
92
93
// Load pwComplexity
94
if (defined('TP_PW_COMPLEXITY') === false) {
95
    // Pw complexity levels
96
    if (isset($_SESSION['user']['user_language']) === true && $_SESSION['user']['user_language'] !== '0') {
97
        define(
98
            'TP_PW_COMPLEXITY',
99
            [
100
                TP_PW_STRENGTH_1 => [TP_PW_STRENGTH_1, langHdl('complex_level1'), 'fas fa-thermometer-empty text-danger'],
101
                TP_PW_STRENGTH_2 => [TP_PW_STRENGTH_2, langHdl('complex_level2'), 'fas fa-thermometer-quarter text-warning'],
102
                TP_PW_STRENGTH_3 => [TP_PW_STRENGTH_3, langHdl('complex_level3'), 'fas fa-thermometer-half text-warning'],
103
                TP_PW_STRENGTH_4 => [TP_PW_STRENGTH_4, langHdl('complex_level4'), 'fas fa-thermometer-three-quarters text-success'],
104
                TP_PW_STRENGTH_5 => [TP_PW_STRENGTH_5, langHdl('complex_level5'), 'fas fa-thermometer-full text-success'],
105
            ]
106
        );
107
    }
108
}
109
110
// LOAD CPASSMAN SETTINGS
111
if (
112
    isset($SETTINGS['cpassman_dir']) === true
113
    && is_dir($SETTINGS['cpassman_dir'] . '/install') === true
114
) {
115
    // Should we delete folder INSTALL?
116
    $row = DB::queryFirstRow(
117
        'SELECT valeur FROM ' . prefixTable('misc') . ' WHERE type=%s AND intitule=%s',
118
        'install',
119
        'clear_install_folder'
120
    );
121
    if (DB::count() > 0 && $row['valeur'] === 'true') {
122
        /**
123
         * Permits to delete files and folders recursively.
124
         *
125
         * @param string $dir Path
126
         *
127
         * @return bool
128
         */
129
        function delTree($dir)
130
        {
131
            $directories = scandir($dir);
132
            if ($directories !== false) {
133
                $files = array_diff($directories, ['.', '..']);
134
                foreach ($files as $file) {
135
                    if (is_dir($dir . '/' . $file)) {
136
                        delTree($dir . '/' . $file);
137
                    } else {
138
                        try {
139
                            unlink($dir . '/' . $file);
140
                        } catch (Exception $e) {
141
                            // do nothing... php will ignore and continue
142
                        }
143
                    }
144
                }
145
146
                return @rmdir($dir);
147
            }
148
149
            // else return false
150
            return false;
151
        }
152
153
        if (is_dir($SETTINGS['cpassman_dir'] . '/install')) {
154
            // Set the permissions on the install directory and delete
155
            // is server Windows or Linux?
156
            if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
157
                recursiveChmod($SETTINGS['cpassman_dir'] . '/install', 0755, 0440);
158
            }
159
            delTree($SETTINGS['cpassman_dir'] . '/install');
160
        }
161
162
        // Delete temporary install table
163
        DB::query('DROP TABLE IF EXISTS `_install`');
164
        // Delete tag
165
        DB::delete(
166
            prefixTable('misc'),
167
            'type=%s AND intitule=%s',
168
            'install',
169
            'clear_install_folder'
170
        );
171
    }
172
}
173
174
// Load Languages stuff
175
if (isset($languagesList) === false) {
176
    $languagesList = [];
177
    $rows = DB::query('SELECT * FROM ' . prefixTable('languages') . ' GROUP BY name, label, code, flag, id ORDER BY name ASC');
178
    foreach ($rows as $record) {
179
        array_push($languagesList, $record['name']);
180
        if (isset($_SESSION['user']['user_language']) && $record['name'] === $_SESSION['user']['user_language']) {
181
            $_SESSION['user_language_flag'] = $record['flag'];
182
            $_SESSION['user_language_code'] = $record['code'];
183
            $_SESSION['user_language_label'] = $record['label'];
184
            $_SESSION['user_language_id'] = $record['id'];
185
        }
186
    }
187
}
188
189
if (isset($_SESSION['user_timezone']) === true && $_SESSION['user_timezone'] !== 'not_defined') {
190
    // use user timezone
191
    date_default_timezone_set($_SESSION['user_timezone']);
192
} elseif (isset($SETTINGS['timezone']) === false || $SETTINGS['timezone'] === null) {
193
    // use server timezone
194
    date_default_timezone_set('UTC');
195
    $SETTINGS['timezone'] = 'UTC';
196
} else {
197
    // use server timezone
198
    date_default_timezone_set($SETTINGS['timezone']);
199
}
200
201
// CHECK IF LOGOUT IS ASKED OR IF SESSION IS EXPIRED
202
if ((isset($get['session']) === true
203
        && $get['session'] === 'expired')
204
    || (filter_input(INPUT_POST, 'session', FILTER_SANITIZE_FULL_SPECIAL_CHARS) !== null
205
        && filter_input(INPUT_POST, 'session', FILTER_SANITIZE_FULL_SPECIAL_CHARS) === 'expired')
206
) {
207
    // Clear User tempo key
208
    if (isset($_SESSION['user_id']) === true) {
209
        DB::update(
210
            prefixTable('users'),
211
            [
212
                'key_tempo' => '',
213
                'timestamp' => '',
214
                'session_end' => '',
215
            ],
216
            'id=%i',
217
            $_SESSION['user_id']
218
        );
219
    }
220
221
    // REDIRECTION PAGE ERREUR
222
    echo '
223
    <script language="javascript" type="text/javascript">
224
    <!--
225
        sessionStorage.clear();
226
        window.location.href = "./includes/core/logout.php";
227
    -->
228
    </script>';
229
    exit;
230
}
231
232
// CHECK IF SESSION EXISTS AND IF SESSION IS VALID
233
if (empty($_SESSION['sessionDuration']) === false) {
234
    $dataSession = DB::queryFirstRow(
235
        'SELECT key_tempo FROM ' . prefixTable('users') . ' WHERE id=%i',
236
        $_SESSION['user_id']
237
    );
238
} else {
239
    $dataSession['key_tempo'] = '';
240
}
241
242
// get some init
243
if (isset($_SESSION['user_id']) === false || (int) $_SESSION['user_id'] === 0) {
244
    $_SESSION['key'] = GenerateCryptKey(50, false, true, true, false, true, ['cpassman_dir' => '.']);
245
    $_SESSION['user_id'] = 0;
246
    $_SESSION['id'] = 1;
247
}
248
249
if (
250
    isset($_SESSION['user_id']) === true
251
    && isset($get['type']) === false
252
    && isset($get['action']) === false
253
    && (int) $_SESSION['user_id'] !== 0
254
    && (empty($_SESSION['sessionDuration']) === true
255
        || $_SESSION['sessionDuration'] < time()
256
        || empty($_SESSION['key']) === true
257
        || empty($dataSession['key_tempo']) === true)
258
) {
259
    // Update table by deleting ID
260
    DB::update(
261
        prefixTable('users'),
262
        [
263
            'key_tempo' => '',
264
            'timestamp' => '',
265
            'session_end' => '',
266
        ],
267
        'id=%i',
268
        $_SESSION['user_id']
269
    );
270
    //Log into DB the user's disconnection
271
    if (
272
        isset($SETTINGS['log_connections']) === true
273
        && (int) $SETTINGS['log_connections'] === 1
274
        && isset($_SESSION['login']) === true
275
        && empty($_SESSION['login']) === false
276
    ) {
277
        logEvents($SETTINGS, 'user_connection', 'disconnect', (string) $_SESSION['user_id'], $_SESSION['login']);
278
    }
279
280
    // erase session table
281
    session_unset();
282
    session_destroy();
283
    $_SESSION = [];
284
    //Redirection
285
    echo '
286
    <script language="javascript" type="text/javascript">
287
    <!--
288
    setTimeout(function(){document.location.href="index.php"}, 1);
289
    -->
290
    </script>';
291
}
292
293
// CHECK IF UPDATE IS NEEDED
294
if ((isset($SETTINGS['update_needed']) === true && ($SETTINGS['update_needed'] !== false
295
        || empty($SETTINGS['update_needed']) === true))
296
    && (isset($_SESSION['user_admin']) === true && $_SESSION['user_admin'] === 1)
297
) {
298
    $row = DB::queryFirstRow(
299
        'SELECT valeur FROM ' . prefixTable('misc') . ' WHERE type=%s_type AND intitule=%s_intitule',
300
        [
301
            'type' => 'admin',
302
            'intitule' => 'teampass_version',
303
        ]
304
    );
305
    $count = DB::count();
306
    if ($count === 0 || $row['valeur'] !== TP_VERSION) {
307
        $SETTINGS['update_needed'] = true;
308
    } else {
309
        $SETTINGS['update_needed'] = false;
310
    }
311
}
312
313
/* CHECK IF MAINTENANCE MODE
314
* IF yes then authorize all ADMIN connections and
315
* reject all others
316
*/
317
if (isset($SETTINGS['maintenance_mode']) === true && (int) $SETTINGS['maintenance_mode'] === 1) {
318
    if (isset($_SESSION['user_admin']) === true && (int) $_SESSION['user_admin'] !== 1) {
319
        // Update table by deleting ID
320
        if (isset($_SESSION['user_id']) === true) {
321
            DB::update(
322
                prefixTable('users'),
323
                [
324
                    'key_tempo' => '',
325
                    'timestamp' => '',
326
                    'session_end' => '',
327
                ],
328
                'id=%i',
329
                $_SESSION['user_id']
330
            );
331
        }
332
333
        //Log into DB the user's disconnection
334
        if (isset($SETTINGS['log_connections']) === true && (int) $SETTINGS['log_connections'] === 1) {
335
            logEvents($SETTINGS, 'user_connection', 'disconnect', (string) $_SESSION['user_id'], $_SESSION['login']);
336
        }
337
338
        syslog(
339
            LOG_WARNING,
340
            'Unlog user: ' . date('Y/m/d H:i:s') . " {$server['remote_addr']} ({$server['http_user_agent']})"
341
        );
342
        // erase session table
343
        $_SESSION = [];
344
        setcookie('pma_end_session');
345
        // REDIRECTION PAGE ERREUR
346
        echo '
347
        <script language="javascript" type="text/javascript">
348
        <!--
349
        setTimeout(
350
            function() {
351
                document.location.href="./includes/core/logout.php"
352
            },
353
            10
354
        );
355
        -->
356
        </script>';
357
        exit;
358
    }
359
}
360
361
/* Force HTTPS Strict Transport Security */
362
if (
363
    isset($SETTINGS['enable_sts']) === true
364
    && (int) $SETTINGS['enable_sts'] === 1
365
    && isset($server['ssl_server_cert']) === true
366
) {
367
    // do a check to make sure that the certificate is not self signed.
368
    // In apache's SSL configuration make sure "SSLOptions +ExportCertData" in enabled
369
    $server_cert = openssl_x509_parse($server['ssl_server_cert']);
370
    $cert_name = $server_cert['name'];
371
    $cert_issuer = '';
372
    foreach ($server_cert['issuer'] as $key => $value) {
373
        if (is_array($value) === false) {
374
            $cert_issuer .= "/${key}=${value}";
375
        }
376
    }
377
    if (isset($cert_name) === true && empty($cert_name) === false && $cert_name !== $cert_issuer) {
378
        if (isset($server['HTTPS'])) {
379
            header('Strict-Transport-Security: max-age=500');
380
            $_SESSION['error']['sts'] = 0;
381
        }
382
    } elseif ($cert_name === $cert_issuer) {
383
        $_SESSION['error']['sts'] = 1;
384
    }
385
}
386
387
/* LOAD INFORMATION CONCERNING USER */
388
if (isset($_SESSION['user_id']) === true && empty($_SESSION['user_id']) === false) {
389
    // query on user
390
    $data = DB::queryfirstrow(
391
        'SELECT login, admin, gestionnaire, can_manage_all_users, groupes_visibles, groupes_interdits, fonction_id, last_connexion, roles_from_ad_groups FROM ' . prefixTable('users') . ' WHERE id=%i',
392
        $_SESSION['user_id']
393
    );
394
    //Check if user has been deleted or unlogged
395
    if (empty($data) === true) {
396
        // erase session table
397
        $_SESSION = [];
398
        // Kill session
399
        session_destroy();
400
        //redirection to index
401
        echo '
402
        <script language="javascript" type="text/javascript">
403
        <!--
404
        setTimeout(function(){document.location.href="index.php"}, 10);
405
        -->
406
        </script>';
407
    } else {
408
        // update user's rights
409
        $_SESSION['user_admin'] = $data['admin'];
410
        $_SESSION['user_manager'] = $data['gestionnaire'];
411
        $_SESSION['user_can_manage_all_users'] = $data['can_manage_all_users'];
412
        $_SESSION['groupes_visibles'] = [];
413
        $_SESSION['no_access_folders'] = [];
414
        if (empty($data['groupes_visibles']) === false) {
415
            $_SESSION['groupes_visibles'] = array_filter(explode(';', $data['groupes_visibles']));
416
        }
417
        if (empty($data['groupes_interdits']) === false) {
418
            $_SESSION['no_access_folders'] = array_filter(explode(';', $data['groupes_interdits']));
419
        }
420
421
        if (isset($_SESSION['sessionDuration']) === false) {
422
            DB::update(
423
                prefixTable('users'),
424
                [
425
                    'timestamp' => time(),
426
                ],
427
                'id=%i',
428
                $_SESSION['user_id']
429
            );
430
        }
431
432
        // get access rights
433
        identifyUserRights(
434
            $data['groupes_visibles'],
435
            $data['groupes_interdits'],
436
            $data['admin'],
437
            is_null($data['roles_from_ad_groups']) === true ? $data['fonction_id'] : (empty($data['roles_from_ad_groups']) === true ? $data['fonction_id'] : $data['fonction_id'] . ';' . $data['roles_from_ad_groups']),
438
            $SETTINGS
439
        );
440
        if (isset($_SESSION['can_create_root_folder']) === true && (int) $_SESSION['can_create_root_folder'] === 1) {
441
            array_push($_SESSION['groupes_visibles'], 0);
442
        }
443
444
        // user type
445
        if (isset($LANG) === true) {
446
            if ((int) $_SESSION['user_admin'] === 1) {
447
                $_SESSION['user_privilege'] = $LANG['god'];
448
            } elseif ((int) $_SESSION['user_manager'] === 1) {
449
                $_SESSION['user_privilege'] = $LANG['gestionnaire'];
450
            } elseif ((int) $_SESSION['user_read_only'] === 1) {
451
                $_SESSION['user_privilege'] = $LANG['read_only_account'];
452
            } else {
453
                $_SESSION['user_privilege'] = $LANG['user'];
454
            }
455
        }
456
    }
457
}
458
459
/*
460
* LOAD CATEGORIES
461
*/
462
if (
463
    isset($SETTINGS['item_extra_fields']) === true
464
    && (int) $SETTINGS['item_extra_fields'] === 1
465
    && isset($get['page']) === true
466
    && $get['page'] === 'items'
467
    && isset($_SESSION['fonction_id']) === true
468
) {
469
    $_SESSION['item_fields'] = [];
470
    $rows = DB::query(
471
        'SELECT *
472
            FROM ' . prefixTable('categories') . '
473
            WHERE level=%i',
474
        '0'
475
    );
476
    foreach ($rows as $record) {
477
        $arrFields = [];
478
        // get each field
479
        $rows2 = DB::query(
480
            'SELECT *
481
            FROM ' . prefixTable('categories') . '
482
            WHERE parent_id=%i
483
            ORDER BY `order` ASC',
484
            $record['id']
485
        );
486
        if (DB::count() > 0) {
487
            foreach ($rows2 as $field) {
488
                // Is this Field visibile by user?
489
                if (
490
                    $field['role_visibility'] === 'all'
491
                    || count(
492
                        array_intersect(
493
                            explode(';', $_SESSION['fonction_id']),
494
                            explode(',', $field['role_visibility'])
495
                        )
496
                    ) > 0
497
                ) {
498
                    array_push(
499
                        $arrFields,
500
                        [
501
                            'id' => $field['id'],
502
                            'title' => addslashes($field['title']),
503
                            'encrypted_data' => $field['encrypted_data'],
504
                            'type' => $field['type'],
505
                            'masked' => $field['masked'],
506
                            'is_mandatory' => $field['is_mandatory'],
507
                            'regex' => $field['regex'],
508
                        ]
509
                    );
510
                }
511
            }
512
        }
513
514
        // store the categories
515
        array_push(
516
            $_SESSION['item_fields'],
517
            [
518
                'id' => $record['id'],
519
                'title' => addslashes($record['title']),
520
                'fields' => $arrFields,
521
            ]
522
        );
523
    }
524
}
525
526
/*
527
* CHECK PASSWORD VALIDITY
528
* Don't take into consideration if LDAP in use
529
*/
530
$_SESSION['numDaysBeforePwExpiration'] = '';
531
//initiliaze variable
532
if (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 1) {
533
    $_SESSION['validite_pw'] = true;
534
    $_SESSION['last_pw_change'] = true;
535
} else {
536
    if (isset($_SESSION['last_pw_change']) === true) {
537
        if ((int) $SETTINGS['pw_life_duration'] === 0) {
538
            $_SESSION['numDaysBeforePwExpiration'] = 'infinite';
539
            $_SESSION['validite_pw'] = true;
540
        } else {
541
            $_SESSION['numDaysBeforePwExpiration'] = $SETTINGS['pw_life_duration'] - round(
542
                (mktime(0, 0, 0, (int) date('m'), (int) date('d'), (int) date('y')) - $_SESSION['last_pw_change']) / (24 * 60 * 60)
543
            );
544
            if ($_SESSION['numDaysBeforePwExpiration'] <= 0) {
545
                $_SESSION['validite_pw'] = false;
546
            } else {
547
                $_SESSION['validite_pw'] = true;
548
            }
549
        }
550
    } else {
551
        $_SESSION['validite_pw'] = false;
552
    }
553
}
554
555
$_SESSION['temporary']['user_can_printout'] = false;
556
if (
557
    isset($SETTINGS['roles_allowed_to_print']) === true
558
    && isset($_SESSION['user_roles']) === true
559
    && (! isset($_SESSION['temporary']['user_can_printout']) || empty($_SESSION['temporary']['user_can_printout']))
560
) {
561
    foreach (explode(';', $SETTINGS['roles_allowed_to_print']) as $role) {
562
        if (in_array($role, $_SESSION['user_roles']) === true) {
563
            $_SESSION['temporary']['user_can_printout'] = true;
564
        }
565
    }
566
}
567
568
/* CHECK NUMBER OF USER ONLINE */
569
DB::query('SELECT * FROM ' . prefixTable('users') . ' WHERE timestamp>=%i', time() - 600);
570
$_SESSION['nb_users_online'] = DB::count();
571