Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

main/auth/ldap/authldap.php (5 issues)

1
<?php
2
/* For licensing terms, see /license.txt */
3
/**
4
 *    LDAP module functions.
5
 *
6
 *    If the application uses LDAP, these functions are used
7
 *    for logging in, searching user info, adding this info
8
 *    to the Chamilo database...
9
    - function ldap_authentication_check()
10
    - function ldap_find_user_info()
11
    - function ldap_login()
12
    - function ldap_put_user_info_locally()
13
    - ldap_set_version()
14
15
    known bugs
16
    ----------
17
    - (fixed 18 june 2003) code has been internationalized
18
    - (fixed 07/05/2003) fixed some non-relative urls or includes
19
    - (fixed 28/04/2003) we now use global config.inc variables instead of local ones
20
    - (fixed 22/04/2003) the last name of a user was restricted to the first part
21
    - (fixed 11/04/2003) the user was never registered as a course manager
22
23
    version history
24
    ---------------
25
    This historial has been discontinued. Please use the Mercurial logs for more
26
    3.2 - updated to allow for specific term search for teachers identification
27
    3.1 - updated code to use database settings, to respect coding conventions
28
 *        as much as possible (camel-case removed) and to allow for non-anonymous login
29
    - Patrick Cool: fixing security hole
30
31
 *    @author Roan Embrechts
32
 *
33
 *    @version 3.0
34
 *
35
 *    @package chamilo.auth.ldap
36
 * Note:
37
 * If you are using a firewall, you might need to check port 389 is open in
38
 * order for Chamilo to communicate with the LDAP server.
39
 * See http://support.chamilo.org/issues/4675 for details.
40
 */
41
/**
42
 * Inclusions.
43
 */
44
use ChamiloSession as Session;
45
46
/**
47
 * Code.
48
 */
49
require_once api_get_path(SYS_CODE_PATH).'auth/external_login/ldap.inc.php';
50
require 'ldap_var.inc.php';
51
/**
52
 *    Check login and password with LDAP.
53
 *
54
 *    @return bool when login & password both OK, false otherwise
55
 *
56
 *    @author Roan Embrechts (based on code from Universit� Jean Monet)
57
 */
58
function ldap_login($login, $password)
59
{
60
    //error_log('Entering ldap_login('.$login.','.$password.')',0);
61
    $res = ldap_authentication_check($login, $password);
62
63
    // res=-1 -> the user does not exist in the ldap database
64
    // res=1 -> invalid password (user does exist)
65
66
    if ($res == 1) { //WRONG PASSWORD
67
        //$errorMessage = "LDAP User or password incorrect, try again.<br />";
68
        if (isset($log)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $log does not exist. Did you maybe mean $login?
Loading history...
69
            unset($log);
70
        }
71
        if (isset($uid)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $uid seems to never exist and therefore isset should always be false.
Loading history...
72
            unset($uid);
73
        }
74
        $loginLdapSucces = false;
75
    }
76
    if ($res == -1) { //WRONG USERNAME
77
        //$errorMessage =  "LDAP User or password incorrect, try again.<br />";
78
        $login_ldap_success = false;
79
    }
80
    if ($res == 0) { //LOGIN & PASSWORD OK - SUCCES
81
        //$errorMessage = "Successful login w/ LDAP.<br>";
82
        $login_ldap_success = true;
83
    }
84
85
    //$result = "This is the result: $errorMessage";
86
    $result = $login_ldap_success;
87
88
    return $result;
89
}
90
91
/**
92
 *    Find user info in LDAP.
93
 *
94
 *    @return array Array with indexes: "firstname", "name", "email", "employeenumber"
95
 *
96
 *    @author Stefan De Wannemacker
97
 *    @author Roan Embrechts
98
 */
99
function ldap_find_user_info($login)
100
{
101
    //error_log('Entering ldap_find_user_info('.$login.')',0);
102
    global $ldap_host, $ldap_port, $ldap_basedn, $ldap_rdn, $ldap_pass, $ldap_search_dn;
103
    // basic sequence with LDAP is connect, bind, search,
104
    // interpret search result, close connection
105
106
    //echo "Connecting ...";
107
    $ldap_connect = ldap_connect($ldap_host, $ldap_port);
108
    ldap_set_version($ldap_connect);
109
    if ($ldap_connect) {
110
        //echo " Connect to LDAP server successful ";
111
        //echo "Binding ...";
112
        $ldap_bind = false;
113
        $ldap_bind_res = ldap_handle_bind($ldap_connect, $ldap_bind);
114
        if ($ldap_bind_res) {
115
            //echo " LDAP bind successful... ";
116
            //echo " Searching for uid... ";
117
            // Search surname entry
118
            //OLD: $sr=ldap_search($ldapconnect,"dc=rug, dc=ac, dc=be", "uid=$login");
119
            //echo "<p> ldapDc = '$LDAPbasedn' </p>";
120
            if (!empty($ldap_search_dn)) {
121
                $sr = ldap_search($ldap_connect, $ldap_search_dn, "uid=$login");
122
            } else {
123
                $sr = ldap_search($ldap_connect, $ldap_basedn, "uid=$login");
124
            }
125
            //echo " Search result is ".$sr;
126
            //echo " Number of entries returned is ".ldap_count_entries($ldapconnect,$sr);
127
            //echo " Getting entries ...";
128
            $info = ldap_get_entries($ldap_connect, $sr);
129
            //echo "Data for ".$info["count"]." items returned:<p>";
130
        } // else could echo "LDAP bind failed...";
131
        //echo "Closing LDAP connection<hr>";
132
        ldap_close($ldap_connect);
133
    } // else could echo "<h3>Unable to connect to LDAP server</h3>";
134
    //DEBUG: $result["firstname"] = "Jan"; $result["name"] = "De Test"; $result["email"] = "[email protected]";
135
    $result["firstname"] = $info[0]["cn"][0];
136
    $result["name"] = $info[0]["sn"][0];
137
    $result["email"] = $info[0]["mail"][0];
138
    $tutor_field = api_get_setting('ldap_filled_tutor_field');
139
    $result[$tutor_field] = $info[0][$tutor_field]; //employeenumber by default
140
141
    return $result;
142
}
143
144
/**
145
 *    This function uses the data from ldap_find_user_info()
146
 *    to add the userdata to Chamilo
147
 *    "firstname", "name", "email", "isEmployee".
148
 *
149
 *    @author Roan Embrechts
150
 */
151
function ldap_put_user_info_locally($login, $info_array)
152
{
153
    //error_log('Entering ldap_put_user_info_locally('.$login.',info_array)',0);
154
    global $ldap_pass_placeholder;
155
    global $submitRegistration, $submit, $uname, $email,
156
            $nom, $prenom, $password, $password1, $status;
157
    global $platformLanguage;
158
    global $loginFailed, $uidReset, $_user;
159
160
    /*----------------------------------------------------------
161
        1. set the necessary variables
162
    ------------------------------------------------------------ */
163
    $uname = $login;
164
    $email = $info_array["email"];
165
    $nom = $info_array["name"];
166
    $prenom = $info_array["firstname"];
167
    $password = $ldap_pass_placeholder;
168
    $password1 = $ldap_pass_placeholder;
169
    $official_code = '';
170
171
    define("STUDENT", 5);
172
    define("COURSEMANAGER", 1);
173
174
    $tutor_field = api_get_setting('ldap_filled_tutor_field');
175
    $tutor_value = api_get_setting('ldap_filled_tutor_field_value');
176
    if (empty($tutor_field)) {
177
        $status = STUDENT;
178
    } else {
179
        if (empty($tutor_value)) {
180
            //in this case, we are assuming that the admin didn't give a criteria
181
            // so that if the field is not empty, it is a tutor
182
            if (!empty($info_array[$tutor_field])) {
183
                $status = COURSEMANAGER;
184
            } else {
185
                $status = STUDENT;
186
            }
187
        } else {
188
            //the tutor_value is filled, so we need to check the contents of the LDAP field
189
            if (is_array($info_array[$tutor_field]) && in_array($tutor_value, $info_array[$tutor_field])) {
190
                $status = COURSEMANAGER;
191
            } else {
192
                $status = STUDENT;
193
            }
194
        }
195
    }
196
    //$official_code = xxx; //example: choose an attribute
197
198
    /*----------------------------------------------------------
199
        2. add info to Chamilo
200
    ------------------------------------------------------------ */
201
202
    $language = api_get_setting('platformLanguage');
203
    if (empty($language)) {
204
        $language = 'english';
205
    }
206
    $_userId = UserManager::create_user(
207
        $prenom,
208
        $nom,
209
        $status,
210
        $email,
211
        $uname,
212
        $password,
213
        $official_code,
214
        $language,
215
        '',
216
        '',
217
        'ldap'
218
    );
219
220
    //echo "new user added to Chamilo, id = $_userId";
221
222
    //user_id, username, password, auth_source
223
224
    /*----------------------------------------------------------
225
        3. register session
226
    ------------------------------------------------------------ */
227
228
    $uData['user_id'] = $_userId;
229
    $uData['username'] = $uname;
230
    $uData['auth_source'] = "ldap";
231
232
    $loginFailed = false;
233
    $uidReset = true;
234
    $_user['user_id'] = $uData['user_id'];
235
    Session::write('_uid', $_user['user_id']);
236
}
237
238
/**
239
 * The code of UGent uses these functions to authenticate.
240
 * function AuthVerifEnseignant ($uname, $passwd)
241
 * function AuthVerifEtudiant ($uname, $passwd)
242
 * function Authentif ($uname, $passwd).
243
 *
244
 * @todo translate the comments and code to english
245
 * @todo let these functions use the variables in config.inc instead of ldap_var.inc
246
 */
247
/**
248
 * Checks the existence of a member in LDAP.
249
 *
250
 * @param string username input on keyboard
251
 * @param string password given by user
252
 *
253
 * @return int 0 if authentication succeeded, 1 if password was incorrect, -1 if it didn't belong to LDAP
254
 */
255
function ldap_authentication_check($uname, $passwd)
256
{
257
    //error_log('Entering ldap_authentication_check('.$uname.','.$passwd.')',0);
258
    global $ldap_host, $ldap_port, $ldap_basedn, $ldap_host2, $ldap_port2, $ldap_rdn, $ldap_pass;
259
    //error_log('Entering ldap_authentication_check('.$uname.','.$passwd.')',0);
260
    // Establish anonymous connection with LDAP server
261
    // Etablissement de la connexion anonyme avec le serveur LDAP
262
    $ds = ldap_connect($ldap_host, $ldap_port);
263
    ldap_set_version($ds);
264
265
    $test_bind = false;
266
    $test_bind_res = ldap_handle_bind($ds, $test_bind);
267
    //if problem, use the replica
268
    if ($test_bind_res === false) {
269
        $ds = ldap_connect($ldap_host2, $ldap_port2);
270
        ldap_set_version($ds);
271
    } // else: error_log('Connected to server '.$ldap_host);
272
    if ($ds !== false) {
273
        //Creation of filter containing values input by the user
274
        // Here it might be necessary to use $filter="(samaccountName=$uname)"; - see http://support.chamilo.org/issues/4675
275
        $filter = "(uid=$uname)";
276
        // Open anonymous LDAP connection
277
        $result = false;
278
        $ldap_bind_res = ldap_handle_bind($ds, $result);
279
        // Executing the search with the $filter parametr
280
        //error_log('Searching for '.$filter.' on LDAP server',0);
281
        $sr = ldap_search($ds, $ldap_basedn, $filter);
282
        $info = ldap_get_entries($ds, $sr);
283
        $dn = ($info[0]["dn"]);
284
        // debug !!    echo"<br> dn = $dn<br> pass = $passwd<br>";
285
        // closing 1st connection
286
        ldap_close($ds);
287
    }
288
289
    // test the Distinguish Name from the 1st connection
290
    if ($dn == "") {
291
        return -1; // doesn't belong to the addressbook
292
    }
293
    //bug ldap.. if password empty, return 1!
294
    if ($passwd == "") {
295
        return 1;
296
    }
297
    // Opening 2nd LDAP connection : Connection user for password check
298
    $ds = ldap_connect($ldap_host, $ldap_port);
299
    ldap_set_version($ds);
300
    if (!$test_bind) {
301
        $ds = ldap_connect($ldap_host2, $ldap_port2);
302
        ldap_set_version($ds);
303
    }
304
    // return in case of wrong password connection error
305
    if (@ldap_bind($ds, $dn, $passwd) === false) {
306
        return 1; // invalid password
307
    } else {// connection successfull
308
        return 0;
309
    }
310
} // end of check
311
/**
312
 * Set the protocol version with version from config file (enables LDAP version 3).
313
 *
314
 * @param    resource    resource LDAP connexion resource, passed by reference
315
 */
316
function ldap_set_version(&$resource)
317
{
318
    //error_log('Entering ldap_set_version(&$resource)',0);
319
    global $ldap_version;
320
    if ($ldap_version > 2) {
321
        ldap_set_option($resource, LDAP_OPT_PROTOCOL_VERSION, 3);
322
        //ok - don't do anything
323
        //failure - should switch back to version 2 by default
324
    }
325
}
326
/**
327
 * Handle bind (whether authenticated or not).
328
 *
329
 * @param    resource    The LDAP handler to which we are connecting (by reference)
330
 * @param    resource    The LDAP bind handler we will be modifying
331
 * @param bool $ldap_bind
332
 *
333
 * @return bool Status of the bind assignment. True for success, false for failure.
334
 */
335
function ldap_handle_bind(&$ldap_handler, &$ldap_bind)
336
{
337
    //error_log('Entering ldap_handle_bind(&$ldap_handler,&$ldap_bind)',0);
338
    global $ldap_rdn, $ldap_pass, $extldap_config;
339
    $ldap_rdn = $extldap_config['admin_dn'];
340
    $ldap_pass = $extldap_config['admin_password'];
341
    if (!empty($ldap_rdn) and !empty($ldap_pass)) {
342
        //error_log('Trying authenticated login :'.$ldap_rdn.'/'.$ldap_pass,0);
343
        $ldap_bind = ldap_bind($ldap_handler, $ldap_rdn, $ldap_pass);
344
        if (!$ldap_bind) {
345
            //error_log('Authenticated login failed',0);
346
            //try in anonymous mode, you never know...
347
            $ldap_bind = ldap_bind($ldap_handler);
348
        }
349
    } else {
350
        // this is an "anonymous" bind, typically read-only access:
351
        $ldap_bind = ldap_bind($ldap_handler);
352
    }
353
    if (!$ldap_bind) {
354
        return false;
355
    } else {
356
        //error_log('Login finally OK',0);
357
        return true;
358
    }
359
}
360
/**
361
 * Get the total number of users on the platform.
362
 *
363
 * @see SortableTable#get_total_number_of_items()
364
 *
365
 * @author    Mustapha Alouani
366
 */
367
function ldap_get_users()
368
{
369
    global $ldap_basedn, $ldap_host, $ldap_port, $ldap_rdn, $ldap_pass, $ldap_search_dn, $extldap_user_correspondance;
370
371
    $keyword_firstname = isset($_GET['keyword_firstname']) ? trim(Database::escape_string($_GET['keyword_firstname'])) : '';
372
    $keyword_lastname = isset($_GET['keyword_lastname']) ? trim(Database::escape_string($_GET['keyword_lastname'])) : '';
373
    $keyword_username = isset($_GET['keyword_username']) ? trim(Database::escape_string($_GET['keyword_username'])) : '';
374
    $keyword_type = isset($_GET['keyword_type']) ? Database::escape_string($_GET['keyword_type']) : '';
375
376
    $ldap_query = [];
377
378
    if ($keyword_username != "") {
379
        $ldap_query[] = str_replace('%username%', $keyword_username, $ldap_search_dn);
380
    } else {
381
        if ($keyword_lastname != "") {
382
            $ldap_query[] = "(".$extldap_user_correspondance['lastname']."=".$keyword_lastname."*)";
383
        }
384
        if ($keyword_firstname != "") {
385
            $ldap_query[] = "(".$extldap_user_correspondance['firstname']."=".$keyword_firstname."*)";
386
        }
387
    }
388
    if ($keyword_type != "" && $keyword_type != "all") {
389
        $ldap_query[] = "(employeeType=".$keyword_type.")";
390
    }
391
392
    if (count($ldap_query) > 1) {
393
        $str_query = "(& ";
394
        foreach ($ldap_query as $query) {
395
            $str_query .= " $query";
396
        }
397
        $str_query .= " )";
398
    } else {
399
        $str_query = count($ldap_query) > 0 ? $ldap_query[0] : null;
400
    }
401
402
    $ds = ldap_connect($ldap_host, $ldap_port);
403
    ldap_set_version($ds);
404
    if ($ds && count($ldap_query) > 0) {
405
        $r = false;
406
        $res = ldap_handle_bind($ds, $r);
407
        //$sr = ldap_search($ds, "ou=test-ou,$ldap_basedn", $str_query);
408
        $sr = ldap_search($ds, $ldap_basedn, $str_query);
409
        //echo "Le nombre de resultats est : ".ldap_count_entries($ds,$sr)."<p>";
410
        $info = ldap_get_entries($ds, $sr);
411
412
        return $info;
413
    } else {
414
        if (count($ldap_query) != 0) {
415
            echo Display::return_message(get_lang('LDAPConnectionError'), 'error');
416
        }
417
418
        return [];
419
    }
420
}
421
422
/**
423
 * Get the total number of users on the platform.
424
 *
425
 * @see SortableTable#get_total_number_of_items()
426
 *
427
 * @author    Mustapha Alouani
428
 */
429
function ldap_get_number_of_users()
430
{
431
    $info = ldap_get_users();
432
    if (count($info) > 0) {
433
        return $info['count'];
434
    } else {
435
        return 0;
436
    }
437
}
438
439
/**
440
 * Get the users to display on the current page.
441
 *
442
 * @see SortableTable#get_table_data($from)
443
 *
444
 * @author    Mustapha Alouani
445
 */
446
function ldap_get_user_data($from, $number_of_items, $column, $direction)
447
{
448
    global $extldap_user_correspondance;
449
450
    $users = [];
451
    $is_western_name_order = api_is_western_name_order();
452
    if (isset($_GET['submit'])) {
453
        $info = ldap_get_users();
454
        if ($info['count'] > 0) {
455
            for ($key = 0; $key < $info["count"]; $key++) {
456
                $user = [];
457
                // Get uid from dn
458
                //YW: this might be a variation between LDAP 2 and LDAP 3, but in LDAP 3, the uid is in
459
                //the corresponding index of the array
460
                //$dn_array=ldap_explode_dn($info[$key]["dn"],1);
461
                //$user[] = $dn_array[0]; // uid is first key
462
                //$user[] = $dn_array[0]; // uid is first key
463
                $user[] = $info[$key][$extldap_user_correspondance['username']][0];
464
                $user[] = $info[$key][$extldap_user_correspondance['username']][0];
465
                if ($is_western_name_order) {
466
                    $user[] = api_convert_encoding($info[$key][$extldap_user_correspondance['firstname']][0], api_get_system_encoding(), 'UTF-8');
467
                    $user[] = api_convert_encoding($info[$key][$extldap_user_correspondance['lastname']][0], api_get_system_encoding(), 'UTF-8');
468
                } else {
469
                    $user[] = api_convert_encoding($info[$key][$extldap_user_correspondance['firstname']][0], api_get_system_encoding(), 'UTF-8');
470
                    $user[] = api_convert_encoding($info[$key][$extldap_user_correspondance['lastname']][0], api_get_system_encoding(), 'UTF-8');
471
                }
472
                $user[] = $info[$key]['mail'][0];
473
                $user[] = $info[$key][$extldap_user_correspondance['username']][0];
474
                $users[] = $user;
475
            }
476
        } else {
477
            echo Display::return_message(get_lang('NoUser'), 'error');
478
        }
479
    }
480
481
    return $users;
482
}
483
484
/**
485
 * Build the modify-column of the table.
486
 *
487
 * @param int    $user_id    The user id
488
 * @param string $url_params
489
 *
490
 * @return string Some HTML-code with modify-buttons
491
 *
492
 * @author    Mustapha Alouani
493
 */
494
function modify_filter($user_id, $url_params, $row)
495
{
496
    $query_string = "id[]=".$row[0];
497
    if (!empty($_GET['id_session'])) {
498
        $query_string .= '&amp;id_session='.Security::remove_XSS($_GET['id_session']);
499
    }
500
    $icon = '';
501
    if (UserManager::is_username_available($user_id)) {
502
        $icon = 'invitation_friend.png';
503
    } else {
504
        $icon = 'reload.png';
505
    }
506
    //$url_params_id="id=".$row[0];
507
    $result = '<a href="ldap_users_list.php?action=add_user&amp;user_id='.$user_id.'&amp;'.$query_string.'&amp;sec_token='.Security::getTokenFromSession().'"  onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"), ENT_QUOTES, api_get_system_encoding()))."'".')) return false;">'.Display::return_icon($icon, get_lang('AddUsers')).'</a>';
508
509
    return $result;
510
}
511
512
/**
513
 * Adds a user to the Chamilo database or updates its data.
514
 *
515
 * @param    string    username (and uid inside LDAP)
516
 *
517
 * @author    Mustapha Alouani
518
 */
519
function ldap_add_user($login)
520
{
521
    if ($ldap_user = extldap_authenticate($login, 'nopass', true)) {
522
        return extldap_add_user_by_array($ldap_user);
523
    }
524
}
525
526
function ldap_add_user_by_array($data, $update_if_exists = true)
527
{
528
    $lastname = api_convert_encoding($data['sn'][0], api_get_system_encoding(), 'UTF-8');
529
    $firstname = api_convert_encoding($data['cn'][0], api_get_system_encoding(), 'UTF-8');
530
    $email = $data['mail'][0];
531
    // Get uid from dn
532
    $dn_array = ldap_explode_dn($data['dn'], 1);
533
    $username = $dn_array[0]; // uid is first key
534
    $outab[] = $data['edupersonprimaryaffiliation'][0]; // Here, "student"
535
    //$val = ldap_get_values_len($ds, $entry, "userPassword");
536
    //$val = ldap_get_values_len($ds, $data, "userPassword");
537
    //$password = $val[0];
538
    // TODO the password, if encrypted at the source, will be encrypted twice, which makes it useless. Try to fix that.
539
    $password = $data['userPassword'][0];
540
    $structure = $data['edupersonprimaryorgunitdn'][0];
541
    $array_structure = explode(",", $structure);
542
    $array_val = explode("=", $array_structure[0]);
543
    $etape = $array_val[1];
544
    $array_val = explode("=", $array_structure[1]);
545
    $annee = $array_val[1];
546
    // To ease management, we add the step-year (etape-annee) code
547
    $official_code = $etape."-".$annee;
548
    $auth_source = 'ldap';
549
    // No expiration date for students (recover from LDAP's shadow expiry)
550
    $expiration_date = '';
551
    $active = 1;
552
    if (empty($status)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $status seems to never exist and therefore empty should always be true.
Loading history...
553
        $status = 5;
554
    }
555
    if (empty($phone)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $phone seems to never exist and therefore empty should always be true.
Loading history...
556
        $phone = '';
557
    }
558
    if (empty($picture_uri)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $picture_uri seems to never exist and therefore empty should always be true.
Loading history...
559
        $picture_uri = '';
560
    }
561
    // Adding user
562
    $user_id = 0;
563
    if (UserManager::is_username_available($username)) {
564
        $user_id = UserManager::create_user(
565
            $firstname,
566
            $lastname,
567
            $status,
568
            $email,
569
            $username,
570
            $password,
571
            $official_code,
572
            api_get_setting('platformLanguage'),
573
            $phone,
574
            $picture_uri,
575
            $auth_source,
576
            $expiration_date,
577
            $active
578
        );
579
    } else {
580
        if ($update_if_exists) {
581
            $user = api_get_user_info($username);
582
            $user_id = $user['user_id'];
583
            UserManager::update_user(
584
                $user_id,
585
                $firstname,
586
                $lastname,
587
                $username,
588
                null,
589
                null,
590
                $email,
591
                $status,
592
                $official_code,
593
                $phone,
594
                $picture_uri,
595
                $expiration_date,
596
                $active
597
            );
598
        }
599
    }
600
601
    return $user_id;
602
}
603
604
/**
605
 * Adds a list of users to one session.
606
 *
607
 * @param    array    Array of user ids
608
 * @param    string    Course code
609
 */
610
function ldap_add_user_to_session($UserList, $id_session)
611
{
612
    // Database Table Definitions
613
    $tbl_session_rel_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
614
615
    $id_session = (int) $id_session;
616
    // Once users are imported in the users base, we can assign them to the session
617
    $result = Database::query("SELECT c_id FROM $tbl_session_rel_course WHERE session_id ='$id_session'");
618
    $CourseList = [];
619
    while ($row = Database::fetch_array($result)) {
620
        $CourseList[] = $row['c_id'];
621
    }
622
623
    SessionManager::insertUsersInCourses($UserList, $CourseList, $id_session);
624
}
625
626
/**
627
 * Synchronize users from the configured LDAP connection (in auth.conf.php). If
628
 * configured to disable old users,.
629
 *
630
 * @param bool $disableOldUsers Whether to disable users who have disappeared from LDAP (true) or just leave them be (default: false)
631
 * @param bool $deleteStudents  Go one step further and delete completely students missing from LDAP
632
 * @param bool $deleteTeachers  Go even one step further and also delete completely teachers missing from LDAP
633
 *
634
 * @return int Total number of users added (not counting possible removals)
635
 */
636
function syncro_users(
637
  $disableOldUsers = false,
638
  $deleteStudents = false,
639
  $deleteTeachers = false
640
) {
641
    global $ldap_basedn, $ldap_host, $ldap_port, $ldap_rdn, $ldap_pass, $ldap_search_dn, $debug;
642
    $i = 0;
643
    if ($debug) {
644
        error_log('Connecting... ('.__FUNCTION__.')');
645
    }
646
    $ldapConnect = ldap_connect($ldap_host, $ldap_port);
647
    ldap_set_version($ldapConnect);
648
    if ($ldapConnect) {
649
        if ($debug) {
650
            error_log('Connected to LDAP server successfully! Binding... ('.__FUNCTION__.')');
651
        }
652
        $ldapBind = false;
653
        $ldapBindRes = ldap_handle_bind($ldapConnect, $ldapBind);
654
        if ($ldapBindRes) {
655
            if ($debug) {
656
                error_log('Bind successful! Searching for uid in LDAP DC: '.$ldap_search_dn);
657
            }
658
            $allUserQuery = "uid=*";
659
            if (!empty($ldap_search_dn)) {
660
                $sr = ldap_search($ldapConnect, $ldap_search_dn, $allUserQuery);
661
            } else {
662
                //OLD: $sr=ldap_search($ldapconnect,"dc=rug, dc=ac, dc=be", "uid=$login");
663
                $sr = ldap_search($ldapConnect, $ldap_basedn, $allUserQuery);
664
            }
665
            if ($debug) {
666
                error_log('Entries returned: '.ldap_count_entries($ldapConnect, $sr));
667
            }
668
            $info = ldap_get_entries($ldapConnect, $sr);
669
            for ($key = 0; $key < $info['count']; $key++) {
670
                $user_id = ldap_add_user_by_array($info[$key], false);
671
                if ($user_id) {
672
                    if ($debug) {
673
                        error_log('User #'.$user_id.' created from LDAP');
674
                    }
675
                    $i++;
676
                } else {
677
                    if ($debug) {
678
                        error_log('User '.$info[$key]['sn'][0].' ('.$info[$key]['mail'][0].') could not be created');
679
                    }
680
                }
681
            }
682
            if ($disableOldUsers === true) {
683
                if ($debug) {
684
                    error_log('Disable mode selected in '.__FUNCTION__);
685
                    if ($deleteStudents) {
686
                        error_log('...with complete deletion of users if disabled');
687
                    }
688
                }
689
                // Get a big array of all user IDs, usernames only if they are
690
                // registered as auth_source = 'ldap'
691
                // This array will take about 60 bytes per user in memory, so
692
                // having  100K users should only take a few (6?) MB and will
693
                // highly reduce the number of DB queries
694
                $usersDBShortList = [];
695
                $usersLDAPShortList = [];
696
                $sql = "SELECT id, username, status FROM user WHERE auth_source = 'ldap' ORDER BY username";
697
                $res = Database::query($sql);
698
                if ($res !== false) {
699
                    // First build a list of users present in LDAP
700
                    for ($key = 0; $key < $info['count']; $key++) {
701
                        $dn_array = ldap_explode_dn($info[$key]['dn'], 1);
702
                        $usersLDAPShortList[$dn_array[0]] = 1;
703
                    }
704
                    // Go through all 'extldap' users. For any that cannot
705
                    // be found in the LDAP list, disable
706
                    while ($row = Database::fetch_assoc($res)) {
707
                        $usersDBShortList[$row['username']] = $row['id'];
708
                        // If any of those users is NOT in LDAP, disable or remove
709
                        if (empty($usersLDAPShortList[$row['username']])) {
710
                            if ($deleteStudents === true && $row['status'] == 5) {
711
                                UserManager::delete_user($usersDBShortList[$row['username']]);
712
                                if ($debug) {
713
                                    error_log('Student '.$row['username'].' removed from Chamilo');
714
                                }
715
                            } elseif ($deleteTeachers === true && $row['status'] == 1) {
716
                                UserManager::delete_user($usersDBShortList[$row['username']]);
717
                                if ($debug) {
718
                                    error_log('Teacher '.$row['username'].' removed from Chamilo');
719
                                }
720
                            } else {
721
                                UserManager::disable($usersDBShortList[$row['username']]);
722
                                if ($debug) {
723
                                    error_log('User '.$row['username'].' disabled in Chamilo');
724
                                }
725
                            }
726
                        }
727
                    }
728
                }
729
            }
730
            if ($debug) {
731
                error_log('Data for '.$info['count'].' items processed');
732
            }
733
            //echo "Data for ".$info["count"]." items returned:<p>";
734
        } else {
735
            error_log('Could not bind to LDAP server');
736
        }
737
        ldap_close($ldapConnect);
738
    } else {
739
        error_log('Could not connect to LDAP server');
740
    }
741
    error_log('Ended execution of function '.__FUNCTION__);
742
}
743