The articles you have seen so far on this blog have been largely demonstrations. When one of our customers asks us how they can do something, such as programmatically creating group policies, we write them some sample code that shows them how to do whatever they have in mind. However, not all problems can be solved by demonstration. We answer the question, “can you do this in Windows” by actually showing you how to do it. Think back to geometry -- you probably have heard at some point that you cannot “square the circle” -- just using a compass and a straightedge, make a square that has the same area as a circle. Yet, how could you prove this?
Sometimes, certain things aren’t possible to achieve in code, given certain constraints, and we won’t be able to provide a sample that will do the impossible. How can we prove that a particular task, given certain constraints, is impossible? One method is reductio ad absurdum, or proof by contradiction. Start by assuming that something is possible, and then show that from this assumption that something results that is clearly impossible -- that, just by inspection, couldn’t possibly happen.
Wouldn’t you like to know who had changed a particular attribute in the Active Directory? We could hold someone accountable for a mistake, or praise them for making a timely change. The Active Directory is an RFC 3377 compliant LDAP directory server (for more information, see the article: Active Directory's LDAP Compliance), but the standard does not define a security model. In the Microsoft implementation, every object is protected by a security descriptor (see: http://msdn.microsoft.com/en-us/library/aa746428(VS.85).aspx). Ultimately, security in the Windows world is role-based -- the highest level of authorization to alter properties of the system is designed to be shared by multiple users, each maintaining their own secret password. If a particular object is protected by being owned only by this highest level, then we can be sure (barring physical compromise of the system or its secrets, of course), that only one of the persons having that role have made the change. Yet, is it possible to go deeper, to know exactly which one of the uses has done the deed?
Suppose that you could actually determine which particular user has made a specific change to an Active Directory object. Suppose that the database that acts as the data store for Active Directory, the Extensible Storage Engine (ESE), actually maintained a record of the security descriptor of the user that made the change -- and that even though there is no “who changed” attribute, there was some record in the DIT file of who that Security Principle was. This is our assumption. From making the assumption, I’m going to demonstrate that a “who changed” attribute is actually impossible without making changes at every domain controller.
Remember that Active Directory is a distributed database. A change made at one domain controller will be propagated, in accord with the enterprises’ replication schedule, to all other domain controllers. Microsoft treats information that travels “across a wire” in a very special way. We disclose it fully. Here (http://msdn.microsoft.com/en-us/openspecifications/default.aspx) is the portal for these Open Specifications, and you can see that the WSPP (Windows Server Protocols) contain a discussion of what domain controllers do when they talk to one another. When you examine the replication protocol, you see the sum total of what is transferred with regard to the information in Active Directory is described by the schema. There is no place for the information to hide. Even if there was some trace in the ESE, that trace couldn’t move from place to place.
You may have seen some programs that could create reports that did distinguish between different users, holding the same security role, changing an attribute in Active Directory. How could such programs possibly work, if there is no “who changed” attribute? How have they managed to square this circle? What they have done is go beyond Active Directory, to augment its functioning. They aren’t accessing something that is there, but hidden -- they are importing an entirely new functionality. This functionality comes with some costs, and some limitations. There are several places where Microsoft provides a way to augment the directory. The Password Change Notification Service (http://technet.microsoft.com/en-us/library/cc720654(WS.10).aspx) is an example. If you install a service on EVERY domain controller in the domain, the service will signal the identity integration server that this has happened. This is an example of a password filter (http://msdn.microsoft.com/en-us/library/ms721882(VS.85).aspx).
In the case of arbitrary LDAP calls, however, there isn’t a predefined hook into the functioning of the wldap32.dll, as we see with password filters. If you wanted to add a “who changed” attribute, you would have to create your own hook. One way to do so would be the Detours library (http://research.microsoft.com/en-us/projects/detours/) from Microsoft Research, which you can incorporate into a program without charge for experimentation, and is licensed for commercial products. It will let you hook into every LDAP call on the machine, and the code in your service will be responsible for updating the “who changed” attribute. Note that this process will need to be installed on every domain controller in the domain. You would need to extend the schema of Active Directory for every attribute that you want to track, so that the information about who changed it can be distributed to the other domain controllers.
A caution, however, in relying upon any “who changed” attribute that a program creates in this fashion. If the way in which the “who changed” service functions is known to the Domain Administrators (if they could use Bing, say, and find the code in a blog post for the “who changed” service), they would be able to impersonate the specific identity of any of the other Domain Administrators in making a change, by changing the attribute directly in the same way in which the service would have changed the attribute. There is no way of guarding the guardians in role-based security, if there is a lack of trust in the final guardians. This fact (http://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes) has been known for quite some time.