Skip to content

Commit 4480efe

Browse files
author
robin.kluth
committed
Added new methos updateAttributes which allows you to update the users AD/LDAP attributes.
1 parent 4cd81cd commit 4480efe

File tree

1 file changed

+71
-18
lines changed

1 file changed

+71
-18
lines changed

src/LdapAuth.php

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class LdapAuth extends BaseObject
4949
private $_ldapBaseDn;
5050
private $_l;
5151
private $_username;
52+
private $_curDn;
5253

5354
public function init()
5455
{
@@ -145,15 +146,34 @@ public function autoDetect($overrideIp = false)
145146
/**
146147
* @param string $username The username to use
147148
* @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!
149150
* @param boolean $fetchUserDN If true, determine users DN and use that as username
151+
* @return bool True on success, false on failure.
150152
* @throws ErrorException
151153
*/
152154
public function login($username, $password, $domainKey = false, $fetchUserDN = false)
153155
{
154156

155157
Yii::debug('Hello! :) Trying to log you in via LDAP!', __METHOD__);
156158

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+
157177
if ($domainKey === false) {
158178
Yii::debug("Using all domains", __METHOD__);
159179
$domains = $this->domains;
@@ -223,22 +243,6 @@ public function login($username, $password, $domainKey = false, $fetchUserDN = f
223243
ldap_set_option($l, LDAP_OPT_REFERRALS, 0);
224244
ldap_set_option($l, LDAP_OPT_NETWORK_TIMEOUT, 3);
225245

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-
242246
$bind_dn = strpos($username, '@') === false && strpos($username, ',') === false ? $username . '@' . $domainData['name'] : $username;
243247

244248
Yii::debug('Trying to authenticate with DN ' . $bind_dn, __METHOD__);
@@ -376,7 +380,7 @@ public function searchUser($searchFor, $attributes = "", $searchFilter = "", $do
376380

377381
if ($result) {
378382
$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__);
380384
foreach ($entries as $entry) {
381385
if (!is_array($entry) || empty($entry)) {
382386
continue;
@@ -444,6 +448,55 @@ public function searchUser($searchFor, $attributes = "", $searchFilter = "", $do
444448

445449
}
446450

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+
447500
public static function SIDtoString($ADsid)
448501
{
449502
$results = [];

0 commit comments

Comments
 (0)