While delivering a PowerShell class, it came to light that the users of PowerShell were not going to have access to the ActiveDirectory module. This changes a lot. The AD module is full of useful cmdlets to help make a Network Administrators life easier. as a matter of fact, I did not move to PowerShell from AD administration until I PowerShell V2 and the ActiveDirectory module were available to me.
One of the more cryptic properties that can be pulled from the user account object is the UserAccountControl property. Here is a description of the flags that can be set with this property. (Source: http://support.microsoft.com/kb/305144)
Here is the kicker. This property is a single value that can represent multiple flags. The value is stored as a decimal value, but converted to binary to determine which flags are set to true. Each flag is represented by a power of 2”
Power | Decimal | Decimal | Flag |
0 | 0 | 1 | SCRIPT |
1 | 1 | 2 | ACCOUNTDISABLE |
2 | 10 | 4 | HOMEDIR_REQUIRED |
3 | 11 | 8 | N/A |
4 | 100 | 16 | LOCKOUT |
5 | 101 | 32 | PASSWD_NOTREQD |
6 | 110 | 64 | PASSWD_CANT_CHANGE |
7 | 111 | 128 | ENCRYPTED_TEXT_PASSWORD_ALLOWED |
8 | 1000 | 256 | TEMP_DUPLICATE_ACCOUNT |
9 | 1001 | 512 | NORMAL_ACCOUNT |
10 | 1010 | 1024 | N/A |
11 | 1011 | 2048 | INTERDOMAIN_TRUST_ACCOUNT |
12 | 1100 | 4096 | WORKSTATION_TRUST_ACCOUNT |
13 | 1101 | 8192 | SERVER_TRUST_ACCOUNT |
14 | 1110 | 16384 | N/A |
15 | 1111 | 32768 | N/A |
16 | 10000 | 65536 | DONT_EXPIRE_PASSWD |
17 | 10001 | 131072 | MNS_LOGON_ACCOUNT |
18 | 10010 | 262144 | SMARTCARD_REQUIRED |
19 | 10011 | 524288 | TRUSTED_FOR_DELEGATION |
20 | 10100 | 1048576 | NOT_DELEGATED |
21 | 10101 | 2097152 | USE_DES_KEY_ONLY |
22 | 10110 | 4194304 | DONT_REQUIRE_PREAUTH |
23 | 10111 | 8388608 | PASSWORD_EXPIRED |
24 | 11000 | 16777216 | TRUSTED_TO_AUTH_FOR_DELEGATION |
25 | 11001 | 33554432 | N/A |
26 | 11010 | 67108864 | PARTIAL_SECRETS_ACCOUNT |
The formula to figure out which flags are set is to a bit complicated. Lets say the value of UserAccountContorl is 546. Moving up the chart, we look for a decimal value that, if subtracted from 546, will leave a value that is greater than or equal to 0. That number is 512. The NORMAL_ACCOUNT flag is set. We then take the remaining value (546 – 512 = 34). Moving up the list, the next number that we can subtract from 34 without the result dropping below zero is 32. The PASSWD_NOTREQD flag is set. This leaves us with 2. The ACCOUNTDISABLE flag is set.
Here is some code to help you out with this. This method uses the Active Directory Services Interface [ADSI] as opposed to using the ActiveDirectory PowerShell module.
# get the User Account Control number.
$ObjUser = [ADSI]"LDAP://CN=User Name,DC=Domain,DC=Com"
$UAC = $ObjUser.userAccountControl
$Num = "$($UAC)"
$Power = 26
Do
{
$Test = [Math]::Pow(2,$Power)
If (($Num - $Test) -ge 0)
{
Switch ($Power)
{
26 {Write-Host "ADS_UF_PARTIAL_SECRETS_ACCOUNT"}
24 {Write-Host "ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION"}
23 {Write-Host "ADS_UF_PASSWORD_EXPIRED"}
22 {Write-Host "ADS_UF_DONT_REQUIRE_PREAUTH"}
21 {Write-Host "ADS_UF_USE_DES_KEY_ONLY "}
20 {Write-Host "ADS_UF_NOT_DELEGATED"}
19 {Write-Host "ADS_UF_TRUSTED_FOR_DELEGATION"}
18 {Write-Host "ADS_UF_SMARTCARD_REQUIRED"}
17 {Write-Host "ADS_UF_MNS_LOGON_ACCOUNT"}
16 {Write-Host "ADS_UF_DONT_EXPIRE_PASSWD"}
13 {Write-Host "ADS_UF_SERVER_TRUST_ACCOUNT"}
12 {Write-Host "ADS_UF_WORKSTATION_TRUST_ACCOUNT"}
11 {Write-Host "ADS_UF_INTERDOMAIN_ TRUST_ACCOUNT"}
9 {Write-Host "ADS_UF_NORMAL_ACCOUNT"}
8 {Write-Host "ADS_UF_TEMP_DUPLICATE_ACCOUNT"}
7 {Write-Host "ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED"}
6 {Write-Host "ADS_UF_PASSWD_CANT_CHANGE"}
5 {Write-Host "ADS_UF_PASSWD_NOTREQD"}
3 {Write-Host "ADS_UF_LOCKOUT"}
2 {Write-Host "ADS_UF_HOMEDIR_REQUIRED"}
1 {Write-Host "ADS_UF_ACCOUNTDISABLE"}
0 {Write-Host "ADS_UF_SCRIPT"}
}
$Num = $Num - $Test
}
$Power--
} While ($Power -ge 0)