Completed
Push — development ( c4d33f...5f74fd )
by Nils
09:26
created

main.functions.php ➔ bCrypt()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1601
1602
    // include librairies & connect to DB
1603
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1604
    $pass = defuse_return_decrypted($pass);
1605
    DB::$host = $server;
1606
    DB::$user = $user;
1607
    DB::$password = $pass;
1608
    DB::$dbName = $database;
1609
    DB::$port = $port;
1610
    DB::$encoding = $encoding;
1611
    DB::$error_handler = true;
1612
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1613
    $link->set_charset($encoding);
1614
1615
    if (!file_exists($tp_config_file) || $action == "rebuild") {
1616
        // perform a copy
1617
        if (file_exists($tp_config_file)) {
1618
            if (!copy($tp_config_file, $tp_config_file.'.'.date("Y_m_d_His", time()))) {
1619
                return "ERROR: Could not copy file '".$tp_config_file."'";
1620
            }
1621
        }
1622
1623
        // regenerate
1624
        $data = array();
1625
        $data[0] = "<?php\n";
1626
        $data[1] = "global \$SETTINGS;\n";
1627
        $data[2] = "\$SETTINGS = array (\n";
1628
        $rows = DB::query(
1629
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s",
1630
            "admin"
1631
        );
1632
        foreach ($rows as $record) {
1633
            array_push($data, "    '".$record['intitule']."' => '".$record['valeur']."',\n");
1634
        }
1635
        array_push($data, ");\n");
1636
        $data = array_unique($data);
1637
    } elseif ($action == "update" && empty($field) === false) {
1638
        $data = file($tp_config_file);
1639
        $inc = 0;
1640
        $bFound = false;
1641
        foreach ($data as $line) {
1642
            if (stristr($line, ");")) {
1643
                break;
1644
            }
1645
1646
            //
1647
            if (stristr($line, "'".$field."' => '")) {
1648
                $data[$inc] = "    '".$field."' => '".filter_var($value, FILTER_SANITIZE_STRING)."',\n";
1649
                $bFound = true;
1650
                break;
1651
            }
1652
            $inc++;
1653
        }
1654
        if ($bFound === false) {
1655
            $data[($inc)] = "    '".$field."' => '".filter_var($value, FILTER_SANITIZE_STRING)."',\n);\n";
1656
        }
1657
    }
1658
1659
    // update file
1660
    file_put_contents($tp_config_file, implode('', isset($data) ? $data : array()));
1661
1662
    return true;
1663
}
1664
1665
/*
1666
** Permits to replace &#92; to permit correct display
1667
*/
1668
/**
1669
 * @param string $input
1670
 */
1671
function handleBackslash($input)
1672
{
1673
    return str_replace("&amp;#92;", "&#92;", $input);
1674
}
1675
1676
/*
1677
** Permits to loas settings
1678
*/
1679
function loadSettings()
1680
{
1681
    global $SETTINGS;
1682
1683
    /* LOAD CPASSMAN SETTINGS */
1684
    if (!isset($SETTINGS['loaded']) || $SETTINGS['loaded'] != 1) {
1685
        $SETTINGS['duplicate_folder'] = 0; //by default, this is set to 0;
1686
        $SETTINGS['duplicate_item'] = 0; //by default, this is set to 0;
1687
        $SETTINGS['number_of_used_pw'] = 5; //by default, this value is set to 5;
1688
        $settings = array();
1689
1690
        $rows = DB::query(
1691
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s_type OR type=%s_type2",
1692
            array(
1693
                'type' => "admin",
1694
                'type2' => "settings"
1695
            )
1696
        );
1697
        foreach ($rows as $record) {
1698
            if ($record['type'] == 'admin') {
1699
                $SETTINGS[$record['intitule']] = $record['valeur'];
1700
            } else {
1701
                $settings[$record['intitule']] = $record['valeur'];
1702
            }
1703
        }
1704
        $SETTINGS['loaded'] = 1;
1705
        $SETTINGS['default_session_expiration_time'] = 5;
1706
    }
1707
}
1708
1709
/*
1710
** check if folder has custom fields.
1711
** Ensure that target one also has same custom fields
1712
*/
1713
function checkCFconsistency($source_id, $target_id)
1714
{
1715
    $source_cf = array();
1716
    $rows = DB::QUERY(
1717
        "SELECT id_category
1718
        FROM ".prefix_table("categories_folders")."
1719
        WHERE id_folder = %i",
1720
        $source_id
1721
    );
1722
    foreach ($rows as $record) {
1723
        array_push($source_cf, $record['id_category']);
1724
    }
1725
1726
    $target_cf = array();
1727
    $rows = DB::QUERY(
1728
        "SELECT id_category
1729
        FROM ".prefix_table("categories_folders")."
1730
        WHERE id_folder = %i",
1731
        $target_id
1732
    );
1733
    foreach ($rows as $record) {
1734
        array_push($target_cf, $record['id_category']);
1735
    }
1736
1737
    $cf_diff = array_diff($source_cf, $target_cf);
1738
    if (count($cf_diff) > 0) {
1739
        return false;
1740
    }
1741
1742
    return true;
1743
}
1744
1745
/*
1746
*
1747
*/
1748
function encrypt_or_decrypt_file($filename_to_rework, $filename_status)
1749
{
1750
    global $server, $user, $pass, $database, $port, $encoding;
1751
    global $SETTINGS;
1752
1753
    // Include librairies & connect to DB
1754
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1755
    $pass = defuse_return_decrypted($pass);
1756
    DB::$host = $server;
1757
    DB::$user = $user;
1758
    DB::$password = $pass;
1759
    DB::$dbName = $database;
1760
    DB::$port = $port;
1761
    DB::$encoding = $encoding;
1762
    DB::$error_handler = true;
1763
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1764
    $link->set_charset($encoding);
1765
1766
    // Get file info in DB
1767
    $fileInfo = DB::queryfirstrow(
1768
        "SELECT id FROM ".prefix_table("files")." WHERE file = %s",
1769
        filter_var($filename_to_rework, FILTER_SANITIZE_STRING)
1770
    );
1771
    if (empty($fileInfo['id']) === false) {
1772
        // Load PhpEncryption library
1773
        $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1774
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1775
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1776
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1777
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1778
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1779
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1780
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1781
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1782
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1783
1784
        // Get KEY
1785
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1786
1787
        if (isset($SETTINGS['enable_attachment_encryption'])
1788
            && $SETTINGS['enable_attachment_encryption'] === "1" &&
1789
            isset($filename_status)
1790
            && ($filename_status === "clear"
1791
                || $filename_status === "0")
1792
        ) {
1793
            // File needs to be encrypted
1794 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1795
                // Make a copy of file
1796
                if (!copy(
1797
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1798
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1799
                )) {
1800
                    exit;
1801
                } else {
1802
                    // Do a bck
1803
                    copy(
1804
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1805
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1806
                    );
1807
                }
1808
1809
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1810
1811
                // Now encrypt the file with saltkey
1812
                $err = '';
1813
                try {
1814
                    \Defuse\Crypto\File::encryptFile(
1815
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1816
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1817
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1818
                    );
1819
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1820
                    $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.";
1821
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1822
                    $err = $ex;
1823
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1824
                    $err = $ex;
1825
                }
1826
                if (empty($err) === false) {
1827
                    echo $err;
1828
                }
1829
1830
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1831
1832
                // update table
1833
                DB::update(
1834
                    prefix_table('files'),
1835
                    array(
1836
                        'status' => 'encrypted'
1837
                        ),
1838
                    "id = %i",
1839
                    $fileInfo['id']
1840
                );
1841
            }
1842
        } elseif (isset($SETTINGS['enable_attachment_encryption'])
1843
            && $SETTINGS['enable_attachment_encryption'] === "0"
1844
            && isset($filename_status)
1845
            && $filename_status === "encrypted"
1846
        ) {
1847
            // file needs to be decrypted
1848 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1849
                // make a copy of file
1850
                if (!copy(
1851
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1852
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1853
                )) {
1854
                    exit;
1855
                } else {
1856
                    // do a bck
1857
                    copy(
1858
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1859
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1860
                    );
1861
                }
1862
1863
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1864
1865
                // Now encrypt the file with saltkey
1866
                $err = '';
1867
                try {
1868
                    \Defuse\Crypto\File::decryptFile(
1869
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1870
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1871
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1872
                    );
1873
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1874
                    $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.";
1875
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1876
                    $err = $ex;
1877
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1878
                    $err = $ex;
1879
                }
1880
                if (empty($err) === false) {
1881
                    echo $err;
1882
                }
1883
1884
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1885
1886
                // update table
1887
                DB::update(
1888
                    prefix_table('files'),
1889
                    array(
1890
                        'status' => 'clear'
1891
                        ),
1892
                    "id = %i",
1893
                    $fileInfo['id']
1894
                );
1895
            }
1896
        }
1897
    }
1898
1899
    // Exit
1900
    return false;
1901
}
1902
1903
/**
1904
 * Will encrypte/decrypt a fil eusing Defuse
1905
 * @param  string $type        can be either encrypt or decrypt
1906
 * @param  string $source_file path to source file
1907
 * @param  string $target_file path to target file
1908
 * @return string              'true' is success or error message
1909
 */
1910
function prepareFileWithDefuse($type, $source_file, $target_file, $password = '')
1911
{
1912
    global $SETTINGS;
1913
1914
    // Load AntiXSS
1915
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1916
    $antiXss = new protect\AntiXSS\AntiXSS();
1917
1918
    // Protect against bad inputs
1919
    if (is_array($source_file) ||is_array($target_file)) {
1920
        return 'error_cannot_be_array';
1921
    }
1922
1923
    // Sanitize
1924
    $source_file = $antiXss->xss_clean($source_file);
1925
    $target_file = $antiXss->xss_clean($target_file);
1926
1927
    // load PhpEncryption library
1928
    $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1929
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1930
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1931
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1932
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1933
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1934
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1935
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1936
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1937
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1938
1939
    if (empty($password) === true) {
1940
    /*
1941
    File encryption/decryption is done with the SALTKEY
1942
     */
1943
1944
        // get KEY
1945
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1946
1947
        // Now perform action on the file
1948
        $err = '';
1949 View Code Duplication
        if ($type === 'decrypt') {
1950
            try {
1951
                \Defuse\Crypto\File::decryptFile(
1952
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1924 can also be of type array; however, Defuse\Crypto\File::decryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1953
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1925 can also be of type array; however, Defuse\Crypto\File::decryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1954
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1955
                );
1956
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1957
                $err = "decryption_not_possible";
1958
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1959
                $err = $ex;
1960
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1961
                $err = $ex;
1962
            }
1963
        } elseif ($type === 'encrypt') {
1964
            try {
1965
                \Defuse\Crypto\File::encryptFile(
1966
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1924 can also be of type array; however, Defuse\Crypto\File::encryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1967
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1925 can also be of type array; however, Defuse\Crypto\File::encryptFile() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1968
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1969
                );
1970
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1971
                $err = "encryption_not_possible";
1972
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1973
                $err = $ex;
1974
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1975
                $err = $ex;
1976
            }
1977
        }
1978
    } else {
1979
    /*
1980
    File encryption/decryption is done with special password and not the SALTKEY
1981
     */
1982
1983
        $err = '';
1984 View Code Duplication
        if ($type === 'decrypt') {
1985
            try {
1986
                \Defuse\Crypto\File::decryptFileWithPassword(
1987
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1924 can also be of type array; however, Defuse\Crypto\File::decryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1988
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1925 can also be of type array; however, Defuse\Crypto\File::decryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1989
                    $password
1990
                );
1991
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1992
                $err = "wrong_key";
1993
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1994
                $err = $ex;
1995
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1996
                $err = $ex;
1997
            }
1998
        } elseif ($type === 'encrypt') {
1999
            try {
2000
                \Defuse\Crypto\File::encryptFileWithPassword(
2001
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1924 can also be of type array; however, Defuse\Crypto\File::encryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2002
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1925 can also be of type array; however, Defuse\Crypto\File::encryptFileWithPassword() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
2003
                    $password
2004
                );
2005
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
2006
                $err = "wrong_key";
2007
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
2008
                $err = $ex;
2009
            } catch (Defuse\Crypto\Exception\IOException $ex) {
2010
                $err = $ex;
2011
            }
2012
        }
2013
    }
2014
2015
    // return error
2016
    if (empty($err) === false) {
2017
        return $err;
2018
    } else {
2019
        return true;
2020
    }
2021
}
2022
2023
/*
2024
* NOT TO BE USED
2025
*/
2026
function debugTeampass($text)
2027
{
2028
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
2029
    fputs($debugFile, $text);
2030
    fclose($debugFile);
2031
}
2032
2033
2034
/**
2035
 * DELETE the file with expected command depending on server type
2036
 * @param  string $file Path to file
2037
 * @return              Nothing
2038
 */
2039
function fileDelete($file)
2040
{
2041
    global $SETTINGS;
2042
2043
    // Load AntiXSS
2044
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2045
    $antiXss = new protect\AntiXSS\AntiXSS();
2046
2047
    $file = $antiXss->xss_clean($file);
2048
    if (is_file($file)) {
2049
        unlink($file);
2050
    }
2051
}
2052
2053
/*
2054
* Permits to extract the file extension
2055
*/
2056
function getFileExtension($file)
2057
{
2058
    if (strpos($file, '.') === false) {
2059
        return $file;
2060
    }
2061
2062
    return substr($file, strrpos($file, '.') + 1);
2063
}
2064
2065
/**
2066
 * array_map
2067
 * @param  [type] $func [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...
2068
 * @param  [type] $arr  [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...
2069
 * @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...
2070
 */
2071
function array_map_r($func, $arr)
2072
{
2073
    $newArr = array();
2074
2075
    foreach ($arr as $key => $value) {
2076
        $newArr[ $key ] = (is_array($value) ? array_map_r($func, $value) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value )));
2077
    }
2078
2079
    return $newArr;
2080
}
2081
2082
/**
2083
 * Permits to clean and sanitize text to be displayed
2084
 * @param  string $text text to clean
0 ignored issues
show
Bug introduced by
There is no parameter named $text. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2085
 * @param  string $type what clean to perform
2086
 * @return string       text cleaned up
2087
 */
2088
function cleanText($string, $type = "")
2089
{
2090
    global $SETTINGS;
2091
2092
    // Load AntiXSS
2093
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2094
    $antiXss = new protect\AntiXSS\AntiXSS();
2095
2096
    if ($type === "css") {
2097
        // Escape text and quotes in UTF8 format
2098
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
2099
    } elseif ($type === "html" || empty($type)) {
2100
        // Html cleaner
2101
        return $antiXss->xss_clean($string);
2102
    }
2103
}
2104
2105
/**
2106
 * Performs chmod operation on subfolders
2107
 * @param  string  $dir             Parent folder
2108
 * @param  integer $dirPermissions  New permission on folders
2109
 * @param  integer $filePermissions New permission on files
2110
 * @return boolean                  Success/Failure
2111
 */
2112 View Code Duplication
function chmodRecursive($dir, $dirPermissions, $filePermissions)
0 ignored issues
show
Best Practice introduced by
The function chmodRecursive() has been defined more than once; this definition is ignored, only the first definition in install/install.queries.php (L20-49) 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...
2113
{
2114
    $pointer_dir = opendir($dir);
0 ignored issues
show
Security File Exposure introduced by
$dir can contain request data and is used in file inclusion context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1146

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...
2115
    $res = true;
2116
    while ($file = readdir($pointer_dir)) {
2117
        if (($file == ".") || ($file == "..")) {
2118
            continue;
2119
        }
2120
2121
        $fullPath = $dir."/".$file;
2122
2123
        if (is_dir($fullPath)) {
2124
            if ($res = @chmod($fullPath, $dirPermissions)) {
0 ignored issues
show
Security File Manipulation introduced by
$fullPath 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 $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1146
  4. $fullPath is assigned
    in sources/main.functions.php on line 2121

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...
2125
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2126
            }
2127
        } else {
2128
            $res = chmod($fullPath, $filePermissions);
0 ignored issues
show
Security File Manipulation introduced by
$fullPath 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 $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1146
  4. $fullPath is assigned
    in sources/main.functions.php on line 2121

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...
2129
        }
2130
        if (!$res) {
2131
            closedir($pointer_dir);
2132
            return false;
2133
        }
2134
    }
2135
    closedir($pointer_dir);
2136
    if (is_dir($dir) && $res) {
2137
        $res = @chmod($dir, $dirPermissions);
0 ignored issues
show
Security File Manipulation introduced by
$dir 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 $_GET
    in includes/libraries/protect/SuperGlobal/SuperGlobal.php on line 45
  2. SuperGlobal::get() returns tainted data, and $session_abspath is assigned
    in install/install.queries.php on line 130
  3. $session_abspath is passed to chmodRecursive()
    in install/install.queries.php on line 1146

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...
2138
    }
2139
2140
    return $res;
2141
}
2142
2143
/**
2144
 * Check if user can access to this item
2145
 * @param $item_id
2146
 */
2147
function accessToItemIsGranted($item_id)
2148
{
2149
    global $SETTINGS;
2150
2151
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
2152
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
2153
2154
    // Prepare superGlobal variables
2155
    $session_groupes_visibles = $superGlobal->get("groupes_visibles", "SESSION");
2156
    $session_list_restricted_folders_for_items = $superGlobal->get("list_restricted_folders_for_items", "SESSION");
2157
2158
    // Load item data
2159
    $data = DB::queryFirstRow(
2160
        "SELECT id_tree
2161
        FROM ".prefix_table("items")."
2162
        WHERE id = %i",
2163
        $item_id
2164
    );
2165
2166
    // Check if user can access this folder
2167
    if (in_array($data['id_tree'], $session_groupes_visibles) === false) {
2168
        // Now check if this folder is restricted to user
2169
        if (isset($session_list_restricted_folders_for_items[$data['id_tree']])
2170
            && !in_array($item_id, $session_list_restricted_folders_for_items[$data['id_tree']])
2171
        ) {
2172
            return "ERR_FOLDER_NOT_ALLOWED";
2173
        } else {
2174
            return "ERR_FOLDER_NOT_ALLOWED";
2175
        }
2176
    }
2177
2178
    return true;
2179
}
2180