Index: trunk/extensions/LdapAuthentication/LdapAuthentication.php |
— | — | @@ -46,7 +46,7 @@ |
47 | 47 | */ |
48 | 48 | $wgExtensionCredits['other'][] = array( |
49 | 49 | 'name' => 'LDAP Authentication Plugin', |
50 | | - 'version' => '1.2a (beta)', |
| 50 | + 'version' => '1.2b (alpha)', |
51 | 51 | 'author' => 'Ryan Lane', |
52 | 52 | 'description' => 'LDAP Authentication plugin with support for multiple LDAP authentication methods', |
53 | 53 | 'url' => 'http://www.mediawiki.org/wiki/Extension:LDAP_Authentication', |
— | — | @@ -64,19 +64,31 @@ |
65 | 65 | |
66 | 66 | class LdapAuthenticationPlugin extends AuthPlugin { |
67 | 67 | |
| 68 | + //ldap connection resource |
| 69 | + var $ldapconn; |
| 70 | + |
68 | 71 | //preferences |
69 | 72 | var $email, $lang, $realname, $nickname, $externalid; |
70 | 73 | |
71 | 74 | //username pulled from ldap |
72 | 75 | var $LDAPUsername; |
73 | 76 | |
| 77 | + //userdn pulled from ldap |
| 78 | + var $userdn; |
| 79 | + |
74 | 80 | //groups pulled from ldap |
75 | | - var $userLDAPGroups, $foundUserLDAPGroups; |
| 81 | + var $userLDAPGroups; |
76 | 82 | var $allLDAPGroups; |
77 | 83 | |
78 | 84 | //boolean to test for failed auth |
79 | 85 | var $authFailed; |
80 | 86 | |
| 87 | + //boolean to test for fetched user info |
| 88 | + var $fetchedUserInfo; |
| 89 | + |
| 90 | + //the user's entry and all attributes |
| 91 | + var $userInfo; |
| 92 | + |
81 | 93 | function LdapAuthenticationPlugin() { |
82 | 94 | } |
83 | 95 | |
— | — | @@ -103,11 +115,11 @@ |
104 | 116 | return true; |
105 | 117 | } |
106 | 118 | |
107 | | - $ldapconn = $this->connect(); |
108 | | - if ( $ldapconn ) { |
| 119 | + $this->ldapconn = $this->connect(); |
| 120 | + if ( $this->ldapconn ) { |
109 | 121 | $this->printDebug( "Successfully connected", NONSENSITIVE ); |
110 | 122 | |
111 | | - $searchstring = $this->getSearchString( $ldapconn, $username ); |
| 123 | + $searchstring = $this->getSearchString( $this->ldapconn, $username ); |
112 | 124 | |
113 | 125 | //If we are using auto authentication, and we got |
114 | 126 | //anything back, then the user exists. |
— | — | @@ -119,7 +131,7 @@ |
120 | 132 | } |
121 | 133 | |
122 | 134 | //Search for the entry. |
123 | | - $entry = @ldap_read( $ldapconn, $searchstring, "objectclass=*" ); |
| 135 | + $entry = @ldap_read( $this->ldapconn, $searchstring, "objectclass=*" ); |
124 | 136 | |
125 | 137 | //getSearchString is going to bind, but will not unbind |
126 | 138 | //Let's clean up |
— | — | @@ -141,7 +153,6 @@ |
142 | 154 | /** |
143 | 155 | * Connect to LDAP |
144 | 156 | * |
145 | | - * @return resource |
146 | 157 | * @access private |
147 | 158 | */ |
148 | 159 | function connect() { |
— | — | @@ -194,14 +205,14 @@ |
195 | 206 | $this->printDebug( "Using servers: $servers", SENSITIVE ); |
196 | 207 | |
197 | 208 | //Connect and set options |
198 | | - $ldapconn = @ldap_connect( $servers ); |
199 | | - ldap_set_option( $ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3); |
200 | | - ldap_set_option( $ldapconn, LDAP_OPT_REFERRALS, 0); |
| 209 | + $this->ldapconn = @ldap_connect( $servers ); |
| 210 | + ldap_set_option( $this->ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3); |
| 211 | + ldap_set_option( $this->ldapconn, LDAP_OPT_REFERRALS, 0); |
201 | 212 | |
202 | 213 | if ( isset( $wgLDAPOptions[$_SESSION['wsDomain']] ) ) { |
203 | 214 | $options = $wgLDAPOptions[$_SESSION['wsDomain']]; |
204 | 215 | foreach ( $options as $key => $value ) { |
205 | | - if ( !ldap_set_option( $ldapconn, constant( $key ), $value ) ) { |
| 216 | + if ( !ldap_set_option( $this->ldapconn, constant( $key ), $value ) ) { |
206 | 217 | $this->printDebug( "Can't set option to LDAP! Option code and value: " . $key . "=" . $value, 1 ); |
207 | 218 | } |
208 | 219 | } |
— | — | @@ -210,13 +221,11 @@ |
211 | 222 | //TLS needs to be started after the connection is made |
212 | 223 | if ( $encryptionType == "tls" ) { |
213 | 224 | $this->printDebug( "Using TLS", SENSITIVE ); |
214 | | - if ( !ldap_start_tls( $ldapconn ) ) { |
| 225 | + if ( !ldap_start_tls( $this->ldapconn ) ) { |
215 | 226 | $this->printDebug( "Failed to start TLS.", SENSITIVE ); |
216 | 227 | return; |
217 | 228 | } |
218 | 229 | } |
219 | | - |
220 | | - return $ldapconn; |
221 | 230 | } |
222 | 231 | |
223 | 232 | /** |
— | — | @@ -232,23 +241,16 @@ |
233 | 242 | * @access public |
234 | 243 | */ |
235 | 244 | function authenticate( $username, $password='' ) { |
236 | | - global $wgLDAPRetrievePrefs, $wgLDAPPreferences; |
237 | | - global $wgLDAPGroupDN, $wgLDAPRequiredGroups; |
238 | | - global $wgLDAPGroupUseFullDN, $wgLDAPGroupUseRetrievedUsername; |
239 | | - global $wgLDAPUseLDAPGroups; |
240 | | - global $wgLDAPRequireAuthAttribute, $wgLDAPAuthAttribute; |
| 245 | + global $wgLDAPAuthAttribute; |
241 | 246 | global $wgLDAPAutoAuthUsername; |
242 | 247 | global $wgLDAPLowerCaseUsername; |
243 | 248 | global $wgLDAPSearchStrings; |
244 | | - global $wgLDAPUniqueAttribute, $wgLDAPUniqueBlockLogin, $wgLDAPUniqueRenameUser; |
245 | | - global $wgLDAPGroupsPrevail; |
246 | 249 | |
247 | 250 | $this->printDebug( "Entering authenticate", NONSENSITIVE ); |
248 | 251 | |
249 | 252 | //We don't handle local authentication |
250 | 253 | if ( 'local' == $_SESSION['wsDomain'] ) { |
251 | 254 | $this->printDebug( "User is using a local domain", SENSITIVE ); |
252 | | - $this->cleanupFailedAuth(); |
253 | 255 | return false; |
254 | 256 | } |
255 | 257 | |
— | — | @@ -257,7 +259,6 @@ |
258 | 260 | //than the one the web server got from the auto-authentication method. |
259 | 261 | if ( $this->useAutoAuth() && $wgLDAPAutoAuthUsername != $username ) { |
260 | 262 | $this->printDebug( "The username provided ($username) doesn't match the username provided by the webserver ($wgLDAPAutoAuthUsername). The user is probably trying to log in to the auto-authentication domain with password authentication via the wiki. Denying access.", SENSITIVE ); |
261 | | - $this->cleanupFailedAuth(); |
262 | 263 | return false; |
263 | 264 | } |
264 | 265 | |
— | — | @@ -268,13 +269,11 @@ |
269 | 270 | //a password to be given; a blank password here is wanted. |
270 | 271 | if ( '' == $password && !$this->useAutoAuth() ) { |
271 | 272 | $this->printDebug( "User used a blank password", NONSENSITIVE ); |
272 | | - $this->cleanupFailedAuth(); |
273 | 273 | return false; |
274 | 274 | } |
275 | 275 | |
276 | | - $ldapconn = $this->connect(); |
277 | | - //This seems really expensive. |
278 | | - if ( $ldapconn ) { |
| 276 | + $this->connect(); |
| 277 | + if ( $this->ldapconn ) { |
279 | 278 | $this->printDebug( "Connected successfully", NONSENSITIVE ); |
280 | 279 | |
281 | 280 | //Mediawiki munges the username before authenticate is called, |
— | — | @@ -286,16 +285,15 @@ |
287 | 286 | $username = strtolower( $username ); |
288 | 287 | } |
289 | 288 | |
290 | | - $userdn = $this->getSearchString( $ldapconn, $username ); |
| 289 | + $this->userdn = $this->getSearchString( $username ); |
291 | 290 | |
292 | 291 | //It is possible that getSearchString will return an |
293 | 292 | //empty string; if this happens, the bind will ALWAYS |
294 | 293 | //return true, and will let anyone in! |
295 | | - if ( '' == $userdn ) { |
| 294 | + if ( '' == $this->userdn ) { |
296 | 295 | $this->printDebug( "User DN is blank", NONSENSITIVE ); |
297 | | - // Lets clean up. |
298 | 296 | @ldap_unbind(); |
299 | | - $this->cleanupFailedAuth(); |
| 297 | + $this->markAuthFailed(); |
300 | 298 | return false; |
301 | 299 | } |
302 | 300 | |
— | — | @@ -305,13 +303,12 @@ |
306 | 304 | $this->printDebug( "Binding as the user", NONSENSITIVE ); |
307 | 305 | |
308 | 306 | //Let's see if the user can authenticate. |
309 | | - $bind = $this->bindAs( $ldapconn, $userdn, $password ); |
| 307 | + $bind = $this->bindAs( $this->userdn, $password ); |
310 | 308 | if ( !$bind ) { |
311 | | - // Lets clean up. |
312 | | - @ldap_unbind(); |
313 | | - $this->cleanupFailedAuth(); |
| 309 | + $this->markAuthFailed(); |
314 | 310 | return false; |
315 | 311 | } |
| 312 | + |
316 | 313 | $this->printDebug( "Bound successfully", NONSENSITIVE ); |
317 | 314 | |
318 | 315 | if ( isset( $wgLDAPSearchStrings[$_SESSION['wsDomain']] ) ) { |
— | — | @@ -320,227 +317,50 @@ |
321 | 318 | //We are most likely configured using USER-NAME@DOMAIN, or |
322 | 319 | //DOMAIN\\USER-NAME. |
323 | 320 | //Get the user's full DN so we can search for groups and such. |
324 | | - $userdn = $this->getUserDN( $ldapconn, $username ); |
325 | | - $this->printDebug( "Pulled the user's DN: $userdn", NONSENSITIVE ); |
| 321 | + $this->userdn = $this->getUserDN( $username ); |
| 322 | + $this->printDebug( "Pulled the user's DN: $this->userdn", NONSENSITIVE ); |
326 | 323 | } |
327 | 324 | } |
328 | 325 | |
329 | | - if ( ( isset( $wgLDAPRequireAuthAttribute[$_SESSION['wsDomain']] ) |
330 | | - && $wgLDAPRequireAuthAttribute[$_SESSION['wsDomain']] ) ) { |
| 326 | + if ( isset( $wgLDAPAuthAttribute[$_SESSION['wsDomain']] ) ) { |
331 | 327 | |
332 | 328 | $this->printDebug( "Checking for auth attributes", NONSENSITIVE ); |
333 | 329 | |
334 | 330 | $filter = "(" . $wgLDAPAuthAttribute[$_SESSION['wsDomain']] . ")"; |
335 | 331 | $attributes = array( "dn" ); |
336 | 332 | |
337 | | - $entry = ldap_read( $ldapconn, $userdn, $filter, $attributes ); |
338 | | - $info = ldap_get_entries( $ldapconn, $entry ); |
| 333 | + $entry = ldap_read( $this->ldapconn, $this->userdn, $filter, $attributes ); |
| 334 | + $info = ldap_get_entries( $this->ldapconn, $entry ); |
339 | 335 | |
340 | 336 | if ( $info["count"] < 1 ) { |
341 | 337 | $this->printDebug( "Failed auth attribute check", NONSENSITIVE ); |
342 | | - // Lets clean up. |
343 | 338 | @ldap_unbind(); |
344 | | - $this->cleanupFailedAuth(); |
| 339 | + $this->markAuthFailed(); |
345 | 340 | return false; |
346 | 341 | } |
347 | 342 | } |
348 | 343 | } |
349 | 344 | |
350 | | - //Old style groups, non-nestable and fairly limited on group type (full DN |
351 | | - //versus username). DEPRECATED |
352 | | - if ( $wgLDAPGroupDN ) { |
353 | | - $this->printDebug( "Checking for (old style) group membership", NONSENSITIVE ); |
354 | | - if ( !$this->isMemberOfLdapGroup( $ldapconn, $userdn, $wgLDAPGroupDN ) ) { |
355 | | - $this->printDebug( "Failed (old style) group membership check", NONSENSITIVE ); |
| 345 | + $this->getGroups( $username ); |
356 | 346 | |
357 | | - //No point in going on if the user isn't in the required group |
358 | | - // Lets clean up. |
359 | | - @ldap_unbind(); |
360 | | - $this->cleanupFailedAuth(); |
361 | | - return false; |
362 | | - } |
| 347 | + if ( !$this->checkGroups( $username ) ) { |
| 348 | + @ldap_unbind(); |
| 349 | + $this->markAuthFailed(); |
| 350 | + return false; |
363 | 351 | } |
364 | 352 | |
365 | | - //New style group checking |
366 | | - if ( isset( $wgLDAPRequiredGroups[$_SESSION['wsDomain']] ) ) { |
367 | | - $this->printDebug( "Checking for (new style) group membership", NONSENSITIVE ); |
| 353 | + $this->getPreferences(); |
368 | 354 | |
369 | | - if ( isset( $wgLDAPGroupUseFullDN[$_SESSION['wsDomain']] ) && $wgLDAPGroupUseFullDN[$_SESSION['wsDomain']] ) { |
370 | | - $inGroup = $this->isMemberOfRequiredLdapGroup( $ldapconn, $userdn ); |
371 | | - } else { |
372 | | - if ( ( isset( $wgLDAPGroupUseRetrievedUsername[$_SESSION['wsDomain']] ) |
373 | | - && $wgLDAPGroupUseRetrievedUsername[$_SESSION['wsDomain']] ) |
374 | | - && $this->LDAPUsername != '' ) { |
375 | | - |
376 | | - $this->printDebug( "Using the username retrieved from the user's entry.", NONSENSITIVE ); |
377 | | - $inGroup = $this->isMemberOfRequiredLdapGroup( $ldapconn, $this->LDAPUsername ); |
378 | | - } else { |
379 | | - $inGroup = $this->isMemberOfRequiredLdapGroup( $ldapconn, $username ); |
380 | | - } |
381 | | - } |
382 | | - |
383 | | - if ( !$inGroup ) { |
384 | | - // Lets clean up. |
385 | | - @ldap_unbind(); |
386 | | - $this->cleanupFailedAuth(); |
387 | | - return false; |
388 | | - } |
389 | | - |
| 355 | + if ( !$this->synchUsername( $username ) ) { |
| 356 | + @ldap_unbind(); |
| 357 | + $this->markAuthFailed(); |
| 358 | + return false; |
390 | 359 | } |
391 | 360 | |
392 | | - //Synch LDAP groups with MediaWiki groups |
393 | | - if ( isset( $wgLDAPUseLDAPGroups[$_SESSION['wsDomain']] ) && $wgLDAPUseLDAPGroups[$_SESSION['wsDomain']] ) { |
394 | | - $this->printDebug( "Retrieving LDAP group membership", NONSENSITIVE ); |
395 | | - |
396 | | - //Let's get the user's LDAP groups |
397 | | - if ( isset( $wgLDAPGroupUseFullDN[$_SESSION['wsDomain']] ) && $wgLDAPGroupUseFullDN[$_SESSION['wsDomain']] ) { |
398 | | - $this->userLDAPGroups = $this->getUserGroups( $ldapconn, $userdn, true ); |
399 | | - } else { |
400 | | - if ( ( isset( $wgLDAPGroupUseRetrievedUsername[$_SESSION['wsDomain']] ) && $wgLDAPGroupUseRetrievedUsername[$_SESSION['wsDomain']] ) |
401 | | - && $this->LDAPUsername != '' ) { |
402 | | - |
403 | | - $this->userLDAPGroups = $this->getUserGroups( $ldapconn, $this->LDAPUsername, true ); |
404 | | - } else { |
405 | | - $this->userLDAPGroups = $this->getUserGroups( $ldapconn, $username, true ); |
406 | | - } |
407 | | - } |
408 | | - |
409 | | - //Only find all groups if the user has any groups; otherwise, we are |
410 | | - //just wasting a search. |
411 | | - if ( $this->foundUserLDAPGroups && ( isset( $wgLDAPGroupsPrevail[$_SESSION['wsDomain']] ) && $wgLDAPGroupsPrevail[$_SESSION['wsDomain']] ) ) { |
412 | | - $this->allLDAPGroups = $this->getAllGroups( $ldapconn, true ); |
413 | | - } |
414 | | - } |
415 | | - |
416 | | - //Retrieve preferences |
417 | | - if ( isset( $wgLDAPPreferences[$_SESSION['wsDomain']] ) ) { |
418 | | - $this->printDebug( "Retrieving preferences", NONSENSITIVE ); |
419 | | - $entry = @ldap_read( $ldapconn, $userdn, "objectclass=*" ); |
420 | | - $info = @ldap_get_entries( $ldapconn, $entry ); |
421 | | - $prefs = $wgLDAPPreferences[$_SESSION['wsDomain']]; |
422 | | - foreach ( array_keys( $prefs ) as $key ) { |
423 | | - switch ( $key ) { |
424 | | - case "email": |
425 | | - if ( isset( $info[0]["$prefs[$key]"] ) ) { |
426 | | - $this->email = $info[0]["$prefs[$key]"][0]; |
427 | | - $this->printDebug( "Retrieved email ($this->email) using attribute ($prefs[$key])", NONSENSITIVE ); |
428 | | - } |
429 | | - break; |
430 | | - case "language": |
431 | | - if ( isset( $info[0]["$prefs[$key]"] ) ) { |
432 | | - $this->lang = $info[0][$prefs[$key]][0]; |
433 | | - $this->printDebug( "Retrieved language ($this->lang) using attribute ($prefs[$key])", NONSENSITIVE ); |
434 | | - } |
435 | | - break; |
436 | | - case "nickname": |
437 | | - if ( isset( $info[0]["$prefs[$key]"] ) ) { |
438 | | - $this->nickname = $info[0]["$prefs[$key]"][0]; |
439 | | - $this->printDebug( "Retrieved nickname ($this->nickname) using attribute ($prefs[$key])", NONSENSITIVE ); |
440 | | - } |
441 | | - break; |
442 | | - case "realname": |
443 | | - if ( isset( $info[0]["$prefs[$key]"] ) ) { |
444 | | - $this->realname = $info[0]["$prefs[$key]"][0]; |
445 | | - $this->printDebug( "Retrieved realname ($this->realname) using attribute ($prefs[$key])", NONSENSITIVE ); |
446 | | - } |
447 | | - break; |
448 | | - } |
449 | | - } |
450 | | - } else if ( isset( $wgLDAPRetrievePrefs[$_SESSION['wsDomain']] ) && $wgLDAPRetrievePrefs[$_SESSION['wsDomain']] ) { |
451 | | - //DEPRECATED. Kept for backwards compatibility. |
452 | | - $this->printDebug( "Retrieving preferences", NONSENSITIVE ); |
453 | | - $this->printDebug( '$wgLDAPRetrievePrefs is a DEPRECATED option, please use $wgLDAPPreferences.', NONSENSITIVE ); |
454 | | - |
455 | | - $entry = @ldap_read( $ldapconn, $userdn, "objectclass=*" ); |
456 | | - $info = @ldap_get_entries( $ldapconn, $entry ); |
457 | | - if (isset($info[0]["mail"])) { |
458 | | - $this->email = $info[0]["mail"][0]; |
459 | | - } |
460 | | - if (isset($info[0]["preferredlanguage"])) { |
461 | | - $this->lang = $info[0]["preferredlanguage"][0]; |
462 | | - } |
463 | | - if (isset($info[0]["displayname"])) { |
464 | | - $this->nickname = $info[0]["displayname"][0]; |
465 | | - } |
466 | | - if (isset($info[0]["cn"])) { |
467 | | - $this->realname = $info[0]["cn"][0]; |
468 | | - } |
469 | | - |
470 | | - $this->printDebug( "Retrieved: $this->email, $this->lang, $this->nickname, $this->realname", SENSITIVE ); |
471 | | - } |
472 | | - |
473 | | - // Are we blocking login/renaming users on unique external ID mismatches? |
474 | | - // *** WARNING *** |
475 | | - // This needs to be fixed before use! This probably does not work correctly |
476 | | - // with all options. It is probably a good idea to refactor the username stuff |
477 | | - // in general (as it is currently somewhat of a kludge). Also, MediaWiki does |
478 | | - // not currently have support for this. |
479 | | - // *** WARNING *** |
480 | | - if ( ( isset( $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) && $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) |
481 | | - || ( isset( $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) && $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) ) { |
482 | | - |
483 | | - $this->printDebug( "Checking for username change in LDAP.", SENSITIVE ); |
484 | | - |
485 | | - //Get the user's unique attribute from LDAP |
486 | | - if ( isset( $wgLDAPUniqueAttribute[$_SESSION['wsDomain']] ) ) { |
487 | | - $ldapuniqueattr = $wgLDAPUniqueAttribute[$_SESSION['wsDomain']]; |
488 | | - $this->externalid = $info[0][$ldapuniqueattr][0]; |
489 | | - } |
490 | | - |
491 | | - $this->printDebug( "Retrieved external id: $this->externalid", SENSITIVE ); |
492 | | - |
493 | | - $retrievedusername = User::whoIsExternalID( "$this->externalid" ); |
494 | | - |
495 | | - $this->printDebug( "Username (in MediaWiki database) of fetched external id: $retrievedusername", SENSITIVE ); |
496 | | - |
497 | | - // See if the username returned from the database matches the username given |
498 | | - if ( $retrievedusername != '' && ( $username != $retrievedusername ) ) { |
499 | | - if ( isset( $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) |
500 | | - && $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) { |
501 | | - |
502 | | - $this->printDebug( "Usernames do not match, blocking login.", SENSITIVE ); |
503 | | - return false; |
504 | | - } else if ( isset( $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) |
505 | | - && $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) { |
506 | | - |
507 | | - $this->printDebug( "Usernames do not match, renaming user in database.", SENSITIVE ); |
508 | | - |
509 | | - global $wgVersion; |
510 | | - if ( version_compare( $wgVersion, '1.7.0', '<' ) ) { |
511 | | - $this->printDebug( "Renaming users is only supported in MediaWiki 1.7+, please upgrade.", SENSITIVE ); |
512 | | - $this->cleanupFailedAuth(); |
513 | | - return false; |
514 | | - } |
515 | | - |
516 | | - $olduser = User::newFromName( $retrievedusername ); |
517 | | - $uid = $olduser->idForName(); |
518 | | - |
519 | | - // Ensure we don't require the same class twice |
520 | | - if ( !class_exists( 'RenameuserSQL' ) ) { |
521 | | - require( 'Renameuser/SpecialRenameuser_body.php' ); |
522 | | - } |
523 | | - |
524 | | - // Make a new rename user object with: from, to, uid of from |
525 | | - $rename = new RenameuserSQL( $retrievedusername, $username, $uid ); |
526 | | - $rename->rename(); |
527 | | - |
528 | | - // For the time being we can't just allow the user to log in |
529 | | - // as MediaWiki will try to create the user account after we |
530 | | - // do a rename. If we don't return false, the user will get |
531 | | - // a database error |
532 | | - $this->cleanupFailedAuth(); |
533 | | - return false; |
534 | | - } |
535 | | - } |
536 | | - |
537 | | - $this->printDebug( "Usernames matched or the user doesn't exist in the database yet.", SENSITIVE ); |
538 | | - } |
539 | | - |
540 | | - // Lets clean up. |
541 | 361 | @ldap_unbind(); |
542 | 362 | } else { |
543 | 363 | $this->printDebug( "Failed to connect", NONSENSITIVE ); |
544 | | - $this->cleanupFailedAuth(); |
| 364 | + $this->markAuthFailed(); |
545 | 365 | return false; |
546 | 366 | } |
547 | 367 | $this->printDebug( "Authentication passed", NONSENSITIVE ); |
— | — | @@ -549,7 +369,7 @@ |
550 | 370 | return true; |
551 | 371 | } |
552 | 372 | |
553 | | - function cleanupFailedAuth() { |
| 373 | + function markAuthFailed() { |
554 | 374 | $this->authFailed = true; |
555 | 375 | } |
556 | 376 | |
— | — | @@ -647,13 +467,13 @@ |
648 | 468 | |
649 | 469 | $pass = $this->getPasswordHash( $password ); |
650 | 470 | |
651 | | - $ldapconn = $this->connect(); |
652 | | - if ( $ldapconn ) { |
| 471 | + $this->connect(); |
| 472 | + if ( $this->ldapconn ) { |
653 | 473 | $this->printDebug( "Connected successfully", NONSENSITIVE ); |
654 | | - $userdn = $this->getSearchString( $ldapconn, $user->getName() ); |
| 474 | + $this->userdn = $this->getSearchString( $user->getName() ); |
655 | 475 | |
656 | 476 | $this->printDebug( "Binding as the writerDN", NONSENSITIVE ); |
657 | | - $bind = $this->bindAs( $ldapconn, $wgLDAPWriterDN[$_SESSION['wsDomain']], $wgLDAPWriterPassword[$_SESSION['wsDomain']] ); |
| 477 | + $bind = $this->bindAs( $wgLDAPWriterDN[$_SESSION['wsDomain']], $wgLDAPWriterPassword[$_SESSION['wsDomain']] ); |
658 | 478 | if ( !$bind ) { |
659 | 479 | return false; |
660 | 480 | } |
— | — | @@ -664,7 +484,7 @@ |
665 | 485 | //domain credentials for security reasons. |
666 | 486 | $password = ''; |
667 | 487 | |
668 | | - $success = ldap_modify( $ldapconn, $userdn, $values ); |
| 488 | + $success = @ldap_modify( $this->ldapconn, $this->userdn, $values ); |
669 | 489 | |
670 | 490 | //Let's clean up |
671 | 491 | @ldap_unbind(); |
— | — | @@ -717,13 +537,13 @@ |
718 | 538 | $this->nickname = $user->getOption( 'nickname' ); |
719 | 539 | $this->language = $user->getOption( 'language' ); |
720 | 540 | |
721 | | - $ldapconn = $this->connect(); |
722 | | - if ( $ldapconn ) { |
| 541 | + $this->connect(); |
| 542 | + if ( $this->ldapconn ) { |
723 | 543 | $this->printDebug( "Connected successfully", NONSENSITIVE ); |
724 | | - $userdn = $this->getSearchString( $ldapconn, $user->getName() ); |
| 544 | + $this->userdn = $this->getSearchString( $user->getName() ); |
725 | 545 | |
726 | 546 | $this->printDebug( "Binding as the writerDN", NONSENSITIVE ); |
727 | | - $bind = $this->bindAs( $ldapconn, $wgLDAPWriterDN[$_SESSION['wsDomain']], $wgLDAPWriterPassword[$_SESSION['wsDomain']] ); |
| 547 | + $bind = $this->bindAs( $wgLDAPWriterDN[$_SESSION['wsDomain']], $wgLDAPWriterPassword[$_SESSION['wsDomain']] ); |
728 | 548 | if ( !$bind ) { |
729 | 549 | return false; |
730 | 550 | } |
— | — | @@ -733,7 +553,7 @@ |
734 | 554 | if ( '' != $this->realname ) { $values["cn"] = $this->realname; } |
735 | 555 | if ( '' != $this->language ) { $values["preferredlanguage"] = $this->language; } |
736 | 556 | |
737 | | - if ( 0 != sizeof( $values ) && ldap_modify( $ldapconn, $userdn, $values ) ) { |
| 557 | + if ( 0 != sizeof( $values ) && @ldap_modify( $this->ldapconn, $this->userdn, $values ) ) { |
738 | 558 | $this->printDebug( "Successfully modified the user's attributes", NONSENSITIVE ); |
739 | 559 | @ldap_unbind(); |
740 | 560 | return true; |
— | — | @@ -811,7 +631,7 @@ |
812 | 632 | global $wgLDAPSearchAttributes; |
813 | 633 | global $wgLDAPWriteLocation; |
814 | 634 | global $wgLDAPRequiredGroups, $wgLDAPGroupDN; |
815 | | - global $wgLDAPRequireAuthAttribute, $wgLDAPAuthAttribute; |
| 635 | + global $wgLDAPAuthAttribute; |
816 | 636 | |
817 | 637 | $this->printDebug( "Entering addUser", NONSENSITIVE ); |
818 | 638 | |
— | — | @@ -844,16 +664,16 @@ |
845 | 665 | |
846 | 666 | $pass = $this->getPasswordHash( $password ); |
847 | 667 | |
848 | | - $ldapconn = $this->connect(); |
849 | | - if ( $ldapconn ) { |
| 668 | + $this->connect(); |
| 669 | + if ( $this->ldapconn ) { |
850 | 670 | $this->printDebug( "Successfully connected", NONSENSITIVE ); |
851 | 671 | |
852 | | - $userdn = $this->getSearchString( $ldapconn, $username ); |
853 | | - if ( '' == $userdn ) { |
854 | | - $this->printDebug( "userdn is blank, attempting to use wgLDAPWriteLocation", NONSENSITIVE ); |
| 672 | + $this->userdn = $this->getSearchString( $username ); |
| 673 | + if ( '' == $this->userdn ) { |
| 674 | + $this->printDebug( "$this->userdn is blank, attempting to use wgLDAPWriteLocation", NONSENSITIVE ); |
855 | 675 | if ( isset( $wgLDAPWriteLocation[$_SESSION['wsDomain']] ) ) { |
856 | 676 | $this->printDebug( "wgLDAPWriteLocation is set, using that", NONSENSITIVE ); |
857 | | - $userdn = $wgLDAPSearchAttributes[$_SESSION['wsDomain']] . "=" . |
| 677 | + $this->userdn = $wgLDAPSearchAttributes[$_SESSION['wsDomain']] . "=" . |
858 | 678 | $username . "," . $wgLDAPWriteLocation[$_SESSION['wsDomain']]; |
859 | 679 | } else { |
860 | 680 | $this->printDebug( "wgLDAPWriteLocation is not set, failing", NONSENSITIVE ); |
— | — | @@ -865,7 +685,7 @@ |
866 | 686 | |
867 | 687 | $this->printDebug( "Binding as the writerDN", NONSENSITIVE ); |
868 | 688 | |
869 | | - $bind = $this->bindAs( $ldapconn, $wgLDAPWriterDN[$_SESSION['wsDomain']], $wgLDAPWriterPassword[$_SESSION['wsDomain']] ); |
| 689 | + $bind = $this->bindAs( $wgLDAPWriterDN[$_SESSION['wsDomain']], $wgLDAPWriterPassword[$_SESSION['wsDomain']] ); |
870 | 690 | if ( !$bind ) { |
871 | 691 | $this->printDebug( "Failed to bind as the writerDN; add failed", NONSENSITIVE ); |
872 | 692 | return false; |
— | — | @@ -881,12 +701,12 @@ |
882 | 702 | $values["userpassword"] = $pass; |
883 | 703 | $values["objectclass"] = "inetorgperson"; |
884 | 704 | |
885 | | - if ( isset ( $wgLDAPRequireAuthAttribute ) && $wgLDAPRequireAuthAttribute[$_SESSION['wsDomain']] ) { |
| 705 | + if ( isset ( $wgLDAPAuthAttribute[$_SESSION['wsDomain']] ) ) { |
886 | 706 | $values[$wgLDAPAuthAttribute[$_SESSION['wsDomain']]] = "true"; |
887 | 707 | } |
888 | 708 | |
889 | 709 | $this->printDebug( "Adding user", NONSENSITIVE ); |
890 | | - if ( @ldap_add( $ldapconn, $userdn, $values ) ) { |
| 710 | + if ( @ldap_add( $this->ldapconn, $this->userdn, $values ) ) { |
891 | 711 | $this->printDebug( "Successfully added user", NONSENSITIVE ); |
892 | 712 | @ldap_unbind(); |
893 | 713 | return true; |
— | — | @@ -1114,12 +934,11 @@ |
1115 | 935 | * Gets the searchstring for a user based upon settings for the domain. |
1116 | 936 | * Returns a full DN for a user. |
1117 | 937 | * |
1118 | | - * @param resource $ldapconn |
1119 | 938 | * @param string $username |
1120 | 939 | * @return string |
1121 | 940 | * @access private |
1122 | 941 | */ |
1123 | | - function getSearchString( $ldapconn, $username ) { |
| 942 | + function getSearchString( $username ) { |
1124 | 943 | global $wgLDAPSearchStrings; |
1125 | 944 | global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword; |
1126 | 945 | |
— | — | @@ -1136,11 +955,11 @@ |
1137 | 956 | if ( isset( $wgLDAPProxyAgent[$_SESSION['wsDomain']] ) ) { |
1138 | 957 | //This is a proxy bind |
1139 | 958 | $this->printDebug( "Doing a proxy bind", NONSENSITIVE ); |
1140 | | - $bind = $this->bindAs( $ldapconn, $wgLDAPProxyAgent[$_SESSION['wsDomain']], $wgLDAPProxyAgentPassword[$_SESSION['wsDomain']] ); |
| 959 | + $bind = $this->bindAs( $wgLDAPProxyAgent[$_SESSION['wsDomain']], $wgLDAPProxyAgentPassword[$_SESSION['wsDomain']] ); |
1141 | 960 | } else { |
1142 | 961 | //This is an anonymous bind |
1143 | 962 | $this->printDebug( "Doing an anonymous bind", NONSENSITIVE ); |
1144 | | - $bind = $this->bindAs( $ldapconn ); |
| 963 | + $bind = $this->bindAs(); |
1145 | 964 | } |
1146 | 965 | |
1147 | 966 | if ( !$bind ) { |
— | — | @@ -1148,7 +967,7 @@ |
1149 | 968 | return ''; |
1150 | 969 | } |
1151 | 970 | |
1152 | | - $userdn = $this->getUserDN( $ldapconn, $username ); |
| 971 | + $userdn = $this->getUserDN( $username ); |
1153 | 972 | } |
1154 | 973 | $this->printDebug( "userdn is: $userdn", SENSITIVE ); |
1155 | 974 | return $userdn; |
— | — | @@ -1159,21 +978,20 @@ |
1160 | 979 | * This function will set $this->LDAPUsername |
1161 | 980 | * You must bind to the server before calling this. |
1162 | 981 | * |
1163 | | - * @param resource $ldapconn |
1164 | 982 | * @param string $username |
1165 | 983 | * @return string |
1166 | 984 | * @access private |
1167 | 985 | */ |
1168 | | - function getUserDN( $ldapconn, $username ) { |
| 986 | + function getUserDN( $username ) { |
1169 | 987 | global $wgLDAPSearchAttributes; |
1170 | | - global $wgLDAPRequireAuthAttribute, $wgLDAPAuthAttribute; |
| 988 | + global $wgLDAPAuthAttribute; |
1171 | 989 | |
1172 | 990 | $this->printDebug("Entering getUserDN", NONSENSITIVE); |
1173 | 991 | |
1174 | 992 | //we need to do a subbase search for the entry |
1175 | 993 | |
1176 | | - //Smartcard auth needs to check LDAP for required attributes. |
1177 | | - if ( ( isset( $wgLDAPRequireAuthAttribute[$_SESSION['wsDomain']] ) && $wgLDAPRequireAuthAttribute[$_SESSION['wsDomain']] ) |
| 994 | + //Auto auth needs to check LDAP for required attributes. |
| 995 | + if ( ( isset( $wgLDAPAuthAttribute[$_SESSION['wsDomain']] ) ) |
1178 | 996 | && $this->useAutoAuth() ) { |
1179 | 997 | $auth_filter = "(" . $wgLDAPAuthAttribute[$_SESSION['wsDomain']] . ")"; |
1180 | 998 | $srch_filter = "(" . $wgLDAPSearchAttributes[$_SESSION['wsDomain']] . "=" . $this->getLdapEscapedString( $username ) . ")"; |
— | — | @@ -1189,269 +1007,388 @@ |
1190 | 1008 | |
1191 | 1009 | $this->printDebug( "Using base: $base", SENSITIVE ); |
1192 | 1010 | |
1193 | | - $entry = @ldap_search( $ldapconn, $base, $filter, $attributes ); |
| 1011 | + $entry = @ldap_search( $this->ldapconn, $base, $filter, $attributes ); |
1194 | 1012 | if ( !$entry ) { |
1195 | 1013 | $this->printDebug( "Couldn't find an entry", NONSENSITIVE ); |
| 1014 | + $this->fetchedUserInfo = false; |
1196 | 1015 | return ''; |
1197 | 1016 | } |
1198 | 1017 | |
1199 | | - $info = @ldap_get_entries( $ldapconn, $entry ); |
| 1018 | + $this->userInfo = @ldap_get_entries( $this->ldapconn, $entry ); |
| 1019 | + $this->fetchedUserInfo = true; |
1200 | 1020 | |
1201 | 1021 | //This is a pretty useful thing to have for auto authentication, |
1202 | 1022 | //group checking, and pulling preferences. |
1203 | | - wfRunHooks( 'SetUsernameAttributeFromLDAP', array( &$this->LDAPUsername, $info ) ); |
| 1023 | + wfRunHooks( 'SetUsernameAttributeFromLDAP', array( &$this->LDAPUsername, $this->userInfo ) ); |
1204 | 1024 | if ( !is_string( $this->LDAPUsername ) ) { |
1205 | 1025 | $this->printDebug( "Fetched username is not a string (check your hook code...). This message can be safely ignored if you do not have the SetUsernameAttributeFromLDAP hook defined.", NONSENSITIVE ); |
1206 | 1026 | $this->LDAPUsername = ''; |
1207 | 1027 | } |
1208 | 1028 | |
1209 | | - $userdn = $info[0]["dn"]; |
| 1029 | + $userdn = $this->userInfo[0]["dn"]; |
1210 | 1030 | return $userdn; |
1211 | 1031 | } |
1212 | 1032 | |
1213 | | - //DEPRECATED |
1214 | | - function isMemberOfLdapGroup( $ldapconn, $userDN, $groupDN ) { |
1215 | | - $this->printDebug( "Entering isMemberOfLdapGroup (DEPRECATED)", NONSENSITIVE ); |
| 1033 | + function getUserInfo() { |
| 1034 | + //Don't fetch the same data more than once |
| 1035 | + if ( $this->fetchedUserInfo ) { |
| 1036 | + return $this->userInfo; |
| 1037 | + } |
1216 | 1038 | |
1217 | | - //we need to do a subbase search for the entry |
1218 | | - $filter = "(member=" . $this->getLdapEscapedString( $userDN ) . ")"; |
1219 | | - $info = ldap_get_entries( $ldapconn, @ldap_search( $ldapconn, $groupDN, $filter ) ); |
1220 | | - |
1221 | | - return ( $info["count"] >= 1 ); |
| 1039 | + $entry = @ldap_read( $this->ldapconn, $this->userdn, "objectclass=*" ); |
| 1040 | + $userInfo = @ldap_get_entries( $this->ldapconn, $entry ); |
| 1041 | + if ( $userInfo["count"] < 1 ) { |
| 1042 | + $this->fetchedUserInfo = false; |
| 1043 | + return; |
| 1044 | + } else { |
| 1045 | + $this->fetchedUserInfo = true; |
| 1046 | + return $userInfo; |
| 1047 | + } |
1222 | 1048 | } |
1223 | 1049 | |
1224 | 1050 | /** |
1225 | | - * Determines whether a user is a member of a group, or a nested group. |
| 1051 | + * Retrieve user preferences from LDAP |
1226 | 1052 | * |
1227 | | - * @param resource $ldapconn |
1228 | 1053 | * @param string $userDN |
1229 | | - * @return bool |
1230 | 1054 | * @access private |
1231 | 1055 | */ |
1232 | | - function isMemberOfRequiredLdapGroup( $ldapconn, $userDN ) { |
1233 | | - global $wgLDAPRequiredGroups; |
1234 | | - global $wgLDAPGroupSearchNestedGroups; |
| 1056 | + function getPreferences() { |
| 1057 | + global $wgLDAPPreferences; |
| 1058 | + global $wgLDAPRetrievePrefs; |
1235 | 1059 | |
1236 | | - $this->printDebug( "Entering isMemberOfRequiredLdapGroup", NONSENSITIVE ); |
| 1060 | + $this->printDebug("Entering getPreferences", NONSENSITIVE); |
1237 | 1061 | |
1238 | | - $reqgroups = $wgLDAPRequiredGroups[$_SESSION['wsDomain']]; |
1239 | | - for ( $i = 0; $i < count( $reqgroups ); $i++ ) { |
1240 | | - $reqgroups[$i] = strtolower( $reqgroups[$i] ); |
| 1062 | + $this->userInfo = $this->getUserInfo(); |
| 1063 | + if ( is_null( $this->userInfo ) ) { |
| 1064 | + $this->printDebug("Failed to get preferences", NONSENSITIVE); |
1241 | 1065 | } |
1242 | 1066 | |
1243 | | - $searchnested = $wgLDAPGroupSearchNestedGroups[$_SESSION['wsDomain']]; |
| 1067 | + //Retrieve preferences |
| 1068 | + if ( isset( $wgLDAPPreferences[$_SESSION['wsDomain']] ) ) { |
| 1069 | + $this->printDebug( "Retrieving preferences", NONSENSITIVE ); |
| 1070 | + $prefs = $wgLDAPPreferences[$_SESSION['wsDomain']]; |
| 1071 | + foreach ( array_keys( $prefs ) as $key ) { |
| 1072 | + switch ( $key ) { |
| 1073 | + case "email": |
| 1074 | + if ( isset( $this->userInfo[0]["$prefs[$key]"] ) ) { |
| 1075 | + $this->email = $this->userInfo[0]["$prefs[$key]"][0]; |
| 1076 | + $this->printDebug( "Retrieved email ($this->email) using attribute ($prefs[$key])", NONSENSITIVE ); |
| 1077 | + } |
| 1078 | + break; |
| 1079 | + case "language": |
| 1080 | + if ( isset( $this->userInfo[0]["$prefs[$key]"] ) ) { |
| 1081 | + $this->lang = $this->userInfo[0][$prefs[$key]][0]; |
| 1082 | + $this->printDebug( "Retrieved language ($this->lang) using attribute ($prefs[$key])", NONSENSITIVE ); |
| 1083 | + } |
| 1084 | + break; |
| 1085 | + case "nickname": |
| 1086 | + if ( isset( $this->userInfo[0]["$prefs[$key]"] ) ) { |
| 1087 | + $this->nickname = $this->userInfo[0]["$prefs[$key]"][0]; |
| 1088 | + $this->printDebug( "Retrieved nickname ($this->nickname) using attribute ($prefs[$key])", NONSENSITIVE ); |
| 1089 | + } |
| 1090 | + break; |
| 1091 | + case "realname": |
| 1092 | + if ( isset( $this->userInfo[0]["$prefs[$key]"] ) ) { |
| 1093 | + $this->realname = $this->userInfo[0]["$prefs[$key]"][0]; |
| 1094 | + $this->printDebug( "Retrieved realname ($this->realname) using attribute ($prefs[$key])", NONSENSITIVE ); |
| 1095 | + } |
| 1096 | + break; |
| 1097 | + } |
| 1098 | + } |
| 1099 | + } else if ( isset( $wgLDAPRetrievePrefs[$_SESSION['wsDomain']] ) && $wgLDAPRetrievePrefs[$_SESSION['wsDomain']] ) { |
| 1100 | + //DEPRECATED. Kept for backwards compatibility. |
| 1101 | + $this->printDebug( "Retrieving preferences", NONSENSITIVE ); |
| 1102 | + $this->printDebug( '$wgLDAPRetrievePrefs is a DEPRECATED option, please use $wgLDAPPreferences.', NONSENSITIVE ); |
1244 | 1103 | |
1245 | | - $this->printDebug( "Required groups:", NONSENSITIVE, $reqgroups ); |
| 1104 | + if (isset($this->userInfo[0]["mail"])) { |
| 1105 | + $this->email = $this->userInfo[0]["mail"][0]; |
| 1106 | + } |
| 1107 | + if (isset($this->userInfo[0]["preferredlanguage"])) { |
| 1108 | + $this->lang = $this->userInfo[0]["preferredlanguage"][0]; |
| 1109 | + } |
| 1110 | + if (isset($this->userInfo[0]["displayname"])) { |
| 1111 | + $this->nickname = $this->userInfo[0]["displayname"][0]; |
| 1112 | + } |
| 1113 | + if (isset($this->userInfo[0]["cn"])) { |
| 1114 | + $this->realname = $this->userInfo[0]["cn"][0]; |
| 1115 | + } |
1246 | 1116 | |
1247 | | - $groups = $this->getUserGroups( $ldapconn, $userDN ); |
| 1117 | + $this->printDebug( "Retrieved: $this->email, $this->lang, $this->nickname, $this->realname", SENSITIVE ); |
| 1118 | + } |
| 1119 | + } |
1248 | 1120 | |
1249 | | - //TODO: using variables for this kind of thing is dirty, let's think of a new way |
1250 | | - // to handle this need. |
1251 | | - if ( !$this->foundUserLDAPGroups ) { |
1252 | | - $this->printDebug( "Couldn't find the user in any groups (1).", NONSENSITIVE ); |
| 1121 | + function synchUsername( $username ) { |
| 1122 | + global $wgLDAPUniqueBlockLogin, $wgLDAPUniqueRenameUser; |
| 1123 | + global $wgLDAPUniqueAttribute; |
1253 | 1124 | |
1254 | | - //User isn't in any groups, so he/she obviously can't be in |
1255 | | - //a required one |
1256 | | - return false; |
1257 | | - } else { |
1258 | | - //User is in groups, let's see if a required group is one of them |
1259 | | - foreach ( $groups as $group ) { |
1260 | | - if ( in_array( $group, $reqgroups ) ) { |
1261 | | - $this->printDebug( "Found user in a group.", NONSENSITIVE ); |
1262 | | - return true; |
1263 | | - } |
| 1125 | + $this->printDebug("Entering synchUsername", NONSENSITIVE); |
| 1126 | + |
| 1127 | + $this->userInfo = $this->getUserInfo(); |
| 1128 | + if ( is_null( $this->userInfo ) ) { |
| 1129 | + $this->printDebug("Failed to get preferences", NONSENSITIVE); |
| 1130 | + } |
| 1131 | + |
| 1132 | + // Are we blocking login/renaming users on unique external ID mismatches? |
| 1133 | + // *** WARNING *** |
| 1134 | + // This needs to be fixed before use! This probably does not work correctly |
| 1135 | + // with all options. It is probably a good idea to refactor the username stuff |
| 1136 | + // in general (as it is currently somewhat of a kludge). Also, MediaWiki does |
| 1137 | + // not currently have support for this. |
| 1138 | + // *** WARNING *** |
| 1139 | + if ( ( isset( $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) && $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) |
| 1140 | + || ( isset( $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) && $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) ) { |
| 1141 | + |
| 1142 | + $this->printDebug( "Checking for username change in LDAP.", SENSITIVE ); |
| 1143 | + |
| 1144 | + //Get the user's unique attribute from LDAP |
| 1145 | + if ( isset( $wgLDAPUniqueAttribute[$_SESSION['wsDomain']] ) ) { |
| 1146 | + $ldapuniqueattr = $wgLDAPUniqueAttribute[$_SESSION['wsDomain']]; |
| 1147 | + $this->externalid = $this->info[0][$ldapuniqueattr][0]; |
| 1148 | + } else { |
| 1149 | + return false; |
1264 | 1150 | } |
1265 | 1151 | |
1266 | | - //We didn't find the user in the group, lets check nested groups |
1267 | | - if ( $searchnested ) { |
1268 | | - if ( $this->searchNestedGroups( $ldapconn, $groups ) ) { |
1269 | | - return true; |
| 1152 | + $this->printDebug( "Retrieved external id: $this->externalid", SENSITIVE ); |
| 1153 | + |
| 1154 | + $retrievedusername = User::whoIsExternalID( "$this->externalid" ); |
| 1155 | + |
| 1156 | + $this->printDebug( "Username (in MediaWiki database) of fetched external id: $retrievedusername", SENSITIVE ); |
| 1157 | + |
| 1158 | + // See if the username returned from the database matches the username given |
| 1159 | + if ( $retrievedusername != '' && ( $username != $retrievedusername ) ) { |
| 1160 | + if ( isset( $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) |
| 1161 | + && $wgLDAPUniqueBlockLogin[$_SESSION['wsDomain']] ) { |
| 1162 | + |
| 1163 | + $this->printDebug( "Usernames do not match, blocking login.", SENSITIVE ); |
| 1164 | + return false; |
| 1165 | + } else if ( isset( $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) |
| 1166 | + && $wgLDAPUniqueRenameUser[$_SESSION['wsDomain']] ) { |
| 1167 | + |
| 1168 | + $this->printDebug( "Usernames do not match, renaming user in database.", SENSITIVE ); |
| 1169 | + |
| 1170 | + global $wgVersion; |
| 1171 | + if ( version_compare( $wgVersion, '1.7.0', '<' ) ) { |
| 1172 | + $this->printDebug( "Renaming users is only supported in MediaWiki 1.7+, please upgrade.", SENSITIVE ); |
| 1173 | + $this->markAuthFailed(); |
| 1174 | + return false; |
| 1175 | + } |
| 1176 | + |
| 1177 | + $olduser = User::newFromName( $retrievedusername ); |
| 1178 | + $uid = $olduser->idForName(); |
| 1179 | + |
| 1180 | + // Ensure we don't require the same class twice |
| 1181 | + if ( !class_exists( 'RenameuserSQL' ) ) { |
| 1182 | + require( 'Renameuser/SpecialRenameuser_body.php' ); |
| 1183 | + } |
| 1184 | + |
| 1185 | + // Make a new rename user object with: from, to, uid of from |
| 1186 | + $rename = new RenameuserSQL( $retrievedusername, $username, $uid ); |
| 1187 | + $rename->rename(); |
| 1188 | + |
| 1189 | + // For the time being we can't just allow the user to log in |
| 1190 | + // as MediaWiki will try to create the user account after we |
| 1191 | + // do a rename. If we don't return false, the user will get |
| 1192 | + // a database error |
| 1193 | + return false; |
1270 | 1194 | } |
1271 | 1195 | } |
1272 | 1196 | |
1273 | | - $this->printDebug("Couldn't find the user in any groups (2).", NONSENSITIVE ); |
1274 | | - |
1275 | | - return false; |
| 1197 | + $this->printDebug( "Usernames matched or the user doesn't exist in the database yet.", SENSITIVE ); |
1276 | 1198 | } |
| 1199 | + |
| 1200 | + return true; |
1277 | 1201 | } |
1278 | 1202 | |
1279 | 1203 | /** |
1280 | | - * Helper function for isMemberOfRequiredLdapGroup. |
1281 | | - * $checkedgroups is used for tail recursion and shouldn't be provided |
1282 | | - * when called externally. |
| 1204 | + * Checks to see whether a user is in a required group. |
1283 | 1205 | * |
1284 | | - * @param resource $ldapconn |
1285 | | - * @param string $userDN |
1286 | | - * @param array $checkedgroups |
| 1206 | + * @param string $username |
1287 | 1207 | * @return bool |
1288 | 1208 | * @access private |
1289 | 1209 | */ |
1290 | | - function searchNestedGroups( $ldapconn, $groups, $checkedgroups = array() ) { |
| 1210 | + function checkGroups( $username ) { |
| 1211 | + global $wgLDAPGroupDN; |
1291 | 1212 | global $wgLDAPRequiredGroups; |
1292 | 1213 | |
1293 | | - $this->printDebug( "Entering searchNestedGroups", NONSENSITIVE ); |
| 1214 | + $this->printDebug("Entering checkGroups", NONSENSITIVE); |
1294 | 1215 | |
1295 | | - //base case, no more groups left to check |
1296 | | - if ( !$groups ) { |
1297 | | - $this->printDebug( "Couldn't find user in any nested groups.", NONSENSITIVE ); |
1298 | | - return false; |
| 1216 | + //Old style groups, non-nestable and fairly limited on group type (full DN |
| 1217 | + //versus username). DEPRECATED |
| 1218 | + if ( $wgLDAPGroupDN ) { |
| 1219 | + $this->printDebug( "Checking for (old style) group membership", NONSENSITIVE ); |
| 1220 | + //we need to do a subbase search for the entry |
| 1221 | + $filter = "(member=" . $this->getLdapEscapedString( $this->userdn ) . ")"; |
| 1222 | + $info = @ldap_get_entries( $this->ldapconn, @ldap_search( $this->ldapconn, $wgLDAPGroupDN, $filter ) ); |
| 1223 | + |
| 1224 | + return ( $info["count"] >= 1 ); |
1299 | 1225 | } |
1300 | 1226 | |
1301 | | - $this->printDebug( "Checking groups:", SENSITIVE, $groups ); |
| 1227 | + //New style group checking |
| 1228 | + if ( isset( $wgLDAPRequiredGroups[$_SESSION['wsDomain']] ) ) { |
| 1229 | + $this->printDebug( "Checking for (new style) group membership", NONSENSITIVE ); |
| 1230 | + $reqgroups = $wgLDAPRequiredGroups[$_SESSION['wsDomain']]; |
| 1231 | + for ( $i = 0; $i < count( $reqgroups ); $i++ ) { |
| 1232 | + $reqgroups[$i] = strtolower( $reqgroups[$i] ); |
| 1233 | + } |
1302 | 1234 | |
1303 | | - $reqgroups = $wgLDAPRequiredGroups[$_SESSION['wsDomain']]; |
1304 | | - for ( $i = 0; $i < count( $reqgroups ); $i++ ) { |
1305 | | - $reqgroups[$i] = strtolower( $reqgroups[$i] ); |
1306 | | - } |
| 1235 | + $this->printDebug( "Required groups:", NONSENSITIVE, $reqgroups ); |
1307 | 1236 | |
1308 | | - $groupstocheck = array(); |
1309 | | - foreach ( $groups as $group ) { |
1310 | | - $returnedgroups = $this->getUserGroups( $ldapconn, $group, false, false ); |
1311 | | - $this->printDebug( "Group $group is in the following groups:", SENSITIVE, $returnedgroups ); |
1312 | | - foreach ( $returnedgroups as $checkme ) { |
1313 | | - if ( in_array( $checkme, $checkedgroups ) ) { |
1314 | | - //We already checked this, move on |
1315 | | - continue; |
| 1237 | + if ( count( $this->userLDAPGroups ) == 0 ) { |
| 1238 | + $this->printDebug( "Couldn't find the user in any groups (1).", NONSENSITIVE ); |
| 1239 | + |
| 1240 | + //User isn't in any groups, so he/she obviously can't be in |
| 1241 | + //a required one |
| 1242 | + return false; |
| 1243 | + } else { |
| 1244 | + //User is in groups, let's see if a required group is one of them |
| 1245 | + foreach ( $this->userLDAPGroups["dn"] as $group ) { |
| 1246 | + $this->printDebug( "Checking against: $group", NONSENSITIVE ); |
| 1247 | + if ( in_array( $group, $reqgroups ) ) { |
| 1248 | + $this->printDebug( "Found user in a group.", NONSENSITIVE ); |
| 1249 | + return true; |
| 1250 | + } |
1316 | 1251 | } |
1317 | | - $this->printDebug( "Checking membership for: $checkme", SENSITIVE ); |
1318 | | - if ( in_array( $checkme, $reqgroups ) ) { |
1319 | | - $this->printDebug( "Found user in a nested group.", NONSENSITIVE ); |
1320 | | - //Woohoo |
1321 | | - return true; |
1322 | | - } else { |
1323 | | - //We'll need to check this group's members now |
1324 | | - array_push( $groupstocheck, $checkme ); |
1325 | | - } |
| 1252 | + |
| 1253 | + $this->printDebug("Couldn't find the user in any groups (2).", NONSENSITIVE ); |
| 1254 | + return false; |
1326 | 1255 | } |
1327 | 1256 | } |
1328 | 1257 | |
1329 | | - $checkedgroups = array_unique( array_merge( $groups, $checkedgroups ) ); |
1330 | | - |
1331 | | - //Mmmmmm. Tail recursion. Tasty. |
1332 | | - return $this->searchNestedGroups( $ldapconn, $groupstocheck, $checkedgroups ); |
| 1258 | + // Ensure we return true if we aren't checking groups. |
| 1259 | + return true; |
1333 | 1260 | } |
1334 | 1261 | |
1335 | 1262 | /** |
1336 | | - * Helper function for isMemberOfRequiredLdapGroup and searchNestedGroups. Returns |
1337 | | - * a list of groups the user is in, all munged to lowercase. |
1338 | | - * Sets $this->foundUserLDAPGroups |
| 1263 | + * Function to get the user's groups. |
1339 | 1264 | * |
1340 | | - * @param resource $ldapconn |
1341 | | - * @param string $dn |
1342 | | - * @return array |
1343 | 1265 | * @access private |
1344 | 1266 | */ |
1345 | | - function getUserGroups( $ldapconn, $dn, $getShortnames = false, $returncache = true ) { |
1346 | | - $this->printDebug( "Entering getUserGroups", NONSENSITIVE ); |
| 1267 | + function getGroups( $username ) { |
| 1268 | + global $wgLDAPRequiredGroups, $wgLDAPUseLDAPGroups; |
| 1269 | + global $wgLDAPGroupUseFullDN, $wgLDAPGroupUseRetrievedUsername; |
| 1270 | + global $wgLDAPGroupSearchNestedGroups; |
| 1271 | + global $wgLDAPGroupsPrevail; |
| 1272 | + global $wgLDAPGroupsUseMemberOf; |
1347 | 1273 | |
1348 | | - //Let's return the saved groups if they are available |
1349 | | - if ( $getShortnames ) { |
1350 | | - if ( $returncache && isset( $this->userLDAPShortnameGroupCache ) ) { |
1351 | | - $this->printDebug( "Returning short name group cache.", NONSENSITIVE ); |
1352 | | - return $this->userLDAPShortnameGroupCache; |
| 1274 | + $this->printDebug("Entering getGroups", NONSENSITIVE); |
| 1275 | + |
| 1276 | + //Find groups |
| 1277 | + if ( isset( $wgLDAPRequiredGroups[$_SESSION['wsDomain']] ) || ( isset( $wgLDAPUseLDAPGroups[$_SESSION['wsDomain']] ) && $wgLDAPUseLDAPGroups[$_SESSION['wsDomain']] ) ) { |
| 1278 | + $this->printDebug( "Retrieving LDAP group membership", NONSENSITIVE ); |
| 1279 | + |
| 1280 | + //Let's figure out what we should be searching for |
| 1281 | + if ( isset( $wgLDAPGroupUseFullDN[$_SESSION['wsDomain']] ) && $wgLDAPGroupUseFullDN[$_SESSION['wsDomain']] ) { |
| 1282 | + $usertopass = $this->userdn; |
| 1283 | + } else { |
| 1284 | + if ( ( isset( $wgLDAPGroupUseRetrievedUsername[$_SESSION['wsDomain']] ) && $wgLDAPGroupUseRetrievedUsername[$_SESSION['wsDomain']] ) |
| 1285 | + && $this->LDAPUsername != '' ) { |
| 1286 | + |
| 1287 | + $usertopass = $this->LDAPUsername; |
| 1288 | + } else { |
| 1289 | + $usertopass = $username; |
| 1290 | + } |
1353 | 1291 | } |
1354 | | - } else { |
1355 | | - if ( $returncache && isset( $this->userLDAPGroupCache ) ) { |
1356 | | - $this->printDebug( "Returning long name group cache.", NONSENSITIVE ); |
1357 | | - return $this->userLDAPGroupCache; |
1358 | | - } |
1359 | | - } |
1360 | 1292 | |
1361 | | - //We haven't done a search yet, lets do it now |
1362 | | - list( $groups, $shortnamegroups ) = $this->getGroups( $ldapconn, $dn ); |
| 1293 | + if ( isset( $wgLDAPGroupsUseMemberOf[$_SESSION['wsDomain']] ) && $wgLDAPGroupsUseMemberOf[$_SESSION['wsDomain']] ) { |
| 1294 | + $this->printDebug( "Using memberOf", NONSENSITIVE ); |
| 1295 | + $this->userInfo = $this->getUserInfo(); |
| 1296 | + if ( is_null( $this->userInfo ) ) { |
| 1297 | + $this->printDebug("Failed to get memberOf attribute", NONSENSITIVE); |
| 1298 | + } |
| 1299 | + if ( isset( $this->userInfo[0]["memberof"] ) ) { |
| 1300 | + # The first entry is always a count |
| 1301 | + $memberOfMembers = $this->userInfo[0]["memberof"]; |
| 1302 | + array_shift( $memberOfMembers ); |
| 1303 | + $groups = array( "dn"=> array(), "short"=>array() ); |
| 1304 | + foreach( $memberOfMembers as $mem ) { |
| 1305 | + array_push( $groups["dn"], strtolower( $mem ) ); |
| 1306 | + } |
| 1307 | + $this->userLDAPGroups = $groups; |
| 1308 | + } |
| 1309 | + } else { |
| 1310 | + $this->printDebug( "Searching for the groups", NONSENSITIVE ); |
| 1311 | + $this->userLDAPGroups = $this->searchGroups( $usertopass ); |
1363 | 1312 | |
1364 | | - //Save the groups for next time we are called |
1365 | | - //Merge groups if a set of groups already exist for |
1366 | | - //nested group searching (half assed) support |
1367 | | - if ( isset( $this->userLDAPGroupCache ) ) { |
1368 | | - array_unique( array_merge( $groups, $this->userLDAPGroupCache ) ); |
1369 | | - } else { |
1370 | | - $this->userLDAPGroupCache = $groups; |
1371 | | - } |
1372 | | - if ( isset( $this->userLDAPShortnameGroupCache ) ) { |
1373 | | - array_unique( array_merge( $shortnamegroups, $this->userLDAPShortnameGroupCache ) ); |
1374 | | - } else { |
1375 | | - $this->userLDAPShortnameGroupCache = $shortnamegroups; |
1376 | | - } |
| 1313 | + if ( isset( $wgLDAPGroupSearchNestedGroups[$_SESSION['wsDomain']] ) && $wgLDAPGroupSearchNestedGroups[$_SESSION['wsDomain']] ) { |
| 1314 | + $this->userLDAPGroups = $this->searchNestedGroups( $this->userLDAPGroups ); |
| 1315 | + $this->printDebug( "Got the following nested groups:", SENSITIVE, $this->userLDAPGroups["dn"] ); |
| 1316 | + } |
| 1317 | + } |
1377 | 1318 | |
1378 | | - //We only need to check one of the two arrays, as they should be |
1379 | | - //identical from a member standpoint. |
1380 | | - if ( count( $groups ) == 0 ) { |
1381 | | - $this->foundUserLDAPGroups = false; |
1382 | | - } else { |
1383 | | - $this->foundUserLDAPGroups = true; |
| 1319 | + //Only find all groups if the user has any groups; otherwise, we are |
| 1320 | + //just wasting a search. |
| 1321 | + if ( ( isset( $wgLDAPGroupsPrevail[$_SESSION['wsDomain']] ) && $wgLDAPGroupsPrevail[$_SESSION['wsDomain']] ) && count( $this->userLDAPGroups ) != 0 ) { |
| 1322 | + $this->allLDAPGroups = $this->searchGroups( '*' ); |
| 1323 | + } |
1384 | 1324 | } |
1385 | | - |
1386 | | - if ( $getShortnames ) { |
1387 | | - return $shortnamegroups; |
1388 | | - } else { |
1389 | | - return $groups; |
1390 | | - } |
1391 | 1325 | } |
1392 | 1326 | |
1393 | 1327 | /** |
1394 | | - * Helper function for retrieving all LDAP groups. Returns |
1395 | | - * a list of all groups in the LDAP server, that match available groups |
1396 | | - * the user is already joined to in MediaWiki, under the appropriate |
1397 | | - * basedn, all munged to lowercase. |
1398 | | - * Sets $this->foundAllLDAPGroups |
| 1328 | + * Function to return an array of nested groups when given a group or list of groups. |
| 1329 | + * $searchedgroups is used for tail recursion and shouldn't be provided |
| 1330 | + * when called externally. |
1399 | 1331 | * |
1400 | | - * @param resource $ldapconn |
1401 | | - * @param string $dn |
1402 | | - * @return array |
| 1332 | + * @param string $userDN |
| 1333 | + * @param array $searchedgroups |
| 1334 | + * @return bool |
1403 | 1335 | * @access private |
1404 | 1336 | */ |
1405 | | - function getAllGroups( $ldapconn, $getShortnames = false ) { |
1406 | | - $this->printDebug( "Entering getAllGroups", NONSENSITIVE ); |
| 1337 | + function searchNestedGroups( $groups, $searchedgroups = array( "dn" => Array(), "short" => Array() ) ) { |
| 1338 | + $this->printDebug( "Entering searchNestedGroups", NONSENSITIVE ); |
1407 | 1339 | |
1408 | | - //Let's return the saved groups if they are available |
1409 | | - if ( $getShortnames ) { |
1410 | | - if ( isset( $this->allLDAPShortnameGroupCache ) ) { |
1411 | | - return $this->allLDAPShortnameGroupCache; |
1412 | | - } |
1413 | | - } else { |
1414 | | - if ( isset( $this->allLDAPGroupCache ) ) { |
1415 | | - return $this->allLDAPGroupCache; |
1416 | | - } |
| 1340 | + //base case, no more groups left to check |
| 1341 | + if ( count( $groups["dn"] ) == 0 ) { |
| 1342 | + $this->printDebug( "No more groups to search.", NONSENSITIVE ); |
| 1343 | + return $searchedgroups; |
1417 | 1344 | } |
1418 | 1345 | |
1419 | | - //We haven't done a search yet, lets do it now |
1420 | | - list( $groups, $shortnamegroups ) = $this->getGroups( $ldapconn, '*' ); |
| 1346 | + $this->printDebug( "Searching groups:", SENSITIVE, $groups["dn"] ); |
1421 | 1347 | |
1422 | | - //Save the groups for next time we are called |
1423 | | - $this->allLDAPGroupCache = $groups; |
1424 | | - $this->allLDAPShortnameGroupCache = $shortnamegroups; |
1425 | | - |
1426 | | - //We only need to check one of the two arrays, as they should be |
1427 | | - //identical from a member standpoint. |
1428 | | - if ( count( $groups ) == 0 ) { |
1429 | | - $this->foundAllLDAPGroups = false; |
1430 | | - } else { |
1431 | | - $this->foundAllLDAPGroups = true; |
| 1348 | + $groupstosearch = array( "short"=>array(), "dn"=>array() ); |
| 1349 | + foreach ( $groups["dn"] as $group ) { |
| 1350 | + $returnedgroups = $this->searchGroups( $group ); |
| 1351 | + $this->printDebug( "Group $group is in the following groups:", SENSITIVE, $returnedgroups["dn"] ); |
| 1352 | + foreach ( $returnedgroups["dn"] as $searchme ) { |
| 1353 | + if ( in_array( $searchme, $searchedgroups["dn"] ) ) { |
| 1354 | + //We already searched this, move on |
| 1355 | + continue; |
| 1356 | + } else { |
| 1357 | + //We'll need to search this group's members now |
| 1358 | + $this->printDebug( "Adding $searchme to the list of groups (1)", SENSITIVE ); |
| 1359 | + $groupstosearch["dn"][] = $searchme; |
| 1360 | + } |
| 1361 | + } |
| 1362 | + foreach ( $returnedgroups["short"] as $searchme ) { |
| 1363 | + if ( in_array( $searchme, $searchedgroups["short"] ) ) { |
| 1364 | + //We already searched this, move on |
| 1365 | + continue; |
| 1366 | + } else { |
| 1367 | + $this->printDebug( "Adding $searchme to the list of groups (2)", SENSITIVE ); |
| 1368 | + //We'll need to search this group's members now |
| 1369 | + $groupstosearch["short"][] = $searchme; |
| 1370 | + } |
| 1371 | + } |
1432 | 1372 | } |
1433 | 1373 | |
1434 | | - if ( $getShortnames ) { |
1435 | | - return $shortnamegroups; |
1436 | | - } else { |
1437 | | - return $groups; |
1438 | | - } |
| 1374 | + $searchedgroups = array_merge_recursive( $groups, $searchedgroups ); |
| 1375 | + |
| 1376 | + //Mmmmmm. Tail recursion. Tasty. |
| 1377 | + return $this->searchNestedGroups( $groupstosearch, $searchedgroups ); |
1439 | 1378 | } |
1440 | 1379 | |
1441 | 1380 | /** |
1442 | | - * Helper function for getUserGroups and getAllGroups. You shouldn't |
1443 | | - * call this directly. |
| 1381 | + * Search groups for the supplied DN |
1444 | 1382 | * |
1445 | | - * @param resource $ldapconn |
1446 | 1383 | * @param string $dn |
1447 | 1384 | * @return array |
1448 | 1385 | * @access private |
1449 | 1386 | */ |
1450 | | - function getGroups( $ldapconn, $dn ) { |
| 1387 | + function searchGroups( $dn ) { |
1451 | 1388 | global $wgLDAPGroupObjectclass, $wgLDAPGroupAttribute, $wgLDAPGroupNameAttribute; |
1452 | 1389 | global $wgLDAPProxyAgent, $wgLDAPProxyAgentPassword; |
1453 | 1390 | global $wgUser; |
1454 | 1391 | |
1455 | | - $this->printDebug( "Entering getGroups", NONSENSITIVE ); |
| 1392 | + $this->printDebug( "Entering searchGroups", NONSENSITIVE ); |
1456 | 1393 | |
1457 | 1394 | $base = $this->getBaseDN( GROUPDN ); |
1458 | 1395 | |
— | — | @@ -1472,44 +1409,37 @@ |
1473 | 1410 | //We'll try to bind as the proxyagent as the proxyagent should normally have more |
1474 | 1411 | //rights than the user. If the proxyagent fails to bind, we will still be able |
1475 | 1412 | //to search as the normal user (which is why we don't return on fail). |
1476 | | - $this->printDebug( "Binding as the proxyagentDN", NONSENSITIVE ); |
1477 | | - $bind = $this->bindAs( $ldapconn, $wgLDAPProxyAgent[$_SESSION['wsDomain']], $wgLDAPProxyAgentPassword[$_SESSION['wsDomain']] ); |
| 1413 | + $this->printDebug( "Binding as the proxyagent", NONSENSITIVE ); |
| 1414 | + $bind = $this->bindAs( $wgLDAPProxyAgent[$_SESSION['wsDomain']], $wgLDAPProxyAgentPassword[$_SESSION['wsDomain']] ); |
1478 | 1415 | } |
1479 | 1416 | |
1480 | | - $info = @ldap_search( $ldapconn, $base, $filter ); |
1481 | | - //TODO: Active Directory always returns something, we need to take this into account |
| 1417 | + $info = @ldap_search( $this->ldapconn, $base, $filter ); |
| 1418 | + #if ( $info["count"] < 1 ) { |
1482 | 1419 | if ( !$info ) { |
1483 | 1420 | $this->printDebug( "No entries returned from search.", SENSITIVE ); |
1484 | 1421 | |
1485 | | - //Return an array with two empty arrays so that other functions |
| 1422 | + //Return an array so that other functions |
1486 | 1423 | //don't error out. |
1487 | | - return array( array(), array() ); |
| 1424 | + return array( "short"=>array(), "dn"=>array() ); |
1488 | 1425 | } |
1489 | 1426 | |
1490 | | - $entries = @ldap_get_entries( $ldapconn, $info ); |
| 1427 | + $entries = @ldap_get_entries( $this->ldapconn, $info ); |
1491 | 1428 | |
1492 | 1429 | //We need to shift because the first entry will be a count |
1493 | 1430 | array_shift( $entries ); |
1494 | 1431 | |
1495 | 1432 | //Let's get a list of both full dn groups and shortname groups |
1496 | | - $groups = array(); |
1497 | | - $shortnamegroups = array(); |
| 1433 | + $groups = array( "short"=>array(), "dn"=>array() ); |
1498 | 1434 | foreach ( $entries as $entry ) { |
1499 | | - $mem = strtolower( $entry['dn'] ); |
1500 | | - $shortnamemem = strtolower( $entry[$nameattribute][0] ); |
1501 | | - |
1502 | | - array_push( $groups, $mem ); |
1503 | | - array_push( $shortnamegroups, $shortnamemem ); |
| 1435 | + $shortMember = strtolower( $entry[$nameattribute][0] ); |
| 1436 | + $dnMember = strtolower( $entry['dn'] ); |
| 1437 | + $groups["short"][] = $shortMember; |
| 1438 | + $groups["dn"][] = $dnMember; |
1504 | 1439 | } |
1505 | 1440 | |
1506 | | - $both_groups = array(); |
1507 | | - array_push( $both_groups, $groups ); |
1508 | | - array_push( $both_groups, $shortnamegroups ); |
| 1441 | + $this->printDebug( "Returned groups:", SENSITIVE, $groups["dn"] ); |
1509 | 1442 | |
1510 | | - $this->printDebug( "Returned groups:", SENSITIVE, $groups ); |
1511 | | - $this->printDebug( "Returned groups:", SENSITIVE, $shortnamegroups ); |
1512 | | - |
1513 | | - return $both_groups; |
| 1443 | + return $groups; |
1514 | 1444 | } |
1515 | 1445 | |
1516 | 1446 | /** |
— | — | @@ -1523,7 +1453,7 @@ |
1524 | 1454 | function hasLDAPGroup( $group ) { |
1525 | 1455 | $this->printDebug( "Entering hasLDAPGroup", NONSENSITIVE ); |
1526 | 1456 | |
1527 | | - return in_array( strtolower( $group ), $this->userLDAPGroups ); |
| 1457 | + return in_array( strtolower( $group ), $this->userLDAPGroups["short"] ); |
1528 | 1458 | } |
1529 | 1459 | |
1530 | 1460 | /** |
— | — | @@ -1536,7 +1466,7 @@ |
1537 | 1467 | function isLDAPGroup( $group ) { |
1538 | 1468 | $this->printDebug( "Entering isLDAPGroup", NONSENSITIVE ); |
1539 | 1469 | |
1540 | | - return in_array( strtolower( $group ), $this->allLDAPGroups ); |
| 1470 | + return in_array( strtolower( $group ), $this->allLDAPGroups["short"] ); |
1541 | 1471 | } |
1542 | 1472 | |
1543 | 1473 | /** |
— | — | @@ -1573,7 +1503,7 @@ |
1574 | 1504 | # Add ldap groups as local groups |
1575 | 1505 | if ( isset( $wgLDAPGroupsPrevail[$_SESSION['wsDomain']] ) && $wgLDAPGroupsPrevail[$_SESSION['wsDomain']] ) { |
1576 | 1506 | $this->printDebug( "Adding all groups to wgGroupPermissions: ", SENSITIVE, $this->allLDAPGroups ); |
1577 | | - foreach ( $this->allLDAPGroups as $ldapgroup ) |
| 1507 | + foreach ( $this->allLDAPGroups["short"] as $ldapgroup ) |
1578 | 1508 | if ( !array_key_exists( $ldapgroup, $wgGroupPermissions ) ) |
1579 | 1509 | $wgGroupPermissions[$ldapgroup] = array(); |
1580 | 1510 | } |
— | — | @@ -1647,16 +1577,17 @@ |
1648 | 1578 | * @param string $debugVal |
1649 | 1579 | * @access private |
1650 | 1580 | */ |
1651 | | - function printDebug( $debugText, $debugVal, $debugArr = Null ) { |
| 1581 | + function printDebug( $debugText, $debugVal, $debugArr = null ) { |
1652 | 1582 | global $wgLDAPDebug; |
1653 | 1583 | |
1654 | 1584 | if ( isset( $debugArr ) ) { |
1655 | 1585 | if ( $wgLDAPDebug > $debugVal ) { |
1656 | | - echo $debugText . implode( ",", $debugArr ) . "<br />"; |
| 1586 | + $text = $debugText . " " . implode( "::", $debugArr ); |
| 1587 | + wfDebugLog( 'ldap', $text, false ); |
1657 | 1588 | } |
1658 | 1589 | } else { |
1659 | 1590 | if ( $wgLDAPDebug > $debugVal ) { |
1660 | | - echo $debugText . "<br />"; |
| 1591 | + wfDebugLog( 'ldap', $debugText, false ); |
1661 | 1592 | } |
1662 | 1593 | } |
1663 | 1594 | } |
— | — | @@ -1665,18 +1596,17 @@ |
1666 | 1597 | * Binds as $userdn with $password. This can be called with only the ldap |
1667 | 1598 | * connection resource for an anonymous bind. |
1668 | 1599 | * |
1669 | | - * @param resourse $ldapconn |
1670 | 1600 | * @param string $userdn |
1671 | 1601 | * @param string $password |
1672 | 1602 | * @return bool |
1673 | 1603 | * @access private |
1674 | 1604 | */ |
1675 | | - function bindAs( $ldapconn, $userdn=null, $password=null ) { |
| 1605 | + function bindAs( $userdn=null, $password=null ) { |
1676 | 1606 | //Let's see if the user can authenticate. |
1677 | 1607 | if ( $userdn == null || $password == null ) { |
1678 | | - $bind = @ldap_bind( $ldapconn ); |
| 1608 | + $bind = @ldap_bind( $this->ldapconn ); |
1679 | 1609 | } else { |
1680 | | - $bind = @ldap_bind( $ldapconn, $userdn, $password ); |
| 1610 | + $bind = @ldap_bind( $this->ldapconn, $userdn, $password ); |
1681 | 1611 | } |
1682 | 1612 | if ( !$bind ) { |
1683 | 1613 | $this->printDebug( "Failed to bind as $userdn", NONSENSITIVE ); |