The schema is the blueprint for data storage in Active Directory. Each object in Active Directory is an instance of a class in the schema. A user object, for example, exists as an instance of the user class. Attributes define the pieces of information that a class, and thus an instance of that class, can hold. Syntaxes define the type of data that can be placed into an attribute. As an example, if an attribute is defined with a syntax of Boolean, it can store True or False as its value, or it can be null. A null value has an implementation-specific meaning; it could mean True or False depending on the application using the value.
Active Directory contains many attributes and classes in the default schema, some of which are based on standards and some of which Microsoft needed for its own use. Each release of Active Directory since Windows 2000 has included updates to the default schema. For background information on schema versions, see the sidebar Schema Versions,” next. However, the Active Directory schema was designed to be extensible, so that administrators could add classes or attributes they deemed necessary. In fact, extending the schema is not a difficult task; it is often more difficult to design the changes that you would like to incorporate. Schema design issues are covered in Chapter 14, and in Chapter 26, we cover how to extend the schema programmatically. In this chapter, we’re concerned only with the fundamentals of the schema.
Table 4-1. Active Directory default schema versions
Windows Server 2003
Windows Server 2003 R2
Windows Server 2008
The Schema Container is located in Active Directory under the
Configuration Container. For example, the distinguished name of the Schema
Container in the http://mycorp.com forest would be
can view the contents of the container directly by pointing an Active
Directory viewer such as ADSIEdit or LDP at it. You can also use the Active
Directory Schema MMC snap-in, which splits the classes and attributes in
separate containers for easy viewing, even though in reality all the
schema objects are stored directly in the Schema Container.
The Active Directory Schema MMC snap-in is not fully enabled by
default. In order to enable the schema management snap-in on a domain
controller, you must first register the DLL which it depends on. To do
that, run this command:
The schema itself is made up of two types of Active Directory
objects: classes and attributes. In Active Directory, these are known respectively as
classSchema (Class-Schema) and
objects. The two distinct forms of the same names result from the
fact that the
attribute of a class contains the hyphenated easy-to-read name of the
class, and the
(LDAP-Display-Name) attribute of a class contains the concatenated string format that is
used when querying Active Directory with LDAP or ADSI. In the schema, the
attribute of each object is normally made by capitalizing the first letter
of each word of the Common-Name, and then removing the hyphens and
concatenating all the words together. Finally, the first letter is made
lowercase. This creates simple names like
user, as well as the more unusual
lDAPDisplayName. We’ll specify the more commonly
used LDAP display name format from now on.
Whenever you need to create new types of objects in Active
Directory, you must first create a
classSchema object, defining the class of the
object and the attributes it contains. Once the class is properly designed
and added to the schema, you can then create objects in Active Directory
that use the class. If the class you are adding will have custom
attributes that are required to be populated when new instances of that
class are created, you must define the
attributeSchema objects first. If you just want
to add a new attribute to an existing class, you must create the
attributeSchema object and associate the
attribute with whatever classes you want to use it with.
Before we delve into what makes up an Active Directory class or attribute, we need to explain how each class that you create is unique not just within your Active Directory but also throughout the world.
Active Directory is based on LDAP, which was originally based on the X.500 standard created by the ISO (International Organization for Standardization) and ITU (International Telecommunications Union) organizations in 1988. To properly understand how the Active Directory schema works, you really need to understand some of the basics of X.500; we’ll run through them next.
The X.500 standard specifies that individual object classes in an organization can be uniquely defined using a special identifying process. The process has to be able to take into account the fact that classes can inherit from one another, as well as the potential need for any organization in the world to define and export a class of their own design.
The first part indicates the unique path to the branch holding the object in the X.500 tree-like structure.
The second part uniquely indicates the object in that branch.
OID notation uses integers for each branch and object, as in the following example OID for an object:
This uniquely references object 497 in branch 22.214.171.124.4.1.3385.12. The 126.96.36.199.4.1.3385.12 branch is contained in a branch whose OID is 188.8.131.52.4.1.3385, and so on.
Each branch within an OID number also corresponds to a name. This means that the dotted notation 184.108.40.206.4.1, for example, is equivalent to iso.org.dod.internet.private.enterprise. As the names are of no relevance to us with Active Directory, we don’t cover them in this book.
This notation continues today and is used in the Active Directory schema. If you wish to create a schema object, you need to obtain a unique OID branch for your organization. Using this as your root, you can then create further branches and leaf nodes within the root, as your organization requires.
The Internet Assigned Numbers Authority (IANA) maintains the main set of root branches and defines itself as “the central coordinator for the assignment of unique parameter values for Internet protocols.” The IANA says of its mission:
The IANA is chartered by the Internet Society (ISOC) and the Federal Network Council (FNC) to act as the clearinghouse to assign and coordinate the use of numerous Internet protocol parameters. The Internet protocol suite, as defined by the Internet Engineering Task Force (IETF) and its steering group (the IESG), contains numerous parameters, such as Internet addresses, domain names, autonomous system numbers (used in some routing protocols), protocol numbers, port numbers, management information base object identifiers, including private enterprise numbers, and many others. The common use of the Internet protocols by the Internet community requires that the particular values used in these parameter fields be assigned uniquely. It is the task of the IANA to make those unique assignments as requested and to maintain a registry of the currently assigned values. The IANA is located at and operated by the Information Sciences Institute (ISI) of the University of Southern California (USC).
You can find the IANA web page at http://www.iana.org.
You can request an OID namespace—i.e., a root OID number from which you can create your own branches—directly from the IANA if you like. These numbers are known as Enterprise Numbers. The entire list of Enterprise Numbers assigned by the IANA can be found at http://www.iana.org/assignments/enterprise-numbers. This list of numbers is updated every time a new one is added.
At the top of the file, you can see that the root that the IANA uses is 220.127.116.11.4.1. If you look down the list, you will see that Microsoft has been allocated branch 311 of that part of the tree, so Microsoft’s OID namespace is 18.104.22.168.4.1.311. Leicester University’s OID namespace is 22.214.171.124.4.1.3385. As each number also has a contact email address alongside it in the list, you can search through the file for any member of your organization that has already been allocated a number. It is likely that large organizations that already have an X.500 directory or that have developed SNMP MIBs will have obtained an OID.
In addition to Enterprise Numbers, country-specific OIDs can be purchased as well. An organization’s Enterprise Number registration has no bearing on whether it has obtained a country-based OID namespace to use. If you don’t see the company listed in the Enterprise Numbers list, don’t be fooled; the organization could still have a number.
For example, Microsoft has been issued the Enterprise Number 126.96.36.199.4.1.311, yet all of its new schema classes use a U.S.-issued OID namespace of 1.2.840.113556 as their root. The 1.2.840 part is uniquely allotted to the United States. In other words, Microsoft has obtained two OID namespaces that it can use but is choosing to use only the U.S.-issued namespace.
If you want to obtain an Enterprise Number, fill in the online form at at http://pen.iana.org/pen/PenApplication.page. If this URL changes, you can navigate to it from the main IANA web page.
Microsoft used to issue unique OID namespaces to customers on request; however, they no longer do this. Instead, Microsoft provides a script that will generate a statistically unique OID branch each time it is run. This script is available from http://go.microsoft.com/fwlink/?LinkId=100725.
Using a unique prefix for schema extensions may not seem important at first glance. The benefit of unique prefixes comes into play if a company finds out another company is also using the same prefix. This can become extremely problematic if the other company is an application vendor.
For example, say that MyCorp Financial Services is prefixing
their schema extensions with the “mycorp” prefix. MyCorp Financial has
extended their schema with two new attributes:
mycorpAttrib2. MyCorp Financial purchases a
software package from another company, MyCorp Software Solutions, who
also chose to use attribute names of
In this scenario, MyCorp Financial Services would be in a very bad position. MyCorp Financial’s only option would be changing all previous uses of their attributes so that the names could be reused by the application. If MyCorp Financial did not rename their attributes, they would not be able to use the application that they purchased.
Once an organization has an OID namespace, it can add unique branches and leaves in any manner desired under the root. For example, Leicester University could decide to have no branches underneath and just give any new object an incrementing integer starting from 1 underneath the 188.8.131.52.4.1.3385 root. Alternatively, they could decide to make a series of numbered branches starting from 1, each corresponding to a certain set of classes or attributes that they wish to create. Thus, the fifth object under the third branch would have an OID of 184.108.40.206.4.1. 3385.3.5.
The range of values in any part of an OID namespace for the Active Directory schema goes from 1 to 268,435,455, i.e., from 20 through 228 – 1.
This limitation has caused issues with schema extensions for some companies in Australia. Australia has the OID 1.2.36, and according to the Australia Standards document MP-75, companies may use their Australian Company Number (excluding leading zeros) to formulate their OID without needing to request an OID. Unfortunately the ACN is nine digits, so it could easily exceed the limitation listed above. This has been filed as a bug and Microsoft is aware of the issue.
To reinforce this point, let’s look at a couple of examples
directly from the Active Directory schema. If you open the Active
Directory Schema snap-in, you can look at the schema class OIDs very
easily. Navigating through the classes when we open the property page
printQueue class, we get
Figure 4-1. You can see that
the unique OID is 1.2.840.1135220.127.116.11. This tells us that the number
is a defined part of Microsoft’s
object class hierarchy.
Figure 4-2 shows
the property page for the
organizationalPerson class. Here, you can see
that the unique OID 18.104.22.168 is very different, because within the
original X.500 standard, a set of original classes was defined. One was
organizationalPerson, and this is a
copy of that class. Microsoft included the entire set of base X.500
classes within Active Directory.
The OID numbering notation has nothing to do with inheritance. Numbering a set of objects a certain way does nothing other than create a structure for you to reference the objects; it does not indicate how objects inherit from one another.
Let’s dissect an example attribute and class to see what they contain. With that information, you will be able to see what is required when you create a new schema object.
Just as class information is stored in Active Directory as instances
of the class called
attributes are represented by instances of the class called
attributeSchema. As with
all objects, the
has a number of attributes that can be set when specifying a new instance.
attributeSchema class inherits
attributes from the class called
However, most of the
top attributes are
not relevant here. All of the attributes of the
attributeSchema class are documented in the
Platforms SDK at http://msdn2.microsoft.com/en-us/library/ms680969(VS.85).aspx.
attribute is used on user objects to provide a unique method of
identifying each user across a forest. Users can log on to a workstation
in any domain in the forest using the UPN if they so desire. The UPN
attribute, in fact, accepts valid RFC 2822 (email) addresses, so the UPN
for user tpood in the http://europe.mycorp.com domain could be
firstname.lastname@example.org, or even
email@example.com. In fact, any UPN suffix, such as
@mycorp.com, can be used in a forest. The only
requirement is that the UPN value for a user is unique across all users
in a forest.
Active Directory does not enforce uniqueness of a UPN when it is set. If two different users in the same forest are assigned the same UPN, neither will be able to log on using the UPN. When duplicate UPNs are detected, domain controllers will log an event from source Key Distribution Center (KDC) with event ID 11. Many large organizations implement scripts or other tools to scan their directories on a regular basis to check for duplicate UPNs.
To dissect the attribute, we need to find out what values had been
set for it. Table 4-2 shows a
subset of the values of attributes that have been set for the
Table 4-2. userPrincipalName’s attributes
cn=Attribute-Schema, cn=Schema, cn=Configuration, dc=mycorp,dc=com
top; attributeSchema (two values of a multivalued attribute)
18 (Category 1 attribute, replicated to GC)
We can see that the name of the attribute is
adminDescription, adminDisplayName, cn, name),
that it is an instance of the
attributeSchema class (
objectClass), that it inherits attributes from
objectClass), and that the UPN attribute is
not visible to casual browsing (
attributes show the following:
It is to be stored in the GC (
It is to be indexed (
It has an OID of 1.2.840.113522.214.171.1246 (
We should use
lDAPDisplayName) when binding to it with ADSI.
Instances can be created by anyone (
It stores single (
isSingleValued) Unicode strings (
In Figure 4-3, you can see many of the values for the UPN attribute. We have indicated which attributes are changed by checking or unchecking each checkbox.
There are several properties on attributes that have significant and varied impact on attribute use and functionality. Here we give a little more detailed information on a few of these attributes that you need to understand when modifying the schema.
The syntax of an attribute represents the kind of data it can hold; people with a programming background are probably more familiar with the term “data type.” Unlike attributes and classes, the supported syntaxes are not represented as objects in Active Directory. Instead, Microsoft has coded these syntaxes internally into Active Directory itself. Consequently, any new attributes you create in the schema must use one of the predefined syntaxes.
Whenever you create a new attribute, you must specify its syntax. To uniquely identify the syntax among the total set of 21 syntaxes, you must specify two pieces of information: the OID of the syntax and a so-called OM syntax. This pair of values must be set together and correctly correlate with Table 4-3. More than one syntax has the same OID, which may seem strange; and to uniquely distinguish between different syntaxes, you thus need a second identifier. This is the result of Microsoft requiring some syntaxes that X.500 did not provide. Table 4-3 shows the 21 expanded syntaxes, including the name of the syntax with alternate names followed in parentheses.
Table 4-3. Syntax definitions
Used internally by the system.
True or false.
A string that does not differentiate between uppercase and lowercase.
A string that differentiates between uppercase and lowercase.
The Fully Qualified Domain Name (FQDN) of an object in Active Directory.
Octet string with binary value and DN. Format: B:<char count>:<binary value>:<object DN>.
Octet string with string value and DN. Format: S:<char count>:<string value>:<object DN>.
ASN1.1 time format, e.g., 20040625234417.0Z.
A 32-bit number.
A 32-bit number.
A 64-bit number.
NT Security Descriptor
A Security Descriptor (SD).
A string of digits.
Octet string (Octet-String)
A byte string.
Print case string (IA5-String)
A normal printable string.
Print case string (Printable-String)
A normal printable string.
A security identifier (SID).
Not a valid syntax.
A wide string.
The number of seconds elapsed since 1 January 1970.
Most of these are standard programming types. If you’re not sure
which syntax to use, take a look at a preexisting attribute and see if
you can find an appropriate syntax for the attribute you wish to create.
For example, the
attribute has an
126.96.36.199 and an
oMSyntax of 64, so it
must contain Unicode strings.
systemFlags attribute is an
often overlooked but important attribute. The attribute is a bitmask
that represents how the attribute should be handled. For more
information on bitmasks, see the upcoming sidebar How to Work with Bitmasks.” New bit values can be defined
any time that Microsoft updates the directory service binaries. The
attribute is configured both on schema definitions of attributes and
classes as well as on any instantiated object throughout the forest.
This can be confusing, but the various bits in the attribute can mean
various things depending on the object the attribute applies to. Table 4-4 lists only the
classSchema objects. A complete
listing of valid
is available in the Platform SDK at http://msdn2.microsoft.com/en-us/library/ms680022(VS.85).aspx.
Table 4-4. System flag values for class and attributes objects
Attribute is not replicated.
Attribute will be replicated to the global catalog.
This value should only be set by Microsoft; do not use. Instead,
Attribute is constructed, not stored in the database. This should only be set by Microsoft; do not use.
Category 1 attribute or class. Category 1 objects are classes and attributes that are included in the base schema with the system. Note that not all classes and attributes included in the base schema are marked as category 1.
The schema object cannot be renamed.
Most attributes are directly stored in the Active Directory
database. Constructed attributes are the exception, and they are
handled by the directory service in order to offer special
functionality. This functionality can range from telling you
approximately how many objects are contained directly under a
container type object (
msDS-Approx-Immed-Subordinates) to telling
you the types of objects that can be instantiated under a given object
possibleInferiors) to telling you
which attributes you have write access to on a given object (
allowedAttributesEffective), and many other
things. These attributes, because they are special, have some rules
you should be aware of:
Constructed attributes are not replicated. They are constructed by each directory instance separately.
Constructed attributes cannot be used in server-side sorting.
Constructed attributes generally cannot be used for queries. The attribute
aNRis an exception here as it is used for constructing the special ANR queries. ANR is covered in the section Ambiguous Name Resolution.”
In some cases, a BASE scope query may be required to retrieve certain constructed attributes; e.g.,
tokenGroupscan only be returned with a BASE scope query.
schemaFlagsEx attribute is
an attribute that has existed since Windows 2000 but was not put into
use until Windows Server 2008. The
schemaFlagsEx attribute is designed to hold
flags that further define the properties of an attribute. There is
currently only one flag implemented in this bitmask as outlined in Table 4-5.
searchFlags attribute is
another bitmask that is best known as the attribute used to control
indexing, but it is a little more involved than that. As indicated by
searchFlags is similar to
systemFlags in that it is a series of
bits representing how the attribute should be handled. Unlike
searchFlags are only set on schema attribute
definitions. See Table 4-6 for all of the
values as of Windows Server 2008.
Table 4-6. Search flag bits
Create an index for the attribute. All other index-based flags require this flag to be enabled as well. Marking linked attributes to be indexed has no effect.
Create an index for the attribute in each container. This is only useful for one-level LDAP queries.
Add attribute to Ambiguous Name Resolution (ANR) set. ANR queries are primarily used for Exchange and other address book tools. ANR attributes must be indexed and must be either UNICODE or Teletex string attribute syntax. Adding attributes to this set can have performance implications on Microsoft Exchange.
Preserve this attribute in a tombstone object. This flag controls what attributes are kept when an object is deleted.
Copy this value when the object is copied. This flag doesn’t do anything in Active Directory; tools such as Active Directory Users and Computers that copy objects can look at this flag to determine what attributes should be copied.
Create tuple index. Tuple indexing is useful for
medial searches. A medial search has a wildcard at the beginning
or in the middle of the search string. For example, the medial
Mark attribute as confidential. Only users with both read property and Control Access right to the attribute so marked can view it when it is so marked. This is a new feature as of Windows Server 2003 SP1. SP1 domain controllers will not allow you to mark Category 1 attributes with this flag.
Never audit changes to this attribute. This flag is new in Windows Server 2008. Windows Server 2008 auditing enhancements are covered in Chapter 13.
Include this attribute in the RODC filtered attribute set. RODCs and the filtered attribute set are covered in Chapter 7.
Attribute indexing is available to boost performance of queries.
When an attribute is indexed, the values are placed in a special table
in a sorted order so that a query using the attribute can be completed
by looking at a subset of all the information in the directory. The
type of index created can be modified by additional bit flags
configured in the
attribute. There are several points to know about indexes:
A query that contains bitwise operations on an indexed attribute diminishes the usefulness of the index. A bitwise operation can’t be directly looked up in the index table and the entire set of values in the index will have to be enumerated and tested. Bitwise queries are queries that query a bitmask, for example, the
A query that contains a NOT of an indexed attribute negates the use of the index for that portion of the query. A NOT of an attribute requires enumerating all objects in the search scope to determine which objects don’t have the attribute or which objects have permissions applied that disallow the trustee to view the attribute value.
Linked attributes are implicitly indexed, and beginning with Windows Server 2003, the necessary logic to use these indexes was implemented. If you modify the flag, it will have no effect due to the implicit indexing behavior.
It is often assumed that indexes cannot be built or do not work well for attributes with multiple values or non-unique values. This is incorrect. In the early days of the original Active Directory beta, there was concern about multiple values and non-unique values, but the issues surrounding them were addressed. This topic is most often raised in regards to the
objectClassattribute and is stated as the reason why Microsoft didn’t index the attribute by default prior to Windows Server 2008.
If you have installed the Exchange Server 2007 schema extensions in your forest,
objectClassis indexed as part of this schema extension.
Windows Server 2008 domain controllers implement a special behavior that indexes
objectClassby default regardless of the
searchFlagssetting in Active Directory. Note that this is considered a special behavior because the attribute will not be indexed on Windows 2000 or Windows Server 2003 domain controllers once you import the Windows Server 2008 schema extensions; however, the attribute will be indexed on any Windows Server 2008 servers. This could cause performance deltas in applications that randomly select domain controllers for use. You may consider indexing
objectclasswhen you apply the Windows Server 2008 schema updates so that you will have a consistent LDAP query experience across your enterprise once Windows Server 2008 domain controllers are introduced.
While indexing attributes can very frequently improve the performance of LDAP queries, it is important to realize that indexes also consume disk space. Adding an index to an attribute that is populated across a large percentage of directory objects may consume a substantial amount of disk space.
Domain controller performance will also be impacted while indexes are being generated. Index data is not replicated, so every domain controller in the forest must build its own copy of an index when it detects a new attribute index must be created. The speed at which an index is created is dependent on how much data must be indexed and also the hardware the domain controller is running on.
Ambiguous Name Resolution (ANR) is used for
address book look-ups. It allows a single small query to be expanded
into searching as many fields as the administrator would like searched
so that users can enter a single piece of information and hopefully
find all possible “hits” on the value they are interested in. When an
ANR query such as
(anr=brian)is submitted, the Active
Directory Query Processor expands the simple filter into a more
complex OR wildcard filter that contains all attributes marked as part
of the ANR set. The specified filter on a default Windows Server 2008
Active Directory would expand that simple query to:
(| (displayName=brian*) (givenName=brian*) (legacyExchangeDN=brian*) (msDS-AdditionalSamAccountName=brian*) (msDS-PhoneticCompanyName=brian*) (msDS-PhoneticDepartment=brian*) (msDS-PhoneticDisplayName=brian*) (msDS-PhoneticFirstName=brian*) (msDS-PhoneticLastName=brian*) (physicalDeliveryOfficeName=brian*) (proxyAddresses=brian*) (name=brian*) (sAMAccountName=brian*) (sn=brian*) )
A Windows Server 2008 Active Directory domain with Exchange Server 2007 SP1 installed would expand the query to:
(| (displayName=brian*) (givenName=brian*) (legacyExchangeDN=brian*) (msDS-AdditionalSamAccountName=brian*) (msDS-PhoneticCompanyName=brian*) (msDS-PhoneticDepartment=brian*) (msDS-PhoneticDisplayName=brian*) (msDS-PhoneticFirstName=brian*) (msDS-PhoneticLastName=brian*) (physicalDeliveryOfficeName=brian*) (proxyAddresses=brian*) (name=brian*) (sAMAccountName=brian*) (sn=brian*) (mail=brian*) (mailNickname=brian*) (msExchResourceSearchProperties=brian*) )
As you can see, a very simple query can quickly be expanded into a very large query. For this reason, you should avoid adding additional ANR attributes.
When a delete request is processed for an object, the object is not immediately deleted. Instead, the object is stripped of most of its attributes and moved to the Deleted Objects container of the partition the object exists in. Deleted objects that have been moved to the Deleted Objects containers are referred to as tombstones. Tombstones remain in the Deleted Objects container for the length of the tombstone period. The default tombstone periods or lifetimes for new forests are documented in Table 4-7. Tombstoning an object allows the delete operation to replicate to all domain controllers holding a copy of the object. The process of undeleting an object in Active Directory is known as tombstone reanimation.
Administrators can modify the tombstone lifetime for a forest
by changing the
attribute of the
The attributes that are retained when an object is tombstoned
are configured through a combination of the
searchFlags setting and some hard-coded
internal functionality. The preserve on tombstone
searchFlags setting is configurable
by administrators so they can choose to add more attributes to what is
kept on a tombstoned object. The purpose of keeping more attributes on
tombstones is directly related to the new capability available in ADAM
and Windows Server 2003 Active Directory to reanimate tombstoned
objects. The more attributes you allow the directory to retain on the
tombstoned object, the fewer attributes you have to recover through
other means after the object is reanimated.
Unfortunately, not all attributes can successfully be added to
the tombstone when the proper
searchFlags bit is set. The most obvious
examples are linked attributes such as group membership. Linked
attributes are handled differently by the directory, and thus there is
no way to force them to be retained. If you configure a linked
attribute to be preserved, Active Directory will simply ignore the
setting. This is unfortunate, as it means that critical information
such as group membership must be either manually maintained in an
additional attribute that can survive the tombstone process, or else
the group membership must be maintained outside of AD.
While some attributes won’t survive the tombstone regardless of
what you set, some attributes will survive the tombstone but will not
survive the reanimation process. The attribute
pwdLastSet attribute, for example, falls
into this category. When you reanimate an object with
pwdLastSet, even though the attribute may be
preserved in the tombstone, it will be overwritten when the object is
Unfortunately, Microsoft has not documented what can and cannot survive a tombstone and subsequent reanimation. So make sure you test any attributes you have configured to be retained to make sure they can actually be reanimated. You don’t want to find yourself in a situation where you discover that an attribute didn’t survive reanimation when it comes time to reanimate an object.
When you create an index, it is optimized for direct look-ups
and, if the attribute syntax supports it, trailing wildcards—e.g.,
(name=joe*). If you use medial queries—that is, queries with
wildcards anywhere but the end of the string, such as
(name=*oe)—performance tends to be rather less than
optimal. Generally, this is okay, but in the cases where an
important application is being significantly impacted due to poor
medial query performance, you may want to consider enabling a tuple
index for the attribute. This is just like enabling a normal index;
you simply enable another bit on the attribute’s searchFlags mask to
specify that a tuple index should be created.
A tuple index is considered an expensive index, and it will increase the Active Directory database (ntds.dit) size more than a “normal” index. In addition, new attribute insertion performance will be impacted slightly. This performance hit will not be noticeable for single attribute insertions, but if you are updating a large number of attributes at once, the performance hit may be more noticeable.
A new bit for the
attribute was defined for Windows Server 2003 Service Pack 1: the
confidential attribute flag. Any attribute that has this flag enabled requires two
permissions in order to be viewed by a trustee (trustees are the
security principals who are granted permissions). The trustee needs
read property for the attribute and also needs
control access for the attribute. This
functionality was put into place primarily to protect sensitive user
attributes such as Social Security numbers and other personal
information. By default, only the administrators and account operators
have full control on all user objects, which means they will be able
to view any confidential attributes. Anyone else who has full control
over a user object will also be able to view the confidential data, so
this is yet another reason to not grant unnecessary rights in the
directory. If you have domain controllers in the domain (or global
catalogs in the forest if you are dealing with an attribute in the
partial attribute set) that are not running Windows Server 2003
Service Pack 1 or newer, then any attributes marked as confidential
will still be viewable without the special access rights on those
domain controllers or global catalogs.
The confidential attribute capability was added as a workaround to issues that exist in the current security model in Active Directory. Unfortunately, there are a large number of explicit read property grant permissions on objects in Active Directory that are terribly difficult to override. This new flag allows you to step in despite all the default grant permissions and quickly deny access to an attribute.
This new function was welcomed with open arms in the Active Directory community until administrators started to realize that Microsoft purposely crippled the functionality by not allowing you to set Category 1 attributes as confidential. Category 1 attributes are many of the attributes defined in the default AD schema, and that list of attributes contains many of the attributes you probably want to make confidential such as telephone numbers, addresses, employee IDs, and so on. It seems the intent is simply to give AD administrators a way to better secure custom attributes they have added to the directory with schema extensions. This limitation drastically reduces the usefulness of this capability for companies that stick to the default schema.
As mentioned, modification of
searchFlags to enable confidential
functions on Category 1 attributes is strictly disallowed by Windows
Server 2003 SP1 domain controllers. If you try to change
searchFlags on one of these DCs so that
the confidential flag is set, you will get either an “Unwilling to
perform” or a poorly worded “The search flags for the attribute are
invalid. The ANR bit is valid only on attributes of Unicode or
Teletex strings” error for your troubles.
This new capability is almost wholly underwhelming for AD LDS. The default security descriptors on all AD LDS base schema objects are configured with no explicit Access Control Entries (ACEs). The result is very few explicit read property grant permissions on objects when they are instantiated, which means you can more easily secure attributes with inherited deny permissions and will not need to depend on the confidential attribute functionality.
Next, we need to discuss the tools that Microsoft has made available starting with Windows Server 2003 Service Pack 1 to handle managing access to confidential attributes. The answer is easy: none. In order to grant a trustee the ability to view a specific confidential attribute on an attribute, a grant ACE with control access permission for the specific attribute needs to be added to the ACL of the object. For more information on modifying the ACL of an object, see Chapter 13.
The GUI tools available for assigning permissions not only do not have the ability to assign this type of permission, but they can’t even display the permission if something else grants it. The command-line tool dsacls.exe is only marginally better; it can display the permission, but cannot grant the permission. The best that the GUI and dsacls.exe tool can do is assign either full control to the object or ALL control access rights to the object, but neither of these is optimal if you prefer to give minimum rights necessary to get the job done. In Windows Server 2003 SP1, the only way to set granular permissions to view a specific confidential attribute is to write a custom program or script to handle the delegation.
Beginning with Windows Server 2003 R2, there is a GUI tool to handle this delegation. The new version of LDP that is loaded in the %windir%\adam directory when you install R2 ADAM has a new ACL editor. This version of updated version of LDP is also available in the free download of ADAM SP1. The version of LDP that is installed with Windows Server 2008 also includes this functionality. If you need to modify this delegation, we recommend you use one of the updated versions of the LDP tool.
The Windows Server 2008 auditing infrastructure has been substantially updated compared to its predecessors. In Windows 2000 Server and Windows Server 2003, there was a single domain-wide directory service auditing setting called Audit Directory Service Access. When this setting was enabled, all directory services auditing events were enabled. In a busy environment, the consequence of this was a substantial amount of security audit traffic in the event logs, to the point that it could easily become unmanageable and thus impractical to have enabled.
Windows Server 2008 domain controllers separate directory services auditing into four subcategories:
Directory Service Access
Directory Service Changes
Directory Service Replication
Detailed Directory Service Replication
Of particular interest to us right now is the Directory Service Changes subcategory. We will discuss the new auditing infrastructure in much more detail in Chapter 13.
By default, all attribute changes will continue to be audited as
required by the System ACL (SACL). In order to
control noise, however, you can set bit 9 on an attribute’s
searchFlags mask to disable all change
audits for that attribute. The Windows Server 2008 GUI tools do not
expose an interactive method to easily set this bit. For directions on
setting this bit, reference the sidebar Controlling Attribute Change Auditing,” next.
The filtered attribute set is part of the overall new Read-Only Domain Controller (RODC) functionality in Windows Server 2008 Active Directory. RODCs can be configured to not replicate certain attributes in the Active Directory schema. There is an in depth discussion of the RODC in Chapter 7; however, we will discuss RODCs briefly in the context of the filtered attribute set here.
RODCs were designed with the mentality that the server that they are running on is compromised by default. Consequentially there are some attributes that we might not wish to have stored on an RODC as they could contain sensitive information. Examples might be schema extensions that contain application-specific secrets, confidential data such as Social Security numbers, and so forth.
You can apply the process illustrated in the sidebar
“Controlling Attribute Change Auditing” to control whether or not
attributes are included in the filtered attribute set. Instead of
0x100, you should
Property sets are described in our Chapter 13 discussion on
Active Directory security. We mention them here because the creation,
modification, and identification of property sets involve the schema
partition. Part of the information for a property set is maintained in
the configuration container in the
cn=extended-rights sub-container, and the rest
is maintained in the schema.
The property sets are defined in the
cn=extended-rights sub-container as
objects. Two of the attributes of the
controlAccessRight object link it to the
schema. The first attribute is the
appliesTo attribute; the second is the
appliesTo attribute is the string
representation of the
attribute of the
that the property set applies to. The
rightsGuid is the string representation of the
binary GUID stamped on the
attributeSecurityGUID attribute of
attributeSchema objects to identify them as
members of the property set.
Microsoft allows distinguished name attributes with
attributeSyntax values of 188.8.131.52, 184.108.40.206,
and 220.127.116.11 to be linked to attributes with an
attributeSyntax of 18.104.22.168. These are called
linked attributes and consist of a forward link and a back link. An
example of a pair of linked attributes is
Attributes are linked by setting the
linkID attributes of two
attributeSchema objects to valid link values.
The values must be unique for all
attributeSchema objects. The value of the
forward link is a positive even value and the back link is the forward
linkID value plus one to make it a
positive odd value. Attributes must be linked when they are first
defined in the schema.
You can use any random
values as long as they result in a unique
linkID pair; however, it is
highly recommended that you auto-generate link IDs.
You cannot use auto-generated link IDs in the case that you need your
schema extension to support Windows 2000. If you need to support Windows
2000, you should email firstname.lastname@example.org to request
unique link IDs.
In order to auto-generate link ID pairs, there are four steps you must follow:
Create the forward link attribute and populate the
linkIDattribute with the value
Reload the schema cache.
Create the back link attribute and populate the
linkIDattribute with the
lDAPDisplayNameof the forward link attribute you created in step 1.
Reload the schema cache.
Schema classes are defined as instances of the
classSchema class. A complete listing of the
attributes on the
classSchema class is
available from the Platform SDK at http://msdn2.microsoft.com/en-us/library/ms680982(VS.85).aspx.
Classes are special in that they can inherit from one another. For
example, let’s say that we wanted to store two new types of objects in
the schema, representing a marketing user and a finance user,
respectively. These users both need all the attributes of the existing
user class as a base. However, the
finance user needs three special attributes, while the marketing user
needs seven. The extra attributes required by both users do not match in
any way. In this example, we can create a
Marketing-User class, a
Finance-User class, and 10 distinctly
new attributes. However, rather than having to specify that the
Marketing-User and Finance-User classes have each of the attributes of
user class individually,
all we need to do is specify that the new classes inherit from the
user class by setting the
subClassOf attribute to
user. When we do this, both of the new classes
inherit every single attribute that the
user class had. We can then add the extra
attributes to each class and we have two new classes. This example is
outlined in Figure 4-4.
You have another option when using Windows Server 2003 Forest Functional Mode or ADAM to resolve this issue. First, define the additional attributes and then create two auxiliary classes and assign the attributes to the classes. Then you can dynamically assign the auxiliary classes to users on ad hoc basis. This is far more flexible in that you can easily reconfigure individual users as necessary. If a user moves from Marketing to Finance, using special inherited classes would require deleting the user and recreating the user with the finance-user class. With dynamic auxiliary classes, you would simply clear the marketing attributes, remove the Marketing auxiliary class, and add the Finance auxiliary class and attributes.
You can think of the Active Directory schema as a treelike
structure, with multiple classes branching down or inheriting from one
base class at the top that has the attributes all objects need to begin
with. This class, unsurprisingly enough, is called
top, which was originally defined in the X.500
specification. Some classes inherit directly from
top, while others exist much lower down the
tree. While each class may have only one parent in this layout, each
class may also inherit attributes from other classes. This is possible
because you can create three categories of
classSchema object, also known as the
abstract, and auxiliary:
It is possible that you would want to create a class that inherits from other classes and has certain attributes, but that is not one you will ever need to create instances of directly. This type of class is known as abstract. Abstract classes can inherit from other classes and can have attributes defined on them directly. The only difference between abstract and structural classes is that an object that is an instance of an abstract class cannot be created in Active Directory. If you are familiar with an object-oriented programming language, abstract schema classes in Active Directory are analogous to abstract classes in the programming language.
An auxiliary class is used to store sets of attributes that other classes can inherit. Auxiliary classes are a way for structural and abstract classes to inherit collections of attributes that do not have to be defined directly within the classes themselves. Auxiliary classes are primarily a grouping mechanism.
The X.500 specifications indicate that an auxiliary class cannot inherit from a structural class, and an abstract class can inherit only from another abstract class.
To comply with the X.500 standards, there are actually four
objects are required to be classified as one of structural, abstract,
or auxiliary by the 1993 X.500 specifications, objects defined before
1993 using the 1988 specifications are not required to comply with
these categories. Such objects have no corresponding 1993 category and
so are defined in the schema as having a special category known as the
Let’s take a look at the
computer classes that are used to
create user and computer accounts within Active Directory. The
computer class and
user class are each structural, which means
that you can instantiate objects of those classes directly in Active
inherits from the
user class, so the
computer class is a special type of
user in a way. The
inherits from the
organizationalPerson Type 88 class. This
means that the total attributes available to objects of class
computer include not only the attributes
defined specifically on the
user classes themselves, but also
all the attributes that are inherited from the
organizationalPerson class. The
organizationalPerson class is a subclass of
person abstract class, which is a
subclass of the abstract
Recall that there are no classes above
top; it is the root class. This relationship
is outlined in Figure 4-5.
user class that Microsoft
needed to define in Active Directory had to be more than just the sum of
the X.500 standard parts. After all, Microsoft uses Security
Identifiers (SIDs) to identify users, and these were not
contained in the original X.500 standards. So, to extend the attributes
that make up a user, Microsoft defined some auxiliary classes and
included these in the user class makeup. The auxiliary classes are
mailRecipient is a collection of attributes
that allow a user to hold information relating to the email address and
mail account associated with that user. The
securityPrincipal attribute is used to hold
the SID and other user-related security attributes that Microsoft
posixAccount auxiliary classes were
added in Windows Server 2003 R2 to support Microsoft Services
If you were to use a tool such as ADSI Edit, you could see the
inheritance and class relationships quite clearly. For example, looking
objectClass attribute of any
user object, you would see that at a minimum, the values held in this
user. In other words, this attribute indicates
that each user object inherits attributes from all these classes.
Similarly, for any computer object, the
objectClass attribute holds
computer. If you were to look at the
subclassOf attribute on the
computer class object itself in the schema,
you would see the
user class. The
user class has a
subClassOf attribute that
so on. You can see this relationship in Figure 4-5.
Let’s now look at the
class in a little more depth. Using a tool like ADSIEdit, we can see the
values of each attribute for the user
classSchema object. Table 4-8 contains a partial
listing of the attributes and values.
Table 4-8. Partial listing of attributes and values for the user class
User attribute’s LDAP-Display-Name
User attribute’s syntax
Value contained in user’s attribute
SDDL text-encoded representation of the default security descriptor
Binary representation of the Security Descriptor for the class
cn=Class-Schema, cn=Schema, cn=Configuration, dc=mycorp, dc=com
<GUID> that uniquely identifies this class
Various attributes. See discussion.
You can learn the following about the user class by inspecting these attribute values:
The name of the class is User (
It is an instance of the
It inherits attributes from both
This object class has a security descriptor governing who can access and manipulate it (
A default Security Descriptor should be applied to new instances of the user class if one is not specified on creation (
The instances of the user class are visible in normal browsing (
The user class itself is not hidden from casual browsing (
userclass has an OID of 1.2.840.113522.214.171.124 (
It inherits attributes not only from
classSchemabut also from
posixAccountauxiliary classes can be associated with
The user class is a direct subclass of the
When connecting to instances of the class via LDAP, the two-letter prefix used should be
This class can be created directly under only three different parents in Active Directory (
The class is structural (
There are a large number of attributes that instances of the user class can have values for (
Let’s look at the
possSuperiors, and their system attribute
pairs. You can see that the only values set are
systemAuxiliaryClass. These were the values
set on the initial creation of the user class and cannot be changed.
Note that there were no mandatory attributes set at the creation of
the original class because the attribute
systemMustContain is not listed. If you
later wished to add an extra set of attributes or a new optional
attribute to the user class, you could use
mayContain and modify the base
definition. This occurs if, for example, you install the Exchange
schema updates in your forest. If you were to do this, the user class
would be directly modified to include three of these Exchange-related
auxiliary classes in the
Exchange is discussed in more detail in Chapter 19.
The attributes that are required when you create a new user are
not listed in the
mustContain attribute. That’s because
sAMAccountName, and the other attributes are inherited from other
classes that make up this one. The
mustContain attributes can be defined
systemAuxiliaryClass, or they can
be defined on the classes inherited from further up the tree. Both
objectSID, for example,
are defined on the
Do not mistake attributes that a class must contain with the attributes that you must explicitly set on object instantiation. Unfortunately there is no effective way to programmatically determine what attributes you need to set on an object when you create an instance of the class. Some of the attributes that an object must contain are system-owned and can only be set by the system; other attributes are optional and will be populated automatically; and finally some attributes are actually required to be specified by the objects creator. To confuse the situation even more, various versions of the OS or AD LDS change the requirements.
The same principle applies to the
mayContain attribute. The entire set of
these attributes is available only when you recurse back up the tree
and identify all the inherited
mayContain attributes on all inherited
on the other hand, can be made up of only those items defined directly
on the class, those defined on the class in the
subClassOf attribute, or any inherited
classes defined on any other
subClassOf attributes up the
subClassOf tree. If that was too confusing,
try this: an instance of the user class can have
itself, from the
organizationalPerson class defined in the
subClassOf attribute, from the
person class (the
subClassOf attribute), and from
top (the person class’s
Take a look at Figure 4-6. This shows the
user class viewed with the Active
Directory Schema snap-in. You can see the relevant general user
Notice that quite a bit of the user class is not configurable after the initial configuration, including:
To see the so-called relationship settings (
systemPossSuperiors), look at Figure 4-7. In this screen,
you can see that the user class in this schema is inheriting
attributes from the four auxiliary classes.
The third and final screen is the Attributes tab for the
user class and is displayed in
Figure 4-8. This
systemMayContain attributes of the
With Windows 2000, auxiliary classes were statically linked to
structural classes via the
systemAuxiliaryClass attributes. This went
against how most directory services implemented auxiliary classes, which
was typically allowing dynamically assigned auxiliary classes on
instances of objects. A new feature in Windows Server 2003 is the
ability to dynamically assign auxiliary classes to individual objects
instead of to an entire class of objects in the schema. Having the
dynamic auxiliary class mechanism provides much more flexibility for
application developers who may want to utilize existing structural and
auxiliary classes, but do not want to extend the schema to define such
Dynamic linking of auxiliary classes requires Windows Server 2003 Forest Functional Level, or higher.
To dynamically link an auxiliary class to an object, you only need
to modify the
objectClass attribute of the object to
include the name of the auxiliary class. Any auxiliary class can be
used, provided that all
contained within the auxiliary class are set at the same time. You can
also remove a dynamically linked auxiliary class by clearing any values
that have been set for attributes defined by the auxiliary class and
then removing the auxiliary class name from the object’s
Now let’s illustrate why dynamically linking auxiliary classes is
a good idea. Assume we have a forest with several domains, each
representing divisions within a company. Each division manages its own
user objects. One of the divisions, named Toasters, wants to assign
additional attributes to their user objects. These new attributes would
only apply to employees within the Toasters division. Under Windows
2000, the only way to accomplish this would be to create the new
attributes in the schema, create a new auxiliary class, and include the
new attributes in the auxiliary class. At that point, the new auxiliary
class could be added to the
auxiliaryClass of the user
classSchema object. That means every user
object contained within the forest would then have the new attributes
available. If each division wanted to do something similar, you can see
how the number of attributes on all user objects within the forest could
grow very quickly and unnecessarily. With Windows Server 2003, you would
still create the new attributes and auxiliary classes in the schema, but
you would not modify the
auxiliaryClass of the user object.
Instead, each division would dynamically link their auxiliary class to
their user objects. This provides for a cleaner and
much more efficient implementation than was possible under Windows
When you dynamically link an auxiliary class to an object, the
auxiliary class is listed in the
objectClass attribute for the object. When
an auxiliary class is statically linked, the auxiliary class is not
listed in the
This can cause issues with applications that determine available
attributes on an object and only look at the schema definitions of an
object class or at the
attribute of the object itself.
In this chapter, we’ve shown you how the internal blueprint for all objects in Active Directory, known as the schema, was derived from the X.500 directory service. We explained the purpose of the OID numbering system and how it can be used as well as the various elements that must be unique in an Active Directory schema extension such as prefix names and link IDs.
We then detailed how an attribute and its syntax are structured in
the schema as
as an example. We showed how attributes are added to classes by detailing
how classes are stored in the schema as instances of
classSchema objects. To make this clearer we dug
into the details of the user class to see how it was constructed. Finally,
we covered how auxiliary classes can be dynamically linked starting in
Windows Server 2003 and why it is significant.
Chapter 14 builds on what you’ve learned here to demonstrate how you can design and implement schema extensions.
 Names defined by the X.500 standard don’t tend to follow this method. For example, the Common-Name attribute has an LDAP-Display-Name of cn, and the Surname attribute has an LDAP-Display-Name of sn.