Completed
Push — development ( f7a32b...603632 )
by Nils
07:21
created

main.functions.php ➔ sanitizeEntry()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 2
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 *
4
 * @file          main.functions.php
5
 * @author        Nils Laumaillé
6
 * @version       2.1.27
7
 * @copyright     (c) 2009-2017 Nils Laumaillé
8
 * @licensing     GNU AFFERO GPL 3.0
9
 * @link
10
 */
11
12
//define pbkdf2 iteration count
13
define('ITCOUNT', '2072');
14
15
if (!isset($_SESSION['CPM']) || $_SESSION['CPM'] != 1) {
16
    die('Hacking attempt...');
17
}
18
19
// load phpCrypt
20
if (!isset($_SESSION['settings']['cpassman_dir']) || empty($_SESSION['settings']['cpassman_dir'])) {
21
    require_once '../includes/libraries/phpcrypt/phpCrypt.php';
22
    require_once '../includes/config/settings.php';
23
} else {
24
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/phpcrypt/phpCrypt.php';
25
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/config/settings.php';
26
}
27
28
// Prepare PHPCrypt class calls
29
use PHP_Crypt\PHP_Crypt as PHP_Crypt;
30
31
32
// Prepare Encryption class calls
33
use \Defuse\Crypto\Crypto;
34
use \Defuse\Crypto\Exception as Ex;
35
36
37
//Generate N# of random bits for use as salt
38
/**
39
 * @param integer $n
40
 */
41
function getBits($n)
42
{
43
    $str = '';
44
    $x = $n + 10;
45
    for ($i = 0; $i < $x; $i++) {
46
        $str .= base_convert(mt_rand(1, 36), 10, 36);
47
    }
48
    return substr($str, 0, $n);
49
}
50
51
//generate pbkdf2 compliant hash
52 View Code Duplication
function strHashPbkdf2($p, $s, $c, $kl, $a = 'sha256', $st = 0)
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
53
{
54
    $kb = $st + $kl; // Key blocks to compute
55
    $dk = ''; // Derived key
56
57
    for ($block = 1; $block <= $kb; $block++) { // Create key
58
        $ib = $h = hash_hmac($a, $s.pack('N', $block), $p, true); // Initial hash for this block
59
        for ($i = 1; $i < $c; $i++) { // Perform block iterations
60
            $ib ^= ($h = hash_hmac($a, $h, $p, true)); // XOR each iterate
61
        }
62
        $dk .= $ib; // Append iterated block
63
    }
64
    return substr($dk, $st, $kl); // Return derived key of correct length
65
}
66
67
/**
68
 * stringUtf8Decode()
69
 *
70
 * utf8_decode
71
 */
72
function stringUtf8Decode($string)
73
{
74
    return str_replace(" ", "+", utf8_decode($string));
75
}
76
77
/**
78
 * encryptOld()
79
 *
80
 * crypt a string
81
 * @param string $text
82
 */
83 View Code Duplication
function encryptOld($text, $personalSalt = "")
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
84
{
85
    if (!empty($personalSalt)) {
86
        return trim(
87
            base64_encode(
88
                mcrypt_encrypt(
89
                    MCRYPT_RIJNDAEL_256,
90
                    $personalSalt,
91
                    $text,
92
                    MCRYPT_MODE_ECB,
93
                    mcrypt_create_iv(
94
                        mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
95
                        MCRYPT_RAND
96
                    )
97
                )
98
            )
99
        );
100
    } else {
101
        return trim(
102
            base64_encode(
103
                mcrypt_encrypt(
104
                    MCRYPT_RIJNDAEL_256,
105
                    SALT,
106
                    $text,
107
                    MCRYPT_MODE_ECB,
108
                    mcrypt_create_iv(
109
                        mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
110
                        MCRYPT_RAND
111
                    )
112
                )
113
            )
114
        );
115
    }
116
}
117
118
/**
119
 * decryptOld()
120
 *
121
 * decrypt a crypted string
122
 */
123 View Code Duplication
function decryptOld($text, $personalSalt = "")
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
{
125
    if (!empty($personalSalt)) {
126
        return trim(
127
            mcrypt_decrypt(
128
                MCRYPT_RIJNDAEL_256,
129
                $personalSalt,
130
                base64_decode($text),
131
                MCRYPT_MODE_ECB,
132
                mcrypt_create_iv(
133
                    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
134
                    MCRYPT_RAND
135
                )
136
            )
137
        );
138
    } else {
139
        return trim(
140
            mcrypt_decrypt(
141
                MCRYPT_RIJNDAEL_256,
142
                SALT,
143
                base64_decode($text),
144
                MCRYPT_MODE_ECB,
145
                mcrypt_create_iv(
146
                    mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
147
                    MCRYPT_RAND
148
                )
149
            )
150
        );
151
    }
152
}
153
154
/**
155
 * encrypt()
156
 *
157
 * crypt a string
158
 * @param string $decrypted
159
 */
160
function encrypt($decrypted, $personalSalt = "")
161
{
162 View Code Duplication
    if (!isset($_SESSION['settings']['cpassman_dir']) || empty($_SESSION['settings']['cpassman_dir'])) {
163
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
164
    } else {
165
        require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
166
    }
167
168
    if (!empty($personalSalt)) {
169
            $staticSalt = $personalSalt;
170
    } else {
171
            $staticSalt = SALT;
172
    }
173
174
    //set our salt to a variable
175
    // Get 64 random bits for the salt for pbkdf2
176
    $pbkdf2Salt = getBits(64);
177
    // generate a pbkdf2 key to use for the encryption.
178
    $key = substr(pbkdf2('sha256', $staticSalt, $pbkdf2Salt, ITCOUNT, 16 + 32, true), 32, 16);
179
    // Build $iv and $ivBase64.  We use a block size of 256 bits (AES compliant)
180
    // and CTR mode.  (Note: ECB mode is inadequate as IV is not used.)
181
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, 'ctr'), MCRYPT_RAND);
182
183
    //base64 trim
184
    if (strlen($ivBase64 = rtrim(base64_encode($iv), '=')) != 43) {
185
        return false;
186
    }
187
    // Encrypt $decrypted
188
    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $decrypted, 'ctr', $iv);
189
    // MAC the encrypted text
190
    $mac = hash_hmac('sha256', $encrypted, $staticSalt);
191
    // We're done!
192
    return base64_encode($ivBase64.$encrypted.$mac.$pbkdf2Salt);
193
}
194
195
/**
196
 * decrypt()
197
 *
198
 * decrypt a crypted string
199
 */
200
function decrypt($encrypted, $personalSalt = "")
201
{
202 View Code Duplication
    if (!isset($_SESSION['settings']['cpassman_dir']) || empty($_SESSION['settings']['cpassman_dir'])) {
203
        require_once '../includes/libraries/Encryption/PBKDF2/PasswordHash.php';
204
    } else {
205
        require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/PBKDF2/PasswordHash.php';
206
    }
207
208
    if (!empty($personalSalt)) {
209
        $staticSalt = $personalSalt;
210
    } else {
211
        $staticSalt = SALT;
212
    }
213
    //base64 decode the entire payload
214
    $encrypted = base64_decode($encrypted);
215
    // get the salt
216
    $pbkdf2Salt = substr($encrypted, -64);
217
    //remove the salt from the string
218
    $encrypted = substr($encrypted, 0, -64);
219
    $key = substr(pbkdf2('sha256', $staticSalt, $pbkdf2Salt, ITCOUNT, 16 + 32, true), 32, 16);
220
    // Retrieve $iv which is the first 22 characters plus ==, base64_decoded.
221
    $iv = base64_decode(substr($encrypted, 0, 43).'==');
222
    // Remove $iv from $encrypted.
223
    $encrypted = substr($encrypted, 43);
224
    // Retrieve $mac which is the last 64 characters of $encrypted.
225
    $mac = substr($encrypted, -64);
226
    // Remove the last 64 chars from encrypted (remove MAC)
227
    $encrypted = substr($encrypted, 0, -64);
228
    //verify the sha256hmac from the encrypted data before even trying to decrypt it
229
    if (hash_hmac('sha256', $encrypted, $staticSalt) != $mac) {
230
        return false;
231
    }
232
    // Decrypt the data.
233
    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, 'ctr', $iv), "\0\4");
234
    // Yay!
235
    return $decrypted;
236
}
237
238
239
/**
240
 * genHash()
241
 *
242
 * Generate a hash for user login
243
 * @param string $password
244
 */
245 View Code Duplication
function bCrypt($password, $cost)
0 ignored issues
show
Best Practice introduced by
The function bCrypt() has been defined more than once; this definition is ignored, only the first definition in install/install.queries.php (L58-70) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
246
{
247
    $salt = sprintf('$2y$%02d$', $cost);
248
    if (function_exists('openssl_random_pseudo_bytes')) {
249
        $salt .= bin2hex(openssl_random_pseudo_bytes(11));
250
    } else {
251
        $chars = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
252
        for ($i = 0; $i < 22; $i++) {
253
            $salt .= $chars[mt_rand(0, 63)];
254
        }
255
    }
256
    return crypt($password, $salt);
257
}
258
259
function cryption_before_defuse($message, $sk, $iv, $type = null, $scope = "public")
260
{
261
    if (DEFUSE_ENCRYPTION === true) {
262
        if ($scope === "perso") {
263
            return defuse_crypto(
264
                $message,
265
                $sk,
266
                $type
267
            );
268
        } else {
269
            return defuse_crypto(
270
                $message,
271
                file_get_contents(SECUREPATH."/teampass-seckey.txt"),
272
                $type
273
            );
274
        }
275
    } else {
276
        return cryption_phpCrypt($message, $sk, $iv, $type);
277
    }
278
}
279
280
/*
281
 * cryption() - Encrypt and decrypt string based upon phpCrypt library
282
 *
283
 * Using AES_128 and mode CBC
284
 *
285
 * $key and $iv have to be given in hex format
286
 */
287
function cryption_phpCrypt($string, $key, $iv, $type)
288
{
289
    // manage key origin
290
    define('SALT', 'LEfzTjADMTzV6qHC');
291
292
    if ($key != SALT) {
293
        // check key (AES-128 requires a 16 bytes length key)
294
        if (strlen($key) < 16) {
295
            for ($x = strlen($key) + 1; $x <= 16; $x++) {
296
                $key .= chr(0);
297
            }
298
        } else if (strlen($key) > 16) {
299
            $key = substr($key, 16);
300
        }
301
    }
302
303
    // load crypt
304
    $crypt = new PHP_Crypt($key, PHP_Crypt::CIPHER_AES_128, PHP_Crypt::MODE_CBC);
305
306
    if ($type == "encrypt") {
307
        // generate IV and encrypt
308
        $iv = $crypt->createIV();
309
        $encrypt = $crypt->encrypt($string);
310
        // return
311
        return array(
312
            "string" => bin2hex($encrypt),
313
            "iv" => bin2hex($iv),
314
            "error" => empty($encrypt) ? "ERR_ENCRYPTION_NOT_CORRECT" : ""
315
        );
316
    } else if ($type == "decrypt") {
317
        // case if IV is empty
318
        if (empty($iv)) {
319
                    return array(
320
                'string' => "",
321
                'error' => "ERR_ENCRYPTION_NOT_CORRECT"
322
            );
323
        }
324
325
        // convert
326
        try {
327
            $string = testHex2Bin(trim($string));
328
            $iv = testHex2Bin($iv);
329
        } catch (Exception $e) {
330
            return array(
331
                'string' => "",
332
                'error' => "ERR_ENCRYPTION_NOT_CORRECT"
333
            );
334
        }
335
336
        // load IV
337
        $crypt->IV($iv);
338
        // decrypt
339
        $decrypt = $crypt->decrypt($string);
340
        // return
341
        return array(
342
            'string' => str_replace(chr(0), "", $decrypt),
343
            'error' => ""
344
        );
345
    }
346
}
347
348
function testHex2Bin($val)
349
{
350
    if (!@hex2bin($val)) {
351
        throw new Exception("ERROR");
352
    }
353
    return hex2bin($val);
354
}
355
356
/**
357
 * @param string $ascii_key
358
 * @param string $type
359
 */
360
function cryption($message, $ascii_key, $type) //defuse_crypto
361
{
362
    // load PhpEncryption library
363 View Code Duplication
    if (!isset($_SESSION['settings']['cpassman_dir']) || empty($_SESSION['settings']['cpassman_dir'])) {
364
        $path = '../includes/libraries/Encryption/Encryption/';
365
    } else {
366
        $path = $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/';
367
    }
368
369
    require_once $path.'Crypto.php';
370
    require_once $path.'Encoding.php';
371
    require_once $path.'DerivedKeys.php';
372
    require_once $path.'Key.php';
373
    require_once $path.'KeyOrPassword.php';
374
    require_once $path.'File.php';
375
    require_once $path.'RuntimeTests.php';
376
    require_once $path.'KeyProtectedByPassword.php';
377
    require_once $path.'Core.php';
378
379
    // init
380
    $err = '';
381
    if (empty($ascii_key)) {
382
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
383
    }
384
385
    // convert KEY
386
    $key = \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key);
387
388
    try {
389
        if ($type === "encrypt") {
390
            $text = \Defuse\Crypto\Crypto::encrypt($message, $key);
391
        } else if ($type === "decrypt") {
392
            $text = \Defuse\Crypto\Crypto::decrypt($message, $key);
393
        }
394
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
395
        $err = "An attack! Either the wrong key was loaded, or the ciphertext has changed since it was created either corrupted in the database or intentionally modified by someone trying to carry out an attack.";
396
    } catch (Defuse\Crypto\Exception\BadFormatException $ex) {
397
        $err = $ex;
398
    } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
399
        $err = $ex;
400
    } catch (Defuse\Crypto\Exception\CryptoException $ex) {
401
        $err = $ex;
402
    } catch (Defuse\Crypto\Exception\IOException $ex) {
403
        $err = $ex;
404
    }
405
406
    return array(
407
        'string' => isset($text) ? $text : "",
408
        'error' => $err
409
    );
410
}
411
412
function defuse_generate_key() {
413
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
414
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
415
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
416
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
417
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
418
    require_once '../includes/libraries/Encryption/Encryption/File.php';
419
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
420
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
421
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
422
423
    $key = \Defuse\Crypto\Key::createNewRandomKey();
424
    $key = $key->saveToAsciiSafeString();
425
    return $key;
426
}
427
428
function defuse_generate_personal_key($psk) {
429
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
430
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
431
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
432
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
433
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
434
    require_once '../includes/libraries/Encryption/Encryption/File.php';
435
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
436
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
437
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
438
439
    $protected_key = \Defuse\Crypto\KeyProtectedByPassword::createRandomPasswordProtectedKey($psk);
440
    $protected_key_encoded = $protected_key->saveToAsciiSafeString();
441
442
    return $protected_key_encoded; // save this in user table
443
}
444
445
/**
446
 * @param string $psk
447
 */
448
function defuse_validate_personal_key($psk, $protected_key_encoded) {
449
    require_once '../includes/libraries/Encryption/Encryption/Crypto.php';
450
    require_once '../includes/libraries/Encryption/Encryption/Encoding.php';
451
    require_once '../includes/libraries/Encryption/Encryption/DerivedKeys.php';
452
    require_once '../includes/libraries/Encryption/Encryption/Key.php';
453
    require_once '../includes/libraries/Encryption/Encryption/KeyOrPassword.php';
454
    require_once '../includes/libraries/Encryption/Encryption/File.php';
455
    require_once '../includes/libraries/Encryption/Encryption/RuntimeTests.php';
456
    require_once '../includes/libraries/Encryption/Encryption/KeyProtectedByPassword.php';
457
    require_once '../includes/libraries/Encryption/Encryption/Core.php';
458
459
    try {
460
        $protected_key = \Defuse\Crypto\KeyProtectedByPassword::loadFromAsciiSafeString($protected_key_encoded);
461
        $user_key = $protected_key->unlockKey($psk);
462
        $user_key_encoded = $user_key->saveToAsciiSafeString();
463
    } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
464
        return "Error - Major issue as the encryption is broken.";
465
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
466
        return "Error - The saltkey is not the correct one.";
467
    }
468
469
    return $user_key_encoded; // store it in session once user has entered his psk
470
}
471
472
/**
473
 * trimElement()
474
 *
475
 * trim a string depending on a specific string
476
 * @param string $element
477
 * @return string
478
 */
479
function trimElement($chaine, $element)
480
{
481
    if (!empty($chaine)) {
482
        $chaine = trim($chaine);
483
        if (substr($chaine, 0, 1) == $element) {
484
            $chaine = substr($chaine, 1);
485
        }
486
        if (substr($chaine, strlen($chaine) - 1, 1) == $element) {
487
            $chaine = substr($chaine, 0, strlen($chaine) - 1);
488
        }
489
    }
490
    return $chaine;
491
}
492
493
/**
494
 * cleanString()
495
 *
496
 * permits to suppress all "special" characters from string
497
 */
498
function cleanString($string, $special = false)
499
{
500
    // Create temporary table for special characters escape
501
    $tabSpecialChar = array();
502
    for ($i = 0; $i <= 31; $i++) {
503
        $tabSpecialChar[] = chr($i);
504
    }
505
    array_push($tabSpecialChar, "<br />");
506
    if ($special == "1") {
507
        $tabSpecialChar = array_merge($tabSpecialChar, array("</li>", "<ul>", "<ol>"));
508
    }
509
510
    return str_replace($tabSpecialChar, "\n", $string);
511
}
512
513
function db_error_handler($params) {
514
    echo "Error: ".$params['error']."<br>\n";
515
    echo "Query: ".$params['query']."<br>\n";
516
    die; // don't want to keep going if a query broke
517
}
518
519
/**
520
 * identifyUserRights()
521
 *
522
 * @return
523
 * @param boolean $refresh
524
 */
525
function identifyUserRights($groupesVisiblesUser, $groupesInterditsUser, $isAdmin, $idFonctions, $refresh)
526
{
527
    global $server, $user, $pass, $database, $pre, $port, $encoding;
528
529
    //load ClassLoader
530
    require_once $_SESSION['settings']['cpassman_dir'].'/sources/SplClassLoader.php';
531
532
    //Connect to DB
533
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
534
    DB::$host = $server;
535
    DB::$user = $user;
536
    DB::$password = $pass;
537
    DB::$dbName = $database;
538
    DB::$port = $port;
539
    DB::$encoding = $encoding;
540
    DB::$error_handler = true;
541
    $link = mysqli_connect($server, $user, $pass, $database, $port);
542
    $link->set_charset($encoding);
543
544
    //Build tree
545
    $tree = new SplClassLoader('Tree\NestedTree', $_SESSION['settings']['cpassman_dir'].'/includes/libraries');
546
    $tree->register();
547
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
548
549
    // Check if user is ADMINISTRATOR
550
    if ($isAdmin == 1) {
551
        $groupesVisibles = array();
552
        $_SESSION['personal_folders'] = array();
553
        $_SESSION['groupes_visibles'] = array();
554
        $_SESSION['groupes_interdits'] = array();
555
        $_SESSION['personal_visible_groups'] = array();
556
        $_SESSION['read_only_folders'] = array();
557
        $_SESSION['list_restricted_folders_for_items'] = array();
558
        $_SESSION['list_folders_editable_by_role'] = array();
559
        $_SESSION['list_folders_limited'] = array();
560
        $_SESSION['groupes_visibles_list'] = "";
561
        $_SESSION['list_folders_limited'] = "";
562
        $rows = DB::query("SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i", 0);
563
        foreach ($rows as $record) {
564
            array_push($groupesVisibles, $record['id']);
565
        }
566
        $_SESSION['groupes_visibles'] = $groupesVisibles;
567
        $_SESSION['all_non_personal_folders'] = $groupesVisibles;
568
        // Exclude all PF
569
        $_SESSION['forbiden_pfs'] = array();
570
        $where = new WhereClause('and'); // create a WHERE statement of pieces joined by ANDs
571
        $where->add('personal_folder=%i', 1);
572
        if (isset($_SESSION['settings']['enable_pf_feature']) && $_SESSION['settings']['enable_pf_feature'] == 1) {
573
            $where->add('title=%s', $_SESSION['user_id']);
574
            $where->negateLast();
575
        }
576
        // Get ID of personal folder
577
        $pf = DB::queryfirstrow(
578
            "SELECT id FROM ".prefix_table("nested_tree")." WHERE title = %s",
579
            $_SESSION['user_id']
580
        );
581
        if (!empty($pf['id'])) {
582
            if (!in_array($pf['id'], $_SESSION['groupes_visibles'])) {
583
                array_push($_SESSION['groupes_visibles'], $pf['id']);
584
                array_push($_SESSION['personal_visible_groups'], $pf['id']);
585
                // get all descendants
586
                $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
587
                $tree->rebuild();
588
                $tst = $tree->getDescendants($pf['id']);
589
                foreach ($tst as $t) {
590
                    array_push($_SESSION['groupes_visibles'], $t->id);
591
                    array_push($_SESSION['personal_visible_groups'], $t->id);
592
                }
593
            }
594
        }
595
596
        // get complete list of ROLES
597
        $tmp = explode(";", $_SESSION['fonction_id']);
598
        $rows = DB::query(
599
            "SELECT * FROM ".prefix_table("roles_title")."
600
            ORDER BY title ASC");
601
        foreach ($rows as $record) {
602
            if (!empty($record['id']) && !in_array($record['id'], $tmp)) {
603
                array_push($tmp, $record['id']);
604
            }
605
        }
606
        $_SESSION['fonction_id'] = implode(";", $tmp);
607
608
        $_SESSION['groupes_visibles_list'] = implode(',', $_SESSION['groupes_visibles']);
609
        $_SESSION['is_admin'] = $isAdmin;
610
        // Check if admin has created Folders and Roles
611
        DB::query("SELECT * FROM ".prefix_table("nested_tree")."");
612
        $_SESSION['nb_folders'] = DB::count();
613
        DB::query("SELECT * FROM ".prefix_table("roles_title"));
614
        $_SESSION['nb_roles'] = DB::count();
615
    } else {
616
        // init
617
        $_SESSION['groupes_visibles'] = array();
618
        $_SESSION['personal_folders'] = array();
619
        $_SESSION['groupes_interdits'] = array();
620
        $_SESSION['personal_visible_groups'] = array();
621
        $_SESSION['read_only_folders'] = array();
622
        $groupesInterdits = array();
623
        if (!is_array($groupesInterditsUser)) {
624
            $groupesInterditsUser = explode(';', trimElement($groupesInterditsUser, ";"));
625
        }
626
        if (!empty($groupesInterditsUser) && count($groupesInterditsUser) > 0) {
627
            $groupesInterdits = $groupesInterditsUser;
628
        }
629
        $_SESSION['is_admin'] = $isAdmin;
630
        $fonctionsAssociees = explode(';', trimElement($idFonctions, ";"));
631
632
        $listAllowedFolders = $listFoldersLimited = $listFoldersEditableByRole = $listRestrictedFoldersForItems = $listReadOnlyFolders = array();
633
634
        // rechercher tous les groupes visibles en fonction des roles de l'utilisateur
635
        foreach ($fonctionsAssociees as $roleId) {
636
            if (!empty($roleId)) {
637
                // Get allowed folders for each Role
638
                $rows = DB::query("SELECT folder_id FROM ".prefix_table("roles_values")." WHERE role_id=%i", $roleId);
639
640
                if (DB::count() > 0) {
641
                    $tmp = DB::queryfirstrow("SELECT allow_pw_change FROM ".prefix_table("roles_title")." WHERE id = %i", $roleId);
642
                    foreach ($rows as $record) {
643
                        if (isset($record['folder_id']) && !in_array($record['folder_id'], $listAllowedFolders)) {
644
                            array_push($listAllowedFolders, $record['folder_id']);
645
                        }
646
                        // Check if this group is allowed to modify any pw in allowed folders
647
                        if ($tmp['allow_pw_change'] == 1 && !in_array($record['folder_id'], $listFoldersEditableByRole)) {
648
                            array_push($listFoldersEditableByRole, $record['folder_id']);
649
                        }
650
                    }
651
                    // Check for the users roles if some specific rights exist on items
652
                    $rows = DB::query(
653
                        "SELECT i.id_tree, r.item_id
654
                        FROM ".prefix_table("items")." as i
655
                        INNER JOIN ".prefix_table("restriction_to_roles")." as r ON (r.item_id=i.id)
656
                        WHERE r.role_id=%i
657
                        ORDER BY i.id_tree ASC",
658
                        $roleId
659
                    );
660
                    $x = 0;
661
                    foreach ($rows as $record) {
662
                        if (isset($record['id_tree'])) {
663
                            $listFoldersLimited[$record['id_tree']][$x] = $record['item_id'];
664
                            $x++;
665
                        }
666
                    }
667
                }
668
            }
669
        }
670
671
        // Does this user is allowed to see other items
672
        $x = 0;
673
        $rows = DB::query(
674
            "SELECT id, id_tree FROM ".prefix_table("items")."
675
            WHERE restricted_to LIKE %ss AND inactif=%s",
676
            $_SESSION['user_id'].';',
677
            '0'
678
        );
679
        foreach ($rows as $record) {
680
            $listRestrictedFoldersForItems[$record['id_tree']][$x] = $record['id'];
681
            $x++;
682
        }
683
        // => Build final lists
684
        // Clean arrays
685
        $listAllowedFolders = array_unique($listAllowedFolders);
686
        $groupesVisiblesUser = explode(';', trimElement($groupesVisiblesUser, ";"));
687
        // Add user allowed folders
688
        $allowedFoldersTmp = array_unique(
689
            array_merge($listAllowedFolders, $groupesVisiblesUser)
690
        );
691
        // Exclude from allowed folders all the specific user forbidden folders
692
        $allowedFolders = array();
693
        foreach ($allowedFoldersTmp as $id) {
694
            if (!in_array($id, $groupesInterditsUser) && !empty($id)) {
695
                array_push($allowedFolders, $id);
696
            }
697
        }
698
699
        // Clean array
700
        $listAllowedFolders = array_filter(array_unique($allowedFolders));
701
702
        // Exclude all PF
703
        $_SESSION['forbiden_pfs'] = array();
704
705
        $where = new WhereClause('and');
706
        $where->add('personal_folder=%i', 1);
707
        if (
708
            isset($_SESSION['settings']['enable_pf_feature']) &&
709
            $_SESSION['settings']['enable_pf_feature'] == 1 &&
710
            isset($_SESSION['personal_folder']) &&
711
            $_SESSION['personal_folder'] == 1
712
        ) {
713
            $where->add('title=%s', $_SESSION['user_id']);
714
            $where->negateLast();
715
        }
716
717
        $pfs = DB::query("SELECT id FROM ".prefix_table("nested_tree")." WHERE %l", $where);
718
        foreach ($pfs as $pfId) {
719
            array_push($_SESSION['forbiden_pfs'], $pfId['id']);
720
        }
721
        // Get IDs of personal folders
722
        if (
723
            isset($_SESSION['settings']['enable_pf_feature']) &&
724
            $_SESSION['settings']['enable_pf_feature'] == 1 &&
725
            isset($_SESSION['personal_folder']) &&
726
            $_SESSION['personal_folder'] == 1
727
        ) {
728
            $pf = DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")." WHERE title = %s", $_SESSION['user_id']);
729
            if (!empty($pf['id'])) {
730
                if (!in_array($pf['id'], $listAllowedFolders)) {
731
                    array_push($_SESSION['personal_folders'], $pf['id']);
732
                    // get all descendants
733
                    $ids = $tree->getDescendants($pf['id'], true, false);
734
                    foreach ($ids as $id) {
735
                        array_push($listAllowedFolders, $id->id);
736
                        array_push($_SESSION['personal_visible_groups'], $id->id);
737
                        array_push($_SESSION['personal_folders'], $id->id);
738
                    }
739
                }
740
            }
741
            // get list of readonly folders when pf is disabled.
742
            // rule - if one folder is set as W or N in one of the Role, then User has access as W
743
            foreach ($listAllowedFolders as $folderId) {
744
                if (!in_array($folderId, array_unique(array_merge($listReadOnlyFolders, $_SESSION['personal_folders'])))) {   //
745
                    DB::query(
746
                        "SELECT *
747
                        FROM ".prefix_table("roles_values")."
748
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
749
                        $folderId,
750
                        $fonctionsAssociees,
751
                        array("W", "ND", "NE", "NDNE")
752
753
                    );
754
                    if (DB::count() == 0 && !in_array($folderId, $groupesVisiblesUser)) {
755
                        array_push($listReadOnlyFolders, $folderId);
756
                    }
757
                }
758
            }
759
        } else {
760
            // get list of readonly folders when pf is disabled.
761
            // rule - if one folder is set as W in one of the Role, then User has access as W
762
            foreach ($listAllowedFolders as $folderId) {
763
                if (!in_array($folderId, $listReadOnlyFolders)) {
764
                    DB::query(
765
                        "SELECT *
766
                        FROM ".prefix_table("roles_values")."
767
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
768
                        $folderId,
769
                        $fonctionsAssociees,
770
                        array("W", "ND", "NE", "NDNE")
771
                    );
772
                    if (DB::count() == 0 && !in_array($folderId, $groupesVisiblesUser)) {
773
                        array_push($listReadOnlyFolders, $folderId);
774
                    }
775
                }
776
            }
777
        }
778
779
        // check if change proposals on User's items
780
        if (isset($_SESSION['settings']['enable_suggestion']) && $_SESSION['settings']['enable_suggestion'] == 1) {
781
            DB::query(
782
                "SELECT *
783
                FROM ".prefix_table("items_change")." AS c
784
                LEFT JOIN ".prefix_table("log_items")." AS i ON (c.item_id = i.id_item)
785
                WHERE i.action = %s AND i.id_user = %i",
786
                "at_creation",
787
                $_SESSION['user_id']
788
            );
789
            $_SESSION['nb_item_change_proposals'] = DB::count();
790
        } else {
791
            $_SESSION['nb_item_change_proposals'] = 0;
792
        }
793
794
        $_SESSION['all_non_personal_folders'] = $listAllowedFolders;
795
        $_SESSION['groupes_visibles'] = $listAllowedFolders;
796
        $_SESSION['groupes_visibles_list'] = implode(',', $listAllowedFolders);
797
        $_SESSION['personal_visible_groups_list'] = implode(',', $_SESSION['personal_visible_groups']);
798
        $_SESSION['read_only_folders'] = $listReadOnlyFolders;
799
        $_SESSION['no_access_folders'] = $groupesInterdits;
800
801
        $_SESSION['list_folders_limited'] = $listFoldersLimited;
802
        $_SESSION['list_folders_editable_by_role'] = $listFoldersEditableByRole;
803
        $_SESSION['list_restricted_folders_for_items'] = $listRestrictedFoldersForItems;
804
        // Folders and Roles numbers
805
        DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")."");
806
        $_SESSION['nb_folders'] = DB::count();
807
        DB::queryfirstrow("SELECT id FROM ".prefix_table("roles_title"));
808
        $_SESSION['nb_roles'] = DB::count();
809
    }
810
811
    // update user's timestamp
812
    DB::update(
813
        prefix_table('users'),
814
        array(
815
            'timestamp' => time()
816
        ),
817
        "id=%i",
818
        $_SESSION['user_id']
819
    );
820
}
821
822
/**
823
 * updateCacheTable()
824
 *
825
 * Update the CACHE table
826
 * @param string $action
827
 */
828
function updateCacheTable($action, $id = "")
829
{
830
    global $db, $server, $user, $pass, $database, $pre, $port, $encoding;
831
    require_once $_SESSION['settings']['cpassman_dir'].'/sources/SplClassLoader.php';
832
833
    //Connect to DB
834
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
835
    DB::$host = $server;
836
    DB::$user = $user;
837
    DB::$password = $pass;
838
    DB::$dbName = $database;
839
    DB::$port = $port;
840
    DB::$encoding = $encoding;
841
    DB::$error_handler = true;
842
    $link = mysqli_connect($server, $user, $pass, $database, $port);
843
    $link->set_charset($encoding);
844
845
    //Load Tree
846
    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
847
    $tree->register();
848
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
849
850
    // Rebuild full cache table
851
    if ($action === "reload") {
852
        // truncate table
853
        DB::query("TRUNCATE TABLE ".$pre."cache");
854
855
        // reload date
856
        $rows = DB::query(
857
            "SELECT *
858
            FROM ".$pre."items as i
859
            INNER JOIN ".$pre."log_items as l ON (l.id_item = i.id)
860
            AND l.action = %s
861
            AND i.inactif = %i",
862
            'at_creation',
863
            0
864
        );
865
        foreach ($rows as $record) {
866
            // Get all TAGS
867
            $tags = "";
868
            $itemTags = DB::query("SELECT tag FROM ".$pre."tags WHERE item_id=%i", $record['id']);
869
            foreach ($itemTags as $itemTag) {
870
                if (!empty($itemTag['tag'])) {
871
                    $tags .= $itemTag['tag']." ";
872
                }
873
            }
874
            // Get renewal period
875
            $resNT = DB::queryfirstrow("SELECT renewal_period FROM ".$pre."nested_tree WHERE id=%i", $record['id_tree']);
876
877
            // form id_tree to full foldername
878
            $folder = "";
879
            $arbo = $tree->getPath($record['id_tree'], true);
880 View Code Duplication
            foreach ($arbo as $elem) {
881
                if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
882
                    $elem->title = $_SESSION['login'];
883
                }
884
                if (empty($folder)) {
885
                    $folder = stripslashes($elem->title);
886
                } else {
887
                    $folder .= " » ".stripslashes($elem->title);
888
                }
889
            }
890
            // store data
891
            DB::insert(
892
                $pre."cache",
893
                array(
894
                    'id' => $record['id'],
895
                    'label' => $record['label'],
896
                    'description' => isset($record['description']) ? $record['description'] : "",
897
                    'url' => (isset($record['url']) && !empty($record['url'])) ? $record['url'] : "0",
898
                    'tags' => $tags,
899
                    'id_tree' => $record['id_tree'],
900
                    'perso' => $record['perso'],
901
                    'restricted_to' => (isset($record['restricted_to']) && !empty($record['restricted_to'])) ? $record['restricted_to'] : "0",
902
                    'login' => isset($record['login']) ? $record['login'] : "",
903
                    'folder' => $folder,
904
                    'author' => $record['id_user'],
905
                    'renewal_period' => isset($resNT['renewal_period']) ? $resNT['renewal_period'] : "0",
906
                    'timestamp' => $record['date']
907
                    )
908
            );
909
        }
910
        // UPDATE an item
911
    } elseif ($action === "update_value") {
912
        // get new value from db
913
        $data = DB::queryfirstrow(
914
            "SELECT label, description, id_tree, perso, restricted_to, login, url
915
            FROM ".$pre."items
916
            WHERE id=%i", $id);
917
        // Get all TAGS
918
        $tags = "";
919
        $itemTags = DB::query("SELECT tag FROM ".$pre."tags WHERE item_id=%i", $id);
920
        foreach ($itemTags as $itemTag) {
921
            if (!empty($itemTag['tag'])) {
922
                $tags .= $itemTag['tag']." ";
923
            }
924
        }
925
        // form id_tree to full foldername
926
        $folder = "";
927
        $arbo = $tree->getPath($data['id_tree'], true);
928 View Code Duplication
        foreach ($arbo as $elem) {
929
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
930
                $elem->title = $_SESSION['login'];
931
            }
932
            if (empty($folder)) {
933
                $folder = stripslashes($elem->title);
934
            } else {
935
                $folder .= " » ".stripslashes($elem->title);
936
            }
937
        }
938
        // finaly update
939
        DB::update(
940
            $pre."cache",
941
            array(
942
                'label' => $data['label'],
943
                'description' => $data['description'],
944
                'tags' => $tags,
945
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
946
                'id_tree' => $data['id_tree'],
947
                'perso' => $data['perso'],
948
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "0",
949
                'login' => isset($data['login']) ? $data['login'] : "",
950
                'folder' => $folder,
951
                'author' => $_SESSION['user_id'],
952
                ),
953
            "id = %i",
954
            $id
955
        );
956
        // ADD an item
957
    } elseif ($action === "add_value") {
958
        // get new value from db
959
        $data = DB::queryFirstRow(
960
            "SELECT i.label, i.description, i.id_tree as id_tree, i.perso, i.restricted_to, i.id, i.login, i.url, l.date
961
            FROM ".$pre."items as i
962
            INNER JOIN ".$pre."log_items as l ON (l.id_item = i.id)
963
            WHERE i.id = %i
964
            AND l.action = %s",
965
            $id,
966
            'at_creation'
967
        );
968
        // Get all TAGS
969
        $tags = "";
970
        $itemTags = DB::query("SELECT tag FROM ".$pre."tags WHERE item_id = %i", $id);
971
        foreach ($itemTags as $itemTag) {
972
            if (!empty($itemTag['tag'])) {
973
                $tags .= $itemTag['tag']." ";
974
            }
975
        }
976
        // form id_tree to full foldername
977
        $folder = "";
978
        $arbo = $tree->getPath($data['id_tree'], true);
979 View Code Duplication
        foreach ($arbo as $elem) {
980
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
981
                $elem->title = $_SESSION['login'];
982
            }
983
            if (empty($folder)) {
984
                $folder = stripslashes($elem->title);
985
            } else {
986
                $folder .= " » ".stripslashes($elem->title);
987
            }
988
        }
989
        // finaly update
990
        DB::insert(
991
            prefix_table("cache"),
992
            array(
993
                'id' => $data['id'],
994
                'label' => $data['label'],
995
                'description' => $data['description'],
996
                'tags' => (isset($tags) && !empty($tags)) ? $tags : "None",
997
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
998
                'id_tree' => $data['id_tree'],
999
                'perso' => (isset($data['perso']) && !empty($data['perso']) && $data['perso'] !== "None") ? $data['perso'] : "0",
1000
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "None",
1001
                'login' => isset($data['login']) ? $data['login'] : "",
1002
                'folder' => $folder,
1003
                'author' => $_SESSION['user_id'],
1004
                'timestamp' => $data['date']
1005
            )
1006
        );
1007
1008
        // DELETE an item
1009
    } elseif ($action === "delete_value") {
1010
        DB::delete($pre."cache", "id = %i", $id);
1011
    }
1012
}
1013
1014
/*
1015
*
1016
*/
1017
function getStatisticsData() {
1018
    DB::query(
1019
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1020
        0
1021
    );
1022
    $counter_folders = DB::count();
1023
1024
    DB::query(
1025
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1026
        1
1027
    );
1028
    $counter_folders_perso = DB::count();
1029
1030
    DB::query(
1031
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1032
        0
1033
    );
1034
    $counter_items = DB::count();
1035
1036
    DB::query(
1037
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1038
        1
1039
    );
1040
    $counter_items_perso = DB::count();
1041
1042
    DB::query(
1043
        "SELECT id FROM ".prefix_table("users").""
1044
    );
1045
    $counter_users = DB::count();
1046
1047
    DB::query(
1048
        "SELECT id FROM ".prefix_table("users")." WHERE admin = %i",
1049
        1
1050
    );
1051
    $admins = DB::count();
1052
1053
    DB::query(
1054
        "SELECT id FROM ".prefix_table("users")." WHERE gestionnaire = %i",
1055
        1
1056
    );
1057
    $managers = DB::count();
1058
1059
    DB::query(
1060
        "SELECT id FROM ".prefix_table("users")." WHERE read_only = %i",
1061
        1
1062
    );
1063
    $ro = DB::count();
1064
1065
    // list the languages
1066
    $usedLang = [];
1067
    $tp_languages = DB::query(
1068
        "SELECT name FROM ".prefix_table("languages")
1069
    );
1070
    foreach ($tp_languages as $tp_language) {
1071
        DB::query(
1072
            "SELECT * FROM ".prefix_table("users")." WHERE user_language = %s",
1073
            $tp_language['name']
1074
        );
1075
        $usedLang[$tp_language['name']] = round((DB::count() * 100 / $counter_users), 0);
1076
    }
1077
1078
    // get list of ips
1079
    $usedIp = [];
1080
    $tp_ips = DB::query(
1081
        "SELECT user_ip FROM ".prefix_table("users")
1082
    );
1083
    foreach ($tp_ips as $ip) {
1084
        if (array_key_exists($ip['user_ip'], $usedIp)) {
1085
            $usedIp[$ip['user_ip']] = $usedIp[$ip['user_ip']] + 1;
1086
        } else if (!empty($ip['user_ip']) && $ip['user_ip'] !== "none") {
1087
            $usedIp[$ip['user_ip']] = 1;
1088
        }
1089
    }
1090
1091
    return array(
1092
        "error" => "",
1093
        "stat_phpversion" => phpversion(),
1094
        "stat_folders" => $counter_folders,
1095
        "stat_folders_shared" => intval($counter_folders) - intval($counter_folders_perso),
1096
        "stat_items" => $counter_items,
1097
        "stat_items_shared" => intval($counter_items) - intval($counter_items_perso),
1098
        "stat_users" => $counter_users,
1099
        "stat_admins" => $admins,
1100
        "stat_managers" => $managers,
1101
        "stat_ro" => $ro,
1102
        "stat_kb" => $_SESSION['settings']['enable_kb'],
1103
        "stat_pf" => $_SESSION['settings']['enable_pf_feature'],
1104
        "stat_fav" => $_SESSION['settings']['enable_favourites'],
1105
        "stat_teampassversion" => $_SESSION['settings']['cpassman_version'],
1106
        "stat_ldap" => $_SESSION['settings']['ldap_mode'],
1107
        "stat_agses" => $_SESSION['settings']['agses_authentication_enabled'],
1108
        "stat_duo" => $_SESSION['settings']['duo'],
1109
        "stat_suggestion" => $_SESSION['settings']['enable_suggestion'],
1110
        "stat_api" => $_SESSION['settings']['api'],
1111
        "stat_customfields" => $_SESSION['settings']['item_extra_fields'],
1112
        "stat_syslog" => $_SESSION['settings']['syslog_enable'],
1113
        "stat_2fa" => $_SESSION['settings']['google_authentication'],
1114
        "stat_stricthttps" => $_SESSION['settings']['enable_sts'],
1115
        "stat_mysqlversion" => DB::serverVersion(),
1116
        "stat_languages" => $usedLang,
1117
        "stat_country" => $usedIp
1118
    );
1119
}
1120
1121
/**
1122
 * sendEmail()
1123
 *
1124
 * @return
1125
 */
1126
function sendEmail($subject, $textMail, $email, $textMailAlt = "")
1127
{
1128
    global $LANG;
1129
    include $_SESSION['settings']['cpassman_dir'].'/includes/config/settings.php';
1130
    //load library
1131
    $user_language = isset($_SESSION['user_language']) ? $_SESSION['user_language'] : "english";
1132
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/language/'.$user_language.'.php';
1133
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Email/Phpmailer/PHPMailerAutoload.php';
1134
1135
    // load PHPMailer
1136
    $mail = new PHPMailer();
1137
1138
    // send to user
1139
    $mail->setLanguage("en", "../includes/libraries/Email/Phpmailer/language/");
1140
    $mail->SMTPDebug = 0; //value 1 can be used to debug
1141
    $mail->Port = $_SESSION['settings']['email_port']; //COULD BE USED
1142
    $mail->CharSet = "utf-8";
1143
    $smtp_security = $_SESSION['settings']['email_security'];
1144
    if ($smtp_security == "tls" || $smtp_security == "ssl") {
1145
        $mail->SMTPSecure = $smtp_security;
1146
    }
1147
    $mail->isSmtp(); // send via SMTP
1148
    $mail->Host = $_SESSION['settings']['email_smtp_server']; // SMTP servers
1149
    $mail->SMTPAuth = $_SESSION['settings']['email_smtp_auth'] == '1' ? true : false; // turn on SMTP authentication
1150
    $mail->Username = $_SESSION['settings']['email_auth_username']; // SMTP username
1151
    $mail->Password = $_SESSION['settings']['email_auth_pwd']; // SMTP password
1152
    $mail->From = $_SESSION['settings']['email_from'];
1153
    $mail->FromName = $_SESSION['settings']['email_from_name'];
1154
    $mail->addAddress($email); //Destinataire
1155
    $mail->WordWrap = 80; // set word wrap
1156
    $mail->isHtml(true); // send as HTML
1157
    $mail->Subject = $subject;
1158
    $mail->Body = $textMail;
1159
    $mail->AltBody = $textMailAlt;
1160
    // send email
1161
    if (!$mail->send()) {
1162
        return '"error":"error_mail_not_send" , "message":"'.str_replace(array("\n", "\t", "\r"), '', $mail->ErrorInfo).'"';
1163
    } else {
1164
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1165
    }
1166
}
1167
1168
/**
1169
 * generateKey()
1170
 *
1171
 * @return
1172
 */
1173
function generateKey()
1174
{
1175
    return substr(md5(rand().rand()), 0, 15);
1176
}
1177
1178
/**
1179
 * dateToStamp()
1180
 *
1181
 * @return
1182
 */
1183
function dateToStamp($date)
1184
{
1185
    $date = date_parse_from_format($_SESSION['settings']['date_format'], $date);
1186
    if ($date['warning_count'] == 0 && $date['error_count'] == 0) {
1187
        return mktime(23, 59, 59, $date['month'], $date['day'], $date['year']);
1188
    } else {
1189
        return false;
1190
    }
1191
}
1192
1193
function isDate($date)
1194
{
1195
    return (strtotime($date) !== false);
1196
}
1197
1198
/**
1199
 * isUTF8()
1200
 *
1201
 * @return integer is the string in UTF8 format.
1202
 */
1203
1204
function isUTF8($string)
1205
{
1206
    if (is_array($string) === true) {
1207
        $string = $string['string'];
1208
    }
1209
    return preg_match(
1210
        '%^(?:
1211
        [\x09\x0A\x0D\x20-\x7E] # ASCII
1212
        | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
1213
        | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
1214
        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
1215
        | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
1216
        | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
1217
        | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
1218
        | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
1219
        )*$%xs',
1220
        $string
1221
    );
1222
}
1223
1224
/*
1225
* FUNCTION
1226
* permits to prepare data to be exchanged
1227
*/
1228
/**
1229
 * @param string $type
1230
 */
1231
function prepareExchangedData($data, $type)
1232
{
1233
    //load ClassLoader
1234
    require_once $_SESSION['settings']['cpassman_dir'].'/sources/SplClassLoader.php';
1235
    //Load AES
1236
    $aes = new SplClassLoader('Encryption\Crypt', '../includes/libraries');
1237
    $aes->register();
1238
1239
    if ($type == "encode") {
1240
        if (
1241
            isset($_SESSION['settings']['encryptClientServer'])
1242
            && $_SESSION['settings']['encryptClientServer'] == 0
1243
        ) {
1244
            return json_encode(
1245
                $data,
1246
                JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1247
            );
1248
        } else {
1249
            return Encryption\Crypt\aesctr::encrypt(
1250
                json_encode(
1251
                    $data,
1252
                    JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1253
                ),
1254
                $_SESSION['key'],
1255
                256
1256
            );
1257
        }
1258
    } elseif ($type == "decode") {
1259
        if (
1260
            isset($_SESSION['settings']['encryptClientServer'])
1261
            && $_SESSION['settings']['encryptClientServer'] == 0
1262
        ) {
1263
            return json_decode(
1264
                $data,
1265
                true
1266
            );
1267
        } else {
1268
            return json_decode(
1269
                Encryption\Crypt\aesctr::decrypt(
1270
                    $data,
1271
                    $_SESSION['key'],
1272
                    256
1273
                ),
1274
                true
1275
            );
1276
        }
1277
    }
1278
}
1279
1280
function make_thumb($src, $dest, $desired_width) {
1281
1282
    /* read the source image */
1283
    $source_image = imagecreatefrompng($src);
1284
    $width = imagesx($source_image);
1285
    $height = imagesy($source_image);
1286
1287
    /* find the "desired height" of this thumbnail, relative to the desired width  */
1288
    $desired_height = floor($height * ($desired_width / $width));
1289
1290
    /* create a new, "virtual" image */
1291
    $virtual_image = imagecreatetruecolor($desired_width, $desired_height);
1292
1293
    /* copy source image at a resized size */
1294
    imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
1295
1296
    /* create the physical thumbnail image to its destination */
1297
    imagejpeg($virtual_image, $dest);
1298
}
1299
1300
/*
1301
** check table prefix in SQL query
1302
*/
1303
/**
1304
 * @param string $table
1305
 */
1306
function prefix_table($table)
1307
{
1308
    global $pre;
1309
    $safeTable = htmlspecialchars($pre.$table);
1310
    if (!empty($safeTable)) {
1311
        // sanitize string
1312
        return $safeTable;
1313
    } else {
1314
        // stop error no table
1315
        return "table_not_exists";
1316
    }
1317
}
1318
1319
/*
1320
 * Creates a KEY using PasswordLib
1321
 */
1322
function GenerateCryptKey($size = "", $secure = false, $numerals = false, $capitalize = false, $ambiguous = false, $symbols = false)
1323
{
1324
    // load library
1325
    $pwgen = new SplClassLoader('Encryption\PwGen', '../includes/libraries');
1326
    $pwgen->register();
1327
    $pwgen = new Encryption\PwGen\pwgen();
1328
1329
    // init
1330
    if (!empty($size)) {
1331
        $pwgen->setLength($size);
1332
    }
1333
    if (!empty($secure)) {
1334
        $pwgen->setSecure($secure);
1335
    }
1336
    if (!empty($numerals)) {
1337
        $pwgen->setNumerals($numerals);
1338
    }
1339
    if (!empty($capitalize)) {
1340
        $pwgen->setCapitalize($capitalize);
1341
    }
1342
    if (!empty($ambiguous)) {
1343
        $pwgen->setAmbiguous($ambiguous);
1344
    }
1345
    if (!empty($symbols)) {
1346
        $pwgen->setSymbols($symbols);
1347
    }
1348
1349
    // generate and send back
1350
    return $pwgen->generate();
1351
}
1352
1353
/*
1354
* Send sysLOG message
1355
*/
1356
/**
1357
 * @param string $message
1358
 * @param string $host
1359
 */
1360
function send_syslog($message, $component = "teampass", $host, $port)
1361
{
1362
    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1363
        //$syslog_message = "<123>" . date('M d H:i:s ') . " " .$host . " " . $component . ": " . $message;
1364
    $syslog_message = "<123>".date('M d H:i:s ').$component.": ".$message;
1365
        socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, $host, $port);
1366
    socket_close($sock);
1367
}
1368
1369
1370
1371
/**
1372
 * logEvents()
1373
 *
1374
 * permits to log events into DB
1375
 * @param string $type
1376
 * @param string $label
1377
 * @param string $field_1
1378
 */
1379
function logEvents($type, $label, $who, $login = "", $field_1 = NULL)
1380
{
1381
    global $server, $user, $pass, $database, $pre, $port, $encoding;
1382
1383
    if (empty($who)) {
1384
        $who = get_client_ip_server();
1385
    }
1386
1387
    // include librairies & connect to DB
1388
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1389
    DB::$host = $server;
1390
    DB::$user = $user;
1391
    DB::$password = $pass;
1392
    DB::$dbName = $database;
1393
    DB::$port = $port;
1394
    DB::$encoding = $encoding;
1395
    DB::$error_handler = true;
1396
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1397
    $link->set_charset($encoding);
1398
1399
    DB::insert(
1400
        prefix_table("log_system"),
1401
        array(
1402
            'type' => $type,
1403
            'date' => time(),
1404
            'label' => $label,
1405
            'qui' => $who,
1406
            'field_1' => $field_1 === null ? "" : $field_1
1407
        )
1408
    );
1409
    if (isset($_SESSION['settings']['syslog_enable']) && $_SESSION['settings']['syslog_enable'] == 1) {
1410
        if ($type == "user_mngt") {
1411
            send_syslog("The User ".$login." perform the acction off ".$label." to the user ".$field_1." - ".$type, "teampass", $_SESSION['settings']['syslog_host'], $_SESSION['settings']['syslog_port']);
1412
        } else {
1413
            send_syslog("The User ".$login." perform the acction off ".$label." - ".$type, "teampass", $_SESSION['settings']['syslog_host'], $_SESSION['settings']['syslog_port']);
1414
        }
1415
    }
1416
}
1417
1418
/**
1419
 * @param string $item
1420
 * @param string $action
1421
 */
1422
function logItems($id, $item, $id_user, $action, $login = "", $raison = NULL, $raison_iv = NULL, $encryption_type = "")
1423
{
1424
    global $server, $user, $pass, $database, $pre, $port, $encoding;
1425
    // include librairies & connect to DB
1426
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1427
    DB::$host = $server;
1428
    DB::$user = $user;
1429
    DB::$password = $pass;
1430
    DB::$dbName = $database;
1431
    DB::$port = $port;
1432
    DB::$encoding = $encoding;
1433
    DB::$error_handler = true;
1434
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1435
    $link->set_charset($encoding);
1436
    DB::insert(
1437
        prefix_table(
1438
            "log_items"),
1439
            array(
1440
                'id_item' => $id,
1441
                'date' => time(),
1442
                'id_user' => $id_user,
1443
                'action' => $action,
1444
                'raison' => $raison,
1445
                'raison_iv' => $raison_iv,
1446
                'encryption_type' => $encryption_type
1447
            )
1448
        );
1449
        if (isset($_SESSION['settings']['syslog_enable']) && $_SESSION['settings']['syslog_enable'] == 1) {
1450
                send_syslog("The Item ".$item." was ".$action." by ".$login." ".$raison, "teampass", $_SESSION['settings']['syslog_host'], $_SESSION['settings']['syslog_port']);
1451
        }
1452
}
1453
1454
/*
1455
* Function to get the client ip address
1456
 */
1457
function get_client_ip_server() {
1458
    if (getenv('HTTP_CLIENT_IP')) {
1459
            $ipaddress = getenv('HTTP_CLIENT_IP');
1460
    } else if (getenv('HTTP_X_FORWARDED_FOR')) {
1461
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
1462
    } else if (getenv('HTTP_X_FORWARDED')) {
1463
            $ipaddress = getenv('HTTP_X_FORWARDED');
1464
    } else if (getenv('HTTP_FORWARDED_FOR')) {
1465
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
1466
    } else if (getenv('HTTP_FORWARDED')) {
1467
            $ipaddress = getenv('HTTP_FORWARDED');
1468
    } else if (getenv('REMOTE_ADDR')) {
1469
            $ipaddress = getenv('REMOTE_ADDR');
1470
    } else {
1471
            $ipaddress = 'UNKNOWN';
1472
    }
1473
1474
    return $ipaddress;
1475
}
1476
1477
/**
1478
 * Escape all HTML, JavaScript, and CSS
1479
 *
1480
 * @param string $input The input string
1481
 * @param string $encoding Which character encoding are we using?
1482
 * @return string
1483
 */
1484
function noHTML($input, $encoding = 'UTF-8')
1485
{
1486
    return htmlspecialchars($input, ENT_QUOTES | ENT_XHTML, $encoding, false);
1487
}
1488
1489
/**
1490
 * handleConfigFile()
1491
 *
1492
 * permits to handle the Teampass config file
1493
 * $action accepts "rebuild" and "update"
1494
 */
1495
function handleConfigFile($action, $field = null, $value = null)
1496
{
1497
    global $server, $user, $pass, $database, $pre, $port, $encoding;
1498
    $tp_config_file = "../includes/config/tp.config.php";
1499
1500
    // Load AntiXSS
1501
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXss.php';
1502
    $antiXss = new protect\AntiXSS\AntiXSS();
1503
    
1504
    // include librairies & connect to DB
1505
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1506
    DB::$host = $server;
1507
    DB::$user = $user;
1508
    DB::$password = $pass;
1509
    DB::$dbName = $database;
1510
    DB::$port = $port;
1511
    DB::$encoding = $encoding;
1512
    DB::$error_handler = true;
1513
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1514
    $link->set_charset($encoding);
1515
1516
    if (!file_exists($tp_config_file) || $action == "rebuild") {
1517
        // perform a copy
1518
        if (file_exists($tp_config_file)) {
1519
            if (!copy($tp_config_file, $tp_config_file.'.'.date("Y_m_d_His", time()))) {
1520
                return "ERROR: Could not copy file '".$tp_config_file."'";
1521
            }
1522
        }
1523
1524
        // regenerate
1525
        $data = array();
1526
        $data[0] = "<?php\n";
1527
        $data[1] = "global \$SETTINGS;\n";
1528
        $data[2] = "\$SETTINGS = array (\n";
1529
        $rows = DB::query(
1530
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s",
1531
            "admin"
1532
        );
1533
        foreach ($rows as $record) {
1534
            array_push($data, "    '".$record['intitule']."' => '".$record['valeur']."',\n");
1535
        }
1536
        array_push($data, ");");
1537
        $data = array_unique($data);
1538
    } else if ($action == "update" && !empty($field)) {
1539
        $data = file($tp_config_file);
1540
        $x = 0;
1541
        $bFound = false;
1542
        foreach ($data as $line) {
1543
            if (stristr($line, ");")) {
1544
                break;
1545
            }
1546
1547
            // 
1548
            if (stristr($line, "'".$field."' => '")) {
1549
                $data[$x] = "    '".$field."' => '".$antiXss->clean($value)."',\n";
0 ignored issues
show
Bug introduced by
The method clean() does not seem to exist on object<protect\AntiXSS\AntiXSS>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1550
                $bFound = true;
1551
                break;
1552
            }
1553
            $x++;
1554
        }
1555
        if ($bFound === false) {
1556
            $data[($x - 1)] = "    '".$field."' => '".$antiXss->clean($value)."',\n";
0 ignored issues
show
Bug introduced by
The method clean() does not seem to exist on object<protect\AntiXSS\AntiXSS>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1557
        }
1558
    }
1559
1560
    // update file
1561
    file_put_contents($tp_config_file, implode('', isset($data) ? $data : array()));
0 ignored issues
show
Security File Manipulation introduced by
implode('', isset($data) ? $data : array()) can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in sources/admin.queries.php on line 1755
  2. Data is decoded by json_decode()
    in vendor/sources/main.functions.php on line 1264
  3. $dataReceived is assigned
    in sources/admin.queries.php on line 1755
  4. $dataReceived['field'] is passed to handleConfigFile()
    in sources/admin.queries.php on line 1857
  5. $data is assigned
    in sources/main.functions.php on line 1556
  6. isset($data) ? $data : array() is passed through implode()
    in sources/main.functions.php on line 1561

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...
1562
1563
    return true;
1564
}
1565
1566
/*
1567
** Permits to replace &#92; to permit correct display
1568
*/
1569
/**
1570
 * @param string $input
1571
 */
1572
function handleBackslash($input)
1573
{
1574
    return str_replace("&amp;#92;", "&#92;", $input);
1575
}
1576
1577
/*
1578
** Permits to loas settings
1579
*/
1580
function loadSettings()
1581
{
1582
    /* LOAD CPASSMAN SETTINGS */
1583 View Code Duplication
    if (!isset($_SESSION['settings']['loaded']) || $_SESSION['settings']['loaded'] != 1) {
1584
        $_SESSION['settings']['duplicate_folder'] = 0; //by default, this is set to 0;
1585
        $_SESSION['settings']['duplicate_item'] = 0; //by default, this is set to 0;
1586
        $_SESSION['settings']['number_of_used_pw'] = 5; //by default, this value is set to 5;
1587
        $settings = array();
1588
1589
        $rows = DB::query("SELECT * FROM ".prefix_table("misc")." WHERE type=%s_type OR type=%s_type2",
1590
            array(
1591
                'type' => "admin",
1592
                'type2' => "settings"
1593
            )
1594
        );
1595
        foreach ($rows as $record) {
1596
            if ($record['type'] == 'admin') {
1597
                $_SESSION['settings'][$record['intitule']] = $record['valeur'];
1598
            } else {
1599
                $settings[$record['intitule']] = $record['valeur'];
1600
            }
1601
        }
1602
        $_SESSION['settings']['loaded'] = 1;
1603
        $_SESSION['settings']['default_session_expiration_time'] = 5;
1604
    }
1605
}
1606
1607
/*
1608
** check if folder has custom fields.
1609
** Ensure that target one also has same custom fields
1610
*/
1611
function checkCFconsistency($source_id, $target_id) {
1612
    $source_cf = array();
1613
    $rows = DB::QUERY(
1614
        "SELECT id_category
1615
        FROM ".prefix_table("categories_folders")."
1616
        WHERE id_folder = %i",
1617
        $source_id
1618
    );
1619
    foreach ($rows as $record) {
1620
        array_push($source_cf, $record['id_category']);
1621
    }
1622
1623
    $target_cf = array();
1624
    $rows = DB::QUERY(
1625
        "SELECT id_category
1626
        FROM ".prefix_table("categories_folders")."
1627
        WHERE id_folder = %i",
1628
        $target_id
1629
    );
1630
    foreach ($rows as $record) {
1631
        array_push($target_cf, $record['id_category']);
1632
    }
1633
1634
    $cf_diff = array_diff($source_cf, $target_cf);
1635
    if (count($cf_diff) > 0) {
1636
        return false;
1637
    }
1638
1639
    return true;
1640
}
1641
1642
/*
1643
*
1644
*/
1645
function encrypt_or_decrypt_file($filename_to_rework, $filename_status) {
1646
    global $server, $user, $pass, $database, $pre, $port, $encoding;
1647
1648
    // include librairies & connect to DB
1649
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1650
    DB::$host = $server;
1651
    DB::$user = $user;
1652
    DB::$password = $pass;
1653
    DB::$dbName = $database;
1654
    DB::$port = $port;
1655
    DB::$encoding = $encoding;
1656
    DB::$error_handler = true;
1657
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1658
    $link->set_charset($encoding);
1659
1660
    // load PhpEncryption library
1661
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Crypto.php';
1662
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Encoding.php';
1663
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'DerivedKeys.php';
1664
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Key.php';
1665
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyOrPassword.php';
1666
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'File.php';
1667
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'RuntimeTests.php';
1668
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyProtectedByPassword.php';
1669
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Core.php';
1670
1671
    // get KEY
1672
    $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1673
1674
    if (isset($_SESSION['settings']['enable_attachment_encryption']) && $_SESSION['settings']['enable_attachment_encryption'] === "1" && isset($filename_status) && ($filename_status === "clear" || $filename_status === "0")) {
1675
        // file needs to be encrypted
1676 View Code Duplication
        if (file_exists($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework)) {
1677
            // make a copy of file
1678
            if (!copy(
1679
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1680
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1681
            )) {
1682
                exit;
1683
            } else {
1684
                // do a bck
1685
                copy(
1686
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1687
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1688
                );
1689
            }
1690
1691
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework);
1692
1693
            // Now encrypt the file with saltkey
1694
            $err = '';
1695
            try {
1696
                \Defuse\Crypto\File::encryptFile(
1697
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1698
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1699
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1700
                );
1701
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1702
                $err = "An attack! Either the wrong key was loaded, or the ciphertext has changed since it was created either corrupted in the database or intentionally modified by someone trying to carry out an attack.";
1703
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1704
                $err = $ex;
1705
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1706
                $err = $ex;
1707
            }
1708
            if (empty($err) === false) {
1709
                echo $err;
1710
            }
1711
1712
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1713
1714
            // update table
1715
            DB::update(
1716
                prefix_table('files'),
1717
                array(
1718
                    'status' => 'encrypted'
1719
                    ),
1720
                "id=%i",
1721
                substr($_POST['uri'], 1)
1722
            );
1723
        }
1724
    } elseif (isset($_SESSION['settings']['enable_attachment_encryption']) && $_SESSION['settings']['enable_attachment_encryption'] === "0" && isset($filename_status) && $filename_status === "encrypted") {
1725
        // file needs to be decrypted
1726 View Code Duplication
        if (file_exists($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework)) {
1727
            // make a copy of file
1728
            if (!copy(
1729
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1730
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1731
            )) {
1732
                exit;
1733
            } else {
1734
                // do a bck
1735
                copy(
1736
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1737
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1738
                );
1739
            }
1740
1741
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework);
1742
1743
            // Now encrypt the file with saltkey
1744
            $err = '';
1745
            try {
1746
                \Defuse\Crypto\File::decryptFile(
1747
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1748
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1749
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1750
                );
1751
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1752
                $err = "An attack! Either the wrong key was loaded, or the ciphertext has changed since it was created either corrupted in the database or intentionally modified by someone trying to carry out an attack.";
1753
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1754
                $err = $ex;
1755
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1756
                $err = $ex;
1757
            }
1758
            if (empty($err) === false) {
1759
                echo $err;
1760
            }
1761
1762
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1763
1764
            // update table
1765
            DB::update(
1766
                prefix_table('files'),
1767
                array(
1768
                    'status' => 'clear'
1769
                    ),
1770
                "id=%i",
1771
                substr($_POST['uri'], 1)
1772
            );
1773
        }
1774
    }
1775
}
1776
1777
/**
1778
 * [prepareFileWithDefuse description]
1779
 * @param  [type] $type        [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1780
 * @param  [type] $source_file [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1781
 * @param  [type] $target_file [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1782
 * @return [type]              [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1783
 */
1784
function prepareFileWithDefuse($type, $source_file, $target_file, $password = '') {
1785
    // Load AntiXSS
1786
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXss.php';
1787
    $antiXss = new protect\AntiXSS\AntiXSS();
1788
    
1789
    // Sanitize
1790
    $source_file = $antiXss->clean($source_file);
0 ignored issues
show
Bug introduced by
The method clean() does not seem to exist on object<protect\AntiXSS\AntiXSS>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1791
    $target_file = $antiXss->clean($target_file);
0 ignored issues
show
Bug introduced by
The method clean() does not seem to exist on object<protect\AntiXSS\AntiXSS>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1792
1793
    // load PhpEncryption library
1794
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Crypto.php';
1795
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Encoding.php';
1796
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'DerivedKeys.php';
1797
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Key.php';
1798
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyOrPassword.php';
1799
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'File.php';
1800
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'RuntimeTests.php';
1801
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyProtectedByPassword.php';
1802
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Core.php';
1803
1804
    if (empty($password) === true) {
1805
        /*
1806
        File encryption/decryption is done with the SALTKEY
1807
         */
1808
1809
        // get KEY
1810
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1811
1812
        // Now perform action on the file
1813
        $err = '';
1814 View Code Duplication
        if ($type === 'decrypt') {
1815
            try {
1816
                \Defuse\Crypto\File::decryptFile(
1817
                    $source_file,
1818
                    $target_file,
1819
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1820
                );
1821
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1822
                $err = "decryption_not_possible";
1823
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1824
                $err = $ex;
1825
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1826
                $err = $ex;
1827
            }
1828
        } else if ($type === 'encrypt') {
1829
            try {
1830
                \Defuse\Crypto\File::encryptFile(
1831
                    $source_file,
1832
                    $target_file,
1833
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1834
                );
1835
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1836
                $err = "encryption_not_possible";
1837
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1838
                $err = $ex;
1839
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1840
                $err = $ex;
1841
            }
1842
        }
1843
1844
    } else {
1845
        /*
1846
        File encryption/decryption is done with special password and not the SALTKEY
1847
         */
1848
1849
        $err = '';
1850 View Code Duplication
        if ($type === 'decrypt') {
1851
            try {
1852
                \Defuse\Crypto\File::decryptFileWithPassword(
1853
                    $source_file,
1854
                    $target_file,
1855
                    $password
1856
                );
1857
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1858
                $err = "wrong_key";
1859
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1860
                $err = $ex;
1861
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1862
                $err = $ex;
1863
            }
1864
        } else if ($type === 'encrypt') {
1865
            try {
1866
                \Defuse\Crypto\File::encryptFileWithPassword(
1867
                    $source_file,
1868
                    $target_file,
1869
                    $password
1870
                );
1871
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1872
                $err = "wrong_key";
1873
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1874
                $err = $ex;
1875
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1876
                $err = $ex;
1877
            }
1878
        }
1879
    }
1880
1881
    // return error
1882
    if (empty($err) === false) {
1883
        return $err;
1884
    } else {
1885
        return true;
1886
    }
1887
}
1888
1889
/*
1890
* NOT TO BE USED
1891
*/
1892
function debugTeampass($text) {
1893
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
1894
    fputs($debugFile, $text);
1895
    fclose($debugFile);
1896
}
1897
1898
1899
/**
1900
 * DELETE the file with expected command depending on server type
1901
 * @param  [type] $file [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1902
 * @return [type]       [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1903
 */
1904
function fileDelete($file) {
1905
    // Load AntiXSS
1906
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXss.php';
1907
    $antiXss = new protect\AntiXSS\AntiXSS();
1908
1909
    $file = $antiXss->clean($file);
0 ignored issues
show
Bug introduced by
The method clean() does not seem to exist on object<protect\AntiXSS\AntiXSS>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1910
    if (is_file($file)) {
1911
        unlink($file);
0 ignored issues
show
Security File Manipulation introduced by
$file can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

4 paths for user data to reach this point

  1. Path: Read from $_POST, and $_POST['option'] is passed through explode(), and $dataPost is assigned in sources/admin.queries.php on line 359
  1. Read from $_POST, and $_POST['option'] is passed through explode(), and $dataPost is assigned
    in sources/admin.queries.php on line 359
  2. $dataPost[0] is escaped by htmlspecialchars() for html (no single-quotes) context(s), and $file is assigned
    in sources/admin.queries.php on line 360
  3. $file is assigned
    in sources/admin.queries.php on line 381
  4. $file is passed to fileDelete()
    in sources/admin.queries.php on line 401
  5. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 1187
  6. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4055
  7. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4006
  8. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3646
  9. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3600
  10. $file is assigned
    in sources/main.functions.php on line 1909
  2. Path: Read from $_POST, and $_POST['title'] is passed through substr(), and $extension is assigned in sources/items.queries.php on line 3377
  1. Read from $_POST, and $_POST['title'] is passed through substr(), and $extension is assigned
    in sources/items.queries.php on line 3377
  2. $_SESSION['settings']['path_to_upload_folder'] . '/' . $image_code . '_delete.' . $extension is passed to fileDelete()
    in sources/items.queries.php on line 3387
  3. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 1187
  4. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4055
  5. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4006
  6. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3646
  7. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3600
  8. $file is assigned
    in sources/main.functions.php on line 1909
  3. Path: Read from $_POST, and $_POST['filename'] is passed to fileDelete() in sources/main.queries.php on line 1131
  1. Read from $_POST, and $_POST['filename'] is passed to fileDelete()
    in sources/main.queries.php on line 1131
  2. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 1187
  3. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4055
  4. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4006
  5. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3646
  6. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3600
  7. $file is assigned
    in sources/main.functions.php on line 1909
  4. Path: Read from $_POST in sources/items.queries.php on line 3430
  1. Read from $_POST
    in sources/items.queries.php on line 3430
  2. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 1187
  3. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4055
  4. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4006
  5. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3646
  6. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3600
  7. $_SESSION['settings']['path_to_upload_folder'] . '/' . $antiXss->clean($result['file'] . $_POST['file_suffix']) is passed to fileDelete()
    in sources/items.queries.php on line 3430
  8. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 1187
  9. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4055
  10. Data is passed through preg_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 4006
  11. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3646
  12. Data is passed through str_replace()
    in vendor/includes/libraries/protect/AntiXSS/UTF8.php on line 3600
  13. $file is assigned
    in sources/main.functions.php on line 1909

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...
1912
    }
1913
}
1914
1915
/*
1916
* Permits to extract the file extension
1917
*/
1918
function getFileExtension($f)
1919
{
1920
    if (strpos($f, '.') === false) {
1921
        return $f;
1922
    }
1923
1924
    return substr($f, strrpos($f, '.') + 1);
1925
}
1926
1927
/**
1928
 * @param  [type]
1929
 * @param  [type]
1930
 * @return [type]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1931
 */
1932
function array_map_r( $func, $arr )
1933
{
1934
    $newArr = array();
1935
1936
    foreach( $arr as $key => $value )
1937
    {
1938
        $newArr[ $key ] = ( is_array( $value ) ? array_map_r( $func, $value ) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value ) ) );
1939
    }
1940
1941
    return $newArr;
1942
}