Completed
Push — development ( 0f5008...5fc91d )
by Nils
06:30
created

main.functions.php ➔ prepareFileWithDefuse()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 34
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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

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

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

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

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

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

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

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

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

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

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

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

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

1 path for user data to reach this point

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

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...
1553
1554
    return true;
1555
}
1556
1557
/*
1558
** Permits to replace &#92; to permit correct display
1559
*/
1560
/**
1561
 * @param string $input
1562
 */
1563
function handleBackslash($input)
1564
{
1565
    return str_replace("&amp;#92;", "&#92;", $input);
1566
}
1567
1568
/*
1569
** Permits to loas settings
1570
*/
1571
function loadSettings()
1572
{
1573
    /* LOAD CPASSMAN SETTINGS */
1574 View Code Duplication
    if (!isset($_SESSION['settings']['loaded']) || $_SESSION['settings']['loaded'] != 1) {
1575
        $_SESSION['settings']['duplicate_folder'] = 0; //by default, this is set to 0;
1576
        $_SESSION['settings']['duplicate_item'] = 0; //by default, this is set to 0;
1577
        $_SESSION['settings']['number_of_used_pw'] = 5; //by default, this value is set to 5;
1578
        $settings = array();
1579
1580
        $rows = DB::query("SELECT * FROM ".prefix_table("misc")." WHERE type=%s_type OR type=%s_type2",
1581
            array(
1582
                'type' => "admin",
1583
                'type2' => "settings"
1584
            )
1585
        );
1586
        foreach ($rows as $record) {
1587
            if ($record['type'] == 'admin') {
1588
                $_SESSION['settings'][$record['intitule']] = $record['valeur'];
1589
            } else {
1590
                $settings[$record['intitule']] = $record['valeur'];
1591
            }
1592
        }
1593
        $_SESSION['settings']['loaded'] = 1;
1594
        $_SESSION['settings']['default_session_expiration_time'] = 5;
1595
    }
1596
}
1597
1598
/*
1599
** check if folder has custom fields.
1600
** Ensure that target one also has same custom fields
1601
*/
1602
function checkCFconsistency($source_id, $target_id) {
1603
    $source_cf = array();
1604
    $rows = DB::QUERY(
1605
        "SELECT id_category
1606
        FROM ".prefix_table("categories_folders")."
1607
        WHERE id_folder = %i",
1608
        $source_id
1609
    );
1610
    foreach ($rows as $record) {
1611
        array_push($source_cf, $record['id_category']);
1612
    }
1613
1614
    $target_cf = array();
1615
    $rows = DB::QUERY(
1616
        "SELECT id_category
1617
        FROM ".prefix_table("categories_folders")."
1618
        WHERE id_folder = %i",
1619
        $target_id
1620
    );
1621
    foreach ($rows as $record) {
1622
        array_push($target_cf, $record['id_category']);
1623
    }
1624
1625
    $cf_diff = array_diff($source_cf, $target_cf);
1626
    if (count($cf_diff) > 0) {
1627
        return false;
1628
    }
1629
1630
    return true;
1631
}
1632
1633
/*
1634
*
1635
*/
1636
function encrypt_or_decrypt_file($filename_to_rework, $filename_status) {
1637
    global $server, $user, $pass, $database, $pre, $port, $encoding;
1638
1639
    // include librairies & connect to DB
1640
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Database/Meekrodb/db.class.php';
1641
    DB::$host = $server;
1642
    DB::$user = $user;
1643
    DB::$password = $pass;
1644
    DB::$dbName = $database;
1645
    DB::$port = $port;
1646
    DB::$encoding = $encoding;
1647
    DB::$error_handler = true;
1648
    $link = mysqli_connect($server, $user, $pass, $database, $port);
1649
    $link->set_charset($encoding);
1650
1651
    // load PhpEncryption library
1652
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Crypto.php';
1653
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Encoding.php';
1654
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'DerivedKeys.php';
1655
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Key.php';
1656
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyOrPassword.php';
1657
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'File.php';
1658
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'RuntimeTests.php';
1659
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyProtectedByPassword.php';
1660
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Core.php';
1661
1662
    // get KEY
1663
    $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1664
1665
    if (isset($_SESSION['settings']['enable_attachment_encryption']) && $_SESSION['settings']['enable_attachment_encryption'] === "1" && isset($filename_status) && ($filename_status === "clear" || $filename_status === "0")) {
1666
        // file needs to be encrypted
1667 View Code Duplication
        if (file_exists($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework)) {
1668
            // make a copy of file
1669
            if (!copy(
1670
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1671
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1672
            )) {
1673
                exit;
1674
            } else {
1675
                // do a bck
1676
                copy(
1677
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1678
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1679
                );
1680
            }
1681
1682
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework);
1683
1684
            // Now encrypt the file with saltkey
1685
            $err = '';
1686
            try {
1687
                \Defuse\Crypto\File::encryptFile(
1688
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1689
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1690
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1691
                );
1692
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1693
                $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.";
1694
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1695
                $err = $ex;
1696
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1697
                $err = $ex;
1698
            }
1699
            if (empty($err) === false) {
1700
                echo $err;
1701
            }
1702
1703
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1704
1705
            // update table
1706
            DB::update(
1707
                prefix_table('files'),
1708
                array(
1709
                    'status' => 'encrypted'
1710
                    ),
1711
                "id=%i",
1712
                substr($_POST['uri'], 1)
1713
            );
1714
        }
1715
    } elseif (isset($_SESSION['settings']['enable_attachment_encryption']) && $_SESSION['settings']['enable_attachment_encryption'] === "0" && isset($filename_status) && $filename_status === "encrypted") {
1716
        // file needs to be decrypted
1717 View Code Duplication
        if (file_exists($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework)) {
1718
            // make a copy of file
1719
            if (!copy(
1720
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1721
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy"
1722
            )) {
1723
                exit;
1724
            } else {
1725
                // do a bck
1726
                copy(
1727
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1728
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".bck"
1729
                );
1730
            }
1731
1732
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework);
1733
1734
            // Now encrypt the file with saltkey
1735
            $err = '';
1736
            try {
1737
                \Defuse\Crypto\File::decryptFile(
1738
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy",
1739
                    $_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework,
1740
                    \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1741
                );
1742
            } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1743
                $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.";
1744
            } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1745
                $err = $ex;
1746
            } catch (Defuse\Crypto\Exception\IOException $ex) {
1747
                $err = $ex;
1748
            }
1749
            if (empty($err) === false) {
1750
                echo $err;
1751
            }
1752
1753
            unlink($_SESSION['settings']['path_to_upload_folder'].'/'.$filename_to_rework.".copy");
1754
1755
            // update table
1756
            DB::update(
1757
                prefix_table('files'),
1758
                array(
1759
                    'status' => 'clear'
1760
                    ),
1761
                "id=%i",
1762
                substr($_POST['uri'], 1)
1763
            );
1764
        }
1765
    }
1766
}
1767
1768
/*
1769
 *
1770
*/
1771
function prepareFileWithDefuse($source_file, $target_file) {
1772
    // load PhpEncryption library
1773
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Crypto.php';
1774
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Encoding.php';
1775
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'DerivedKeys.php';
1776
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Key.php';
1777
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyOrPassword.php';
1778
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'File.php';
1779
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'RuntimeTests.php';
1780
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'KeyProtectedByPassword.php';
1781
    require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Encryption/Encryption/'.'Core.php';
1782
1783
    // get KEY
1784
    $ascii_key = file_get_contents(SECUREPATH."/teampass-seckey.txt");
1785
1786
    // Now decrypt the file
1787
    $err = '';
1788
    try {
1789
        \Defuse\Crypto\File::decryptFile(
1790
            $_SESSION['settings']['path_to_upload_folder'].'/'.$source_file,
1791
            $_SESSION['settings']['path_to_upload_folder'].'/'.$target_file,
1792
            \Defuse\Crypto\Key::loadFromAsciiSafeString($ascii_key)
1793
        );
1794
    } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
1795
        $err = "decryption_not_possible";
1796
    } catch (Defuse\Crypto\Exception\EnvironmentIsBrokenException $ex) {
1797
        $err = $ex;
1798
    } catch (Defuse\Crypto\Exception\IOException $ex) {
1799
        $err = $ex;
1800
    }
1801
    if (empty($err) === false) {
1802
        echo $err;
1803
    }
1804
}
1805
1806
/*
1807
* NOT TO BE USED
1808
*/
1809
function debugTeampass($text) {
1810
    $debugFile = fopen('D:/wamp64/www/TeamPass/debug.txt', 'r+');
1811
    fputs($debugFile, $text);
1812
    fclose($debugFile);
1813
}
1814
1815
/*
1816
* DELETE the file with expected command depending on server type
1817
*/
1818
function fileDelete($file) {
1819
    $file = filter_var($file, FILTER_SANITIZE_STRING);
1820
    if (is_file($file)) {
1821
        unlink($file);
0 ignored issues
show
Security File Manipulation introduced by
$file can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

4 paths for user data to reach this point

  1. Path: Read from $_POST, and $_POST['title'] is passed through substr(), and $extension is assigned in sources/items.queries.php on line 3376
  1. Read from $_POST, and $_POST['title'] is passed through substr(), and $extension is assigned
    in sources/items.queries.php on line 3376
  2. $_SESSION['settings']['path_to_upload_folder'] . '/' . $image_code . '_delete.' . $extension is passed to fileDelete()
    in sources/items.queries.php on line 3386
  3. $file is passed through filter_var(), and $file is assigned
    in sources/main.functions.php on line 1819
  2. Path: Read from $_POST, and $_SESSION['settings']['path_to_upload_folder'] . '/' . $result['file'] . $_POST['file_suffix'] is passed to fileDelete() in sources/items.queries.php on line 3428
  1. Read from $_POST, and $_SESSION['settings']['path_to_upload_folder'] . '/' . $result['file'] . $_POST['file_suffix'] is passed to fileDelete()
    in sources/items.queries.php on line 3428
  2. $file is passed through filter_var(), and $file is assigned
    in sources/main.functions.php on line 1819
  3. Path: Read from $_POST, and $_POST['filename'] is passed to fileDelete() in sources/main.queries.php on line 1135
  1. Read from $_POST, and $_POST['filename'] is passed to fileDelete()
    in sources/main.queries.php on line 1135
  2. $file is passed through filter_var(), and $file is assigned
    in sources/main.functions.php on line 1819
  4. Path: Read from $_POST, and $_SESSION is assigned in sources/upload/upload.attachments.php on line 85
  1. Read from $_POST, and $_SESSION is assigned
    in sources/upload/upload.attachments.php on line 85
  2. $_SESSION['settings']['path_to_upload_folder'] is passed through filter_var(), and $targetDir is assigned
    in sources/upload/upload.attachments.php on line 137
  3. $tmpfilePath is assigned
    in sources/upload/upload.attachments.php on line 231
  4. $tmpfilePath is passed to fileDelete()
    in sources/upload/upload.attachments.php on line 238
  5. $file is passed through filter_var(), and $file is assigned
    in sources/main.functions.php on line 1819

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...
1822
    }
1823
}
1824
1825
/*
1826
* Permits to extract the file extension
1827
*/
1828
function getFileExtension($f)
1829
{
1830
    if (strpos($f, '.') === false) {
1831
        return $f;
1832
    }
1833
1834
    return substr($f, strrpos($f, '.') + 1);
1835
}