"Fossies" - the Fresh Open Source Software Archive

Member "adLDAP-4.0.4/src/classes/adLDAPUsers.php" (13 Apr 2013, 28353 Bytes) of package /linux/www/old/adLDAP-4.0.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "adLDAPUsers.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 /**
    3  * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY 
    4  * Version 4.0.4
    5  * 
    6  * PHP Version 5 with SSL and LDAP support
    7  * 
    8  * Written by Scott Barnett, Richard Hyland
    9  *   email: scott@wiggumworld.com, adldap@richardhyland.com
   10  *   http://adldap.sourceforge.net/
   11  * 
   12  * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
   13  * 
   14  * We'd appreciate any improvements or additions to be submitted back
   15  * to benefit the entire community :)
   16  * 
   17  * This library is free software; you can redistribute it and/or
   18  * modify it under the terms of the GNU Lesser General Public
   19  * License as published by the Free Software Foundation; either
   20  * version 2.1 of the License.
   21  * 
   22  * This library is distributed in the hope that it will be useful,
   23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   25  * Lesser General Public License for more details.
   26  * 
   27  * @category ToolsAndUtilities
   28  * @package adLDAP
   29  * @subpackage User
   30  * @author Scott Barnett, Richard Hyland
   31  * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
   32  * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
   33  * @revision $Revision: 97 $
   34  * @version 4.0.4
   35  * @link http://adldap.sourceforge.net/
   36  */
   37 require_once(dirname(__FILE__) . '/../adLDAP.php');
   38 require_once(dirname(__FILE__) . '/../collections/adLDAPUserCollection.php');
   39 
   40 /**
   41 * USER FUNCTIONS
   42 */
   43 class adLDAPUsers {
   44     /**
   45     * The current adLDAP connection via dependency injection
   46     * 
   47     * @var adLDAP
   48     */
   49     protected $adldap;
   50     
   51     public function __construct(adLDAP $adldap) {
   52         $this->adldap = $adldap;
   53     }
   54     
   55     /**
   56     * Validate a user's login credentials
   57     * 
   58     * @param string $username A user's AD username
   59     * @param string $password A user's AD password
   60     * @param bool optional $prevent_rebind
   61     * @return bool
   62     */
   63     public function authenticate($username, $password, $preventRebind = false) {
   64         return $this->adldap->authenticate($username, $password, $preventRebind);
   65     }
   66     
   67     /**
   68     * Create a user
   69     * 
   70     * If you specify a password here, this can only be performed over SSL
   71     * 
   72     * @param array $attributes The attributes to set to the user account
   73     * @return bool
   74     */
   75     public function create($attributes)
   76     {
   77         // Check for compulsory fields
   78         if (!array_key_exists("username", $attributes)){ return "Missing compulsory field [username]"; }
   79         if (!array_key_exists("firstname", $attributes)){ return "Missing compulsory field [firstname]"; }
   80         if (!array_key_exists("surname", $attributes)){ return "Missing compulsory field [surname]"; }
   81         if (!array_key_exists("email", $attributes)){ return "Missing compulsory field [email]"; }
   82         if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
   83         if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
   84 
   85         if (array_key_exists("password",$attributes) && (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS())){ 
   86             throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
   87         }
   88 
   89         if (!array_key_exists("display_name", $attributes)) { 
   90             $attributes["display_name"] = $attributes["firstname"] . " " . $attributes["surname"]; 
   91         }
   92 
   93         // Translate the schema
   94         $add = $this->adldap->adldap_schema($attributes);
   95         
   96         // Additional stuff only used for adding accounts
   97         $add["cn"][0] = $attributes["display_name"];
   98         $add["samaccountname"][0] = $attributes["username"];
   99         $add["objectclass"][0] = "top";
  100         $add["objectclass"][1] = "person";
  101         $add["objectclass"][2] = "organizationalPerson";
  102         $add["objectclass"][3] = "user"; //person?
  103         //$add["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
  104 
  105         // Set the account control attribute
  106         $control_options = array("NORMAL_ACCOUNT");
  107         if (!$attributes["enabled"]) { 
  108             $control_options[] = "ACCOUNTDISABLE"; 
  109         }
  110         $add["userAccountControl"][0] = $this->accountControl($control_options);
  111         
  112         // Determine the container
  113         $attributes["container"] = array_reverse($attributes["container"]);
  114         $container = "OU=" . implode(", OU=",$attributes["container"]);
  115 
  116         // Add the entry
  117         $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"][0] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
  118         if ($result != true) { 
  119             return false; 
  120         }
  121         
  122         return true;
  123     }
  124     
  125     /**
  126     * Account control options
  127     *
  128     * @param array $options The options to convert to int 
  129     * @return int
  130     */
  131     protected function accountControl($options)
  132     {
  133         $val=0;
  134 
  135         if (is_array($options)) {
  136             if (in_array("SCRIPT",$options)){ $val=$val+1; }
  137             if (in_array("ACCOUNTDISABLE",$options)){ $val=$val+2; }
  138             if (in_array("HOMEDIR_REQUIRED",$options)){ $val=$val+8; }
  139             if (in_array("LOCKOUT",$options)){ $val=$val+16; }
  140             if (in_array("PASSWD_NOTREQD",$options)){ $val=$val+32; }
  141             //PASSWD_CANT_CHANGE Note You cannot assign this permission by directly modifying the UserAccountControl attribute.
  142             //For information about how to set the permission programmatically, see the "Property flag descriptions" section.
  143             if (in_array("ENCRYPTED_TEXT_PWD_ALLOWED",$options)){ $val=$val+128; }
  144             if (in_array("TEMP_DUPLICATE_ACCOUNT",$options)){ $val=$val+256; }
  145             if (in_array("NORMAL_ACCOUNT",$options)){ $val=$val+512; }
  146             if (in_array("INTERDOMAIN_TRUST_ACCOUNT",$options)){ $val=$val+2048; }
  147             if (in_array("WORKSTATION_TRUST_ACCOUNT",$options)){ $val=$val+4096; }
  148             if (in_array("SERVER_TRUST_ACCOUNT",$options)){ $val=$val+8192; }
  149             if (in_array("DONT_EXPIRE_PASSWORD",$options)){ $val=$val+65536; }
  150             if (in_array("MNS_LOGON_ACCOUNT",$options)){ $val=$val+131072; }
  151             if (in_array("SMARTCARD_REQUIRED",$options)){ $val=$val+262144; }
  152             if (in_array("TRUSTED_FOR_DELEGATION",$options)){ $val=$val+524288; }
  153             if (in_array("NOT_DELEGATED",$options)){ $val=$val+1048576; }
  154             if (in_array("USE_DES_KEY_ONLY",$options)){ $val=$val+2097152; }
  155             if (in_array("DONT_REQ_PREAUTH",$options)){ $val=$val+4194304; } 
  156             if (in_array("PASSWORD_EXPIRED",$options)){ $val=$val+8388608; }
  157             if (in_array("TRUSTED_TO_AUTH_FOR_DELEGATION",$options)){ $val=$val+16777216; }
  158         }
  159         return $val;
  160     }
  161     
  162     /**
  163     * Delete a user account
  164     * 
  165     * @param string $username The username to delete (please be careful here!)
  166     * @param bool $isGUID Is the username a GUID or a samAccountName
  167     * @return array
  168     */
  169     public function delete($username, $isGUID = false) 
  170     {      
  171         $userinfo = $this->info($username, array("*"), $isGUID);
  172         $dn = $userinfo[0]['distinguishedname'][0];
  173         $result = $this->adldap->folder()->delete($dn);
  174         if ($result != true) { 
  175             return false;
  176         }        
  177         return true;
  178     }
  179     
  180     /**
  181     * Groups the user is a member of
  182     * 
  183     * @param string $username The username to query
  184     * @param bool $recursive Recursive list of groups
  185     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  186     * @return array
  187     */
  188     public function groups($username, $recursive = NULL, $isGUID = false)
  189     {
  190         if ($username === NULL) { return false; }
  191         if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
  192         if (!$this->adldap->getLdapBind()) { return false; }
  193         
  194         // Search the directory for their information
  195         $info = @$this->info($username, array("memberof", "primarygroupid"), $isGUID);
  196         $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); // Presuming the entry returned is our guy (unique usernames)
  197 
  198         if ($recursive === true){
  199             foreach ($groups as $id => $groupName){
  200                 $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
  201                 $groups = array_merge($groups, $extraGroups);
  202             }
  203         }
  204         
  205         return $groups;
  206     }
  207     
  208     /**
  209     * Find information about the users. Returned in a raw array format from AD
  210     * 
  211     * @param string $username The username to query
  212     * @param array $fields Array of parameters to query
  213     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  214     * @return array
  215     */
  216     public function info($username, $fields = NULL, $isGUID = false)
  217     {
  218         if ($username === NULL) { return false; }
  219         if (!$this->adldap->getLdapBind()) { return false; }
  220 
  221         if ($isGUID === true) {
  222             $username = $this->adldap->utilities()->strGuidToHex($username);
  223             $filter = "objectguid=" . $username;
  224         }
  225         else if (strstr($username, "@")) {
  226              $filter = "userPrincipalName=" . $username;
  227         }
  228         else {
  229              $filter = "samaccountname=" . $username;
  230         }
  231         $filter = "(&(objectCategory=person)({$filter}))";
  232         if ($fields === NULL) { 
  233             $fields = array("samaccountname","mail","memberof","department","displayname","telephonenumber","primarygroupid","objectsid"); 
  234         }
  235         if (!in_array("objectsid", $fields)) {
  236             $fields[] = "objectsid";
  237         }
  238         $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
  239         $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
  240         
  241         if (isset($entries[0])) {
  242             if ($entries[0]['count'] >= 1) {
  243                 if (in_array("memberof", $fields)) {
  244                     // AD does not return the primary group in the ldap query, we may need to fudge it
  245                     if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["objectsid"][0])){
  246                         //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
  247                         $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
  248                     } else {
  249                         $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
  250                     }
  251                     if (!isset($entries[0]["memberof"]["count"])) {
  252                         $entries[0]["memberof"]["count"] = 0;
  253                     }
  254                     $entries[0]["memberof"]["count"]++;
  255                 }
  256             }
  257             
  258             return $entries;
  259         }
  260         return false;
  261     }
  262     
  263     /**
  264     * Find information about the users. Returned in a raw array format from AD
  265     * 
  266     * @param string $username The username to query
  267     * @param array $fields Array of parameters to query
  268     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  269     * @return mixed
  270     */
  271     public function infoCollection($username, $fields = NULL, $isGUID = false)
  272     {
  273         if ($username === NULL) { return false; }
  274         if (!$this->adldap->getLdapBind()) { return false; }
  275         
  276         $info = $this->info($username, $fields, $isGUID);
  277         
  278         if ($info !== false) {
  279             $collection = new adLDAPUserCollection($info, $this->adldap);
  280             return $collection;
  281         }
  282         return false;
  283     }
  284     
  285     /**
  286     * Determine if a user is in a specific group
  287     * 
  288     * @param string $username The username to query
  289     * @param string $group The name of the group to check against
  290     * @param bool $recursive Check groups recursively
  291     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  292     * @return bool
  293     */
  294     public function inGroup($username, $group, $recursive = NULL, $isGUID = false)
  295     {
  296         if ($username === NULL) { return false; }
  297         if ($group === NULL) { return false; }
  298         if (!$this->adldap->getLdapBind()) { return false; }
  299         if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
  300         
  301         // Get a list of the groups
  302         $groups = $this->groups($username, $recursive, $isGUID);
  303         
  304         // Return true if the specified group is in the group list
  305         if (in_array($group, $groups)) { 
  306             return true; 
  307         }
  308 
  309         return false;
  310     }
  311     
  312     /**
  313     * Determine a user's password expiry date
  314     * 
  315     * @param string $username The username to query
  316     * @param book $isGUID Is the username passed a GUID or a samAccountName
  317     * @requires bcmath http://www.php.net/manual/en/book.bc.php
  318     * @return array
  319     */
  320     public function passwordExpiry($username, $isGUID = false) 
  321     {
  322         if ($username === NULL) { return "Missing compulsory field [username]"; }
  323         if (!$this->adldap->getLdapBind()) { return false; }
  324         if (!function_exists('bcmod')) { throw new adLDAPException("Missing function support [bcmod] http://www.php.net/manual/en/book.bc.php"); };
  325         
  326         $userInfo = $this->info($username, array("pwdlastset", "useraccountcontrol"), $isGUID);
  327         $pwdLastSet = $userInfo[0]['pwdlastset'][0];
  328         $status = array();
  329         
  330         if ($userInfo[0]['useraccountcontrol'][0] == '66048') {
  331             // Password does not expire
  332             return "Does not expire";
  333         }
  334         if ($pwdLastSet === '0') {
  335             // Password has already expired
  336             return "Password has expired";
  337         }
  338         
  339          // Password expiry in AD can be calculated from TWO values:
  340          //   - User's own pwdLastSet attribute: stores the last time the password was changed
  341          //   - Domain's maxPwdAge attribute: how long passwords last in the domain
  342          //
  343          // Although Microsoft chose to use a different base and unit for time measurements.
  344          // This function will convert them to Unix timestamps
  345          $sr = ldap_read($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), 'objectclass=*', array('maxPwdAge'));
  346          if (!$sr) {
  347              return false;
  348          }
  349          $info = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
  350          $maxPwdAge = $info[0]['maxpwdage'][0];
  351          
  352 
  353          // See MSDN: http://msdn.microsoft.com/en-us/library/ms974598.aspx
  354          //
  355          // pwdLastSet contains the number of 100 nanosecond intervals since January 1, 1601 (UTC), 
  356          // stored in a 64 bit integer. 
  357          //
  358          // The number of seconds between this date and Unix epoch is 11644473600.
  359          //
  360          // maxPwdAge is stored as a large integer that represents the number of 100 nanosecond
  361          // intervals from the time the password was set before the password expires.
  362          //
  363          // We also need to scale this to seconds but also this value is a _negative_ quantity!
  364          //
  365          // If the low 32 bits of maxPwdAge are equal to 0 passwords do not expire
  366          //
  367          // Unfortunately the maths involved are too big for PHP integers, so I've had to require
  368          // BCMath functions to work with arbitrary precision numbers.
  369          if (bcmod($maxPwdAge, 4294967296) === '0') {
  370             return "Domain does not expire passwords";
  371         }
  372         
  373         // Add maxpwdage and pwdlastset and we get password expiration time in Microsoft's
  374         // time units.  Because maxpwd age is negative we need to subtract it.
  375         $pwdExpire = bcsub($pwdLastSet, $maxPwdAge);
  376     
  377         // Convert MS's time to Unix time
  378         $status['expiryts'] = bcsub(bcdiv($pwdExpire, '10000000'), '11644473600');
  379         $status['expiryformat'] = date('Y-m-d H:i:s', bcsub(bcdiv($pwdExpire, '10000000'), '11644473600'));
  380         
  381         return $status;
  382     }
  383     
  384     /**
  385     * Modify a user
  386     * 
  387     * @param string $username The username to query
  388     * @param array $attributes The attributes to modify.  Note if you set the enabled attribute you must not specify any other attributes
  389     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  390     * @return bool
  391     */
  392     public function modify($username, $attributes, $isGUID = false)
  393     {
  394         if ($username === NULL) { return "Missing compulsory field [username]"; }
  395         if (array_key_exists("password", $attributes) && !$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) { 
  396             throw new adLDAPException('SSL/TLS must be configured on your webserver and enabled in the class to set passwords.');
  397         }
  398 
  399         // Find the dn of the user
  400         $userDn = $this->dn($username, $isGUID);
  401         if ($userDn === false) { 
  402             return false; 
  403         }
  404         
  405         // Translate the update to the LDAP schema                
  406         $mod = $this->adldap->adldap_schema($attributes);
  407         
  408         // Check to see if this is an enabled status update
  409         if (!$mod && !array_key_exists("enabled", $attributes)){ 
  410             return false; 
  411         }
  412         
  413         // Set the account control attribute (only if specified)
  414         if (array_key_exists("enabled", $attributes)){
  415             if ($attributes["enabled"]){ 
  416                 $controlOptions = array("NORMAL_ACCOUNT"); 
  417             }
  418             else { 
  419                 $controlOptions = array("NORMAL_ACCOUNT", "ACCOUNTDISABLE"); 
  420             }
  421             $mod["userAccountControl"][0] = $this->accountControl($controlOptions);
  422         }
  423 
  424         // Do the update
  425         $result = @ldap_modify($this->adldap->getLdapConnection(), $userDn, $mod);
  426         if ($result == false) { 
  427             return false; 
  428         }
  429         
  430         return true;
  431     }
  432     
  433     /**
  434     * Disable a user account
  435     * 
  436     * @param string $username The username to disable
  437     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  438     * @return bool
  439     */
  440     public function disable($username, $isGUID = false)
  441     {
  442         if ($username === NULL) { return "Missing compulsory field [username]"; }
  443         $attributes = array("enabled" => 0);
  444         $result = $this->modify($username, $attributes, $isGUID);
  445         if ($result == false) { return false; }
  446         
  447         return true;
  448     }
  449     
  450     /**
  451     * Enable a user account
  452     * 
  453     * @param string $username The username to enable
  454     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  455     * @return bool
  456     */
  457     public function enable($username, $isGUID = false)
  458     {
  459         if ($username === NULL) { return "Missing compulsory field [username]"; }
  460         $attributes = array("enabled" => 1);
  461         $result = $this->modify($username, $attributes, $isGUID);
  462         if ($result == false) { return false; }
  463         
  464         return true;
  465     }
  466     
  467     /**
  468     * Set the password of a user - This must be performed over SSL
  469     * 
  470     * @param string $username The username to modify
  471     * @param string $password The new password
  472     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  473     * @return bool
  474     */
  475     public function password($username, $password, $isGUID = false)
  476     {
  477         if ($username === NULL) { return false; }
  478         if ($password === NULL) { return false; }
  479         if (!$this->adldap->getLdapBind()) { return false; }
  480         if (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) { 
  481             throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
  482         }
  483         
  484         $userDn = $this->dn($username, $isGUID);
  485         if ($userDn === false) { 
  486             return false; 
  487         }
  488                 
  489         $add=array();
  490         $add["unicodePwd"][0] = $this->encodePassword($password);
  491         
  492         $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $add);
  493         if ($result === false){
  494             $err = ldap_errno($this->adldap->getLdapConnection());
  495             if ($err) {
  496                 $msg = 'Error ' . $err . ': ' . ldap_err2str($err) . '.';
  497                 if($err == 53) {
  498                     $msg .= ' Your password might not match the password policy.';
  499                 }
  500                 throw new adLDAPException($msg);
  501             }
  502             else {
  503                 return false;
  504             }
  505         }
  506         
  507         return true;
  508     }
  509     
  510     /**
  511     * Encode a password for transmission over LDAP
  512     *
  513     * @param string $password The password to encode
  514     * @return string
  515     */
  516     public function encodePassword($password)
  517     {
  518         $password="\"".$password."\"";
  519         $encoded="";
  520         for ($i=0; $i <strlen($password); $i++){ $encoded.="{$password{$i}}\000"; }
  521         return $encoded;
  522     }
  523      
  524     /**
  525     * Obtain the user's distinguished name based on their userid 
  526     * 
  527     * 
  528     * @param string $username The username
  529     * @param bool $isGUID Is the username passed a GUID or a samAccountName
  530     * @return string
  531     */
  532     public function dn($username, $isGUID=false)
  533     {
  534         $user = $this->info($username, array("cn"), $isGUID);
  535         if ($user[0]["dn"] === NULL) { 
  536             return false; 
  537         }
  538         $userDn = $user[0]["dn"];
  539         return $userDn;
  540     }
  541     
  542     /**
  543     * Return a list of all users in AD
  544     * 
  545     * @param bool $includeDescription Return a description of the user
  546     * @param string $search Search parameter
  547     * @param bool $sorted Sort the user accounts
  548     * @return array
  549     */
  550     public function all($includeDescription = false, $search = "*", $sorted = true)
  551     {
  552         if (!$this->adldap->getLdapBind()) { return false; }
  553         
  554         // Perform the search and grab all their details
  555         $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=" . $search . "))";
  556         $fields = array("samaccountname","displayname");
  557         $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
  558         $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
  559 
  560         $usersArray = array();
  561         for ($i=0; $i<$entries["count"]; $i++){
  562             if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
  563                 $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
  564             } elseif ($includeDescription){
  565                 $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
  566             } else {
  567                 array_push($usersArray, $entries[$i]["samaccountname"][0]);
  568             }
  569         }
  570         if ($sorted) { 
  571             asort($usersArray); 
  572         }
  573         return $usersArray;
  574     }
  575     
  576     /**
  577     * Converts a username (samAccountName) to a GUID
  578     * 
  579     * @param string $username The username to query
  580     * @return string
  581     */
  582     public function usernameToGuid($username) 
  583     {
  584         if (!$this->adldap->getLdapBind()){ return false; }
  585         if ($username === null){ return "Missing compulsory field [username]"; }
  586         
  587         $filter = "samaccountname=" . $username; 
  588         $fields = array("objectGUID"); 
  589         $sr = @ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields); 
  590         if (ldap_count_entries($this->adldap->getLdapConnection(), $sr) > 0) { 
  591             $entry = @ldap_first_entry($this->adldap->getLdapConnection(), $sr); 
  592             $guid = @ldap_get_values_len($this->adldap->getLdapConnection(), $entry, 'objectGUID'); 
  593             $strGUID = $this->adldap->utilities()->binaryToText($guid[0]);          
  594             return $strGUID; 
  595         }
  596         return false; 
  597     }
  598     
  599     /**
  600     * Return a list of all users in AD that have a specific value in a field
  601     *
  602     * @param bool $includeDescription Return a description of the user
  603     * @param string $searchField Field to search search for
  604     * @param string $searchFilter Value to search for in the specified field
  605     * @param bool $sorted Sort the user accounts
  606     * @return array
  607     */
  608     public function find($includeDescription = false, $searchField = false, $searchFilter = false, $sorted = true){
  609         if (!$this->adldap->getLdapBind()){ return false; }
  610           
  611         // Perform the search and grab all their details
  612         $searchParams = "";
  613         if ($searchField) {
  614             $searchParams = "(" . $searchField . "=" . $searchFilter . ")";
  615         }                           
  616         $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)" . $searchParams . ")";
  617         $fields = array("samaccountname","displayname");
  618         $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
  619         $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
  620 
  621         $usersArray = array();
  622         for ($i=0; $i < $entries["count"]; $i++) {
  623             if ($includeDescription && strlen($entries[$i]["displayname"][0]) > 0) {
  624                 $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
  625             }
  626             else if ($includeDescription) {
  627                 $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
  628             }
  629             else {
  630                 array_push($usersArray, $entries[$i]["samaccountname"][0]);
  631             }
  632         }
  633         if ($sorted){ 
  634           asort($usersArray); 
  635         }
  636         return ($usersArray);
  637     }
  638     
  639     /**
  640     * Move a user account to a different OU
  641     *
  642     * @param string $username The username to move (please be careful here!)
  643     * @param array $container The container or containers to move the user to (please be careful here!).
  644     * accepts containers in 1. parent 2. child order
  645     * @return array
  646     */
  647     public function move($username, $container) 
  648     {
  649         if (!$this->adldap->getLdapBind()) { return false; }
  650         if ($username === null) { return "Missing compulsory field [username]"; }
  651         if ($container === null) { return "Missing compulsory field [container]"; }
  652         if (!is_array($container)) { return "Container must be an array"; }
  653         
  654         $userInfo = $this->info($username, array("*"));
  655         $dn = $userInfo[0]['distinguishedname'][0];
  656         $newRDn = "cn=" . $username;
  657         $container = array_reverse($container);
  658         $newContainer = "ou=" . implode(",ou=",$container);
  659         $newBaseDn = strtolower($newContainer) . "," . $this->adldap->getBaseDn();
  660         $result = @ldap_rename($this->adldap->getLdapConnection(), $dn, $newRDn, $newBaseDn, true);
  661         if ($result !== true) {
  662             return false;
  663         }
  664         return true;
  665     }
  666     
  667     /**
  668     * Get the last logon time of any user as a Unix timestamp
  669     * 
  670     * @param string $username
  671     * @return long $unixTimestamp
  672     */
  673     public function getLastLogon($username) {
  674         if (!$this->adldap->getLdapBind()) { return false; }
  675         if ($username === null) { return "Missing compulsory field [username]"; }
  676         $userInfo = $this->info($username, array("lastLogonTimestamp"));
  677         $lastLogon = adLDAPUtils::convertWindowsTimeToUnixTime($userInfo[0]['lastLogonTimestamp'][0]);
  678         return $lastLogon;
  679     }
  680     
  681 }
  682 ?>