Commit | Line | Data |
---|---|---|
a7aff74f PS |
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_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.'); | |
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(4, $DB->count_records('user', array('auth'=>'ldap'))); | |
173 | $this->assertEquals(1, $DB->count_records('user', array('auth'=>'nologin', 'username'=>'username1'))); | |
174 | $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); | |
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 | ||
192 | set_config('removeuser', AUTH_REMOVEUSER_FULLDELETE, 'auth/ldap'); | |
193 | ||
194 | /** @var auth_plugin_ldap $auth */ | |
195 | $auth = get_auth_plugin('ldap'); | |
196 | ||
197 | $this->delete_ldap_user($connection, $topdn, 1); | |
198 | ||
199 | ob_start(); | |
200 | $auth->sync_users(true); | |
201 | ob_end_clean(); | |
202 | ||
203 | $this->assertEquals(5, $DB->count_records('user', array('auth'=>'ldap'))); | |
204 | $this->assertEquals(0, $DB->count_records('user', array('username'=>'username1'))); | |
205 | $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); | |
206 | $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); | |
207 | $this->assertEquals(1, $DB->count_records('role_assignments')); | |
208 | $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); | |
209 | ||
210 | $this->create_ldap_user($connection, $topdn, 1); | |
211 | ||
212 | ob_start(); | |
213 | $auth->sync_users(true); | |
214 | ob_end_clean(); | |
215 | ||
216 | $this->assertEquals(6, $DB->count_records('user', array('auth'=>'ldap'))); | |
217 | $this->assertEquals(1, $DB->count_records('user', array('username'=>'username1'))); | |
218 | $this->assertEquals(0, $DB->count_records('user', array('suspended'=>1))); | |
219 | $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); | |
220 | $this->assertEquals(2, $DB->count_records('role_assignments')); | |
221 | $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$creatorrole->id))); | |
222 | ||
223 | ||
224 | $this->recursive_delete($connection, TEST_AUTH_LDAP_DOMAIN, 'dc=moodletest'); | |
225 | ldap_close($connection); | |
226 | } | |
227 | ||
228 | protected function create_ldap_user($connection, $topdn, $i) { | |
229 | $o = array(); | |
230 | $o['objectClass'] = array('inetOrgPerson', 'organizationalPerson', 'person', 'posixAccount'); | |
231 | $o['cn'] = 'username'.$i; | |
232 | $o['sn'] = 'Lastname'.$i; | |
233 | $o['givenName'] = 'Firstname'.$i; | |
234 | $o['uid'] = $o['cn']; | |
235 | $o['uidnumber'] = 2000+$i; | |
236 | $o['gidNumber'] = 1000+$i; | |
237 | $o['homeDirectory'] = '/'; | |
238 | $o['mail'] = 'user'.$i.'@example.com'; | |
239 | $o['userPassword'] = 'pass'.$i; | |
240 | ldap_add($connection, 'cn='.$o['cn'].',ou=users,'.$topdn, $o); | |
241 | } | |
242 | ||
243 | protected function delete_ldap_user($connection, $topdn, $i) { | |
244 | ldap_delete($connection, 'cn=username'.$i.',ou=users,'.$topdn); | |
245 | } | |
246 | ||
247 | protected function enable_plugin() { | |
248 | $auths = get_enabled_auth_plugins(true); | |
249 | if (!in_array('ldap', $auths)) { | |
250 | $auths[] = 'ldap'; | |
251 | ||
252 | } | |
253 | set_config('auth', implode(',', $auths)); | |
254 | } | |
255 | ||
256 | protected function recursive_delete($connection, $dn, $filter) { | |
257 | if ($res = ldap_list($connection, $dn, $filter, array('dn'))) { | |
258 | $info = ldap_get_entries($connection, $res); | |
259 | ldap_free_result($res); | |
260 | if ($info['count'] > 0) { | |
261 | if ($res = ldap_search($connection, "$filter,$dn", 'cn=*', array('dn'))) { | |
262 | $info = ldap_get_entries($connection, $res); | |
263 | ldap_free_result($res); | |
264 | foreach ($info as $i) { | |
265 | if (isset($i['dn'])) { | |
266 | ldap_delete($connection, $i['dn']); | |
267 | } | |
268 | } | |
269 | } | |
270 | if ($res = ldap_search($connection, "$filter,$dn", 'ou=*', array('dn'))) { | |
271 | $info = ldap_get_entries($connection, $res); | |
272 | ldap_free_result($res); | |
273 | foreach ($info as $i) { | |
274 | if (isset($i['dn']) and $info[0]['dn'] != $i['dn']) { | |
275 | ldap_delete($connection, $i['dn']); | |
276 | } | |
277 | } | |
278 | } | |
279 | ldap_delete($connection, "$filter,$dn"); | |
280 | } | |
281 | } | |
282 | } | |
283 | } |