From 11aec52adf81e5d1a752ce9c3d83692014bfc19f Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 14 Jan 2011 10:50:13 +0100 Subject: updated adLDAP library to 3.3.2 [+] New feature: Move the user to a new OU using user_move() function [-] Bug fix: Prevent an 'undefined index' error in recursive_groups() when full PHP E_ALL logging is enabled [-] Bug fix: user_groups() does not return primary group when objectsid is not given (Tracker ID:2931213) [-] Bug fix: Undefined index in function user_info for non-existent users (Tracker ID:2922729) [-] Bug fix: Force user_info to find objectCategory of person as if a sAMAccountName also exists in a group it will return that group. (Tracker ID:3006096) [-] Bug fix: Return false for user_info if the user does not exist [-] Bug fix: user_info, checks for for a "count" value that not exist in $entries array if "memberof" isn't passed in $fields array. (Tracker ID:2993172) [-] Bug fix: In authenticate() if user authentication fails function returns and does not rebind with admin credentials - so the other funcions don't work anymore as $this->_bind === false. (Tracker ID:2987887) [-] Bug fix: When calling $ldap->user_modify('user', array("expires"=>0)) the function fails due to the value being 0. Changed to isset (Tracker ID:3036726) --- inc/adLDAP.php | 118 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 26 deletions(-) (limited to 'inc/adLDAP.php') diff --git a/inc/adLDAP.php b/inc/adLDAP.php index 94cd8a50d..4c8ee5db3 100644 --- a/inc/adLDAP.php +++ b/inc/adLDAP.php @@ -1,7 +1,7 @@ _bind = @ldap_bind($this->_conn,$username.$this->_account_suffix,$password); - if (!$this->_bind){ return (false); } + $ret = true; + $this->_bind = @ldap_bind($this->_conn, $username . $this->_account_suffix, $password); + if (!$this->_bind){ $ret = false; } // Cnce we've checked their details, kick back into admin mode if we have it - if ($this->_ad_username!=NULL && !$prevent_rebind){ - $this->_bind = @ldap_bind($this->_conn,$this->_ad_username.$this->_account_suffix,$this->_ad_password); + if ($this->_ad_username !== NULL && !$prevent_rebind) { + $this->_bind = @ldap_bind($this->_conn, $this->_ad_username . $this->_account_suffix , $this->_ad_password); if (!$this->_bind){ // This should never happen in theory throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->get_last_error()); } } - return (true); + return $ret; } //***************************************************************************************************************** @@ -758,7 +759,7 @@ class adLDAP { $ret_groups=array(); $groups=$this->group_info($group,array("memberof")); - if (is_array($groups[0]["memberof"])) { + if (isset($groups[0]["memberof"]) && is_array($groups[0]["memberof"])) { $groups=$groups[0]["memberof"]; if ($groups){ @@ -861,7 +862,7 @@ class adLDAP { * @param array $attributes The attributes to set to the user account * @return bool */ - public function user_create($attributes){ + public function user_create($attributes){ // Check for compulsory fields if (!array_key_exists("username",$attributes)){ return ("Missing compulsory field [username]"); } if (!array_key_exists("firstname",$attributes)){ return ("Missing compulsory field [firstname]"); } @@ -963,25 +964,36 @@ class adLDAP { $username = $this->strguid2hex($username); $filter="objectguid=".$username; } + else if (strstr($username, "@")) { + $filter="userPrincipalName=".$username; + } else { - $filter="samaccountname=".$username; + $filter="samaccountname=".$username; } + $filter = "(&(objectCategory=person)({$filter}))"; if ($fields===NULL){ $fields=array("samaccountname","mail","memberof","department","displayname","telephonenumber","primarygroupid","objectsid"); } + if (!in_array("objectsid",$fields)){ + $fields[] = "objectsid"; + } $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); $entries = ldap_get_entries($this->_conn, $sr); - if ($entries[0]['count'] >= 1) { - // AD does not return the primary group in the ldap query, we may need to fudge it - if ($this->_real_primarygroup && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["objectsid"][0])){ - //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]); - $entries[0]["memberof"][]=$this->get_primary_group($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]); - } else { - $entries[0]["memberof"][]="CN=Domain Users,CN=Users,".$this->_base_dn; + if (isset($entries[0])) { + if ($entries[0]['count'] >= 1) { + if (in_array("memberof", $fields)) { + // AD does not return the primary group in the ldap query, we may need to fudge it + if ($this->_real_primarygroup && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["objectsid"][0])){ + //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]); + $entries[0]["memberof"][]=$this->get_primary_group($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]); + } else { + $entries[0]["memberof"][]="CN=Domain Users,CN=Users,".$this->_base_dn; + } + $entries[0]["memberof"]["count"]++; + } } + return $entries; } - - $entries[0]["memberof"]["count"]++; - return ($entries); + return false; } /** @@ -1232,6 +1244,33 @@ class adLDAP { } } + /** + * Move a user account to a different OU + * + * @param string $username The username to move (please be careful here!) + * @param array $container The container or containers to move the user to (please be careful here!). + * accepts containers in 1. parent 2. child order + * @return array + */ + public function user_move($username, $container) { + if (!$this->_bind){ return (false); } + if ($username === null){ return ("Missing compulsory field [username]"); } + if ($container === null){ return ("Missing compulsory field [container]"); } + if (!is_array($container)){ return ("Container must be an array"); } + + $userinfo = $this->user_info($username, array("*")); + $dn = $userinfo[0]['distinguishedname'][0]; + $newrdn = "cn=" . $username; + $container = array_reverse($container); + $newcontainer = "ou=" . implode(",ou=",$container); + $newbasedn = strtolower($newcontainer) . "," . $this->_base_dn; + $result=@ldap_rename($this->_conn,$dn,$newrdn,$newbasedn,true); + if ($result !== true) { + return (false); + } + return (true); + } + //***************************************************************************************************************** // CONTACT FUNCTIONS // * Still work to do in this area, and new functions to write @@ -1567,6 +1606,32 @@ class adLDAP { return ($groups); } + //************************************************************************************************************ + // ORGANIZATIONAL UNIT FUNCTIONS + + /** + * Create an organizational unit + * + * @param array $attributes Default attributes of the ou + * @return bool + */ + public function ou_create($attributes){ + if (!is_array($attributes)){ return ("Attributes must be an array"); } + if (!array_key_exists("ou_name",$attributes)){ return ("Missing compulsory field [ou_name]"); } + if (!array_key_exists("container",$attributes)){ return ("Missing compulsory field [container]"); } + if (!is_array($attributes["container"])){ return ("Container attribute must be an array."); } + $attributes["container"]=array_reverse($attributes["container"]); + + $add=array(); + $add["objectClass"] = "organizationalUnit"; + + $container="OU=".implode(",OU=",$attributes["container"]); + $result=ldap_add($this->_conn,"CN=".$add["cn"].", ".$container.",".$this->_base_dn,$add); + if ($result!=true){ return (false); } + + return (true); + } + //************************************************************************************************************ // EXCHANGE FUNCTIONS @@ -1998,6 +2063,7 @@ class adLDAP { if ($attributes["exchange_usedefaults"]){ $mod["mDBUseDefaults"][0]=$attributes["exchange_usedefaults"]; } if ($attributes["exchange_policyexclude"]){ $mod["msExchPoliciesExcluded"][0]=$attributes["exchange_policyexclude"]; } if ($attributes["exchange_policyinclude"]){ $mod["msExchPoliciesIncluded"][0]=$attributes["exchange_policyinclude"]; } + if ($attributes["exchange_addressbook"]){ $mod["showInAddressBook"][0]=$attributes["exchange_addressbook"]; } // This schema is designed for contacts if ($attributes["exchange_hidefromlists"]){ $mod["msExchHideFromAddressLists"][0]=$attributes["exchange_hidefromlists"]; } -- cgit v1.2.3 From 14a7c26b85836db9a38608feff653b4b9a8dfa17 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 24 Jan 2011 14:17:15 +0100 Subject: correctly catch password policy problems in adLDAP This patch supresses a warning in the adLDAP library when a password change is attempted but fails due to the configured Active Directory Password Policy. Instead of the error an Exception is thrown. This change probably needs to be replicated in the user modification function. Patch sent to upstream. --- inc/adLDAP.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'inc/adLDAP.php') diff --git a/inc/adLDAP.php b/inc/adLDAP.php index 4c8ee5db3..a64096b85 100644 --- a/inc/adLDAP.php +++ b/inc/adLDAP.php @@ -1183,8 +1183,17 @@ class adLDAP { $add=array(); $add["unicodePwd"][0]=$this->encode_password($password); - $result=ldap_mod_replace($this->_conn,$user_dn,$add); - if ($result==false){ return (false); } + $result=@ldap_mod_replace($this->_conn,$user_dn,$add); + if ($result==false){ + $err = ldap_errno($this->_conn); + if($err){ + $msg = 'Error '.$err.': '.ldap_err2str($err).'.'; + if($err == 53) $msg .= ' Your password might not match the password policy.'; + throw new adLDAPException($msg); + }else{ + return false; + } + } return (true); } -- cgit v1.2.3