Completed
Push — development ( 281cae...aca8b3 )
by Nils
09:28
created

main.functions.php ➔ uniqidReal()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 11
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 View Code Duplication
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) === false) {
678
                // Get allowed folders for each Role
679
                $rows = DB::query(
680
                    "SELECT folder_id FROM ".prefix_table("roles_values")." WHERE role_id=%i",
681
                    $roleId
682
                );
683
684
                if (DB::count() > 0) {
685
                    $tmp = DB::queryfirstrow(
686
                        "SELECT allow_pw_change FROM ".prefix_table("roles_title")." WHERE id = %i",
687
                        $roleId
688
                    );
689
                    foreach ($rows as $record) {
690 View Code Duplication
                        if (isset($record['folder_id']) && in_array($record['folder_id'], $listAllowedFolders) === false) {
691
                            array_push($listAllowedFolders, $record['folder_id']);
692
                        }
693
                        // Check if this group is allowed to modify any pw in allowed folders
694 View Code Duplication
                        if ($tmp['allow_pw_change'] == 1 && in_array($record['folder_id'], $listFoldersEditableByRole) === false) {
695
                            array_push($listFoldersEditableByRole, $record['folder_id']);
696
                        }
697
                    }
698
                    // Check for the users roles if some specific rights exist on items
699
                    $rows = DB::query(
700
                        "SELECT i.id_tree, r.item_id
701
                        FROM ".prefix_table("items")." as i
702
                        INNER JOIN ".prefix_table("restriction_to_roles")." as r ON (r.item_id=i.id)
703
                        WHERE r.role_id=%i
704
                        ORDER BY i.id_tree ASC",
705
                        $roleId
706
                    );
707
                    $inc = 0;
708
                    foreach ($rows as $record) {
709
                        if (isset($record['id_tree'])) {
710
                            $listFoldersLimited[$record['id_tree']][$inc] = $record['item_id'];
711
                            $inc++;
712
                        }
713
                    }
714
                }
715
            }
716
        }
717
718
        // Does this user is allowed to see other items
719
        $inc = 0;
720
        $rows = DB::query(
721
            "SELECT id, id_tree FROM ".prefix_table("items")."
722
            WHERE restricted_to LIKE %ss AND inactif=%s",
723
            $_SESSION['user_id'].';',
724
            '0'
725
        );
726
        foreach ($rows as $record) {
727
            $listRestrictedFoldersForItems[$record['id_tree']][$inc] = $record['id'];
728
            $inc++;
729
        }
730
        // => Build final lists
731
        // Clean arrays
732
        $listAllowedFolders = array_unique($listAllowedFolders);
733
        $groupesVisiblesUser = explode(';', trimElement($groupesVisiblesUser, ";"));
734
        // Add user allowed folders
735
        $allowedFoldersTmp = array_unique(
736
            array_merge($listAllowedFolders, $groupesVisiblesUser)
737
        );
738
        // Exclude from allowed folders all the specific user forbidden folders
739
        $allowedFolders = array();
740
        foreach ($allowedFoldersTmp as $ident) {
741
            if (!in_array($ident, $groupesInterditsUser) && !empty($ident)) {
742
                array_push($allowedFolders, $ident);
743
            }
744
        }
745
746
        // Clean array
747
        $listAllowedFolders = array_filter(array_unique($allowedFolders));
748
749
        // Exclude all PF
750
        $_SESSION['forbiden_pfs'] = array();
751
752
        $where = new WhereClause('and');
753
        $where->add('personal_folder=%i', 1);
754
        if (isset($SETTINGS['enable_pf_feature']) === true && $SETTINGS['enable_pf_feature'] === '1'
755
            && isset($_SESSION['personal_folder']) === true && $_SESSION['personal_folder'] === '1'
756
        ) {
757
            $where->add('title=%s', $_SESSION['user_id']);
758
            $where->negateLast();
759
        }
760
761
        $persoFlds = DB::query(
762
            "SELECT id
763
            FROM ".prefix_table("nested_tree")."
764
            WHERE %l",
765
            $where
766
        );
767
        foreach ($persoFlds as $persoFldId) {
768
            array_push($_SESSION['forbiden_pfs'], $persoFldId['id']);
769
        }
770
        // Get IDs of personal folders
771
        if (isset($SETTINGS['enable_pf_feature']) === true && $SETTINGS['enable_pf_feature'] === '1'
772
            && isset($_SESSION['personal_folder']) === true &&  $_SESSION['personal_folder'] === '1'
773
        ) {
774
            $persoFld = DB::queryfirstrow(
775
                "SELECT id
776
                FROM ".prefix_table("nested_tree")."
777
                WHERE title = %s AND personal_folder = %i",
778
                $_SESSION['user_id'],
779
                1
780
            );
781
            if (empty($persoFld['id']) === false) {
782
                if (in_array($persoFld['id'], $listAllowedFolders) === false) {
783
                    array_push($_SESSION['personal_folders'], $persoFld['id']);
784
                    // get all descendants
785
                    $ids = $tree->getDescendants($persoFld['id'], true, false);
786
                    foreach ($ids as $ident) {
787
                        array_push($listAllowedFolders, $ident->id);
788
                        array_push($_SESSION['personal_visible_groups'], $ident->id);
789
                        array_push($_SESSION['personal_folders'], $ident->id);
790
                    }
791
                }
792
            }
793
            // get list of readonly folders when pf is disabled.
794
            $_SESSION['personal_folders'] = array_unique($_SESSION['personal_folders']);
795
            // rule - if one folder is set as W or N in one of the Role, then User has access as W
796
            foreach ($listAllowedFolders as $folderId) {
797
                if (in_array($folderId, array_unique(array_merge($listReadOnlyFolders, $_SESSION['personal_folders']))) === false) {
798
                    DB::query(
799
                        "SELECT *
800
                        FROM ".prefix_table("roles_values")."
801
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
802
                        $folderId,
803
                        $fonctionsAssociees,
804
                        array("W", "ND", "NE", "NDNE")
805
                    );
806
                    if (DB::count() === 0 && in_array($folderId, $groupesVisiblesUser) === false) {
807
                        array_push($listReadOnlyFolders, $folderId);
808
                    }
809
                }
810
            }
811
        } else {
812
            // get list of readonly folders when pf is disabled.
813
            // rule - if one folder is set as W in one of the Role, then User has access as W
814
            foreach ($listAllowedFolders as $folderId) {
815
                if (in_array($folderId, $listReadOnlyFolders) === false) {
816
                    DB::query(
817
                        "SELECT *
818
                        FROM ".prefix_table("roles_values")."
819
                        WHERE folder_id = %i AND role_id IN %li AND type IN %ls",
820
                        $folderId,
821
                        $fonctionsAssociees,
822
                        array("W", "ND", "NE", "NDNE")
823
                    );
824
                    if (DB::count() == 0 && !in_array($folderId, $groupesVisiblesUser)) {
825
                        array_push($listReadOnlyFolders, $folderId);
826
                    }
827
                }
828
            }
829
        }
830
831
        // check if change proposals on User's items
832
        if (isset($SETTINGS['enable_suggestion']) === true && $SETTINGS['enable_suggestion'] === '1') {
833
            DB::query(
834
                "SELECT *
835
                FROM ".prefix_table("items_change")." AS c
836
                LEFT JOIN ".prefix_table("log_items")." AS i ON (c.item_id = i.id_item)
837
                WHERE i.action = %s AND i.id_user = %i",
838
                "at_creation",
839
                $_SESSION['user_id']
840
            );
841
            $_SESSION['nb_item_change_proposals'] = DB::count();
842
        } else {
843
            $_SESSION['nb_item_change_proposals'] = 0;
844
        }
845
846
        $_SESSION['all_non_personal_folders'] = $listAllowedFolders;
847
        $_SESSION['groupes_visibles'] = $listAllowedFolders;
848
        $_SESSION['groupes_visibles_list'] = implode(',', $listAllowedFolders);
849
        $_SESSION['personal_visible_groups_list'] = implode(',', $_SESSION['personal_visible_groups']);
850
        $_SESSION['read_only_folders'] = $listReadOnlyFolders;
851
        $_SESSION['no_access_folders'] = $groupesInterdits;
852
853
        $_SESSION['list_folders_limited'] = $listFoldersLimited;
854
        $_SESSION['list_folders_editable_by_role'] = $listFoldersEditableByRole;
855
        $_SESSION['list_restricted_folders_for_items'] = $listRestrictedFoldersForItems;
856
        // Folders and Roles numbers
857
        DB::queryfirstrow("SELECT id FROM ".prefix_table("nested_tree")."");
858
        $_SESSION['nb_folders'] = DB::count();
859
        DB::queryfirstrow("SELECT id FROM ".prefix_table("roles_title"));
860
        $_SESSION['nb_roles'] = DB::count();
861
    }
862
863
    // update user's timestamp
864
    DB::update(
865
        prefix_table('users'),
866
        array(
867
            'timestamp' => time()
868
        ),
869
        "id=%i",
870
        $_SESSION['user_id']
871
    );
872
}
873
874
/**
875
 * updateCacheTable()
876
 *
877
 * Update the CACHE table
878
 * @param string $action
879
 */
880
function updateCacheTable($action, $ident = "")
881
{
882
    global $server, $user, $pass, $database, $port, $encoding;
883
    global $SETTINGS;
884
885
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
886
887
    //Connect to DB
888
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
889
    $pass = defuse_return_decrypted($pass);
890
    DB::$host = $server;
891
    DB::$user = $user;
892
    DB::$password = $pass;
893
    DB::$dbName = $database;
894
    DB::$port = $port;
895
    DB::$encoding = $encoding;
896
    DB::$error_handler = true;
897
    $link = mysqli_connect($server, $user, $pass, $database, $port);
898
    $link->set_charset($encoding);
899
900
    //Load Tree
901
    $tree = new SplClassLoader('Tree\NestedTree', '../includes/libraries');
902
    $tree->register();
903
    $tree = new Tree\NestedTree\NestedTree(prefix_table("nested_tree"), 'id', 'parent_id', 'title');
904
905
    // Rebuild full cache table
906
    if ($action === "reload") {
907
        // truncate table
908
        DB::query("TRUNCATE TABLE ".prefix_table("cache"));
909
910
        // reload date
911
        $rows = DB::query(
912
            "SELECT *
913
            FROM ".prefix_table('items')." as i
914
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
915
            AND l.action = %s
916
            AND i.inactif = %i",
917
            'at_creation',
918
            0
919
        );
920
        foreach ($rows as $record) {
921
            if (empty($record['id_tree']) === false) {
922
                // Get all TAGS
923
                $tags = "";
924
                $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $record['id']);
925 View Code Duplication
                foreach ($itemTags as $itemTag) {
926
                    if (!empty($itemTag['tag'])) {
927
                        $tags .= $itemTag['tag']." ";
928
                    }
929
                }
930
                // Get renewal period
931
                $resNT = DB::queryfirstrow("SELECT renewal_period FROM ".prefix_table('nested_tree')." WHERE id=%i", $record['id_tree']);
932
933
                // form id_tree to full foldername
934
                $folder = "";
935
                $arbo = $tree->getPath($record['id_tree'], true);
936 View Code Duplication
                foreach ($arbo as $elem) {
937
                    if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
938
                        $elem->title = $_SESSION['login'];
939
                    }
940
                    if (empty($folder)) {
941
                        $folder = stripslashes($elem->title);
942
                    } else {
943
                        $folder .= " » ".stripslashes($elem->title);
944
                    }
945
                }
946
                // store data
947
                DB::insert(
948
                    prefix_table('cache'),
949
                    array(
950
                        'id' => $record['id'],
951
                        'label' => $record['label'],
952
                        'description' => isset($record['description']) ? $record['description'] : "",
953
                        'url' => (isset($record['url']) && !empty($record['url'])) ? $record['url'] : "0",
954
                        'tags' => $tags,
955
                        'id_tree' => $record['id_tree'],
956
                        'perso' => $record['perso'],
957
                        'restricted_to' => (isset($record['restricted_to']) && !empty($record['restricted_to'])) ? $record['restricted_to'] : "0",
958
                        'login' => isset($record['login']) ? $record['login'] : "",
959
                        'folder' => $folder,
960
                        'author' => $record['id_user'],
961
                        'renewal_period' => isset($resNT['renewal_period']) ? $resNT['renewal_period'] : "0",
962
                        'timestamp' => $record['date']
963
                        )
964
                );
965
            }
966
        }
967
        // UPDATE an item
968
    } elseif ($action === "update_value") {
969
        // get new value from db
970
        $data = DB::queryfirstrow(
971
            "SELECT label, description, id_tree, perso, restricted_to, login, url
972
            FROM ".prefix_table('items')."
973
            WHERE id=%i",
974
            $ident
975
        );
976
        // Get all TAGS
977
        $tags = "";
978
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id=%i", $ident);
979 View Code Duplication
        foreach ($itemTags as $itemTag) {
980
            if (!empty($itemTag['tag'])) {
981
                $tags .= $itemTag['tag']." ";
982
            }
983
        }
984
        // form id_tree to full foldername
985
        $folder = "";
986
        $arbo = $tree->getPath($data['id_tree'], true);
987 View Code Duplication
        foreach ($arbo as $elem) {
988
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
989
                $elem->title = $_SESSION['login'];
990
            }
991
            if (empty($folder)) {
992
                $folder = stripslashes($elem->title);
993
            } else {
994
                $folder .= " » ".stripslashes($elem->title);
995
            }
996
        }
997
        // finaly update
998
        DB::update(
999
            prefix_table('cache'),
1000
            array(
1001
                'label' => $data['label'],
1002
                'description' => $data['description'],
1003
                'tags' => $tags,
1004
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
1005
                'id_tree' => $data['id_tree'],
1006
                'perso' => $data['perso'],
1007
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "0",
1008
                'login' => isset($data['login']) ? $data['login'] : "",
1009
                'folder' => $folder,
1010
                'author' => $_SESSION['user_id'],
1011
                ),
1012
            "id = %i",
1013
            $ident
1014
        );
1015
        // ADD an item
1016
    } elseif ($action === "add_value") {
1017
        // get new value from db
1018
        $data = DB::queryFirstRow(
1019
            "SELECT i.label, i.description, i.id_tree as id_tree, i.perso, i.restricted_to, i.id, i.login, i.url, l.date
1020
            FROM ".prefix_table('items')." as i
1021
            INNER JOIN ".prefix_table('log_items')." as l ON (l.id_item = i.id)
1022
            WHERE i.id = %i
1023
            AND l.action = %s",
1024
            $ident,
1025
            'at_creation'
1026
        );
1027
        // Get all TAGS
1028
        $tags = "";
1029
        $itemTags = DB::query("SELECT tag FROM ".prefix_table('tags')." WHERE item_id = %i", $ident);
1030 View Code Duplication
        foreach ($itemTags as $itemTag) {
1031
            if (!empty($itemTag['tag'])) {
1032
                $tags .= $itemTag['tag']." ";
1033
            }
1034
        }
1035
        // form id_tree to full foldername
1036
        $folder = "";
1037
        $arbo = $tree->getPath($data['id_tree'], true);
1038 View Code Duplication
        foreach ($arbo as $elem) {
1039
            if ($elem->title == $_SESSION['user_id'] && $elem->nlevel == 1) {
1040
                $elem->title = $_SESSION['login'];
1041
            }
1042
            if (empty($folder)) {
1043
                $folder = stripslashes($elem->title);
1044
            } else {
1045
                $folder .= " » ".stripslashes($elem->title);
1046
            }
1047
        }
1048
        // finaly update
1049
        DB::insert(
1050
            prefix_table('cache'),
1051
            array(
1052
                'id' => $data['id'],
1053
                'label' => $data['label'],
1054
                'description' => $data['description'],
1055
                'tags' => (isset($tags) && !empty($tags)) ? $tags : "None",
1056
                'url' => (isset($data['url']) && !empty($data['url'])) ? $data['url'] : "0",
1057
                'id_tree' => $data['id_tree'],
1058
                'perso' => (isset($data['perso']) && !empty($data['perso']) && $data['perso'] !== "None") ? $data['perso'] : "0",
1059
                'restricted_to' => (isset($data['restricted_to']) && !empty($data['restricted_to'])) ? $data['restricted_to'] : "0",
1060
                'login' => isset($data['login']) ? $data['login'] : "",
1061
                'folder' => $folder,
1062
                'author' => $_SESSION['user_id'],
1063
                'timestamp' => $data['date']
1064
            )
1065
        );
1066
1067
        // DELETE an item
1068
    } elseif ($action === "delete_value") {
1069
        DB::delete(prefix_table('cache'), "id = %i", $ident);
1070
    }
1071
}
1072
1073
/*
1074
*
1075
*/
1076
function getStatisticsData()
1077
{
1078
    global $SETTINGS;
1079
1080
    DB::query(
1081
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1082
        0
1083
    );
1084
    $counter_folders = DB::count();
1085
1086
    DB::query(
1087
        "SELECT id FROM ".prefix_table("nested_tree")." WHERE personal_folder = %i",
1088
        1
1089
    );
1090
    $counter_folders_perso = DB::count();
1091
1092
    DB::query(
1093
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1094
        0
1095
    );
1096
    $counter_items = DB::count();
1097
1098
    DB::query(
1099
        "SELECT id FROM ".prefix_table("items")." WHERE perso = %i",
1100
        1
1101
    );
1102
    $counter_items_perso = DB::count();
1103
1104
    DB::query(
1105
        "SELECT id FROM ".prefix_table("users").""
1106
    );
1107
    $counter_users = DB::count();
1108
1109
    DB::query(
1110
        "SELECT id FROM ".prefix_table("users")." WHERE admin = %i",
1111
        1
1112
    );
1113
    $admins = DB::count();
1114
1115
    DB::query(
1116
        "SELECT id FROM ".prefix_table("users")." WHERE gestionnaire = %i",
1117
        1
1118
    );
1119
    $managers = DB::count();
1120
1121
    DB::query(
1122
        "SELECT id FROM ".prefix_table("users")." WHERE read_only = %i",
1123
        1
1124
    );
1125
    $readOnly = DB::count();
1126
1127
    // list the languages
1128
    $usedLang = [];
1129
    $tp_languages = DB::query(
1130
        "SELECT name FROM ".prefix_table("languages")
1131
    );
1132
    foreach ($tp_languages as $tp_language) {
1133
        DB::query(
1134
            "SELECT * FROM ".prefix_table("users")." WHERE user_language = %s",
1135
            $tp_language['name']
1136
        );
1137
        $usedLang[$tp_language['name']] = round((DB::count() * 100 / $counter_users), 0);
1138
    }
1139
1140
    // get list of ips
1141
    $usedIp = [];
1142
    $tp_ips = DB::query(
1143
        "SELECT user_ip FROM ".prefix_table("users")
1144
    );
1145
    foreach ($tp_ips as $ip) {
1146
        if (array_key_exists($ip['user_ip'], $usedIp)) {
1147
            $usedIp[$ip['user_ip']] = $usedIp[$ip['user_ip']] + 1;
1148
        } elseif (!empty($ip['user_ip']) && $ip['user_ip'] !== "none") {
1149
            $usedIp[$ip['user_ip']] = 1;
1150
        }
1151
    }
1152
1153
    return array(
1154
        "error" => "",
1155
        "stat_phpversion" => phpversion(),
1156
        "stat_folders" => $counter_folders,
1157
        "stat_folders_shared" => intval($counter_folders) - intval($counter_folders_perso),
1158
        "stat_items" => $counter_items,
1159
        "stat_items_shared" => intval($counter_items) - intval($counter_items_perso),
1160
        "stat_users" => $counter_users,
1161
        "stat_admins" => $admins,
1162
        "stat_managers" => $managers,
1163
        "stat_ro" => $readOnly,
1164
        "stat_kb" => $SETTINGS['enable_kb'],
1165
        "stat_pf" => $SETTINGS['enable_pf_feature'],
1166
        "stat_fav" => $SETTINGS['enable_favourites'],
1167
        "stat_teampassversion" => $SETTINGS['cpassman_version'],
1168
        "stat_ldap" => $SETTINGS['ldap_mode'],
1169
        "stat_agses" => $SETTINGS['agses_authentication_enabled'],
1170
        "stat_duo" => $SETTINGS['duo'],
1171
        "stat_suggestion" => $SETTINGS['enable_suggestion'],
1172
        "stat_api" => $SETTINGS['api'],
1173
        "stat_customfields" => $SETTINGS['item_extra_fields'],
1174
        "stat_syslog" => $SETTINGS['syslog_enable'],
1175
        "stat_2fa" => $SETTINGS['google_authentication'],
1176
        "stat_stricthttps" => $SETTINGS['enable_sts'],
1177
        "stat_mysqlversion" => DB::serverVersion(),
1178
        "stat_languages" => $usedLang,
1179
        "stat_country" => $usedIp
1180
    );
1181
}
1182
1183
/**
1184
 * sendEmail()
1185
 *
1186
 * @return
1187
 */
1188
function sendEmail($subject, $textMail, $email, $textMailAlt = "")
1189
{
1190
    global $LANG;
1191
    global $SETTINGS;
1192
1193
    // CAse where email not defined
1194
    if ($email === "none") {
1195
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1196
    }
1197
1198
    // Load settings
1199
    include $SETTINGS['cpassman_dir'].'/includes/config/settings.php';
1200
1201
    // Load superglobal
1202
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
1203
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
1204
1205
    // Get user language
1206
    $session_user_language = $superGlobal->get("user_language", "SESSION");
1207
1208
    // Load library
1209
    $user_language = isset($session_user_language) ? $session_user_language : "english";
1210
    require_once $SETTINGS['cpassman_dir'].'/includes/language/'.$user_language.'.php';
1211
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Email/Phpmailer/PHPMailerAutoload.php';
1212
1213
    // load PHPMailer
1214
    $mail = new PHPMailer();
1215
1216
    // send to user
1217
    $mail->setLanguage("en", "../includes/libraries/Email/Phpmailer/language/");
1218
    $mail->SMTPDebug = 0; //value 1 can be used to debug - 4 for debuging connections
1219
    $mail->Port = $SETTINGS['email_port']; //COULD BE USED
1220
    $mail->CharSet = "utf-8";
1221
    if ($SETTINGS['email_security'] === "tls" || $SETTINGS['email_security'] === "ssl") {
1222
        $mail->SMTPSecure = $SETTINGS['email_security'];
1223
        $SMTPAutoTLS = true;
1224
    } else {
1225
        $SMTPAutoTLS = false;
1226
        $mail->SMTPSecure = "";
1227
    }
1228
    $mail->SMTPAutoTLS = $SMTPAutoTLS;
1229
    $mail->isSmtp(); // send via SMTP
1230
    $mail->Host = $SETTINGS['email_smtp_server']; // SMTP servers
1231
    $mail->SMTPAuth = $SETTINGS['email_smtp_auth'] == '1' ? true : false; // turn on SMTP authentication
1232
    $mail->Username = $SETTINGS['email_auth_username']; // SMTP username
1233
    $mail->Password = $SETTINGS['email_auth_pwd']; // SMTP password
1234
    $mail->From = $SETTINGS['email_from'];
1235
    $mail->FromName = $SETTINGS['email_from_name'];
1236
1237
    // Prepare for each person
1238
    $dests = explode(",", $email);
1239
    foreach ($dests as $dest) {
1240
        $mail->addAddress($dest);
1241
    }
1242
1243
    $mail->WordWrap = 80; // set word wrap
1244
    $mail->isHtml(true); // send as HTML
1245
    $mail->Subject = $subject;
1246
    $mail->Body = $textMail;
1247
    $mail->AltBody = $textMailAlt;
1248
    // send email
1249
    if (!$mail->send()) {
1250
        return '"error":"error_mail_not_send" , "message":"'.str_replace(array("\n", "\t", "\r"), '', $mail->ErrorInfo).'"';
1251
    } else {
1252
        return '"error":"" , "message":"'.$LANG['forgot_my_pw_email_sent'].'"';
1253
    }
1254
}
1255
1256
/**
1257
 * generateKey()
1258
 *
1259
 * @return
1260
 */
1261
function generateKey()
1262
{
1263
    return substr(md5(rand().rand()), 0, 15);
1264
}
1265
1266
/**
1267
 * dateToStamp()
1268
 *
1269
 * @return
1270
 */
1271
function dateToStamp($date)
1272
{
1273
    global $SETTINGS;
1274
1275
    $date = date_parse_from_format($SETTINGS['date_format'], $date);
1276
    if ($date['warning_count'] == 0 && $date['error_count'] == 0) {
1277
        return mktime(23, 59, 59, $date['month'], $date['day'], $date['year']);
1278
    } else {
1279
        return false;
1280
    }
1281
}
1282
1283
function isDate($date)
1284
{
1285
    return (strtotime($date) !== false);
1286
}
1287
1288
/**
1289
 * isUTF8()
1290
 *
1291
 * @return integer is the string in UTF8 format.
1292
 */
1293
1294
function isUTF8($string)
1295
{
1296
    if (is_array($string) === true) {
1297
        $string = $string['string'];
1298
    }
1299
    return preg_match(
1300
        '%^(?:
1301
        [\x09\x0A\x0D\x20-\x7E] # ASCII
1302
        | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
1303
        | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
1304
        | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
1305
        | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
1306
        | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
1307
        | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
1308
        | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
1309
        )*$%xs',
1310
        $string
1311
    );
1312
}
1313
1314
/*
1315
* FUNCTION
1316
* permits to prepare data to be exchanged
1317
*/
1318
/**
1319
 * @param string $type
1320
 */
1321
function prepareExchangedData($data, $type)
1322
{
1323
    global $SETTINGS;
1324
1325
    //load ClassLoader
1326
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
1327
    //Load AES
1328
    $aes = new SplClassLoader('Encryption\Crypt', $SETTINGS['cpassman_dir'].'/includes/libraries');
1329
    $aes->register();
1330
1331
    if ($type == "encode") {
1332
        if (isset($SETTINGS['encryptClientServer'])
1333
            && $SETTINGS['encryptClientServer'] === "0"
1334
        ) {
1335
            return json_encode(
1336
                $data,
1337
                JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1338
            );
1339 View Code Duplication
        } else {
1340
            return Encryption\Crypt\aesctr::encrypt(
1341
                json_encode(
1342
                    $data,
1343
                    JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
1344
                ),
1345
                $_SESSION['key'],
1346
                256
1347
            );
1348
        }
1349
    } elseif ($type == "decode") {
1350
        if (isset($SETTINGS['encryptClientServer'])
1351
            && $SETTINGS['encryptClientServer'] === "0"
1352
        ) {
1353
            return json_decode(
1354
                $data,
1355
                true
1356
            );
1357
        } else {
1358
            return json_decode(
1359
                Encryption\Crypt\aesctr::decrypt(
1360
                    $data,
1361
                    $_SESSION['key'],
1362
                    256
1363
                ),
1364
                true
1365
            );
1366
        }
1367
    }
1368
}
1369
1370
function make_thumb($src, $dest, $desired_width)
1371
{
1372
    /* read the source image */
1373
    $source_image = imagecreatefrompng($src);
1374
    $width = imagesx($source_image);
1375
    $height = imagesy($source_image);
1376
1377
    /* find the "desired height" of this thumbnail, relative to the desired width  */
1378
    $desired_height = floor($height * ($desired_width / $width));
1379
1380
    /* create a new, "virtual" image */
1381
    $virtual_image = imagecreatetruecolor($desired_width, $desired_height);
1382
1383
    /* copy source image at a resized size */
1384
    imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $width, $height);
1385
1386
    /* create the physical thumbnail image to its destination */
1387
    imagejpeg($virtual_image, $dest);
1388
}
1389
1390
/*
1391
** check table prefix in SQL query
1392
*/
1393
/**
1394
 * @param string $table
1395
 */
1396
function prefix_table($table)
1397
{
1398
    global $pre;
1399
    $safeTable = htmlspecialchars($pre.$table);
1400
    if (!empty($safeTable)) {
1401
        // sanitize string
1402
        return $safeTable;
1403
    } else {
1404
        // stop error no table
1405
        return "table_not_exists";
1406
    }
1407
}
1408
1409
/*
1410
 * Creates a KEY using PasswordLib
1411
 */
1412
function GenerateCryptKey($size = "", $secure = false, $numerals = false, $capitalize = false, $symbols = false)
1413
{
1414
    global $SETTINGS;
1415
    require_once $SETTINGS['cpassman_dir'].'/sources/SplClassLoader.php';
1416
1417
    if ($secure === true) {
1418
        $numerals = true;
1419
        $capitalize = true;
1420
        $symbols = true;
1421
    }
1422
1423
    // Load libraries
1424
    $generator = new SplClassLoader('PasswordGenerator\Generator', '../includes/libraries');
1425
    $generator->register();
1426
    $generator = new PasswordGenerator\Generator\ComputerPasswordGenerator();
1427
1428
    // Can we use PHP7 random_int function?
1429
    if (version_compare(phpversion(), '7.0', '>=')) {
1430
        require_once $SETTINGS['cpassman_dir'].'/includes/libraries/PasswordGenerator/RandomGenerator/Php7RandomGenerator.php';
1431
         $generator->setRandomGenerator(new PasswordGenerator\RandomGenerator\Php7RandomGenerator());
1432
    }
1433
1434
    // init
1435
    if (!empty($size)) {
1436
        $generator->setLength(intval($size));
1437
    }
1438
    if (!empty($numerals)) {
1439
        $generator->setNumbers($numerals);
1440
    }
1441
    if (!empty($capitalize)) {
1442
        $generator->setUppercase($capitalize);
1443
    }
1444
    if (!empty($symbols)) {
1445
        $generator->setSymbols($symbols);
1446
    }
1447
1448
    // generate and send back
1449
    return $generator->generatePassword();
1450
}
1451
1452
/*
1453
* Send sysLOG message
1454
* @param string $message
1455
* @param string $host
1456
*/
1457
function send_syslog($message, $host, $port, $component = "teampass")
1458
{
1459
    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
1460
    $syslog_message = "<123>".date('M d H:i:s ').$component.": ".$message;
1461
    socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, $host, $port);
1462
    socket_close($sock);
1463
}
1464
1465
1466
1467
/**
1468
 * logEvents()
1469
 *
1470
 * permits to log events into DB
1471
 * @param string $type
1472
 * @param string $label
1473
 * @param string $field_1
1474
 */
1475
function logEvents($type, $label, $who, $login = "", $field_1 = null)
1476
{
1477
    global $server, $user, $pass, $database, $port, $encoding;
1478
    global $SETTINGS;
1479
1480
    if (empty($who)) {
1481
        $who = get_client_ip_server();
1482
    }
1483
1484
    // include librairies & connect to DB
1485
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1486
    $pass = defuse_return_decrypted($pass);
1487
    DB::$host = $server;
1488
    DB::$user = $user;
1489
    DB::$password = $pass;
1490
    DB::$dbName = $database;
1491
    DB::$port = $port;
1492
    DB::$encoding = $encoding;
1493
    DB::$error_handler = true;
1494
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1495
    $link->set_charset($encoding);
1496
1497
    DB::insert(
1498
        prefix_table("log_system"),
1499
        array(
1500
            'type' => $type,
1501
            'date' => time(),
1502
            'label' => $label,
1503
            'qui' => $who,
1504
            'field_1' => $field_1 === null ? "" : $field_1
1505
        )
1506
    );
1507
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1508
        if ($type == "user_mngt") {
1509
            send_syslog(
1510
                "The User ".$login." performed the action of ".$label." to the user ".$field_1." - ".$type,
1511
                $SETTINGS['syslog_host'],
1512
                $SETTINGS['syslog_port'],
1513
                "teampass"
1514
            );
1515
        } else {
1516
            send_syslog(
1517
                "The User ".$login." performed the action of ".$label." - ".$type,
1518
                $SETTINGS['syslog_host'],
1519
                $SETTINGS['syslog_port'],
1520
                "teampass"
1521
            );
1522
        }
1523
    }
1524
}
1525
1526
/**
1527
 * @param string $item
1528
 * @param string $action
1529
 */
1530
function logItems($ident, $item, $id_user, $action, $login = "", $raison = null, $raison_iv = null, $encryption_type = "")
1531
{
1532
    global $server, $user, $pass, $database, $port, $encoding;
1533
    global $SETTINGS;
1534
1535
    // include librairies & connect to DB
1536
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1537
    $pass = defuse_return_decrypted($pass);
1538
    DB::$host = $server;
1539
    DB::$user = $user;
1540
    DB::$password = $pass;
1541
    DB::$dbName = $database;
1542
    DB::$port = $port;
1543
    DB::$encoding = $encoding;
1544
    DB::$error_handler = true;
1545
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1546
    $link->set_charset($encoding);
1547
    DB::insert(
1548
        prefix_table("log_items"),
1549
        array(
1550
            'id_item' => $ident,
1551
            'date' => time(),
1552
            'id_user' => $id_user,
1553
            'action' => $action,
1554
            'raison' => $raison,
1555
            'raison_iv' => $raison_iv,
1556
            'encryption_type' => $encryption_type
1557
        )
1558
    );
1559
    if (isset($SETTINGS['syslog_enable']) && $SETTINGS['syslog_enable'] == 1) {
1560
        send_syslog(
1561
            "The Item ".$item." was ".$action." by ".$login." ".$raison,
1562
            $SETTINGS['syslog_host'],
1563
            $SETTINGS['syslog_port'],
1564
            "teampass"
1565
        );
1566
    }
1567
}
1568
1569
/*
1570
* Function to get the client ip address
1571
 */
1572
function get_client_ip_server()
1573
{
1574
    if (getenv('HTTP_CLIENT_IP')) {
1575
            $ipaddress = getenv('HTTP_CLIENT_IP');
1576
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
1577
            $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
1578
    } elseif (getenv('HTTP_X_FORWARDED')) {
1579
            $ipaddress = getenv('HTTP_X_FORWARDED');
1580
    } elseif (getenv('HTTP_FORWARDED_FOR')) {
1581
            $ipaddress = getenv('HTTP_FORWARDED_FOR');
1582
    } elseif (getenv('HTTP_FORWARDED')) {
1583
            $ipaddress = getenv('HTTP_FORWARDED');
1584
    } elseif (getenv('REMOTE_ADDR')) {
1585
            $ipaddress = getenv('REMOTE_ADDR');
1586
    } else {
1587
            $ipaddress = 'UNKNOWN';
1588
    }
1589
1590
    return $ipaddress;
1591
}
1592
1593
/**
1594
 * Escape all HTML, JavaScript, and CSS
1595
 *
1596
 * @param string $input The input string
1597
 * @param string $encoding Which character encoding are we using?
1598
 * @return string
1599
 */
1600
function noHTML($input, $encoding = 'UTF-8')
1601
{
1602
    return htmlspecialchars($input, ENT_QUOTES | ENT_XHTML, $encoding, false);
1603
}
1604
1605
/**
1606
 * handleConfigFile()
1607
 *
1608
 * permits to handle the Teampass config file
1609
 * $action accepts "rebuild" and "update"
1610
 */
1611
function handleConfigFile($action, $field = null, $value = null)
1612
{
1613
    global $server, $user, $pass, $database, $port, $encoding;
1614
    global $SETTINGS;
1615
1616
    $tp_config_file = "../includes/config/tp.config.php";
1617
1618
    // include librairies & connect to DB
1619
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1620
    $pass = defuse_return_decrypted($pass);
1621
    DB::$host = $server;
1622
    DB::$user = $user;
1623
    DB::$password = $pass;
1624
    DB::$dbName = $database;
1625
    DB::$port = $port;
1626
    DB::$encoding = $encoding;
1627
    DB::$error_handler = true;
1628
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1629
    $link->set_charset($encoding);
1630
1631
    if (!file_exists($tp_config_file) || $action == "rebuild") {
1632
        // perform a copy
1633
        if (file_exists($tp_config_file)) {
1634
            if (!copy($tp_config_file, $tp_config_file.'.'.date("Y_m_d_His", time()))) {
1635
                return "ERROR: Could not copy file '".$tp_config_file."'";
1636
            }
1637
        }
1638
1639
        // regenerate
1640
        $data = array();
1641
        $data[0] = "<?php\n";
1642
        $data[1] = "global \$SETTINGS;\n";
1643
        $data[2] = "\$SETTINGS = array (\n";
1644
        $rows = DB::query(
1645
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s",
1646
            "admin"
1647
        );
1648
        foreach ($rows as $record) {
1649
            array_push($data, "    '".$record['intitule']."' => '".$record['valeur']."',\n");
1650
        }
1651
        array_push($data, ");\n");
1652
        $data = array_unique($data);
1653
    } elseif ($action == "update" && empty($field) === false) {
1654
        $data = file($tp_config_file);
1655
        $inc = 0;
1656
        $bFound = false;
1657
        foreach ($data as $line) {
1658
            if (stristr($line, ");")) {
1659
                break;
1660
            }
1661
1662
            //
1663
            if (stristr($line, "'".$field."' => '")) {
1664
                $data[$inc] = "    '".$field."' => '".filter_var($value, FILTER_SANITIZE_STRING)."',\n";
1665
                $bFound = true;
1666
                break;
1667
            }
1668
            $inc++;
1669
        }
1670
        if ($bFound === false) {
1671
            $data[($inc)] = "    '".$field."' => '".filter_var($value, FILTER_SANITIZE_STRING)."',\n);\n";
1672
        }
1673
    }
1674
1675
    // update file
1676
    file_put_contents($tp_config_file, implode('', isset($data) ? $data : array()));
1677
1678
    return true;
1679
}
1680
1681
/*
1682
** Permits to replace &#92; to permit correct display
1683
*/
1684
/**
1685
 * @param string $input
1686
 */
1687
function handleBackslash($input)
1688
{
1689
    return str_replace("&amp;#92;", "&#92;", $input);
1690
}
1691
1692
/*
1693
** Permits to loas settings
1694
*/
1695
function loadSettings()
1696
{
1697
    global $SETTINGS;
1698
1699
    /* LOAD CPASSMAN SETTINGS */
1700
    if (!isset($SETTINGS['loaded']) || $SETTINGS['loaded'] != 1) {
1701
        $SETTINGS['duplicate_folder'] = 0; //by default, this is set to 0;
1702
        $SETTINGS['duplicate_item'] = 0; //by default, this is set to 0;
1703
        $SETTINGS['number_of_used_pw'] = 5; //by default, this value is set to 5;
1704
        $settings = array();
1705
1706
        $rows = DB::query(
1707
            "SELECT * FROM ".prefix_table("misc")." WHERE type=%s_type OR type=%s_type2",
1708
            array(
1709
                'type' => "admin",
1710
                'type2' => "settings"
1711
            )
1712
        );
1713
        foreach ($rows as $record) {
1714
            if ($record['type'] == 'admin') {
1715
                $SETTINGS[$record['intitule']] = $record['valeur'];
1716
            } else {
1717
                $settings[$record['intitule']] = $record['valeur'];
1718
            }
1719
        }
1720
        $SETTINGS['loaded'] = 1;
1721
        $SETTINGS['default_session_expiration_time'] = 5;
1722
    }
1723
}
1724
1725
/*
1726
** check if folder has custom fields.
1727
** Ensure that target one also has same custom fields
1728
*/
1729
function checkCFconsistency($source_id, $target_id)
1730
{
1731
    $source_cf = array();
1732
    $rows = DB::QUERY(
1733
        "SELECT id_category
1734
        FROM ".prefix_table("categories_folders")."
1735
        WHERE id_folder = %i",
1736
        $source_id
1737
    );
1738
    foreach ($rows as $record) {
1739
        array_push($source_cf, $record['id_category']);
1740
    }
1741
1742
    $target_cf = array();
1743
    $rows = DB::QUERY(
1744
        "SELECT id_category
1745
        FROM ".prefix_table("categories_folders")."
1746
        WHERE id_folder = %i",
1747
        $target_id
1748
    );
1749
    foreach ($rows as $record) {
1750
        array_push($target_cf, $record['id_category']);
1751
    }
1752
1753
    $cf_diff = array_diff($source_cf, $target_cf);
1754
    if (count($cf_diff) > 0) {
1755
        return false;
1756
    }
1757
1758
    return true;
1759
}
1760
1761
/*
1762
*
1763
*/
1764
function encrypt_or_decrypt_file($filename_to_rework, $filename_status)
1765
{
1766
    global $server, $user, $pass, $database, $port, $encoding;
1767
    global $SETTINGS;
1768
1769
    // Include librairies & connect to DB
1770
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1771
    $pass = defuse_return_decrypted($pass);
1772
    DB::$host = $server;
1773
    DB::$user = $user;
1774
    DB::$password = $pass;
1775
    DB::$dbName = $database;
1776
    DB::$port = $port;
1777
    DB::$encoding = $encoding;
1778
    DB::$error_handler = true;
1779
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1780
    $link->set_charset($encoding);
1781
1782
    // Get file info in DB
1783
    $fileInfo = DB::queryfirstrow(
1784
        "SELECT id FROM ".prefix_table("files")." WHERE file = %s",
1785
        filter_var($filename_to_rework, FILTER_SANITIZE_STRING)
1786
    );
1787
    if (empty($fileInfo['id']) === false) {
1788
        // Load PhpEncryption library
1789
        $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1790
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1791
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1792
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1793
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1794
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1795
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1796
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1797
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1798
        require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1799
1800
        // Get KEY
1801
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1802
1803
        if (isset($SETTINGS['enable_attachment_encryption'])
1804
            && $SETTINGS['enable_attachment_encryption'] === "1" &&
1805
            isset($filename_status)
1806
            && ($filename_status === "clear"
1807
                || $filename_status === "0")
1808
        ) {
1809
            // File needs to be encrypted
1810 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1811
                // Make a copy of file
1812
                if (!copy(
1813
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1814
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1815
                )) {
1816
                    exit;
1817
                } else {
1818
                    // Do a bck
1819
                    copy(
1820
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1821
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1822
                    );
1823
                }
1824
1825
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1826
1827
                // Now encrypt the file with saltkey
1828
                $err = '';
1829
                try {
1830
                    \Defuse\Crypto\File::encryptFile(
1831
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1832
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1833
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1834
                    );
1835
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1836
                    $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.";
1837
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1838
                    $err = $ex;
1839
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1840
                    $err = $ex;
1841
                }
1842
                if (empty($err) === false) {
1843
                    echo $err;
1844
                }
1845
1846
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1847
1848
                // update table
1849
                DB::update(
1850
                    prefix_table('files'),
1851
                    array(
1852
                        'status' => 'encrypted'
1853
                        ),
1854
                    "id = %i",
1855
                    $fileInfo['id']
1856
                );
1857
            }
1858
        } elseif (isset($SETTINGS['enable_attachment_encryption'])
1859
            && $SETTINGS['enable_attachment_encryption'] === "0"
1860
            && isset($filename_status)
1861
            && $filename_status === "encrypted"
1862
        ) {
1863
            // file needs to be decrypted
1864 View Code Duplication
            if (file_exists($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework)) {
1865
                // make a copy of file
1866
                if (!copy(
1867
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1868
                    $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1869
                )) {
1870
                    exit;
1871
                } else {
1872
                    // do a bck
1873
                    copy(
1874
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1875
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1876
                    );
1877
                }
1878
1879
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework);
1880
1881
                // Now encrypt the file with saltkey
1882
                $err = '';
1883
                try {
1884
                    \Defuse\Crypto\File::decryptFile(
1885
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1886
                        $SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework,
1887
                        \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1888
                    );
1889
                } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1890
                    $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.";
1891
                } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1892
                    $err = $ex;
1893
                } catch (Defuse\Crypto\Exception\IOException $ex) {
1894
                    $err = $ex;
1895
                }
1896
                if (empty($err) === false) {
1897
                    echo $err;
1898
                }
1899
1900
                unlink($SETTINGS['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1901
1902
                // update table
1903
                DB::update(
1904
                    prefix_table('files'),
1905
                    array(
1906
                        'status' => 'clear'
1907
                        ),
1908
                    "id = %i",
1909
                    $fileInfo['id']
1910
                );
1911
            }
1912
        }
1913
    }
1914
1915
    // Exit
1916
    return false;
1917
}
1918
1919
/**
1920
 * Will encrypte/decrypt a fil eusing Defuse
1921
 * @param  string $type        can be either encrypt or decrypt
1922
 * @param  string $source_file path to source file
1923
 * @param  string $target_file path to target file
1924
 * @return string              'true' is success or error message
1925
 */
1926
function prepareFileWithDefuse($type, $source_file, $target_file, $password = '')
1927
{
1928
    global $SETTINGS;
1929
1930
    // Load AntiXSS
1931
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
1932
    $antiXss = new protect\AntiXSS\AntiXSS();
1933
1934
    // Protect against bad inputs
1935
    if (is_array($source_file) ||is_array($target_file)) {
1936
        return 'error_cannot_be_array';
1937
    }
1938
1939
    // Sanitize
1940
    $source_file = $antiXss->xss_clean($source_file);
1941
    $target_file = $antiXss->xss_clean($target_file);
1942
1943
    // load PhpEncryption library
1944
    $path_to_encryption = '/includes/libraries/Encryption/Encryption/';
1945
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Crypto.php';
1946
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Encoding.php';
1947
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'DerivedKeys.php';
1948
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Key.php';
1949
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyOrPassword.php';
1950
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'File.php';
1951
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'RuntimeTests.php';
1952
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'KeyProtectedByPassword.php';
1953
    require_once $SETTINGS['cpassman_dir'].$path_to_encryption.'Core.php';
1954
1955
    if (empty($password) === true) {
1956
    /*
1957
    File encryption/decryption is done with the SALTKEY
1958
     */
1959
1960
        // get KEY
1961
        $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1962
1963
        // Now perform action on the file
1964
        $err = '';
1965 View Code Duplication
        if ($type === 'decrypt') {
1966
            try {
1967
                \Defuse\Crypto\File::decryptFile(
1968
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1940 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...
1969
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1941 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...
1970
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1971
                );
1972
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1973
                $err = "decryption_not_possible";
1974
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1975
                $err = $ex;
1976
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1977
                $err = $ex;
1978
            }
1979
        } elseif ($type === 'encrypt') {
1980
            try {
1981
                \Defuse\Crypto\File::encryptFile(
1982
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1940 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...
1983
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1941 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...
1984
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1985
                );
1986
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1987
                $err = "encryption_not_possible";
1988
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1989
                $err = $ex;
1990
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1991
                $err = $ex;
1992
            }
1993
        }
1994
    } else {
1995
    /*
1996
    File encryption/decryption is done with special password and not the SALTKEY
1997
     */
1998
1999
        $err = '';
2000 View Code Duplication
        if ($type === 'decrypt') {
2001
            try {
2002
                \Defuse\Crypto\File::decryptFileWithPassword(
2003
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1940 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...
2004
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1941 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...
2005
                    $password
2006
                );
2007
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
2008
                $err = "wrong_key";
2009
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
2010
                $err = $ex;
2011
            } catch (Defuse\Crypto\Exception\IOException $ex) {
2012
                $err = $ex;
2013
            }
2014
        } elseif ($type === 'encrypt') {
2015
            try {
2016
                \Defuse\Crypto\File::encryptFileWithPassword(
2017
                    $source_file,
0 ignored issues
show
Bug introduced by
It seems like $source_file defined by $antiXss->xss_clean($source_file) on line 1940 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...
2018
                    $target_file,
0 ignored issues
show
Bug introduced by
It seems like $target_file defined by $antiXss->xss_clean($target_file) on line 1941 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...
2019
                    $password
2020
                );
2021
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
2022
                $err = "wrong_key";
2023
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
2024
                $err = $ex;
2025
            } catch (Defuse\Crypto\Exception\IOException $ex) {
2026
                $err = $ex;
2027
            }
2028
        }
2029
    }
2030
2031
    // return error
2032
    if (empty($err) === false) {
2033
        return $err;
2034
    } else {
2035
        return true;
2036
    }
2037
}
2038
2039
/*
2040
* NOT TO BE USED
2041
*/
2042
function debugTeampass($text)
2043
{
2044
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
2045
    fputs($debugFile, $text);
2046
    fclose($debugFile);
2047
}
2048
2049
2050
/**
2051
 * DELETE the file with expected command depending on server type
2052
 * @param  string $file Path to file
2053
 * @return              Nothing
2054
 */
2055
function fileDelete($file)
2056
{
2057
    global $SETTINGS;
2058
2059
    // Load AntiXSS
2060
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2061
    $antiXss = new protect\AntiXSS\AntiXSS();
2062
2063
    $file = $antiXss->xss_clean($file);
2064
    if (is_file($file)) {
2065
        unlink($file);
2066
    }
2067
}
2068
2069
/*
2070
* Permits to extract the file extension
2071
*/
2072
function getFileExtension($file)
2073
{
2074
    if (strpos($file, '.') === false) {
2075
        return $file;
2076
    }
2077
2078
    return substr($file, strrpos($file, '.') + 1);
2079
}
2080
2081
/**
2082
 * array_map
2083
 * @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...
2084
 * @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...
2085
 * @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...
2086
 */
2087
function array_map_r($func, $arr)
2088
{
2089
    $newArr = array();
2090
2091
    foreach ($arr as $key => $value) {
2092
        $newArr[ $key ] = (is_array($value) ? array_map_r($func, $value) : ( is_array($func) ? call_user_func_array($func, $value) : $func( $value )));
2093
    }
2094
2095
    return $newArr;
2096
}
2097
2098
/**
2099
 * Permits to clean and sanitize text to be displayed
2100
 * @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...
2101
 * @param  string $type what clean to perform
2102
 * @return string       text cleaned up
2103
 */
2104
function cleanText($string, $type = "")
2105
{
2106
    global $SETTINGS;
2107
2108
    // Load AntiXSS
2109
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/AntiXSS/AntiXSS.php';
2110
    $antiXss = new protect\AntiXSS\AntiXSS();
2111
2112
    if ($type === "css") {
2113
        // Escape text and quotes in UTF8 format
2114
        return htmlentities($string, ENT_QUOTES | ENT_HTML5, 'UTF-8');
2115
    } elseif ($type === "html" || empty($type)) {
2116
        // Html cleaner
2117
        return $antiXss->xss_clean($string);
2118
    }
2119
}
2120
2121
/**
2122
 * Performs chmod operation on subfolders
2123
 * @param  string  $dir             Parent folder
2124
 * @param  integer $dirPermissions  New permission on folders
2125
 * @param  integer $filePermissions New permission on files
2126
 * @return boolean                  Success/Failure
2127
 */
2128 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...
2129
{
2130
    $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 1161

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...
2131
    $res = true;
2132
    while ($file = readdir($pointer_dir)) {
2133
        if (($file == ".") || ($file == "..")) {
2134
            continue;
2135
        }
2136
2137
        $fullPath = $dir."/".$file;
2138
2139
        if (is_dir($fullPath)) {
2140
            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 1161
  4. $fullPath is assigned
    in sources/main.functions.php on line 2137

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...
2141
                $res = @chmodRecursive($fullPath, $dirPermissions, $filePermissions);
2142
            }
2143
        } else {
2144
            $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 1161
  4. $fullPath is assigned
    in sources/main.functions.php on line 2137

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...
2145
        }
2146
        if (!$res) {
2147
            closedir($pointer_dir);
2148
            return false;
2149
        }
2150
    }
2151
    closedir($pointer_dir);
2152
    if (is_dir($dir) && $res) {
2153
        $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 1161

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...
2154
    }
2155
2156
    return $res;
2157
}
2158
2159
/**
2160
 * Check if user can access to this item
2161
 * @param $item_id
2162
 */
2163
function accessToItemIsGranted($item_id)
2164
{
2165
    global $SETTINGS;
2166
2167
    require_once $SETTINGS['cpassman_dir'].'/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
2168
    $superGlobal = new protect\SuperGlobal\SuperGlobal();
2169
2170
    // Prepare superGlobal variables
2171
    $session_groupes_visibles = $superGlobal->get("groupes_visibles", "SESSION");
2172
    $session_list_restricted_folders_for_items = $superGlobal->get("list_restricted_folders_for_items", "SESSION");
2173
2174
    // Load item data
2175
    $data = DB::queryFirstRow(
2176
        "SELECT id_tree
2177
        FROM ".prefix_table("items")."
2178
        WHERE id = %i",
2179
        $item_id
2180
    );
2181
2182
    // Check if user can access this folder
2183
    if (in_array($data['id_tree'], $session_groupes_visibles) === false) {
2184
        // Now check if this folder is restricted to user
2185
        if (isset($session_list_restricted_folders_for_items[$data['id_tree']])
2186
            && !in_array($item_id, $session_list_restricted_folders_for_items[$data['id_tree']])
2187
        ) {
2188
            return "ERR_FOLDER_NOT_ALLOWED";
2189
        } else {
2190
            return "ERR_FOLDER_NOT_ALLOWED";
2191
        }
2192
    }
2193
2194
    return true;
2195
}
2196
2197
/**
2198
 * Creates a unique key
2199
 * @param  integer $lenght key lenght
2200
 * @return string          key
2201
 */
2202
function uniqidReal($lenght = 13) {
2203
    // uniqid gives 13 chars, but you could adjust it to your needs.
2204
    if (function_exists("random_bytes")) {
2205
        $bytes = random_bytes(ceil($lenght / 2));
2206
    } elseif (function_exists("openssl_random_pseudo_bytes")) {
2207
        $bytes = openssl_random_pseudo_bytes(ceil($lenght / 2));
2208
    } else {
2209
        throw new Exception("no cryptographically secure random function available");
2210
    }
2211
    return substr(bin2hex($bytes), 0, $lenght);
2212
}