@@ -49,6 +49,7 @@ class LdapAuth extends BaseObject
49
49
private $ _ldapBaseDn ;
50
50
private $ _l ;
51
51
private $ _username ;
52
+ private $ _curDn ;
52
53
53
54
public function init ()
54
55
{
@@ -145,15 +146,34 @@ public function autoDetect($overrideIp = false)
145
146
/**
146
147
* @param string $username The username to use
147
148
* @param string $password The users AD/LDAP password
148
- * @param integer|false $domainKey The array key of the domain config to use. False to try every single domain
149
+ * @param integer|false $domainKey The array key of the domain config to use. False to try every single domain. HAS NO EFFECT IF $fetchUserDn IS TRUE!
149
150
* @param boolean $fetchUserDN If true, determine users DN and use that as username
151
+ * @return bool True on success, false on failure.
150
152
* @throws ErrorException
151
153
*/
152
154
public function login ($ username , $ password , $ domainKey = false , $ fetchUserDN = false )
153
155
{
154
156
155
157
Yii::debug ('Hello! :) Trying to log you in via LDAP! ' , __METHOD__ );
156
158
159
+ if ($ fetchUserDN ) {
160
+ Yii::debug ("We have to determine the user DN first! " , __METHOD__ );
161
+ $ userDNSearch = $ this ->searchUser ($ username , ['dn ' ], null , $ domainKey , true );
162
+ Yii::debug ("fetchUserDN: yes - Result: " , __METHOD__ );
163
+ Yii::debug ($ userDNSearch , __METHOD__ );
164
+
165
+ $ firstArrayKey = !$ userDNSearch ? false : array_key_first ($ userDNSearch );
166
+
167
+ if ($ userDNSearch && count ($ userDNSearch ) == 1 && $ firstArrayKey ) {
168
+ Yii::debug ("Overwrite username " . $ username . " to " . $ userDNSearch [$ firstArrayKey ]['dn ' ], __METHOD__ );
169
+ $ this ->_curDn = $ username = $ userDNSearch [$ firstArrayKey ]['dn ' ];
170
+ $ domainKey = $ userDNSearch [$ firstArrayKey ]['domainKey ' ];
171
+ Yii::debug ("And domainKey to: " . $ domainKey , __METHOD__ );
172
+ } else {
173
+ Yii::warning ("Should overwrite username to DN, but something went wrong while finding the users DN. Leave it as is " , __METHOD__ );
174
+ }
175
+ }
176
+
157
177
if ($ domainKey === false ) {
158
178
Yii::debug ("Using all domains " , __METHOD__ );
159
179
$ domains = $ this ->domains ;
@@ -223,22 +243,6 @@ public function login($username, $password, $domainKey = false, $fetchUserDN = f
223
243
ldap_set_option ($ l , LDAP_OPT_REFERRALS , 0 );
224
244
ldap_set_option ($ l , LDAP_OPT_NETWORK_TIMEOUT , 3 );
225
245
226
- if ($ fetchUserDN ) {
227
- Yii::debug ("We have to determine the user DN first! " , __METHOD__ );
228
- $ userDNSearch = $ this ->searchUser ($ username , ['dn ' ], null , $ domainKey , true );
229
- Yii::debug ("fetchUserDN: yes - Result: " , __METHOD__ );
230
- Yii::debug ($ userDNSearch , __METHOD__ );
231
-
232
- $ firstArrayKey = !$ userDNSearch ? false : array_key_first ($ userDNSearch );
233
-
234
- if ($ userDNSearch && count ($ userDNSearch ) == 1 && $ firstArrayKey ) {
235
- Yii::debug ("Overwrite username " . $ username . " to " . $ userDNSearch [$ firstArrayKey ]['dn ' ], __METHOD__ );
236
- $ username = $ userDNSearch [$ firstArrayKey ]['dn ' ];
237
- } else {
238
- Yii::warning ("Should overwrite username to DN, but something went wrong while finding the users DN. Leave it as is " , __METHOD__ );
239
- }
240
- }
241
-
242
246
$ bind_dn = strpos ($ username , '@ ' ) === false && strpos ($ username , ', ' ) === false ? $ username . '@ ' . $ domainData ['name ' ] : $ username ;
243
247
244
248
Yii::debug ('Trying to authenticate with DN ' . $ bind_dn , __METHOD__ );
@@ -376,7 +380,7 @@ public function searchUser($searchFor, $attributes = "", $searchFilter = "", $do
376
380
377
381
if ($ result ) {
378
382
$ entries = ldap_get_entries ($ this ->_l , $ result );
379
- Yii::debug ('Found entries: ' . ($ entries ? count ( $ entries) : '0 ' ), __FUNCTION__ );
383
+ Yii::debug ('Found entries: ' . ($ entries ? $ entries[ " count " ] : '0 ' ), __FUNCTION__ );
380
384
foreach ($ entries as $ entry ) {
381
385
if (!is_array ($ entry ) || empty ($ entry )) {
382
386
continue ;
@@ -444,6 +448,55 @@ public function searchUser($searchFor, $attributes = "", $searchFilter = "", $do
444
448
445
449
}
446
450
451
+ /**
452
+ * Performs attribute updates (with special handling of a few attributes, like unicodepwd). A previous ->login is required!
453
+ * @param array $attributes The attribute (array keys are the attribute names, the array values are the attribute values)
454
+ * @param string $dn The DN which should be updated - if not provided, the eventually previous examined one will be used.
455
+ */
456
+ public function updateAttributes ($ attributes , $ dn = null )
457
+ {
458
+ if (empty ($ dn ) && empty ($ this ->_curDn )) {
459
+ Yii::error ('provided DN is empty and got no dn from previous login! ' , __FUNCTION__ );
460
+ return false ;
461
+ }
462
+
463
+ $ dn = empty ($ dn ) ? $ this ->_curDn : $ dn ;
464
+
465
+ if (!is_array ($ attributes )) {
466
+ Yii::error ('Provided attributes are not an array! ' , __FUNCTION__ );
467
+ return false ;
468
+ }
469
+
470
+ foreach ($ attributes as $ attribute => $ value ) {
471
+ Yii::info ('Processing attribute ' . $ attribute , __FUNCTION__ );
472
+
473
+ switch ($ attribute ) {
474
+ case 'unicodepwd ' :
475
+ Yii::info ('Patching new password ' , __FUNCTION__ );
476
+ $ password = "\"$ value \"" ;
477
+ $ len = strlen ($ password );
478
+ $ newPassw = "" ;
479
+
480
+ for ($ i = 0 ; $ i < $ len ; $ i ++) {
481
+ $ newPassw .= "{$ password [$ i ]}\000" ;
482
+ }
483
+
484
+ $ value = $ newPassw ;
485
+ break ;
486
+ }
487
+
488
+ Yii::debug ('Trying to set ' . $ attribute . ' to ' . print_r ($ value , true ), __FUNCTION__ );
489
+
490
+ if (!ldap_mod_replace ($ this ->_l , $ dn , [$ attribute => $ value ])) {
491
+ Yii::error ('Could not update attribute: ' . ldap_error ($ this ->_l ), __FUNCTION__ );
492
+ return false ;
493
+ }
494
+ }
495
+
496
+ return true ;
497
+
498
+ }
499
+
447
500
public static function SIDtoString ($ ADsid )
448
501
{
449
502
$ results = [];
0 commit comments