Recently in working with Laura Hunter on my Technical Review of Active Directory Cookbook 3rd Edition, I mentioned that AdFind and AdMod could be used together to do a smart™ update of bit flag attributes. She was a bit surprised so I figured I would mention it here as well for everyone.
But first let’s back up…
Some attributes in AD are not as intuitive as they could be. A subset of these attributes are attributes that are bit flags. This is an attribute with a numeric/integer format that has meaning at the bit level instead of the overall value level. The most common example is probably userAccountControl so let’s discuss that a little.
The userAccountControl value will look something like 512 or 514 or 546 or maybe 4096 or who knows what else… Many people will look at those at absolute values but you absolutely cannot do that… Because it isn’t right.
The userAccountControl is actually a bit flag where each bit in the value means something different. The current enumeration looks like (http://msdn.microsoft.com/en-us/library/ms680832.aspx)
Hexadecimal value
Identifier (defined in iads.h)
Description
0x00000001
ADS_UF_SCRIPT
The logon script is executed.
0x00000002
ADS_UF_ACCOUNTDISABLE
The user account is disabled.
0x00000008
ADS_UF_HOMEDIR_REQUIRED
The home directory is required.
0x00000010
ADS_UF_LOCKOUT
The account is currently locked out.
0x00000020
ADS_UF_PASSWD_NOTREQD
No password is required.
0x00000040
ADS_UF_PASSWD_CANT_CHANGE
The user cannot change the password.
Note You cannot assign the permission settings of PASSWD_CANT_CHANGE by directly modifying the UserAccountControl attribute. For more information and a code example that shows how to prevent a user from changing the password, see User Cannot Change Password.
0x00000080
ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
The user can send an encrypted password.
0x00000100
ADS_UF_TEMP_DUPLICATE_ACCOUNT
This is an account for users whose primary account is in another domain. This account provides user access to this domain, but not to any domain that trusts this domain. Also known as a local user account.
0x00000200
ADS_UF_NORMAL_ACCOUNT
This is a default account type that represents a typical user.
0x00000800
ADS_UF_INTERDOMAIN_TRUST_ACCOUNT
This is a permit to trust account for a system domain that trusts other domains.
0x00001000
ADS_UF_WORKSTATION_TRUST_ACCOUNT
This is a computer account for a computer that is a member of this domain.
0x00002000
ADS_UF_SERVER_TRUST_ACCOUNT
This is a computer account for a system backup domain controller that is a member of this domain.
0x00004000
N/A
Not used.
0x00008000
N/A
Not used.
0x00010000
ADS_UF_DONT_EXPIRE_PASSWD
The password for this account will never expire.
0x00020000
ADS_UF_MNS_LOGON_ACCOUNT
This is an MNS logon account.
0x00040000
ADS_UF_SMARTCARD_REQUIRED
The user must log on using a smart card.
0x00080000
ADS_UF_TRUSTED_FOR_DELEGATION
The service account (user or computer account), under which a service runs, is trusted for Kerberos delegation. Any such service can impersonate a client requesting the service.
0x00100000
ADS_UF_NOT_DELEGATED
The security context of the user will not be delegated to a service even if the service account is set as trusted for Kerberos delegation.
0x00200000
ADS_UF_USE_DES_KEY_ONLY
Restrict this principal to use only Data Encryption Standard (DES) encryption types for keys.
0x00400000
ADS_UF_DONT_REQUIRE_PREAUTH
This account does not require Kerberos pre-authentication for logon.
0x00800000
ADS_UF_PASSWORD_EXPIRED
The user password has expired. This flag is created by the system using data from the Pwd-Last-Set attribute and the domain policy.
0x01000000
ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
The account is enabled for delegation. This is a security-sensitive setting; accounts with this option enabled should be strictly controlled. This setting enables a service running under the account to assume a client identity and authenticate as that user to other remote servers on the network.
So if you have something like 512, that is actually 0x200 or 1000000000 (base 2) which looking at the list above translates to ADS_UF_NORMAL_ACCOUNT… Ok so a normal user account. 514 is 0x202 or 1000000010 (base 2) which is ADS_UF_NORMAL_ACCOUNT combined with ADS_UF_ACCOUNTDISABLE… A disabled account. See how easy?
Now the hard part is that you want to update that value but you don’t want to screw up what might already be there… For example, say you want to enable a user account, what value do you put in… Some may say right off (and incorrectly) to write the value 512 to the attribute. That may work some or most or none of the time… What if the account is set up to use a smart card?? The proper value then would be 262656 (0x40200 or 1000000001000000000 (base 2)).
So the smart, or proper, way to handle these types of attributes, attributes such as userAccountControl, options, searchFlags, systemFlags, etc is to do bitwise math when setting or clearing a value. This is the AND/OR/XOR/NOT stuff that you may have glossed over if you had a computer science class that actually tried to teach it…
Anyway you don’t really have to understand how it works in order to modify it properly. Just use adfind and admod together…
Say I want to enable an account with a samaccountname of joewareupdatesvc I would run a command like
adfind -default -f samaccountname=joewareupdatesvc useraccountcontrol -adcsv | admod useraccountcontrol::{{.:CLR:2}}
or to disable the account you would run
adfind -default -f samaccountname=joewareupdatesvc useraccountcontrol -adcsv | admod useraccountcontrol::{{.:SET:2}}
That way, regardless of the current settings, you wouldn’t mess anything up. You would do the one thing you wanted to do, enable or disable the account.
This isn’t special magic just for userAccountControl, adfind|admod can do that for any bit flag attribute. The idea is that you have AdFind pipe the current value of the attribute to AdMod so it can take that info, manipulate it, and then set the new value.
There are some special shortcuts in AdMod for this as well that do apply to userAccountControl, but in the background, they simply specify the commands above on your behalf, specifically you could use the -sc uacset, -sc uacclear, -sc ad-disable, -sc ad-enable shortcuts… Something like
adfind -default -f samaccountname=joewareupdatesvc useraccountcontrol -adcsv | admod -sc ad-enable
or
adfind -default -f samaccountname=joewareupdatesvc useraccountcontrol -adcsv | admod -sc ad-disable
Very easy… While I use the userAccountControl stuff a lot, I would say anymore my most common use of this is when playing around with schemas…. I am constantly flipping bits in the searchFlags attributes to enable/disable indexing for various attributes or other functions that are controlled by the bits in searchFlags (see http://msdn.microsoft.com/en-us/library/ms679765(VS.85).aspx). So when I am playing around and say need to index objectclass for a few minutes for a test I run
adfind -sc s:objectclass searchflags -adcsv | admod searchflags::{{.:SET:1}}
then when I want to go back to the previous setting…
adfind -sc s:objectclass searchflags -adcsv | admod searchflags::{{.:CLR:1}}
joe