[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * LDAP authentication plugin tests. 19 * 20 * NOTE: in order to execute this test you need to set up 21 * OpenLDAP server with core, cosine, nis and internet schemas 22 * and add configuration constants to config.php or phpunit.xml configuration file: 23 * 24 * define('TEST_AUTH_LDAP_HOST_URL', 'ldap://127.0.0.1'); 25 * define('TEST_AUTH_LDAP_BIND_DN', 'cn=someuser,dc=example,dc=local'); 26 * define('TEST_AUTH_LDAP_BIND_PW', 'somepassword'); 27 * define('TEST_AUTH_LDAP_DOMAIN', 'dc=example,dc=local'); 28 * 29 * @package auth_ldap 30 * @category phpunit 31 * @copyright 2013 Petr Skoda {@link http://skodak.org} 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 35 defined('MOODLE_INTERNAL') || die(); 36 37 class auth_ldap_plugin_testcase extends advanced_testcase { 38 39 public function test_auth_ldap() { 40 global $CFG, $DB; 41 42 if (!extension_loaded('ldap')) { 43 $this->markTestSkipped('LDAP extension is not loaded.'); 44 } 45 46 $this->resetAfterTest(); 47 48 require_once($CFG->dirroot.'/auth/ldap/auth.php'); 49 require_once($CFG->libdir.'/ldaplib.php'); 50 51 if (!defined('TEST_AUTH_LDAP_HOST_URL') or !defined('TEST_AUTH_LDAP_BIND_DN') or !defined('TEST_AUTH_LDAP_BIND_PW') or !defined('TEST_AUTH_LDAP_DOMAIN')) { 52 $this->markTestSkipped('External LDAP test server not configured.'); 53 } 54 55 // Make sure we can connect the server. 56 $debuginfo = ''; 57 if (!$connection = ldap_connect_moodle(TEST_AUTH_LDAP_HOST_URL, 3, 'rfc2307', TEST_AUTH_LDAP_BIND_DN, TEST_AUTH_LDAP_BIND_PW, LDAP_DEREF_NEVER, $debuginfo, false)) { 58 $this->markTestSkipped('Can not connect to LDAP test server: '.$debuginfo); 59 } 60 61 $this->enable_plugin(); 62 63 // Create new empty test container. 64 $topdn = 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN; 65 66 $this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest'); 67 68 $o = array(); 69 $o['objectClass'] = array('dcObject', 'organizationalUnit'); 70 $o['dc'] = 'moodletest'; 71 $o['ou'] = 'MOODLETEST'; 72 if (!ldap_add($connection, 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN, $o)) { 73 $this->markTestSkipped('Can not create test LDAP container.'); 74 } 75 76 // Create a few users. 77 $o = array(); 78 $o['objectClass'] = array('organizationalUnit'); 79 $o['ou'] = 'users'; 80 ldap_add($connection, 'ou='.$o['ou'].','.$topdn, $o); 81 82 for ($i=1; $i<=5; $i++) { 83 $this->create_ldap_user($connection, $topdn, $i); 84 } 85 86 // Set up creators group. 87 $o = array(); 88 $o['objectClass'] = array('posixGroup'); 89 $o['cn'] = 'creators'; 90 $o['gidNumber'] = 1; 91 $o['memberUid'] = array('username1', 'username2'); 92 ldap_add($connection, 'cn='.$o['cn'].','.$topdn, $o); 93 94 $creatorrole = $DB->get_record('role', array('shortname'=>'coursecreator')); 95 $this->assertNotEmpty($creatorrole); 96 97 98 // Configure the plugin a bit. 99 set_config('host_url', TEST_AUTH_LDAP_HOST_URL, 'auth/ldap'); 100 set_config('start_tls', 0, 'auth/ldap'); 101 set_config('ldap_version', 3, 'auth/ldap'); 102 set_config('ldapencoding', 'utf-8', 'auth/ldap'); 103 set_config('pagesize', '2', 'auth/ldap'); 104 set_config('bind_dn', TEST_AUTH_LDAP_BIND_DN, 'auth/ldap'); 105 set_config('bind_pw', TEST_AUTH_LDAP_BIND_PW, 'auth/ldap'); 106 set_config('user_type', 'rfc2307', 'auth/ldap'); 107 set_config('contexts', 'ou=users,'.$topdn, 'auth/ldap'); 108 set_config('search_sub', 0, 'auth/ldap'); 109 set_config('opt_deref', LDAP_DEREF_NEVER, 'auth/ldap'); 110 set_config('user_attribute', 'cn', 'auth/ldap'); 111 set_config('memberattribute', 'memberuid', 'auth/ldap'); 112 set_config('memberattribute_isdn', 0, 'auth/ldap'); 113 set_config('creators', 'cn=creators,'.$topdn, 'auth/ldap'); 114 set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth/ldap'); 115 116 set_config('field_map_email', 'mail', 'auth/ldap'); 117 set_config('field_updatelocal_email', 'oncreate', 'auth/ldap'); 118 set_config('field_updateremote_email', '0', 'auth/ldap'); 119 set_config('field_lock_email', 'unlocked', 'auth/ldap'); 120 121 set_config('field_map_firstname', 'givenName', 'auth/ldap'); 122 set_config('field_updatelocal_firstname', 'oncreate', 'auth/ldap'); 123 set_config('field_updateremote_firstname', '0', 'auth/ldap'); 124 set_config('field_lock_firstname', 'unlocked', 'auth/ldap'); 125 126 set_config('field_map_lastname', 'sn', 'auth/ldap'); 127 set_config('field_updatelocal_lastname', 'oncreate', 'auth/ldap'); 128 set_config('field_updateremote_lastname', '0', 'auth/ldap'); 129 set_config('field_lock_lastname', 'unlocked', 'auth/ldap'); 130 131 132 $this->assertEquals(2, $DB->count_records('user')); 133 $this->assertEquals(0, $DB->count_records('role_assignments')); 134 135 /** @var auth_plugin_ldap $auth */ 136 $auth = get_auth_plugin('ldap'); 137 138 ob_start(); 139 $auth->sync_users(true); 140 ob_end_clean(); 141 142 $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap'))); 143 $this->assertEquals(2, $DB->count_records('role_assignments')); 144 $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); 145 146 for ($i=1; $i<=5; $i++) { 147 $this->assertTrue($DB->record_exists('user', array('username'=>'username'.$i, 'email'=>'user'.$i.'@example.com', 'firstname'=>'Firstname'.$i, 'lastname'=>'Lastname'.$i))); 148 } 149 150 $this->delete_ldap_user($connection, $topdn, 1); 151 152 ob_start(); 153 $auth->sync_users(true); 154 ob_end_clean(); 155 156 $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap'))); 157 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 158 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 159 $this->assertEquals(2, $DB->count_records('role_assignments')); 160 $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); 161 162 163 set_config('removeuser', AUTH_REMOVEUSER_SUSPEND, 'auth/ldap'); 164 165 /** @var auth_plugin_ldap $auth */ 166 $auth = get_auth_plugin('ldap'); 167 168 ob_start(); 169 $auth->sync_users(true); 170 ob_end_clean(); 171 172 $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap'))); 173 $this->assertEquals(0, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1'))); 174 $this->assertEquals(1, $DB->count_records('user', array('auth'=>'ldap', 'suspended'=>'1', 'username'=>'username1'))); 175 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 176 $this->assertEquals(2, $DB->count_records('role_assignments')); 177 $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); 178 179 $this->create_ldap_user($connection, $topdn, 1); 180 181 ob_start(); 182 $auth->sync_users(true); 183 ob_end_clean(); 184 185 $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap'))); 186 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 187 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 188 $this->assertEquals(2, $DB->count_records('role_assignments')); 189 $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); 190 191 $DB->set_field('user', 'auth', 'nologin', array('username'=>'username1')); 192 193 ob_start(); 194 $auth->sync_users(true); 195 ob_end_clean(); 196 197 $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap'))); 198 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 199 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 200 $this->assertEquals(2, $DB->count_records('role_assignments')); 201 $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); 202 203 set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth/ldap'); 204 205 /** @var auth_plugin_ldap $auth */ 206 $auth = get_auth_plugin('ldap'); 207 208 $this->delete_ldap_user($connection, $topdn, 1); 209 210 ob_start(); 211 $auth->sync_users(true); 212 ob_end_clean(); 213 214 $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap'))); 215 $this->assertEquals(0, $DB->count_records('user', array('username'=>'username1'))); 216 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 217 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); 218 $this->assertEquals(1, $DB->count_records('role_assignments')); 219 $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); 220 221 $this->create_ldap_user($connection, $topdn, 1); 222 223 ob_start(); 224 $auth->sync_users(true); 225 ob_end_clean(); 226 227 $this->assertEquals(6, $DB->count_records('user', array('auth'=>'ldap'))); 228 $this->assertEquals(1, $DB->count_records('user', array('username'=>'username1'))); 229 $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); 230 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); 231 $this->assertEquals(2, $DB->count_records('role_assignments')); 232 $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); 233 234 235 $this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest'); 236 ldap_close($connection); 237 } 238 239 /** 240 * Test logging in via LDAP calls a user_loggedin event. 241 */ 242 public function test_ldap_user_loggedin_event() { 243 global $CFG, $DB, $USER; 244 245 require_once($CFG->dirroot . '/auth/ldap/auth.php'); 246 247 $this->resetAfterTest(); 248 249 $this->assertFalse(isloggedin()); 250 $user = $DB->get_record('user', array('username'=>'admin')); 251 252 // Note: we are just going to trigger the function that calls the event, 253 // not actually perform a LDAP login, for the sake of sanity. 254 $ldap = new auth_plugin_ldap(); 255 256 // Set the key for the cache flag we want to set which is used by LDAP. 257 set_cache_flag($ldap->pluginconfig . '/ntlmsess', sesskey(), $user->username, AUTH_NTLMTIMEOUT); 258 259 // We are going to need to set the sesskey as the user's password in order for the LDAP log in to work. 260 update_internal_user_password($user, sesskey()); 261 262 // The function ntlmsso_finish is responsible for triggering the event, so call it directly and catch the event. 263 $sink = $this->redirectEvents(); 264 // We need to supress this function call, or else we will get the message "session_regenerate_id(): Cannot 265 // regenerate session id - headers already sent" as the ntlmsso_finish function calls complete_user_login 266 @$ldap->ntlmsso_finish(); 267 $events = $sink->get_events(); 268 $sink->close(); 269 270 // Check that the event is valid. 271 $this->assertCount(1, $events); 272 $event = reset($events); 273 $this->assertInstanceOf('\core\event\user_loggedin', $event); 274 $this->assertEquals('user', $event->objecttable); 275 $this->assertEquals('2', $event->objectid); 276 $this->assertEquals(context_system::instance()->id, $event->contextid); 277 $expectedlog = array(SITEID, 'user', 'login', 'view.php?id=' . $USER->id . '&course=' . SITEID, $user->id, 278 0, $user->id); 279 $this->assertEventLegacyLogData($expectedlog, $event); 280 } 281 282 /** 283 * Test logging in via LDAP calls a user_loggedin event. 284 */ 285 public function test_ldap_user_signup() { 286 global $CFG, $DB; 287 288 // User to create. 289 $user = array( 290 'username' => 'usersignuptest1', 291 'password' => 'Moodle2014!', 292 'idnumber' => 'idsignuptest1', 293 'firstname' => 'First Name User Test 1', 294 'lastname' => 'Last Name User Test 1', 295 'middlename' => 'Middle Name User Test 1', 296 'lastnamephonetic' => '最後のお名前のテスト一号', 297 'firstnamephonetic' => 'お名前のテスト一号', 298 'alternatename' => 'Alternate Name User Test 1', 299 'email' => '[email protected]', 300 'description' => 'This is a description for user 1', 301 'city' => 'Perth', 302 'country' => 'au', 303 'mnethostid' => $CFG->mnet_localhost_id, 304 'auth' => 'ldap' 305 ); 306 307 if (!extension_loaded('ldap')) { 308 $this->markTestSkipped('LDAP extension is not loaded.'); 309 } 310 311 $this->resetAfterTest(); 312 313 require_once($CFG->dirroot.'/auth/ldap/auth.php'); 314 require_once($CFG->libdir.'/ldaplib.php'); 315 316 if (!defined('TEST_AUTH_LDAP_HOST_URL') or !defined('TEST_AUTH_LDAP_BIND_DN') or !defined('TEST_AUTH_LDAP_BIND_PW') or !defined('TEST_AUTH_LDAP_DOMAIN')) { 317 $this->markTestSkipped('External LDAP test server not configured.'); 318 } 319 320 // Make sure we can connect the server. 321 $debuginfo = ''; 322 if (!$connection = ldap_connect_moodle(TEST_AUTH_LDAP_HOST_URL, 3, 'rfc2307', TEST_AUTH_LDAP_BIND_DN, TEST_AUTH_LDAP_BIND_PW, LDAP_DEREF_NEVER, $debuginfo, false)) { 323 $this->markTestSkipped('Can not connect to LDAP test server: '.$debuginfo); 324 } 325 326 $this->enable_plugin(); 327 328 // Create new empty test container. 329 $topdn = 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN; 330 331 $this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest'); 332 333 $o = array(); 334 $o['objectClass'] = array('dcObject', 'organizationalUnit'); 335 $o['dc'] = 'moodletest'; 336 $o['ou'] = 'MOODLETEST'; 337 if (!ldap_add($connection, 'dc=moodletest,'.TEST_AUTH_LDAP_DOMAIN, $o)) { 338 $this->markTestSkipped('Can not create test LDAP container.'); 339 } 340 341 // Create a few users. 342 $o = array(); 343 $o['objectClass'] = array('organizationalUnit'); 344 $o['ou'] = 'users'; 345 ldap_add($connection, 'ou='.$o['ou'].','.$topdn, $o); 346 347 // Configure the plugin a bit. 348 set_config('host_url', TEST_AUTH_LDAP_HOST_URL, 'auth/ldap'); 349 set_config('start_tls', 0, 'auth/ldap'); 350 set_config('ldap_version', 3, 'auth/ldap'); 351 set_config('ldapencoding', 'utf-8', 'auth/ldap'); 352 set_config('pagesize', '2', 'auth/ldap'); 353 set_config('bind_dn', TEST_AUTH_LDAP_BIND_DN, 'auth/ldap'); 354 set_config('bind_pw', TEST_AUTH_LDAP_BIND_PW, 'auth/ldap'); 355 set_config('user_type', 'rfc2307', 'auth/ldap'); 356 set_config('contexts', 'ou=users,'.$topdn, 'auth/ldap'); 357 set_config('search_sub', 0, 'auth/ldap'); 358 set_config('opt_deref', LDAP_DEREF_NEVER, 'auth/ldap'); 359 set_config('user_attribute', 'cn', 'auth/ldap'); 360 set_config('memberattribute', 'memberuid', 'auth/ldap'); 361 set_config('memberattribute_isdn', 0, 'auth/ldap'); 362 set_config('creators', 'cn=creators,'.$topdn, 'auth/ldap'); 363 set_config('removeuser', AUTH_REMOVEUSER_KEEP, 'auth/ldap'); 364 365 set_config('field_map_email', 'mail', 'auth/ldap'); 366 set_config('field_updatelocal_email', 'oncreate', 'auth/ldap'); 367 set_config('field_updateremote_email', '0', 'auth/ldap'); 368 set_config('field_lock_email', 'unlocked', 'auth/ldap'); 369 370 set_config('field_map_firstname', 'givenName', 'auth/ldap'); 371 set_config('field_updatelocal_firstname', 'oncreate', 'auth/ldap'); 372 set_config('field_updateremote_firstname', '0', 'auth/ldap'); 373 set_config('field_lock_firstname', 'unlocked', 'auth/ldap'); 374 375 set_config('field_map_lastname', 'sn', 'auth/ldap'); 376 set_config('field_updatelocal_lastname', 'oncreate', 'auth/ldap'); 377 set_config('field_updateremote_lastname', '0', 'auth/ldap'); 378 set_config('field_lock_lastname', 'unlocked', 'auth/ldap'); 379 set_config('passtype', 'md5', 'auth/ldap'); 380 set_config('create_context', 'ou=users,'.$topdn, 'auth/ldap'); 381 382 $this->assertEquals(2, $DB->count_records('user')); 383 $this->assertEquals(0, $DB->count_records('role_assignments')); 384 385 /** @var auth_plugin_ldap $auth */ 386 $auth = get_auth_plugin('ldap'); 387 388 $sink = $this->redirectEvents(); 389 $auth->user_signup((object)$user, false); 390 $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting'); 391 $events = $sink->get_events(); 392 $sink->close(); 393 394 // Verify 2 events get generated. 395 $this->assertCount(2, $events); 396 397 // Get record from db. 398 $dbuser = $DB->get_record('user', array('username' => $user['username'])); 399 $user['id'] = $dbuser->id; 400 401 // Last event is user_created. 402 $event = array_pop($events); 403 $this->assertInstanceOf('\core\event\user_created', $event); 404 $this->assertEquals($user['id'], $event->objectid); 405 $this->assertEquals('user_created', $event->get_legacy_eventname()); 406 $this->assertEquals(context_user::instance($user['id']), $event->get_context()); 407 $expectedlogdata = array(SITEID, 'user', 'add', '/view.php?id='.$event->objectid, fullname($dbuser)); 408 $this->assertEventLegacyLogData($expectedlogdata, $event); 409 410 // First event is user_password_updated. 411 $event = array_pop($events); 412 $this->assertInstanceOf('\core\event\user_password_updated', $event); 413 $this->assertEventContextNotUsed($event); 414 415 // Delete user which we just created. 416 ldap_delete($connection, 'cn='.$user['username'].',ou=users,'.$topdn); 417 } 418 419 protected function create_ldap_user($connection, $topdn, $i) { 420 $o = array(); 421 $o['objectClass'] = array('inetOrgPerson', 'organizationalPerson', 'person', 'posixAccount'); 422 $o['cn'] = 'username'.$i; 423 $o['sn'] = 'Lastname'.$i; 424 $o['givenName'] = 'Firstname'.$i; 425 $o['uid'] = $o['cn']; 426 $o['uidnumber'] = 2000+$i; 427 $o['gidNumber'] = 1000+$i; 428 $o['homeDirectory'] = '/'; 429 $o['mail'] = 'user'.$i.'@example.com'; 430 $o['userPassword'] = 'pass'.$i; 431 ldap_add($connection, 'cn='.$o['cn'].',ou=users,'.$topdn, $o); 432 } 433 434 protected function delete_ldap_user($connection, $topdn, $i) { 435 ldap_delete($connection, 'cn=username'.$i.',ou=users,'.$topdn); 436 } 437 438 protected function enable_plugin() { 439 $auths = get_enabled_auth_plugins(true); 440 if (!in_array('ldap', $auths)) { 441 $auths[] = 'ldap'; 442 443 } 444 set_config('auth', implode(',', $auths)); 445 } 446 447 protected function recursive_delete($connection, $dn, $filter) { 448 if ($res = ldap_list($connection, $dn, $filter, array('dn'))) { 449 $info = ldap_get_entries($connection, $res); 450 ldap_free_result($res); 451 if ($info['count'] > 0) { 452 if ($res = ldap_search($connection, "$filter,$dn", 'cn=*', array('dn'))) { 453 $info = ldap_get_entries($connection, $res); 454 ldap_free_result($res); 455 foreach ($info as $i) { 456 if (isset($i['dn'])) { 457 ldap_delete($connection, $i['dn']); 458 } 459 } 460 } 461 if ($res = ldap_search($connection, "$filter,$dn", 'ou=*', array('dn'))) { 462 $info = ldap_get_entries($connection, $res); 463 ldap_free_result($res); 464 foreach ($info as $i) { 465 if (isset($i['dn']) and $info[0]['dn'] != $i['dn']) { 466 ldap_delete($connection, $i['dn']); 467 } 468 } 469 } 470 ldap_delete($connection, "$filter,$dn"); 471 } 472 } 473 } 474 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |