PHP Active Directory Integration: get userAccountControl attributes

While trying to integrate an AD based login in my php application, I came across the problem of checking which user accounts were not disabled.

After going through some forums I did the following to see accounts which were not disabled:
$result = ldap_search($ad, "OU=Users,OU=Office1,DC=country,DC=company,DC=com", "(&(objectCategory=user)(!(userAccountControl=514)))");

Microsoft returns the flags set for any user in the userAccountControl attribute in a cumulative manner. The flag values used by Active Directory are mentioned here.

So e.g.
John has a Normal Account [Flag 512]
Alex had a Normal Account [Flag 512] but now has been disabled [Flag 2] so the status on his account now is [512+2 = 514].

This works fine in most cases but as the flags can be summed up in any order, ldap_search returned 66050 for some users.  Seeing the table what that means is:

[Flag 65536 ]+ [Flag 512] + [Flag 2] which translates to

[Password Doesn't Expire] + [was a Normal Account] + [but has been disabled now.]

So checking for 66050 in my php script was the next dirty fix to exclude such people as well like so:

$result = ldap_search($ad, "OU=Users,OU=Office1,DC=country,DC=company,DC=com", "(&(objectCategory=user)(!(userAccountControl=514))(!(userAccountControl=66050)))");

While making the admin section to manage these users I had to show the users for our different offices (located in different countries) and also what settings they had.

The userAccountControl just gives back the sum of all the flags set when we do an ldap_search and get all entries for any user object.

To solve this problem of mine, I made the following function to breakdown the codes returned in the useraccountcontrol field into their corresponding flags which have been set in the userAccountControl attribute.

function getUserAccountControlAttributes($inputCode)
{
/**
* http://support.microsoft.com/kb/305144
*
* You cannot set some of the values on a user or computer object because
* these values can be set or reset only by the directory service.
*
*/
$userAccountControlFlags = array(16777216 => "TRUSTED_TO_AUTH_FOR_DELEGATION",
8388608 => "PASSWORD_EXPIRED",
4194304 => "DONT_REQ_PREAUTH",
2097152 => "USE_DES_KEY_ONLY",
1048576 => "NOT_DELEGATED",
524288 => "TRUSTED_FOR_DELEGATION",
262144 => "SMARTCARD_REQUIRED",
131072 => "MNS_LOGON_ACCOUNT",
65536 => "DONT_EXPIRE_PASSWORD",
8192 => "SERVER_TRUST_ACCOUNT",
4096 => "WORKSTATION_TRUST_ACCOUNT",
2048 => "INTERDOMAIN_TRUST_ACCOUNT",
512 => "NORMAL_ACCOUNT",
256 => "TEMP_DUPLICATE_ACCOUNT",
128 => "ENCRYPTED_TEXT_PWD_ALLOWED",
64 => "PASSWD_CANT_CHANGE",
32 => "PASSWD_NOTREQD",
16 => "LOCKOUT",
8 => "HOMEDIR_REQUIRED",
2 => "ACCOUNTDISABLE",
1 => "SCRIPT"
);


$attributes = NULL;
while($inputCode > 0)
{
foreach($userAccountControlFlags as $flag => $flagName)
{
$temp = $inputCode-$flag;
if($temp>0)
{
$attributes[$userAccountControlFlags[$flag]] = $flag;
$inputCode = $temp;
}
if($temp==0)
{
if(isset($userAccountControlFlags[$inputCode]))
{
$attributes[$userAccountControlFlags[$inputCode]] = $inputCode;
}
$inputCode = $temp;
}
}
}
return $attributes;
}


$userAccountControlAttributes = getUserAccountControlAttributes(66048);
var_dump($userAccountControlAttributes);

On doing a var_dump this function returns this:
array(2) { ["DONT_EXPIRE_PASSWORD"]=> int(65536) ["NORMAL_ACCOUNT"]=> int(512) }

This made it easier for me to display the attributes set on each user in my admin panel and I also removed the checks for Flag 514, and Flag 66050 in my ldap_search filter and instead checked if the ACCOUNTDISABLE was set and showed only those users in my list like so:
if(!isset($userAccountControlAttributes["ACCOUNTDISABLE"]))
{
// do something
}

Hope this helps someone trying to show account attributes using php.

3 Responses to “PHP Active Directory Integration: get userAccountControl attributes”

  1. steffen said:

    Jan 01, 10 at 8:37 am

    There is a mistake!

    This works fine in most cases but as the flags can be summed up in any order, ldap_search returned 66050 for some users. Seeing the table what that means is:

    [Flag 66536 ]+ [Flag 512] + [Flag 2] which translates to

    [Password Doesn't Expire] + [was a Normal Account] + [but has been disabled now.]

    Correct:

    [Flag 65536 ]+ [Flag 512] + [Flag 2] which translates to

    Really good tutorial!!

  2. zooperman said:

    Jan 13, 10 at 1:35 am

    thanks steffen, have corrected the typo. :)

  3. Jan said:

    Mar 04, 10 at 2:43 am

    Thanks a lot.
    That was what im searching for. Thx


Leave a Reply