Every object in Active Directory and ADAM contains an attribute called ntSecurityDescriptor. This attribute contains a Windows security descriptor object that contains the discretionary access control list (DACL), the system access control list (SACL), group, and owner information that controls the object's access control behavior.
In .NET 2.0, a new property called SecurityMasks has been added to DirectorySearcher that allows us to control which components of the security descriptor are returned in the data when we request the ntSecurityDescriptor attribute in a search operation.
We cover security descriptors in great detail in Chapters 6 and 8. Chapter 6 contains a complete discussion of reading and writing security descriptors as a whole, and Chapter 8 actually focuses on the internal structure of security descriptors. Please refer to both of those chapters for an explanation of why this property is important and what we can do with the data once we have it.
In this chapter, we will simply demonstrate how to use the new property of the DirectorySearcher effectively. Listing 5.9 contains a sample.
Listing 5.9. Retrieving a Security Descriptor
string adsPath = "LDAP://dc=domain,dc=com"; //explicitly create our searchroot DirectoryEntry searchRoot = new DirectoryEntry( adsPath, null, null, AuthenticationTypes.Secure ); using (searchRoot) //we are responsible for disposing { DirectorySearcher ds = new DirectorySearcher( searchRoot, "(cn=User1)", new string[]{"ntSecurityDescriptor"} ); //Get the Security for this object ds.SecurityMasks = SecurityMasks.Dacl | SecurityMasks.Group | SecurityMasks.Owner; SearchResult sr = ds.FindOne(); if (sr == null) throw new Exception("No user found"); byte[] descriptorBytes = (byte[])sr.Properties["ntSecurityDescriptor"][0]; ActiveDirectorySecurity ads = new ActiveDirectorySecurity(); ads.SetSecurityDescriptorBinaryForm( descriptorBytes, AccessControlSections.All ); //helper function PrintSD(ads); AuthorizationRuleCollection rules = ads.GetAccessRules( true, true, typeof(NTAccount) ); foreach (ActiveDirectoryAccessRule rule in rules) { //helper function PrintAce(rule); } } Sample output: =====Security Descriptor===== Owner: S-1-450115865-2557621802-512 Group: S-1-450115865-2557621802-512 =====ACE===== Identity: NT AUTHORITYSELF AccessControlType: Allow ActiveDirectoryRights: ExtendedRight InheritanceType: None ObjectType: ab721a53-1e2f-11d0-9819-00aa0040529b InheritedObjectType: ObjectFlags: ObjectAceTypePresent |
We show the code for the two helper functions mentioned in Listing 5.3, called PrintSD and PrintAce, in Chapter 8, Listing 8.2. We omitted them here for brevity.
Asynchronous Searches |
Part I: Fundamentals
Introduction to LDAP and Active Directory
Introduction to .NET Directory Services Programming
Binding and CRUD Operations with DirectoryEntry
Searching with the DirectorySearcher
Advanced LDAP Searches
Reading and Writing LDAP Attributes
Active Directory and ADAM Schema
Security in Directory Services Programming
Introduction to the ActiveDirectory Namespace
Part II: Practical Applications
User Management
Group Management
Authentication
Part III: Appendixes
Appendix A. Three Approaches to COM Interop with ADSI
Appendix B. LDAP Tools for Programmers
Appendix C. Troubleshooting and Help
Index