Passed
Push — teampass_3.0 ( 84b7c5...4b45d9 )
by Nils
09:36
created

redirect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 11
c 2
b 0
f 0
nc 2
nop 1
dl 0
loc 19
rs 9.9
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      core.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
21
if (isset($_SESSION['CPM']) === false || (int)$_SESSION['CPM'] !== 1) {
22
    die('Please login...');
23
}
24
25
// Load config
26
if (file_exists('../includes/config/tp.config.php')) {
27
    include_once '../includes/config/tp.config.php';
28
} elseif (file_exists('./includes/config/tp.config.php')) {
29
    include_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
/**
35
 * Redirection management.
36
 *
37
 * @param string $url new url
38
 *
39
 * @return string refresh page to url
40
 */
41
function redirect($url)
42
{
43
    // Load AntiXSS
44
    include_once '../includes/libraries/voku/helper/AntiXSS.php';
45
    $antiXss = new voku\helper\AntiXSS();
46
47
    if (!headers_sent()) {    //If headers not sent yet... then do php redirect
48
        header('Location: ' . $antiXss->xss_clean($url));
49
50
        return;
51
    }
52
53
    //If headers are sent... do java redirect... if java disabled, do html redirect.
54
    echo '<script type="text/javascript">';
55
    echo 'window.location.href="' . $antiXss->xss_clean($url) . '";';
56
    echo '</script>';
57
    echo '<noscript>';
58
    echo '<meta http-equiv="refresh" content="0;url=' . $antiXss->xss_clean($url) . '" />';
59
    echo '</noscript>';
60
}
61
62
// Include files
63
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
64
$superGlobal = new protect\SuperGlobal\SuperGlobal();
65
66
// Prepare GET variables
67
$get_group = $superGlobal->get('group', 'GET');
68
69
// Redirect needed?
70
if (isset($_SERVER['HTTPS']) === true
71
    && $_SERVER['HTTPS'] !== 'on'
72
    && isset($SETTINGS['enable_sts']) === true
73
    && (int) $SETTINGS['enable_sts'] === 1
74
) {
75
    redirect('https://' . $superGlobal->get('HTTP_HOST', 'SERVER') . $superGlobal->get('REQUEST_URI', 'SERVER'));
76
}
77
78
// Load pwComplexity
79
if (defined('TP_PW_COMPLEXITY') === false) {
80
    // Pw complexity levels
81
    if (isset($_SESSION['user_language']) === true && $_SESSION['user_language'] !== '0') {
82
        define(
83
            'TP_PW_COMPLEXITY',
84
            array(
85
                0 => array(0, langHdl('complex_level0'), 'fas fa-bolt text-danger'),
86
                25 => array(25, langHdl('complex_level1'), 'fas fa-thermometer-empty text-danger'),
87
                50 => array(50, langHdl('complex_level2'), 'fas fa-thermometer-quarter text-warning'),
88
                60 => array(60, langHdl('complex_level3'), 'fas fa-thermometer-half text-warning'),
89
                70 => array(70, langHdl('complex_level4'), 'fas fa-thermometer-three-quarters text-success'),
90
                80 => array(80, langHdl('complex_level5'), 'fas fa-thermometer-full text-success'),
91
                90 => array(90, langHdl('complex_level6'), 'far fa-gem text-success'),
92
            )
93
        );
94
    }
95
}
96
97
// LOAD CPASSMAN SETTINGS
98
if (
99
    isset($SETTINGS['cpassman_dir']) === true
100
    && is_dir($SETTINGS['cpassman_dir'] . '/install') === true
101
) {
102
    // Should we delete folder INSTALL?
103
    $row = DB::queryFirstRow(
104
        'SELECT valeur FROM ' . prefixTable('misc') . ' WHERE type=%s AND intitule=%s',
105
        'install',
106
        'clear_install_folder'
107
    );
108
    if (DB::count() > 0 && $row['valeur'] === 'true') {
109
        /**
110
         * Permits to delete files and folders recursively.
111
         */
112
        function delTree($dir)
113
        {
114
            $directories = scandir($dir);
115
            if ($directories !== false) {
116
                $files = array_diff($directories, array('.', '..'));
117
118
                foreach ($files as $file) {
119
                    if (is_dir($dir . '/' . $file)) {
120
                        delTree($dir . '/' . $file);
121
                    } else {
122
                        try {
123
                            unlink($dir . '/' . $file);
124
                        } catch (Exception $e) {
125
                            // do nothing... php will ignore and continue
126
                        }
127
                    }
128
                }
129
130
                return @rmdir($dir);
131
            } else {
132
                return false;
133
            }
134
        }
135
136
        if (is_dir($SETTINGS['cpassman_dir'] . '/install')) {
137
            // Set the permissions on the install directory and delete
138
            // is server Windows or Linux?
139
            if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
140
                chmodRecursive($SETTINGS['cpassman_dir'] . '/install', 0755, 0440);
141
            }
142
            delTree($SETTINGS['cpassman_dir'] . '/install');
143
        }
144
145
        // Delete temporary install table
146
        DB::query('DROP TABLE IF EXISTS `_install`');
147
148
        // Delete tag
149
        DB::delete(
150
            prefixTable('misc'),
151
            'type=%s AND intitule=%s',
152
            'install',
153
            'clear_install_folder'
154
        );
155
    }
156
}
157
158
// Load Languages stuff
159
if (isset($languagesList) === false) {
160
    $languagesList = array();
161
    $rows = DB::query('SELECT * FROM ' . prefixTable('languages') . ' GROUP BY name, label, code, flag, id ORDER BY name ASC');
162
    foreach ($rows as $record) {
163
        array_push($languagesList, $record['name']);
164
        if (isset($_SESSION['user_language']) && $record['name'] == $_SESSION['user_language']) {
165
            $_SESSION['user_language_flag'] = $record['flag'];
166
            $_SESSION['user_language_code'] = $record['code'];
167
            $_SESSION['user_language_label'] = $record['label'];
168
            $_SESSION['user_language_id'] = $record['id'];
169
        }
170
    }
171
}
172
173
if (isset($_SESSION['user']['usertimezone']) === true && $_SESSION['user']['usertimezone'] !== 'not_defined') {
174
    // use user timezone
175
    date_default_timezone_set($_SESSION['user']['usertimezone']);
176
} elseif (isset($SETTINGS['timezone']) === false || $SETTINGS['timezone'] === null) {
177
    // use server timezone
178
    date_default_timezone_set('UTC');
179
    $SETTINGS['timezone'] = 'UTC';
180
} else {
181
    // use server timezone
182
    date_default_timezone_set($SETTINGS['timezone']);
183
}
184
185
// CHECK IF LOGOUT IS ASKED OR IF SESSION IS EXPIRED
186
if ((isset($_GET['session']) === true
187
        && $_GET['session'] == 'expired')
188
    || (null !== filter_input(INPUT_POST, 'session', FILTER_SANITIZE_STRING)
189
        && filter_input(INPUT_POST, 'session', FILTER_SANITIZE_STRING) === 'expired')
190
) {
191
    // Clear User tempo key
192
    if (isset($_SESSION['user_id']) === true) {
193
        DB::update(
194
            prefixTable('users'),
195
            array(
196
                'key_tempo' => '',
197
                'timestamp' => '',
198
                'session_end' => '',
199
            ),
200
            'id=%i',
201
            $_SESSION['user_id']
202
        );
203
    }
204
205
    // REDIRECTION PAGE ERREUR
206
    echo '
207
    <script language="javascript" type="text/javascript">
208
    <!--
209
        sessionStorage.clear();
210
        window.location.href = "./includes/core/logout.php";
211
    -->
212
    </script>';
213
    exit;
214
}
215
216
// CHECK IF SESSION EXISTS AND IF SESSION IS VALID
217
if (empty($_SESSION['sessionDuration']) === false) {
218
    $dataSession = DB::queryFirstRow(
219
        'SELECT key_tempo FROM ' . prefixTable('users') . ' WHERE id=%i',
220
        $_SESSION['user_id']
221
    );
222
} else {
223
    $dataSession['key_tempo'] = '';
224
}
225
226
// get some init
227
if (isset($_SESSION['user_id']) === false || (int) $_SESSION['user_id'] === 0) {
228
    $_SESSION['key'] = GenerateCryptKey(50, false, true, true, false, true, array('cpassman_dir' => '.'));
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $_SESSION['key'] is correct as GenerateCryptKey(50, fal...'cpassman_dir' => '.')) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
229
    $_SESSION['user_id'] = 0;
230
    $_SESSION['id'] = 1;
231
}
232
233
if (
234
    isset($_SESSION['user_id']) === true
235
    && isset($_GET['type']) === false
236
    && isset($_GET['action']) === false
237
    && (int) $_SESSION['user_id'] !== 0
238
    && (empty($_SESSION['sessionDuration']) === true
239
        || $_SESSION['sessionDuration'] < time()
240
        || empty($_SESSION['key']) === true
241
        || empty($dataSession['key_tempo']) === true)
242
) {
243
    // Update table by deleting ID
244
    DB::update(
245
        prefixTable('users'),
246
        array(
247
            'key_tempo' => '',
248
            'timestamp' => '',
249
            'session_end' => '',
250
        ),
251
        'id=%i',
252
        $_SESSION['user_id']
253
    );
254
255
    //Log into DB the user's disconnection
256
    if (
257
        isset($SETTINGS['log_connections']) === true
258
        && (int) $SETTINGS['log_connections'] === 1
259
        && isset($_SESSION['login']) === true
260
        && empty($_SESSION['login']) === false
261
    ) {
262
        logEvents($SETTINGS, 'user_connection', 'disconnection', $_SESSION['user_id'], $_SESSION['login']);
263
    }
264
265
    // erase session table
266
    session_unset();
267
    session_destroy();
268
    $_SESSION = array();
269
270
    //Redirection
271
    echo '
272
    <script language="javascript" type="text/javascript">
273
    <!--
274
    setTimeout(function(){document.location.href="index.php"}, 1);
275
    -->
276
    </script>';
277
}
278
279
// CHECK IF UPDATE IS NEEDED
280
if ((isset($SETTINGS['update_needed']) === true && ($SETTINGS['update_needed'] !== false
281
        || empty($SETTINGS['update_needed']) === true))
282
    && (isset($_SESSION['user_admin']) === true && $_SESSION['user_admin'] == 1)
283
) {
284
    $row = DB::queryFirstRow(
285
        'SELECT valeur FROM ' . prefixTable('misc') . ' WHERE type=%s_type AND intitule=%s_intitule',
286
        array(
287
            'type' => 'admin',
288
            'intitule' => 'cpassman_version',
289
        )
290
    );
291
    if ($row['valeur'] != TP_VERSION_FULL) {
292
        $SETTINGS['update_needed'] = true;
293
    } else {
294
        $SETTINGS['update_needed'] = false;
295
    }
296
}
297
298
/*
299
 * Set the personal SaltKey if authorized
300
 */
301
/*
302
if (isset($SETTINGS['enable_personal_saltkey_cookie']) === true
303
    && $SETTINGS['enable_personal_saltkey_cookie'] == 1
304
    && isset($_SESSION['user_id']) === true
305
    && isset($_COOKIE['TeamPass_PFSK_'.md5($_SESSION['user_id'])]) === true
306
) {
307
    // Only defuse key
308
    if (substr($_COOKIE['TeamPass_PFSK_'.md5($_SESSION['user_id'])], 0, 3) === 'def') {
309
        $_SESSION['user']['session_psk'] = $_COOKIE['TeamPass_PFSK_'.md5($_SESSION['user_id'])];
310
    } else {
311
        // Remove old cookie
312
        unset($_COOKIE['TeamPass_PFSK_'.md5($_SESSION['user_id'])]);
313
        setcookie('TeamPass_PFSK_'.md5($_SESSION['user_id']), '', time() - 3600, '/'); // empty value and old timestamp
314
    }
315
}
316
*/
317
318
/* CHECK IF MAINTENANCE MODE
319
* IF yes then authorize all ADMIN connections and
320
* reject all others
321
*/
322
if (isset($SETTINGS['maintenance_mode']) === true && (int) $SETTINGS['maintenance_mode'] === 1) {
323
    if (isset($_SESSION['user_admin']) === true && (int) $_SESSION['user_admin'] !== 1) {
324
        // Update table by deleting ID
325
        if (isset($_SESSION['user_id']) === true) {
326
            DB::update(
327
                prefixTable('users'),
328
                array(
329
                    'key_tempo' => '',
330
                    'timestamp' => '',
331
                    'session_end' => '',
332
                ),
333
                'id=%i',
334
                $_SESSION['user_id']
335
            );
336
        }
337
338
        //Log into DB the user's disconnection
339
        if (isset($SETTINGS['log_connections']) === true && $SETTINGS['log_connections'] == 1) {
340
            logEvents($SETTINGS, 'user_connection', 'disconnection', $_SESSION['user_id'], $_SESSION['login']);
341
        }
342
343
        syslog(
344
            LOG_WARNING,
345
            'Unlog user: ' . date('Y/m/d H:i:s') . " {$_SERVER['REMOTE_ADDR']} ({$_SERVER['HTTP_USER_AGENT']})"
346
        );
347
348
        // erase session table
349
        $_SESSION = array();
350
351
        setcookie('pma_end_session');
352
353
        // REDIRECTION PAGE ERREUR
354
        echo '
355
        <script language="javascript" type="text/javascript">
356
        <!--
357
        setTimeout(
358
            function() {
359
                document.location.href="./includes/core/logout.php"
360
            },
361
            10
362
        );
363
        -->
364
        </script>';
365
        exit;
366
    }
367
}
368
369
/* Force HTTPS Strict Transport Security */
370
if (
371
    isset($SETTINGS['enable_sts']) === true
372
    && (int) $SETTINGS['enable_sts'] === 1
373
    && isset($_SERVER['SSL_SERVER_CERT']) === true
374
) {
375
    // do a check to make sure that the certificate is not self signed.
376
    // In apache's SSL configuration make sure "SSLOptions +ExportCertData" in enabled
377
    $server_cert = openssl_x509_parse($_SERVER['SSL_SERVER_CERT']);
378
    $cert_name = $server_cert['name'];
379
    $cert_issuer = '';
380
    foreach ($server_cert['issuer'] as $key => $value) {
381
        if (is_array($value) === false) {
382
            $cert_issuer .= "/$key=$value";
383
        }
384
    }
385
    if (isset($cert_name) === true && empty($cert_name) === false && $cert_name != $cert_issuer) {
386
        if (isset($_SERVER['HTTPS'])) {
387
            header('Strict-Transport-Security: max-age=500');
388
            $_SESSION['error']['sts'] = 0;
389
        }
390
    } elseif ($cert_name == $cert_issuer) {
391
        $_SESSION['error']['sts'] = 1;
392
    }
393
}
394
395
/* LOAD INFORMATION CONCERNING USER */
396
if (isset($_SESSION['user_id']) === true && empty($_SESSION['user_id']) === false) {
397
    // query on user
398
    $data = DB::queryfirstrow(
399
        'SELECT login, admin, gestionnaire, can_manage_all_users, groupes_visibles, groupes_interdits, fonction_id, last_connexion FROM ' . prefixTable('users') . ' WHERE id=%i',
400
        $_SESSION['user_id']
401
    );
402
403
    //Check if user has been deleted or unlogged
404
    if (empty($data) === true) {
405
        // erase session table
406
        $_SESSION = array();
407
408
        // Kill session
409
        session_destroy();
410
411
        //redirection to index
412
        echo '
413
        <script language="javascript" type="text/javascript">
414
        <!--
415
        setTimeout(function(){document.location.href="index.php"}, 10);
416
        -->
417
        </script>';
418
    } else {
419
        // update user's rights
420
        $_SESSION['user_admin'] = $data['admin'];
421
        $_SESSION['user_manager'] = $data['gestionnaire'];
422
        $_SESSION['user_can_manage_all_users'] = $data['can_manage_all_users'];
423
        $_SESSION['groupes_visibles'] = array();
424
        $_SESSION['no_access_folders'] = array();
425
        if (empty($data['groupes_visibles']) === false) {
426
            $_SESSION['groupes_visibles'] = array_filter(explode(';', $data['groupes_visibles']));
427
        }
428
        if (empty($data['groupes_interdits']) === false) {
429
            $_SESSION['no_access_folders'] = array_filter(explode(';', $data['groupes_interdits']));
430
        }
431
432
        if (isset($_SESSION['sessionDuration']) === false) {
433
            DB::update(
434
                prefixTable('users'),
435
                array(
436
                    'timestamp' => time(),
437
                ),
438
                'id=%i',
439
                $_SESSION['user_id']
440
            );
441
        }
442
443
        // get access rights
444
        identifyUserRights(
445
            $data['groupes_visibles'],
446
            $data['groupes_interdits'],
447
            $data['admin'],
448
            $data['fonction_id'],
449
            $SETTINGS
450
        );
451
452
        if (isset($_SESSION['can_create_root_folder']) === true && (int) $_SESSION['can_create_root_folder'] === 1) {
453
            array_push($_SESSION['groupes_visibles'], 0);
454
        };
455
456
        // user type
457
        if (isset($LANG) === true) {
458
            if ((int) $_SESSION['user_admin'] === 1) {
459
                $_SESSION['user_privilege'] = $LANG['god'];
460
            } elseif ((int) $_SESSION['user_manager'] === 1) {
461
                $_SESSION['user_privilege'] = $LANG['gestionnaire'];
462
            } elseif ((int) $_SESSION['user_read_only'] === 1) {
463
                $_SESSION['user_privilege'] = $LANG['read_only_account'];
464
            } else {
465
                $_SESSION['user_privilege'] = $LANG['user'];
466
            }
467
        }
468
    }
469
}
470
471
/*
472
* LOAD CATEGORIES
473
*/
474
if (
475
    isset($SETTINGS['item_extra_fields']) === true
476
    && (int) $SETTINGS['item_extra_fields'] === 1
477
    && isset($_GET['page']) === true
478
    && $_GET['page'] === 'items'
479
    && isset($_SESSION['fonction_id']) === true
480
) {
481
    $_SESSION['item_fields'] = array();
482
    $rows = DB::query(
483
        'SELECT *
484
        FROM ' . prefixTable('categories') . '
485
        WHERE level=%i',
486
        '0'
487
    );
488
    foreach ($rows as $record) {
489
        $arrFields = array();
490
491
        // get each field
492
        $rows2 = DB::query(
493
            'SELECT *
494
            FROM ' . prefixTable('categories') . '
495
            WHERE parent_id=%i
496
            ORDER BY `order` ASC',
497
            $record['id']
498
        );
499
500
        if (DB::count() > 0) {
501
            foreach ($rows2 as $field) {
502
                // Is this Field visibile by user?
503
                if (
504
                    $field['role_visibility'] === 'all'
505
                    || count(
506
                        array_intersect(
507
                            explode(';', $_SESSION['fonction_id']),
508
                            explode(',', $field['role_visibility'])
509
                        )
510
                    ) > 0
511
                ) {
512
                    array_push(
513
                        $arrFields,
514
                        array(
515
                            'id' => $field['id'],
516
                            'title' => addslashes($field['title']),
517
                            'encrypted_data' => $field['encrypted_data'],
518
                            'type' => $field['type'],
519
                            'masked' => $field['masked'],
520
                            'is_mandatory' => $field['is_mandatory'],
521
                        )
522
                    );
523
                }
524
            }
525
        }
526
527
        // store the categories
528
        array_push(
529
            $_SESSION['item_fields'],
530
            array(
531
                'id' => $record['id'],
532
                'title' => addslashes($record['title']),
533
                'fields' => $arrFields,
534
            )
535
        );
536
    }
537
}
538
539
/*
540
* CHECK PASSWORD VALIDITY
541
* Don't take into consideration if LDAP in use
542
*/
543
$_SESSION['numDaysBeforePwExpiration'] = ''; //initiliaze variable
544
if (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 1) {
545
    $_SESSION['validite_pw'] = true;
546
    $_SESSION['last_pw_change'] = true;
547
} else {
548
    if (isset($_SESSION['last_pw_change']) === true) {
549
        if ((int) $SETTINGS['pw_life_duration'] === 0) {
550
            $_SESSION['numDaysBeforePwExpiration'] = 'infinite';
551
            $_SESSION['validite_pw'] = true;
552
        } else {
553
            $_SESSION['numDaysBeforePwExpiration'] = $SETTINGS['pw_life_duration'] - round(
554
                (mktime(0, 0, 0, (int) date('m'), (int) date('d'), (int) date('y')) - $_SESSION['last_pw_change']) / (24 * 60 * 60)
555
            );
556
            if ($_SESSION['numDaysBeforePwExpiration'] <= 0) {
557
                $_SESSION['validite_pw'] = false;
558
            } else {
559
                $_SESSION['validite_pw'] = true;
560
            }
561
        }
562
    } else {
563
        $_SESSION['validite_pw'] = false;
564
    }
565
}
566
567
/*
568
**
569
*/
570
$_SESSION['temporary']['user_can_printout'] = false;
571
if (
572
    isset($SETTINGS['roles_allowed_to_print']) === true
573
    && isset($_SESSION['user_roles']) === true
574
    && (!isset($_SESSION['temporary']['user_can_printout']) || empty($_SESSION['temporary']['user_can_printout']))
575
) {
576
    foreach (explode(';', $SETTINGS['roles_allowed_to_print']) as $role) {
577
        if (in_array($role, $_SESSION['user_roles']) === true) {
578
            $_SESSION['temporary']['user_can_printout'] = true;
579
        }
580
    }
581
}
582
583
/* CHECK NUMBER OF USER ONLINE */
584
DB::query('SELECT * FROM ' . prefixTable('users') . ' WHERE timestamp>=%i', time() - 600);
585
$_SESSION['nb_users_online'] = DB::count();
586