FIM REFERENCE: How to Enable/Disable an AD account and set other UAC flags in a Declarative Sync Rule
Introduction
The purpose of this wiki page is to provide a simple example of an Outbound Synchronization Rule attribute flow which will enable or disable an Active Directory Account using FIM. There are a number of fantastic resources which delve into the basics of using BitAnd and BitOr operators in attribute flow mappings (I have attempted one below), but for the purposes of this exercise this information may not be pertinent. In other words, if you just want to add this functionality, the example outlined below should do the trick.
Setting the disable flag on userAccountControl with BitOr (Disable Account)
Provided userAccountControl value is in the metaverse, applying the outbound attribute flow below will disable the account:
BitOr(2,userAccountControl) ==> userAccountControl
Clearing the disable flag on userAccountControl with BitAnd (Enable Account)
Provided userAccountControl value is in the metaverse, applying the outbound attribute flow below will enable the account:
BitAnd(-3,userAccountControl) ==> userAccountControl
Some more "intelligent" attribute flows
Using a Boolean Value
Here we will set userAccountControl based on the boolean value of a custom attribute "AccountEnabled." The sync rule will automatically disable an account that has a "false" value for AccountEnabled, and clear the disabled flag if AccountEnabled is "true."
IIF(AccountEnabled,BitAnd(-3,userAccountControl),BitOr(2,userAccountControl)) ==> userAccountControl
Using a String Value
IIF(Eq(employeeStatus,"Enabled"),BitAnd(-3,userAccountControl),BitOr(2,userAccountControl)) ==> userAccountControl
An Inbound Flow Example
IIF(Eq(BitOr(userAccountControl,2),userAccountControl),"true","false") ==> accountDisabled
Using Bitwise operators for other userAccountControl flags
Adding an example to show how one might manipulate other UAC flags in this way. Let's say, for example, we want to force smartcard logon for any user in the FIM portal. First, we look up the UAC value from this KB article, and see decimal value for SMARTCARD_REQUIRED is 262144. If we look in Active Directory Users and computers, we see a user that is a normal user with the smartcard required checkbox checked will have a UAC value of 512+262144 = 262656. Convert to binary (by actually doing the division or using one of the readily available online tools), and you have the following: 1000000001000000000. Using the same method, convert 512 and 262144 to binary and take a look at the values.
0000000001000000000 --> 512 (Normal Account)
1000000000000000000 --> 262144 (Smartcard logon required)
1000000001000000000 --> 262656 (Normal Account + Smartcard logon required)
Understanding how bitwise OR works we know BitOr(0,1) = BitOr(1,1) = BitOr(1,0) = 1
, and BitOr(0,0) = 0
We see that BitOr(512,262144)
1000000000000000000 (262144) OR 0000000001000000000 (512)
1000000001000000000 (262656)
Notice this is the decimal value for a normal account with smartcard logon required.
It follows that BitOr(262144,userAccountControl) ===> userAccountControl
will update the UAC value to require smartcard logon. This is exactly like the disabling scenario (BitOr(2,UserAccountControl)! Simply put, it flips the bit for SMARTCARD_REQUIRED only, regardless of the other flag values. See that BitOr(262144,262656) still results in 262656.
Understanding how bitwise And works we know BitAnd(1,1) = 1
and BitAnd(0,0) = BitAnd(1,0) = BitAnd(0,1) = 0
We see that BitAnd(262144,262656)
1000000001000000000 (262656) AND 1000000000000000000 (262144)
1000000000000000000 (262144) Notice this is the flag value in decimal.
So, we can then use an advanced flow, IIF(Eq(BitAnd(262144,userAccountControl),262144),"true","false"))
to tell if a user is smartcard logon required.
But wait! what if we want to set smartcard logon to false? This gets a little tricky. Recall for the disabled bit we used BitAnd(-3,userAccountControl) to do this. The question becomes, what binary number can we And with our current UAC value to set smartcardlogonrequired to false?
Let's start with a normal user account with smartcard logon required (512+262144 = 262656). Our goal is to start with a normal user + smartcard required 1000000001000000000 (262656) and end with a normal user account 0000000001000000000 (512).
BitAnd(something,262656)
??????????????????? AND 1000000001000000000 (262656)
0000000001000000000 (512)
We might notice that simply BitAnd(512,262656) looks like it might work. In fact, it will for this example...But...there's a problem. What if there's other information in UAC besides normal account? What if, for example, we have a user that is a normal account (512) with a password that doesn't expire (65536), but is disabled (2)?
512+65536+2 = 328194 --> 1010000001000000010
Quickly we see that BitAnd(328194,512) -> 512. Which isn't what we want here. We only want to flip the smartcard logon required bit. We really want something that, when we apply the bitwise operator, we retain all values. Any bit that was on in the original UAC value needs to remain on after our BitAnd operation. How can we do this?
Since we know BitAnd(1,1) = 1, we can start with a mask of all 1's. Since userAccountControl is a 4 byte (32 bit), the largest flag we need to make is 1111111111111111111111111111111, or 8589934591 in decimal. Knowing we want to flip only one bit, simply change this binary value of our mask so the AND operator turns off only the bit for smart card required (bold).
1111111111111**0
111111111111111111 (8589672447)
AND 00000000000001**010000001000000010 (328194)
0000000000000
0
010000001000000010``
(66050 = 512 +65536+2 --> Normal + password does not expire + disabled. It worked!)
Like the disabled example, the binary mask can also be converted to a negative decimal. The decimal becomes -262145.
BitAnd(-262145,userAccountControl)
will turn off the smartcard login required bit.
Takeaway
- You can turn
ON
any userAccountControl flag withBitOr(<flag in decimal>,userAccountControl)
- You can turn
OFF
BitAnd(<mask>,userAccountControl)
, where<mask
> is the decimal equivalent to the signed binary that is inverse of the flag we are setting false. Make sure to left pad the mask with 1s to make it 32 bits. - Using this technique, you can use Bitwise operators to set or clear one or multiple flags simultaneously in your sync rule flows
One last example
Alright, you made it this far. Now let's do one last example so that I've appropriately addressed (or at least attempted to) any scenario with UAC flags that you might run into.
Let's say you want to both clear the ACCOUNTDISABLE flag (enabling the account) and set DONT_EXPIRE_PASSWORD. We know turning off a flag requires a BitAnd function, and turning on a flag requires BitOr. Let's give it a go.
In decimal, we recall ACCOUNTDISABLE flag has a value of 2, and we can look up DONT_EXPIRE_PASSWORD and find it is 65536. Setting Don't expire password is easy, right? BitOr(userAccountControl,65536). But how do we also enable the account? Recall enabling an account can be done with BitAnd(-3,userAccountControl). Quite simply, we arrive at a solution:
BitAnd(-3,BitOr(userAccountControl,65526))
See Also
- How to Enable or Disable Accounts in Active Directory Domain Service Using FIM
- Using the UserAccountControl flag to manipulate user account properties