# Code Coverage for /Volumes/Rest/Dev/Sites/authLDAP/authLdap.php

| Code Coverage
| Classes and Traits | Functions and Methods | Lines
Total | 100.00% covered (success) |  | 0 / 0 | 100.00% covered (success) | 100.00% | 0 / 0 | CRAP | 0.00% covered (danger) | 0.00% | 0 / 476
authLdap_debug | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 5
authLdap_addmenu | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 5
authLdap_get_post | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 3
authLdap_options_panel | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 59
authLdap_get_server | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 10
authLdap_login | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 177
authLdap_get_uid | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 15
authLdap_user_role | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 15
authLdap_groupmap | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 47
authLdap_show_password_fields | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 9
authLdap_allow_password_reset | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 9
authLdap_sort_roles_by_capabilities | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 14
authLdap_sortByCapabilitycount | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 9
authLdap_load_options | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 65
authLdap_get_option | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 9
authLdap_set_options | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 12
authLdap_send_change_email | 0.00% covered (danger) | 0.00% | 0 / 1 | 0 | 0.00% covered (danger) | 0.00% | 0 / 6

1 | <?php
2 | /*
3 | Plugin Name: AuthLDAP
4 | Plugin URI: https://github.com/heiglandreas/authLdap
5 | Description: This plugin allows you to use your existing LDAP as authentication base for WordPress
6 | Version: 1.4.18
7 | Author: Andreas Heigl <a.heigl@wdv.de>
8 | Author URI: http://andreas.heigl.org
9 | */
10 |
11 | require_once dirname(__FILE__) . '/ldap.php';
12 |
13 | function authLdap_debug($message)
14 | {
15 | if (authLdap_get_option('Debug')) {
16 | error_log('[AuthLDAP] ' . $message, 0);
17 | }
18 | }
19 |
20 |
21 | function authLdap_addmenu()
22 | {
23 | if (function_exists('add_options_page')) {
24 | add_options_page('AuthLDAP', 'AuthLDAP', 'manage_options', basename(__FILE__), 'authLdap_options_panel');
25 | }
26 | }
27 |
28 | function authLdap_get_post($name, $default = '')
29 | {
30 | return isset($_POST[$name]) ? $_POST[$name] : $default;
31 | }
32 |
33 | function authLdap_options_panel()
34 | {
35 | // inclusde style sheet
36 | wp_enqueue_style('authLdap-style', plugin_dir_url(__FILE__) . 'authLdap.css');
37 |
38 | if (($_SERVER['REQUEST_METHOD'] == 'POST') && array_key_exists('ldapOptionsSave', $_POST)) {
39 | $new_options = array(
40 | 'Enabled' => authLdap_get_post('authLDAPAuth', false),
41 | 'CachePW' => authLdap_get_post('authLDAPCachePW', false),
42 | 'URI' => authLdap_get_post('authLDAPURI'),
43 | 'Filter' => authLdap_get_post('authLDAPFilter'),
44 | 'NameAttr' => authLdap_get_post('authLDAPNameAttr'),
45 | 'SecName' => authLdap_get_post('authLDAPSecName'),
46 | 'UidAttr' => authLdap_get_post('authLDAPUidAttr'),
47 | 'MailAttr' => authLdap_get_post('authLDAPMailAttr'),
48 | 'WebAttr' => authLdap_get_post('authLDAPWebAttr'),
49 | 'Groups' => authLdap_get_post('authLDAPGroups', array()),
50 | 'GroupSeparator'=> authLdap_get_post('authLDAPGroupSeparator', ','),
51 | 'Debug' => authLdap_get_post('authLDAPDebug', false),
52 | 'GroupAttr' => authLdap_get_post('authLDAPGroupAttr'),
53 | 'GroupFilter' => authLdap_get_post('authLDAPGroupFilter'),
54 | 'DefaultRole' => authLdap_get_post('authLDAPDefaultRole'),
55 | 'GroupEnable' => authLdap_get_post('authLDAPGroupEnable', false),
56 | 'GroupOverUser' => authLdap_get_post('authLDAPGroupOverUser', false),
57 | );
58 | if (authLdap_set_options($new_options)) {
59 | echo "<div class='updated'><p>Saved Options!</p></div>";
60 | } else {
61 | echo "<div class='error'><p>Could not save Options!</p></div>";
62 | }
63 | }
64 |
65 | // Do some initialization for the admin-view
66 | $authLDAP = authLdap_get_option('Enabled');
67 | $authLDAPCachePW = authLdap_get_option('CachePW');
68 | $authLDAPURI = authLdap_get_option('URI');
69 | $authLDAPFilter = authLdap_get_option('Filter');
70 | $authLDAPNameAttr = authLdap_get_option('NameAttr');
71 | $authLDAPSecName = authLdap_get_option('SecName');
72 | $authLDAPMailAttr = authLdap_get_option('MailAttr');
73 | $authLDAPUidAttr = authLdap_get_option('UidAttr');
74 | $authLDAPWebAttr = authLdap_get_option('WebAttr');
75 | $authLDAPGroups = authLdap_get_option('Groups');
76 | $authLDAPGroupSeparator= authLdap_get_option('GroupSeparator');
77 | $authLDAPDebug = authLdap_get_option('Debug');
78 | $authLDAPGroupAttr = authLdap_get_option('GroupAttr');
79 | $authLDAPGroupFilter = authLdap_get_option('GroupFilter');
80 | $authLDAPDefaultRole = authLdap_get_option('DefaultRole');
81 | $authLDAPGroupEnable = authLdap_get_option('GroupEnable');
82 | $authLDAPGroupOverUser = authLdap_get_option('GroupOverUser');
83 |
84 | $tChecked = ($authLDAP) ? ' checked="checked"' : '';
85 | $tDebugChecked = ($authLDAPDebug) ? ' checked="checked"' : '';
86 | $tPWChecked = ($authLDAPCachePW) ? ' checked="checked"' : '';
87 | $tGroupChecked = ($authLDAPGroupEnable) ? ' checked="checked"' : '';
88 | $tGroupOverUserChecked = ($authLDAPGroupOverUser) ? ' checked="checked"' : '';
89 |
90 | $roles = new WP_Roles();
91 |
92 | $action = $_SERVER['REQUEST_URI'];
93 | if (! extension_loaded('ldap')) {
94 | echo '<div class="warning">The LDAP-Extension is not available on your '
95 | . 'WebServer. Therefore Everything you can alter here does not '
96 | . 'make any sense!</div>';
97 | }
98 |
99 | include dirname(__FILE__) . '/view/admin.phtml';
100 | }
101 |
102 | /**
103 | * get a LDAP server object
104 | *
105 | * throws exception if there is a problem connecting
106 | *
107 | * @return object LDAP server object
108 | * @conf boolean authLDAPDebug true, if debugging should be turned on
109 | * @conf string authLDAPURI LDAP server URI
110 | */
111 | function authLdap_get_server()
112 | {
113 | static $_server = null;
114 | if (is_null($_server)) {
115 | $authLDAPDebug = authLdap_get_option('Debug');
116 | $authLDAPURI = authLdap_get_option('URI');
117 |
118 | //$authLDAPURI = 'ldap:/foo:bar@server/trallala';
119 | authLdap_debug('connect to LDAP server');
120 | $_server = new LDAP($authLDAPURI, $authLDAPDebug);
121 | }
122 | return $_server;
123 | }
124 |
125 |
126 | /**
127 | * This method authenticates a user using either the LDAP or, if LDAP is not
128 | * available, the local database
129 | *
130 | * For this we store the hashed passwords in the WP_Database to ensure working
131 | * conditions even without an LDAP-Connection
132 | *
133 | * @param null|WP_User|WP_Error
134 | * @param string $username
135 | * @param string $password
136 | * @param boolean $already_md5
137 | * @return boolean true, if login was successfull or false, if it wasn't
138 | * @conf boolean authLDAP true, if authLDAP should be used, false if not. Defaults to false
139 | * @conf string authLDAPFilter LDAP filter to use to find correct user, defaults to '(uid=%s)'
140 | * @conf string authLDAPNameAttr LDAP attribute containing user (display) name, defaults to 'name'
141 | * @conf string authLDAPSecName LDAP attribute containing second name, defaults to ''
142 | * @conf string authLDAPMailAttr LDAP attribute containing user e-mail, defaults to 'mail'
143 | * @conf string authLDAPUidAttr LDAP attribute containing user id (the username we log on with), defaults to 'uid'
144 | * @conf string authLDAPWebAttr LDAP attribute containing user website, defaults to ''
145 | * @conf string authLDAPDefaultRole default role for authenticated user, defaults to ''
146 | * @conf boolean authLDAPGroupEnable true, if we try to map LDAP groups to Wordpress roles
147 | * @conf boolean authLDAPGroupOverUser true, if LDAP Groups have precedence over existing user roles
148 | */
149 | function authLdap_login($user, $username, $password, $already_md5 = false)
150 | {
151 | // don't do anything when authLDAP is disabled
152 | if (! authLdap_get_option('Enabled')) {
153 | authLdap_debug('LDAP disabled in AuthLDAP plugin options (use the first option in the AuthLDAP options to enable it)');
154 | return $user;
155 | }
156 |
157 | // If the user has already been authenticated (only in that case we get a
158 | // WP_User-Object as $user) we skip LDAP-authentication and simply return
159 | // the existing user-object
160 | if ($user instanceof WP_User) {
161 | authLdap_debug(sprintf(
162 | 'User %s has already been authenticated - skipping LDAP-Authentication',
163 | $user->get('nickname')));
164 | return $user;
165 | }
166 |
167 | authLdap_debug("User '$username' logging in");
168 |
169 | if ($username == 'admin') {
170 | authLdap_debug('Doing nothing for possible local user admin');
171 | return $user;
172 | }
173 |
174 | global $wpdb, $error;
175 | try {
176 | $authLDAP = authLdap_get_option('Enabled');
177 | $authLDAPFilter = authLdap_get_option('Filter');
178 | $authLDAPNameAttr = authLdap_get_option('NameAttr');
179 | $authLDAPSecName = authLdap_get_option('SecName');
180 | $authLDAPMailAttr = authLdap_get_option('MailAttr');
181 | $authLDAPUidAttr = authLdap_get_option('UidAttr');
182 | $authLDAPWebAttr = authLdap_get_option('WebAttr');
183 | $authLDAPDefaultRole = authLdap_get_option('DefaultRole');
184 | $authLDAPGroupEnable = authLdap_get_option('GroupEnable');
185 | $authLDAPGroupOverUser = authLdap_get_option('GroupOverUser');
186 |
187 | if (! $username) {
188 | authLdap_debug('Username not supplied: return false');
189 | return false;
190 | }
191 |
192 | if (! $password) {
193 | authLdap_debug('Password not supplied: return false');
194 | $error = __('<strong>Error</strong>: The password field is empty.');
195 | return false;
196 | }
197 | // First check for valid values and set appropriate defaults
198 | if (! $authLDAPFilter) {
199 | $authLDAPFilter = '(uid=%s)';
200 | }
201 | if (! $authLDAPNameAttr) {
202 | $authLDAPNameAttr = 'name';
203 | }
204 | if (! $authLDAPMailAttr) {
205 | $authLDAPMailAttr = 'mail';
206 | }
207 | if (! $authLDAPUidAttr) {
208 | $authLDAPUidAttr = 'uid';
209 | }
210 |
211 | // If already_md5 is TRUE, then we're getting the user/password from the cookie. As we don't want to store LDAP passwords in any
212 | // form, we've already replaced the password with the hashed username and LDAP_COOKIE_MARKER
213 | if ($already_md5) {
214 | if ($password == md5($username).md5($ldapCookieMarker)) {
215 | authLdap_debug('cookie authentication');
216 | return true;
217 | }
218 | }
219 |
220 | // No cookie, so have to authenticate them via LDAP
221 | $result = false;
222 | try {
223 | authLdap_debug('about to do LDAP authentication');
224 | $result = authLdap_get_server()->Authenticate($username, $password, $authLDAPFilter);
225 | } catch (Exception $e) {
226 | authLdap_debug('LDAP authentication failed with exception: ' . $e->getMessage());
227 | return false;
228 | }
229 |
230 | // Rebind with the default credentials after the user has been loged in
231 | // Otherwise the credentials of the user trying to login will be used
232 | // This fixes #55
233 | authLdap_get_server()->bind();
234 |
235 | if (true !== $result) {
236 | authLdap_debug('LDAP authentication failed');
237 | // TODO what to return? WP_User object, true, false, even an WP_Error object... all seem to fall back to normal wp user authentication
238 | return;
239 | }
240 |
241 | authLdap_debug('LDAP authentication successfull');
242 | $attributes = array_values(
243 | array_filter(
244 | array(
245 | $authLDAPNameAttr,
246 | $authLDAPSecName,
247 | $authLDAPMailAttr,
248 | $authLDAPWebAttr,
249 | $authLDAPUidAttr
250 | )
251 | )
252 | );
253 |
254 | try {
255 | $attribs = authLdap_get_server()->search(
256 | sprintf($authLDAPFilter, $username),
257 | $attributes
258 | );
259 | // First get all the relevant group informations so we can see if
260 | // whether have been changes in group association of the user
261 | if (! isset($attribs[0]['dn'])) {
262 | authLdap_debug('could not get user attributes from LDAP');
263 | throw new UnexpectedValueException('dn has not been returned');
264 | }
265 | if (! isset($attribs[0][strtolower($authLDAPUidAttr)][0])) {
266 | authLdap_debug('could not get user attributes from LDAP');
267 | throw new UnexpectedValueException('The user-ID attribute has not been returned');
268 |
269 | }
270 |
271 | $dn = $attribs[0]['dn'];
272 | $realuid = $attribs[0][strtolower($authLDAPUidAttr)][0];
273 | } catch (Exception $e) {
274 | authLdap_debug('Exception getting LDAP user: ' . $e->getMessage());
275 | return false;
276 | }
277 |
278 | $uid = authLdap_get_uid($realuid);
279 | $role = '';
280 |
281 | // we only need this if either LDAP groups are disabled or
282 | // if the WordPress role of the user overrides LDAP groups
283 | if (!$authLDAPGroupEnable || !$authLDAPGroupOverUser) {
284 | $role = authLdap_user_role($uid);
285 | }
286 |
287 | // do LDAP group mapping if needed
288 | // (if LDAP groups override worpress user role, $role is still empty)
289 | if (empty($role) && $authLDAPGroupEnable) {
290 | $role = authLdap_groupmap($realuid, $dn);
291 | authLdap_debug('role from group mapping: ' . $role);
292 | }
293 |
294 | // if we don't have a role yet, use default role
295 | if (empty($role) && !empty($authLDAPDefaultRole)) {
296 | authLdap_debug('no role yet, set default role');
297 | $role = $authLDAPDefaultRole;
298 | }
299 |
300 | if (empty($role)) {
301 | // Sorry, but you are not in any group that is allowed access
302 | trigger_error('no group found');
303 | authLdap_debug('user is not in any group that is allowed access');
304 | return false;
305 | } else {
306 | $roles = new WP_Roles();
307 | // not sure if this is needed, but it can't hurt
308 | if (!$roles->is_role($role)) {
309 | trigger_error('no group found');
310 | authLdap_debug('role is invalid');
311 | return false;
312 | }
313 | }
314 |
315 | // from here on, the user has access!
316 | // now, lets update some user details
317 | $user_info = array();
318 | $user_info['user_login'] = $realuid;
319 | $user_info['role'] = $role;
320 | $user_info['user_email'] = '';
321 |
322 | // first name
323 | if (isset($attribs[0][strtolower($authLDAPNameAttr)][0])) {
324 | $user_info['first_name'] = $attribs[0][strtolower($authLDAPNameAttr)][0];
325 | }
326 |
327 | // last name
328 | if (isset($attribs[0][strtolower($authLDAPSecName)][0])) {
329 | $user_info['last_name'] = $attribs[0][strtolower($authLDAPSecName)][0];
330 | }
331 |
332 | // mail address
333 | if (isset($attribs[0][strtolower($authLDAPMailAttr)][0])) {
334 | $user_info['user_email'] = $attribs[0][strtolower($authLDAPMailAttr)][0];
335 | }
336 |
337 | // website
338 | if (isset($attribs[0][strtolower($authLDAPWebAttr)][0])) {
339 | $user_info['user_url'] = $attribs[0][strtolower($authLDAPWebAttr)][0];
340 | }
341 |
342 | // display name, nickname, nicename
343 | if (array_key_exists('first_name', $user_info)) {
344 | $user_info['display_name'] = $user_info['first_name'];
345 | $user_info['nickname'] = $user_info['first_name'];
346 | $user_info['user_nicename'] = sanitize_title_with_dashes($user_info['first_name']);
347 | if (array_key_exists('last_name', $user_info)) {
348 | $user_info['display_name'] .= ' ' . $user_info['last_name'];
349 | $user_info['nickname'] .= ' ' . $user_info['last_name'];
350 | $user_info['user_nicename'] .= '_' . sanitize_title_with_dashes($user_info['last_name']);
351 | }
352 | }
353 |
354 | // optionally store the password into the wordpress database
355 | if (authLdap_get_option('CachePW')) {
356 | // Password will be hashed inside wp_update_user or wp_insert_user
357 | $user_info['user_pass'] = $password;
358 | } else {
359 | // clear the password
360 | $user_info['user_pass'] = '';
361 | }
362 |
363 | // add uid if user exists
364 | if ($uid) {
365 | // found user in the database
366 | authLdap_debug('The LDAP user has an entry in the WP-Database');
367 | $user_info['ID'] = $uid;
368 | unset ($user_info['display_name'], $user_info['nickname']);
369 | $userid = wp_update_user($user_info);
370 | } else {
371 | // new wordpress account will be created
372 | authLdap_debug('The LDAP user does not have an entry in the WP-Database, a new WP account will be created');
373 |
374 | $userid = wp_insert_user($user_info);
375 | }
376 |
377 | // if the user exists, wp_insert_user will update the existing user record
378 | if (is_wp_error($userid)) {
379 | authLdap_debug('Error creating user : ' . $userid->get_error_message());
380 | trigger_error('Error creating user: ' . $userid->get_error_message());
381 | return $userid;
382 | }
383 |
384 | authLdap_debug('user id = ' . $userid);
385 |
386 | // flag the user as an ldap user so we can hide the password fields in the user profile
387 | update_user_meta($userid, 'authLDAP', true);
388 |
389 | // return a user object upon positive authorization
390 | return new WP_User($userid);
391 | } catch (Exception $e) {
392 | authLdap_debug($e->getMessage() . '. Exception thrown in line ' . $e->getLine());
393 | trigger_error($e->getMessage() . '. Exception thrown in line ' . $e->getLine());
394 | }
395 | }
396 |
397 | /**
398 | * Get user's user id
399 | *
400 | * Returns null if username not found
401 | *
402 | * @param string $username username
403 | * @param string user id, null if not found
404 | */
405 | function authLdap_get_uid($username)
406 | {
407 | global $wpdb;
408 |
409 | // find out whether the user is already present in the database
410 | $uid = $wpdb->get_var(
411 | $wpdb->prepare(
412 | "SELECT ID FROM {$wpdb->users} WHERE user_login = %s",
413 | $username
414 | )
415 | );
416 | if ($uid) {
417 | authLdap_debug("Existing user, uid = {$uid}");
418 | return $uid;
419 | } else {
420 | return null;
421 | }
422 | }
423 |
424 | /**
425 | * Get the user's current role
426 | *
427 | * Returns empty string if not found.
428 | *
429 | * @param int $uid wordpress user id
430 | * @return string role, empty if none found
431 | */
432 | function authLdap_user_role($uid)
433 | {
434 | global $wpdb;
435 |
436 | if (!$uid) {
437 | return '';
438 | }
439 |
440 | $meta_value = $wpdb->get_var("SELECT meta_value FROM {$wpdb->usermeta} WHERE meta_key = '{$wpdb->prefix}capabilities' AND user_id = {$uid}");
441 |
442 | if (!$meta_value) {
443 | return '';
444 | }
445 |
446 | $capabilities = unserialize($meta_value);
447 | $roles = is_array($capabilities) ? array_keys($capabilities) : array('');
448 | $role = $roles[0];
449 |
450 | authLdap_debug("Existing user's role: {$role}");
451 | return $role;
452 | }
453 |
454 | /**
455 | * Get LDAP groups for user and map to role
456 | *
457 | * @param string $username
458 | * @param string $dn
459 | * @return string role, empty string if no mapping found, first found role otherwise
460 | * @conf array authLDAPGroups, associative array, role => ldap_group
461 | * @conf string authLDAPGroupAttr, ldap attribute that holds name of group
462 | * @conf string authLDAPGroupFilter, LDAP filter to find groups. can contain %s and %dn% placeholders
463 | */
464 | function authLdap_groupmap($username, $dn)
465 | {
466 | $authLDAPGroups = authLdap_sort_roles_by_capabilities(
467 | authLdap_get_option('Groups')
468 | );
469 | $authLDAPGroupAttr = authLdap_get_option('GroupAttr');
470 | $authLDAPGroupFilter = authLdap_get_option('GroupFilter');
471 | $authLDAPGroupSeparator = authLdap_get_option('GroupSeparator');
472 | if (! $authLDAPGroupAttr) {
473 | $authLDAPGroupAttr = 'gidNumber';
474 | }
475 | if (! $authLDAPGroupFilter) {
476 | $authLDAPGroupFilter = '(&(objectClass=posixGroup)(memberUid=%s))';
477 | }
478 | if (! $authLDAPGroupSeparator) {
479 | $authLDAPGroupSeparator = ',';
480 | }
481 |
482 | if (!is_array($authLDAPGroups) || count(array_filter(array_values($authLDAPGroups))) == 0) {
483 | authLdap_debug('No group names defined');
484 | return '';
485 | }
486 |
487 | try {
488 | // To allow searches based on the DN instead of the uid, we replace the
489 | // string %dn% with the users DN.
490 | $authLDAPGroupFilter = str_replace('%dn%', $dn, $authLDAPGroupFilter);
491 | authLdap_debug('Group Filter: ' . json_encode($authLDAPGroupFilter));
492 | $groups = authLdap_get_server()->search(sprintf($authLDAPGroupFilter, $username), array($authLDAPGroupAttr));
493 | } catch (Exception $e) {
494 | authLdap_debug('Exception getting LDAP group attributes: ' . $e->getMessage());
495 | return '';
496 | }
497 |
498 | $grp = array();
499 | for ($i = 0; $i < $groups ['count']; $i++) {
500 | for ($k = 0; $k < $groups[$i][strtolower($authLDAPGroupAttr)]['count']; $k++) {
501 | $grp[] = $groups[$i][strtolower($authLDAPGroupAttr)][$k];
502 | }
503 | }
504 |
505 | authLdap_debug('LDAP groups: ' . json_encode($grp));
506 |
507 | // Check whether the user is member of one of the groups that are
508 | // allowed acces to the blog. If the user is not member of one of
509 | // The groups throw her out! ;-)
510 | // If the user is member of more than one group only the first one
511 | // will be taken into account!
512 |
513 | $role = '';
514 | foreach ($authLDAPGroups as $key => $val) {
515 | $currentGroup = explode($authLDAPGroupSeparator, $val);
516 | // Remove whitespaces around the group-ID
517 | $currentGroup = array_map('trim', $currentGroup);
518 | if (0 < count(array_intersect($currentGroup, $grp))) {
519 | $role = $key;
520 | break;
521 | }
522 | }
523 |
524 | authLdap_debug("Role from LDAP group: {$role}");
525 | return $role;
526 | }
527 |
528 | /**
529 | * This function disables the password-change fields in the users preferences.
530 | *
531 | * It does not make sense to authenticate via LDAP and then allow the user to
532 | * change the password only in the wordpress database. And changing the password
533 | * LDAP-wide can not be the scope of Wordpress!
534 | *
535 | * Whether the user is an LDAP-User or not is determined using the authLDAP-Flag
536 | * of the users meta-informations
537 | *
538 | * @return false, if the user whose prefs are viewed is an LDAP-User, true if
539 | * he isn't
540 | * @conf boolean authLDAP
541 | */
542 | function authLdap_show_password_fields($return, $user)
543 | {
544 | if (! $user) {
545 | return true;
546 | }
547 |
548 | if (get_user_meta($user->ID, 'authLDAP')) {
549 | return false;
550 | }
551 |
552 | return $return;
553 | }
554 |
555 | /**
556 | * This function disables the password reset for a user.
557 | *
558 | * It does not make sense to authenticate via LDAP and then allow the user to
559 | * reset the password only in the wordpress database. And changing the password
560 | * LDAP-wide can not be the scope of Wordpress!
561 | *
562 | * Whether the user is an LDAP-User or not is determined using the authLDAP-Flag
563 | * of the users meta-informations
564 | *
565 | * @author chaplina (https://github.com/chaplina)
566 | * @conf boolean authLDAP
567 | * @return false, if the user is an LDAP-User, true if he isn't
568 | */
569 | function authLdap_allow_password_reset($return, $userid)
570 | {
571 | if (!(isset($userid))) {
572 | return true;
573 | }
574 |
575 | if (get_user_meta($userid, 'authLDAP')) {
576 | return false;
577 | }
578 | return $return;
579 | }
580 |
581 | /**
582 | * Sort the given roles by number of capabilities
583 | *
584 | * @param array $roles
585 | *
586 | * @return array
587 | */
588 | function authLdap_sort_roles_by_capabilities($roles)
589 | {
590 | global $wpdb;
591 | $myRoles = get_option($wpdb->get_blog_prefix() . 'user_roles');
592 |
593 | authLdap_debug(print_r($roles, true));
594 | uasort($myRoles, 'authLdap_sortByCapabilitycount');
595 |
596 | $return = array();
597 |
598 | foreach ($myRoles as $key => $role) {
599 | if (isset($roles[$key])) {
600 | $return[$key] = $roles[$key];
601 | }
602 | }
603 |
604 | authLdap_debug(print_r($return, true));
605 | return $return;
606 | }
607 |
608 | /**
609 | * Sort according to the number of capabilities
610 | *
611 | * @param $a
612 | * @param $b
613 | */
614 | function authLdap_sortByCapabilitycount($a, $b)
615 | {
616 | if (count($a['capabilities']) > count($b['capabilities'])) {
617 | return -1;
618 | }
619 | if (count($a['capabilities']) < count($b['capabilities'])) {
620 | return 1;
621 | }
622 |
623 | return 0;
624 | }
625 |
626 | /**
627 | * Load AuthLDAP Options
628 | *
629 | * Sets and stores defaults if options are not up to date
630 | */
631 | function authLdap_load_options($reload = false)
632 | {
633 | static $options = null;
634 |
635 | // the current version for options
636 | $option_version_plugin = 1;
637 |
638 | if (is_null($options) || $reload) {
639 | $options = get_option('authLDAPOptions', array());
640 | }
641 |
642 | // check if option version has changed (or if it's there at all)
643 | if (!isset($options['Version']) || ($options['Version'] != $option_version_plugin)) {
644 | // defaults for all options
645 | $options_default = array(
646 | 'Enabled' => false,
647 | 'CachePW' => false,
648 | 'URI' => '',
649 | 'Filter' => '', // '(uid=%s)'
650 | 'NameAttr' => '', // 'name'
651 | 'SecName' => '',
652 | 'UidAttr' => '', // 'uid'
653 | 'MailAttr' => '', // 'mail'
654 | 'WebAttr' => '',
655 | 'Groups' => array(),
656 | 'Debug' => false,
657 | 'GroupAttr' => '', // 'gidNumber'
658 | 'GroupFilter' => '', // '(&(objectClass=posixGroup)(memberUid=%s))'
659 | 'DefaultRole' => '',
660 | 'GroupEnable' => true,
661 | 'GroupOverUser' => true,
662 | 'Version' => $option_version_plugin,
663 | );
664 |
665 | // check if we got a version
666 | if (!isset($options['Version'])) {
667 | // we just changed to the new option format
668 | // read old options, then delete them
669 | $old_option_new_option = array(
670 | 'authLDAP' => 'Enabled',
671 | 'authLDAPCachePW' => 'CachePW',
672 | 'authLDAPURI' => 'URI',
673 | 'authLDAPFilter' => 'Filter',
674 | 'authLDAPNameAttr' => 'NameAttr',
675 | 'authLDAPSecName' => 'SecName',
676 | 'authLDAPUidAttr' => 'UidAttr',
677 | 'authLDAPMailAttr' => 'MailAttr',
678 | 'authLDAPWebAttr' => 'WebAttr',
679 | 'authLDAPGroups' => 'Groups',
680 | 'authLDAPDebug' => 'Debug',
681 | 'authLDAPGroupAttr' => 'GroupAttr',
682 | 'authLDAPGroupFilter' => 'GroupFilter',
683 | 'authLDAPDefaultRole' => 'DefaultRole',
684 | 'authLDAPGroupEnable' => 'GroupEnable',
685 | 'authLDAPGroupOverUser' => 'GroupOverUser',
686 | );
687 | foreach ($old_option_new_option as $old_option => $new_option) {
688 | $value = get_option($old_option, null);
689 | if (!is_null($value)) {
690 | $options[$new_option] = $value;
691 | }
692 | delete_option($old_option);
693 | }
694 | delete_option('authLDAPCookieMarker');
695 | delete_option('authLDAPCookierMarker');
696 | }
697 |
698 | // set default for all options that are missing
699 | foreach ($options_default as $key => $default) {
700 | if (!isset($options[$key])) {
701 | $options[$key] = $default;
702 | }
703 | }
704 |
705 | // set new version and save
706 | $options['Version'] = $option_version_plugin;
707 | update_option('authLDAPOptions', $options);
708 | }
709 | return $options;
710 | }
711 |
712 | /**
713 | * Get an individual option
714 | */
715 | function authLdap_get_option($optionname)
716 | {
717 | $options = authLdap_load_options();
718 | if (isset($options[$optionname])) {
719 | return $options[$optionname];
720 | } else {
721 | authLdap_debug('option name invalid: ' . $optionname);
722 | return null;
723 | }
724 | }
725 |
726 | /**
727 | * Set new options
728 | */
729 | function authLdap_set_options($new_options = array())
730 | {
731 | // initialize the options with what we currently have
732 | $options = authLdap_load_options();
733 |
734 | // set the new options supplied
735 | foreach ($new_options as $key => $value) {
736 | $options[$key] = $value;
737 | }
738 |
739 | // store options
740 | if (update_option('authLDAPOptions', $options)) {
741 | // reload the option cache
742 | authLdap_load_options(true);
743 |
744 | return true;
745 | } else {
746 | // could not set options
747 | return false;
748 | }
749 | }
750 |
751 | /**
752 | * Do not send an email after changing the password or the email of the user!
753 | *
754 | * @param boolean $result The initial resturn value
755 | * @param array $user The old userdata
756 | * @param array $newUserData The changed userdata
757 | *
758 | * @return bool
759 | */
760 | function authLdap_send_change_email($result, $user, $newUserData)
761 | {
762 | if (get_usermeta($user['ID'], 'authLDAP')) {
763 | return false;
764 | }
765 |
766 | return $result;
767 | }
768 |
769 | add_action('admin_menu', 'authLdap_addmenu');
770 | add_filter('show_password_fields', 'authLdap_show_password_fields', 10, 2);
771 | add_filter('allow_password_reset', 'authLdap_allow_password_reset', 10, 2);
772 | add_filter('authenticate', 'authLdap_login', 10, 3);
773 | /** This only works from WP 4.3.0 on */
774 | add_filter('send_password_change_email', 'authLdap_send_change_email', 10, 3);
775 | add_filter('send_email_change_email', 'authLdap_send_change_email', 10, 3);