Share via


How to Enable or Disable Accounts in Active Directory Domain Service Using FIM

To tell you one thing up front, there might be smarter ways to address this issue; however, I was looking for something that is as simple as possible and I think, I have found it. The other day, I was looking into using FIM to enable or disable accounts in Active Directory.

How can you do this? In Active Directory, this is governed by the value of an attribute called userAccountControl. The userAccountControl attribute is a bit vector. I’m not sure, how much you know about bit vectors. Personally, I like them a lot because Boolean operations are still the fastest operations your computer can perform and bit vectors are part of them. If you want to speed up something significantly, there is no better way than using Boolean operations. For those of you, how are not familiar with them, here is a little overview…

This topic is a how to.
Please keep it as clear and simple as possible. Avoid speculative discussions as well as a deep dive into underlying mechanisms or related technologies.

Introduction to bit vectors

Computers are to a certain degree pretty “dumb” machines that can only deal with numbers and some very basic operations. The native language a computer “speaks” is called assembly. Fortunately, I had the pleasure to learn assembly as part of my professional education. To give you some sort of an idea, this is a programming language, where you spend countless hours on producing an endless amount of lines of code to solve a problem and when you proudly show the end result to a non-programmer you get some weird looks back (“So many lines of code for such a simple operation and he is happy about it - what's wrong with him? ”).

Anyway… Your computer thinks binary – either yes or no; either 1 or 0. Imagine, you have an object and you want to track some of the information about your object that can be answer with either yes or no in a very simple manner. How could you do this? You could do this, simply, by using a number.

Let’s assume, you want to track whether your object:

  • Is enabled
  • Has an expired password
  • Requires a password

This is a lot of information about your object; however, it is possible to squeeze all of this into one single value. Since your computer thinks binary, tracking this kind of information requires exactly three bits – XXX. As human beings, we are not used to think in binary values; our world is typically decimal. From the three bits, the biggest number you can get is a value, in which all bits are set to 1 – 111. If you translate the binary “111” into a decimal value, you will find that it is a 7.

http://psd5ig.bay.livefilestore.com/y1pW1U5NwBTyqLaWtiUxhTtYjdhUwlTzNsv1aO6ySgDNffIRpBojTb73fRCRy4S2PSops2U8qLPg1GKv-OsmkJiK-nQPfOwNp4r/UAC07.jpg

How can you use this as a decimal thinking human? If you run into a decimal representation of our attribute, you need to convert the decimal value into a binary one and lookup the meaning from your specification. For example, if the decimal value for this attribute is 5, the binary representation is “101” and according to our specification, this means: The object is enabled, doesn’t have an expired password and requires a password.

As you can see, there is a lot of information encapsulated into this small number. In other words, a bit vector is a number in which each bit of the binary representation of that number is used to store a specific "yes-or-no" property.

Introduction to the userAccountControl attribute

Using the information from the previous section, the description of what the userAccountContol attribute is, is relatively short. The userAccountControl attribute is a bit vector attribute in Active Directory that is used to store some information about an object in a single value. If you want to know more about the details that are actually stored in this attribute, you should read this article.

For the scope of this article, it is sufficient to know that:

  • The userAccountControl attribute is a bit vector
  • The second bit in this bit vector is used whether an account is enabled

Working with bit vectors in attribute flow mappings

In our busy life, there is not much room for really looking into the background implementation of something. We tend to try to find an example for how someone else "has done this", and then we are leveraging what we find for our own purpose. An example for this is the usage of the userAccountControl attribute to enable or disable an account in Active Directory. If you do a research, you can find examples for setting this attribute to 512 for an enabled account or 514 for a disabled account. But, wait a minute, what does this really mean?

If you look at the table in the referenced document above, you will find:

  • 512 = NORMAL_ACCOUNT
  • 514 = NORMAL_ACCOUNT + ACCOUNTDISABLE

This looks good – doesn’t it? If you look at the Introduction to bit vectors again, you will notice that an “=” assignment for bit vectors only works for the initialization of them. Using our little example in that section, an assignment of 4 to the attribute in this section certainly enables the account; however, it also sets:

  • Account doesn't have an expired password
  • Account doesn’t require a password.

In other words, by using the “=” assignment, you have set three properties of your object although you just wanted to set one! Apparently, this is not what we wanted to do. If you want to set “something” on an initialized bit vector, you have to use Boolean operations.

There are two operations that are relevant in this case:

  • OR
  • AND

These operations are basically easy to understand. First of all, both operations are binary operations. This means if you have an OR or and AND operation between two numbers, your computer translates both numbers into the binary representation and performs a “bit-wise” operation on them:

  • In case of an OR, the result is only 0 if both bits are 0; otherwise the resulting bit is 1.
  • In case of an AND, the result is only 1 if both bits are 1; otherwise the resulting bit is 0.

Applying this to our attribute in the sample section means, if we want to enable an object, we have to OR its value with a binary 100 or a decimal 4:

http://psd5ig.bay.livefilestore.com/y1pum3qHDJTRcOmU_a2mwUPlXSaTQ5iU6ngpTWwYbt0Ia0nzB3gtzr75Qn7SRw5B4x5QQzk5-pv4Qx6ahvarRZwa027wJPr4XOU/UAC04.jpg

In other words, no matter what the value was before the operation, the object is enabled after performing the operation on the attribute. If the object was already enabled, it will remain enabled. If the object was disabled, it will be enabled. This is exactly, what we wanted. If we want to disable an object, we have to AND it with a binary 011 or a decimal 3:

http://public.bay.livefilestore.com/y1p9omwbBrgWpyPyK_VwoA9FkQECfUvHdlwcr3Wtb5Zi5mbz382UEOugm-lpVEgwYpHPeKHHVdOVK7_ji55M84fBA/UAC05.jpg

What you can see in these examples is that you can have an impact on the value of one bit in a number by using Boolean operations.

Working with useraccountControl in attribute flow mappings

In the previous section, you have learned that you need the source value and a mask if you want to perform a Boolean operation (setting or clearing a bit) in a bit vector. How can you apply this to an attribute flow mapping in declarative provisioning? 

In declarative provisioning, you have two related functions to do these operations:

  • BitAnd
  • BitOr

Both operations have a mask and a flag parameter. For the actual operation, it doesn’t really matter whether you are configuring userAccountControl to be the mask or the flag. However, I’m using the parameters according to the discussion we have in this article. This means, mask is the number that contains our filter and flag is our source bit vector attribute.

Disabling an Active Directory account by using the useraccountControl attribute

Disabling an initialized account is a rather simple operation. Looking at the userAccountControl specification, you will find that the second bit ("2") in this bit vector is in charge of defining this state. Our goal is to only set this bit without changing the current setting of the other bits in the bit vector. Looking at the OR explanation, you will find, that the target attributes of our flag value are not touched as long as we have a "0" in our mask. The only value that has a potential to change something in the target value is a 1 in the mask. In other words, no matter what the userAccountControl value is before performing our Boolean operation, the target value represents a disabled account if we apply a BitOr operation with a decimal "2" as mask.

Enabling an Active Directory account by using the useraccountControl attribute

While disabling an account is a rather simple exercise, things look a bit different in case of enabling an account. You need to keep our goal in mind – all, we want to do, is to have an impact on the enabled state. All other properties that are tracked in our userAccountControl attribute should not be changed!

Looking at how an AND works, the implementation seems at a first glance not to be as simple as in case of disabling an account. In general, when you want to set some bits in a bit vector, you only need to set these bits in your mask to 1 and use a 0 for the other bits. The position of the highest bit flag in your mask helps you to determine the decimal value you need for your mask. However, in case of clearing a bit, things are not that simple. Our mask must have all bits we don’t want to touch set to 1 and just the bits we want to change (if necessary) must be 0.

How does this translate to decimal value? As a starting point, we need to know what the maximal value (all bits set to 1) for our mask is.

When I’ve looked at this the first time, I got a bit frustrated. Do I have to know all meanings that are currently encoded in the userAccountControl attribute? What if new meanings are introduced in future versions of Windows?

What about other bit vectors? What you typically care about, are the bits you want to set and not all available meanings the bits in a bit vector have. If this is all true, doesn't this mean that the BitAnd function in FIM is poorly implemented? A BitAnd with "2"  has always "2" as result. Shouldn't I be able to use BitAnd with a mask of "2" again and what what I'm looking for - that bit 2 is cleared in the target value if necessary?

When I started to work on the description for the related bug, I realized that I made a logical mistake. In case of a Boolean AND,  a "1" doesn't change anything in the target value. Also, there is one constraint all bit vectors have in common - the biggest number you can process as mask value with a given architecture.

Instead of looking at a bit vector, you need to determine the biggest number your mask can have to find a solution that works for all possible bit vectors. You can either lookup this value from the specifications or you can determine it with some tests. FIM is only supported on 64bit Windows.

The biggest number (all bits set to 1) you can have with a 64 bit number is the following:

 18446744073709551615

When you try to configure mask with this value, you will get an error:

http://public.bay.livefilestore.com/y1pasjZ5QpysvMUt7uUsbPBdwqFn0xlcjoeOnrjKCk0z_b8zfoIJGCJ5v1YnpM8igrBdPRO3isMx3CFwsLfQ6eofw/UAC03.jpg

Apparently, this value is already bigger than the maximum value a Number can store. Integer values can be signed or unsigned. This means, a number can start at 0 (unsigned) or at -<something> (signed). The maximum value of a signed 64 bit Integer is the following:

9223372036854775807

If you enter this value as mask, FIM accepts it, which means, we have found the maximum for Number:

http://psd5ig.bay.livefilestore.com/y1pQUohYCfDN-Ou2x-2NV13APIiu6_FvPKRbLOTiWzhOBtbEugdDJ7O_7RhyAIzi_me1AHjlb6oSmykGoeT8L-ySnlskD0wD8yG/UAC06.jpg

Since we want to clear bit 2 in case of our enabled account, we just have to subtract 2 from 9223372036854775807. This means, our silver bullet implementation for “enable the account and don’t touch the other tracked properties" is a BitAnd of the userAccountControl and 9223372036854775805:

http://public.bay.livefilestore.com/y1ps3HI7A6LnKFtP3ezZ1C5UmAEzwcmxUABdoEvFU7Woqrd5ypUyYvdfqwauYcdZG_CWj6tMD-kDxyU5In3JhgTHA/UAC01.jpg

Summary

If you need to set or clear flags on an initialized bit vector, you should use the Boolean operations AND or OR. As a first step, you need to calculate a sum that represents the flags you want to update if necessary.

If you need the flag sum to be set in a bit vector, you can use the sum in a BitOr function.

If you need the flag sum to be cleared, you can use 9223372036854775807 - the sum in a BitAnd operation.

Next to solving the problem of how to enable or disable an account, you should now also have an idea of how the BitOr and the BitAnd functions in FIM work and how you can use them in your projects.