Here is the theory for building a bit-wise search:

###
### We need to scan through all users.
###
### We need to find those user's who:
###     Are normal users                       0x00000200 ADS_UF_NORMAL_ACCOUNT
###     Are not disabled                       0x00000002 ADS_UF_ACCOUNTDISABLE
###     Do not have "password never expires"   0x00010000 
ADS_UF_DONT_EXPIRE_PASSWD
###     Do not have "no password required"     0x00000020 ADS_UF_PASSWD_NOTREQD
###
### The most efficient way to find users is to do an LDAP search. But building 
the
### proper search isn't that easy. We need a number of filters:
###
###     objectCategory=Person
###     (userAccountControl & ADS_UF_NORMAL_ACCOUNT)     <> 0
###     (userAccountControl & ADS_UF_ACCOUNTDISABLE)     == 0
###     (userAccountControl & ADS_UF_DONT_EXPIRE_PASSWD) == 0
###     (userAccountControl & ADS_UF_PASSWD_NOTREQD)     == 0
###
### Since userAccountControl is a BIT-FLAG attribute (meaning that individuals 
bits
### of the value control these options) then we need to be able to do a bit-wise
### LDAP search. It's important to realize that with a bit-wise search, the 
result
### of a particular filter is either not-one (!1, which is false) or not-zero 
(!0,
### which is true).
###
### So the next step in building our query is to use the LDAP bit-wise AND 
filter:
###
###     1.2.840.113556.1.4.803
###
### This is used to do a bit-wise AND of the attribute on the left to the value
### on the right. For example:
###
###     attribute:1.2.840.113556.1.4.803:=1024
###
### This means a bit-wise AND is done of the value of the attribute to the value
### 1024 (which is 0x400 in hexadecimal). If the result of that bit-wise AND is
### zero, then the value of the filter is false. If the result is non-zero, then
### the value of the filter is true. Putting a "!" in front of a false result
### makes the result true. Putting a "!" in front of a true result, makes it 
false.
###
### A combination of these two techniques makes it possible to scan for zero and
### non-zero bits (that is, those which are set to one and those which are set 
to
### zero).
###
### LDAP also supports a bit-wise OR filter, using the special value of:
###
###     1.2.840.113556.1.4.804
###
### Given the presence of AND and OR filters, it is possible to build very 
complex
### combination filters.
###
### A combination filter is built up of individual filters combined with either 
a
### logical OR ("|") or a logical AND ("&") and surrounded by parentheses.
###
###     (&
###             (objectCategory=Person)
###             (userAccountControl:1.2.840.113556.1.4.803:=512)
###             (!userAccountControl:1.2.840.113556.1.4.803:=2)
###             (!userAccountControl:1.2.840.113556.1.4.803:=65536)
###             (!userAccountControl:1.2.840.113556.1.4.803:=32)
###     )
###
### So, in pseudo-C code this is:
###
###     if( ( objectCategory == Person ) AND
###         ( ( userAccountControl & ADS_UF_NORMAL_ACCOUNT     ) != 0 ) AND
###         ( ( userAccountControl & ADS_UF_ACCOUNTDISABLE     ) == 0 ) AND
###         ( ( userAccountControl & ADS_UF_DONT_EXPIRE_PASSWD ) == 0 ) AND
###         ( ( userAccountControl & ADS_UF_PASSWD_NOTREQD     ) == 0 ) )
###     {
###             ### we've got a matching user!
###     }
###
$ldapFilter =   "(&"                                                          +
                        "(objectCategory=Person)"                             +
                        "(userAccountControl:1.2.840.113556.1.4.803:=512)"    +
                        "(!userAccountControl:1.2.840.113556.1.4.803:=2)"     +
                        "(!userAccountControl:1.2.840.113556.1.4.803:=65536)" +
                        "(!userAccountControl:1.2.840.113556.1.4.803:=32)"    +
                ")"

If you aren't searching, and are evaluating individual user objects, then it 
goes like this:

$ADS_UF_NORMAL_ACCOUNT     = 0x00200
$ADS_UF_ACCOUNTDISABLE     = 0x00002
$ADS_UF_DONT_EXPIRE_PASSWD = 0x10000
$ADS_UF_PASSWD_NOTREQD     = 0x00020

....
                if( $uac -band $ADS_UF_NORMAL_ACCOUNT )
                {
                        "`t`tNormal account"
                }
                else
                {
                        "`t`tNot a normal account"
                }
                if( $uac -band $ADS_UF_ACCOUNTDISABLE )
                {
                        "`t`tAccount disabled"
                }
                else
                {
                        "`t`tAccount enabled"
                }
                if( $uac -band $ADS_UF_DONT_EXPIRE_PASSWD )
                {
                        "`t`tPassword doesn't expire"
                }
                else
                {
                        "`t`tPassword expires"
                }
                if( $uac -band $ADS_UF_PASSWD_NOTREQD )
                {
                        "`t`tPassword not required"
                }
                else
                {
                        "`t`tPassword required"
                }
....

Obviously assuming that $uac contains the value of the userAccountControl 
attribute.

Regards,

Michael B. Smith
Consultant and Exchange MVP
http://TheEssentialExchange.com


-----Original Message-----
From: Damien Solodow [mailto:damien.solo...@harrison.edu] 
Sent: Wednesday, December 28, 2011 2:07 PM
To: NT System Admin Issues
Subject: RE: Deciphering "UserAccountControl" using PowerShell

You might be over-engineering the solution. :) 
Try this to get a list of disabled users: Get-ADUser -Filter {enabled -eq 
$false}

DAMIEN SOLODOW
Systems Engineer
317.447.6033 (office)
317.447.6014 (fax)
HARRISON COLLEGE


-----Original Message-----
From: Michael Leone [mailto:oozerd...@gmail.com] 
Sent: Wednesday, December 28, 2011 2:01 PM
To: NT System Admin Issues
Subject: Deciphering "UserAccountControl" using PowerShell

So I know that the AD attribute "UserAccountControl" is the sum of the values 
of 21 different values (i.e., so a value of 546 = 2+32+512, which is composed 
of the sum of the constants ACCOUNT_DISABLED, PASSWORD_NOT_REQUIRED, and 
NORMAL_ACCOUNT). But how do I break that down in Powershell? For example, I 
want to do certain actions if a normal user account is disabled. However, I 
can't just check for a value of 514 (2+512), since - like this example - the 
value may be different, even tho this is an account I want to process. So how 
do I go about testing for ACCOUNT_DISABLED within the total value of 
"UserAccountControl"?

(in my case, I am planning to examine user home folders, and anyone who is 
disabled, move them to a different holding folder. In our case, the user login 
is used as the name of the folder, so I just need to match the folder name with 
the "sAMAccountName" in AD)

Thanks

~ Finally, powerful endpoint security that ISN'T a resource hog! ~ ~ 
<http://www.sunbeltsoftware.com/Business/VIPRE-Enterprise/>  ~

---
To manage subscriptions click here: 
http://lyris.sunbelt-software.com/read/my_forums/
or send an email to listmana...@lyris.sunbeltsoftware.com
with the body: unsubscribe ntsysadmin

~ Finally, powerful endpoint security that ISN'T a resource hog! ~
~ <http://www.sunbeltsoftware.com/Business/VIPRE-Enterprise/>  ~

---
To manage subscriptions click here: 
http://lyris.sunbelt-software.com/read/my_forums/
or send an email to listmana...@lyris.sunbeltsoftware.com
with the body: unsubscribe ntsysadmin


~ Finally, powerful endpoint security that ISN'T a resource hog! ~
~ <http://www.sunbeltsoftware.com/Business/VIPRE-Enterprise/>  ~

---
To manage subscriptions click here: 
http://lyris.sunbelt-software.com/read/my_forums/
or send an email to listmana...@lyris.sunbeltsoftware.com
with the body: unsubscribe ntsysadmin

Reply via email to