Chapter 4. Active Directory Schema

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

Schema version

Release

13

Windows 2000

30

Windows Server 2003

31

Windows Server 2003 R2

44

Windows Server 2008

Structure of the Schema

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 cn=schema,cn=Configuration,dc=mycorp,dc=com. You 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.

Note

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: regsvr32 schmmgmt.dll.

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 attributeSchema (Attribute-Schema) objects. The two distinct forms of the same names result from the fact that the cn (Common-Name) attribute of a class contains the hyphenated easy-to-read name of the class, and the lDAPDisplayName (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 lDAPDisplayName 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.[3] This creates simple names like user, as well as the more unusual sAMAccountName and 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.

X.500 and the OID Namespace

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.

To that end, the X.500 standard defined an Object Identifier (OID) to uniquely identify every schema object. This OID is composed of two parts:

  • 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:

1.3.6.1.4.1.3385.12.497

This uniquely references object 497 in branch 1.3.6.1.4.1.3385.12. The 1.3.6.1.4.1.3385.12 branch is contained in a branch whose OID is 1.3.6.1.4.1.3385, and so on.

Note

Each branch within an OID number also corresponds to a name. This means that the dotted notation 1.3.6.1.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 1.3.6.1.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 1.3.6.1.4.1.311. Leicester University’s OID namespace is 1.3.6.1.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.

Note

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 1.3.6.1.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.

Note

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: mycorpAttrib1 and mycorpAttrib2. MyCorp Financial purchases a software package from another company, MyCorp Software Solutions, who also chose to use attribute names of mycorpAttrib1 and mycorpAttrib2.

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 1.3.6.1.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 1.3.6.1.4.1. 3385.3.5.

Warning

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 for the printQueue class, we get Figure 4-1. You can see that the unique OID is 1.2.840.113556.1.5.23. This tells us that the number is a defined part of Microsoft’s object class hierarchy.

printQueue Schema class properties

Figure 4-1. printQueue Schema class properties

Figure 4-2 shows the property page for the organizationalPerson class. Here, you can see that the unique OID 2.5.6.7 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.

Note

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.

organizationalPerson Schema class properties

Figure 4-2. organizationalPerson Schema class properties

Attributes (attributeSchema Objects)

Just as class information is stored in Active Directory as instances of the class called classSchema, attributes are represented by instances of the class called attributeSchema. As with all objects, the attributeSchema class has a number of attributes that can be set when specifying a new instance. The attributeSchema class inherits attributes from the class called top. 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.

Dissecting an Example Active Directory Attribute

The userPrincipalName (UPN) 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 or , or even . In fact, any UPN suffix, such as , 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.

Note

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 userPrincipalName attributeSchema instance.

Table 4-2. userPrincipalName’s attributes

Attribute lDAPDisplayName

Attribute syntax

Attribute value

adminDescription

CASE_IGNORE_STRING

User-Principal-Name

adminDisplayName

CASE_IGNORE_STRING

User-Principal-Name

attributeID

CASE_IGNORE_STRING

1.2.840.113556.1.4.656

attributeSyntax

CASE_IGNORE_STRING

2.5.5.12

cn

CASE_IGNORE_STRING

User-Principal-Name

isMemberOfPartialAttributeSet

BOOLEAN

True

isSingleValued

BOOLEAN

True

lDAPDisplayName

CASE_IGNORE_STRING

userPrincipalName

name

CASE_IGNORE_STRING

User-Principal-Name

objectCategory

DN_STRING

cn=Attribute-Schema, cn=Schema, cn=Configuration, dc=mycorp,dc=com

objectClass

CASE_IGNORE_STRING

top; attributeSchema (two values of a multivalued attribute)

oMSyntax

INTEGER

64

searchFlags

INTEGER

1 (Indexed)

showInAdvancedViewOnly

BOOLEAN

True

systemFlags

INTEGER

18 (Category 1 attribute, replicated to GC)

systemOnly

BOOLEAN

False

We can see that the name of the attribute is User-Principal-Name (adminDescription, adminDisplayName, cn, name), that it is an instance of the attributeSchema class (ob-jectCategory and objectClass), that it inherits attributes from both top and attributeSchema (objectClass), and that the UPN attribute is not visible to casual browsing (showInAdvancedViewOnly).

The userPrincipalName attributes show the following:

  • It is to be stored in the GC (isMemberOfPartialAttributeSet and systemFlags).

  • It is to be indexed (searchFlags).

  • It has an OID of 1.2.840.113556.1.4.656 (attributeID).

  • We should use userPrincipalName (lDAPDisplayName) when binding to it with ADSI.

  • Instances can be created by anyone (systemOnly).

  • It stores single (isSingleValued) Unicode strings (attributeSyntax and oMSyntax).

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.

Attribute Properties

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 UPN attribute as viewed by the Active Directory Schema snap-in

Figure 4-3. The UPN attribute as viewed by the Active Directory Schema snap-in

Attribute Syntax

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

Syntax

OID

OM syntax

Description

Address

2.5.5.13

127

Used internally by the system.

Boolean

2.5.5.8

1

True or false.

Case-insensitive string

2.5.5.4

20

A string that does not differentiate between uppercase and lowercase.

Case-sensitive string

2.5.5.3

27

A string that differentiates between uppercase and lowercase.

Distinguished name

2.5.5.1

127

The Fully Qualified Domain Name (FQDN) of an object in Active Directory.

DN-Binary

2.5.5.7

127

Octet string with binary value and DN. Format: B:<char count>:<binary value>:<object DN>.

DN-String

2.5.5.14

127

Octet string with string value and DN. Format: S:<char count>:<string value>:<object DN>.

Generalized-Time

2.5.5.11

24

ASN1.1 time format, e.g., 20040625234417.0Z.

Integer (enumeration)

2.5.5.9

10

A 32-bit number.

Integer (integer)

2.5.5.9

2

A 32-bit number.

Large integer

2.5.5.16

65

A 64-bit number.

NT Security Descriptor

2.5.5.15

66

A Security Descriptor (SD).

Numeric string

2.5.5.6

18

A string of digits.

Object ID

2.5.5.2

6

OID.

Octet string (Octet-String)

2.5.5.10

4

A byte string.

Print case string (IA5-String)

2.5.5.5

22

A normal printable string.

Print case string (Printable-String)

2.5.5.5

19

A normal printable string.

Replica-Link

2.5.5.10

127

Replication information.

SID

2.5.5.17

4

A security identifier (SID).

Undefined

2.5.5.0

N/A

Not a valid syntax.

Unicode

2.5.5.12

64

A wide string.

UTC-Time

2.5.5.11

23

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 userPrincipalName attribute has an attributeSyntax of 2.5.5.12 and an oMSyntax of 64, so it must contain Unicode strings.

System Flags

The 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 systemFlags 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 values for systemFlags on attributeSchema and classSchema objects. A complete listing of valid systemFlags settings 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

Value

Description

1 (0x0001)

Attribute is not replicated.

2 (0x0002)

Attribute will be replicated to the global catalog. This value should only be set by Microsoft; do not use. Instead, use isMemberOfPartialAttributeSet attribute for adding attributes to PAS.

4 (0x0004)

Attribute is constructed, not stored in the database. This should only be set by Microsoft; do not use.

16 (0x0010)

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.

134217728 (0x08000000)

The schema object cannot be renamed.

Constructed attributes

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 aNR is 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., tokenGroups can only be returned with a BASE scope query.

Category 1 objects

Category 1 objects are a subset of the attributes and classes that come with AD LDS or Active Directory. They are marked with a special bit flag so that Microsoft can track and protect them from certain types of modifications.

Schema FlagsEx

The 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.

Table 4-5. schemaFlagsEx values

Bit Number

Value

Description

1

1 (0x1)

Marks an attribute as critical. Critical attributes cannot be added to the filtered attribute set regardless of the value of the tenth bit of the searchFlags attribute.

Search Flags

The 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 the name, searchFlags is similar to systemFlags in that it is a series of bits representing how the attribute should be handled. Unlike systemFlags, 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

Bit Number

Value

Description

1

1 (0x0001)

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.

2

2 (0x0002)

Create an index for the attribute in each container. This is only useful for one-level LDAP queries.

3

4 (0x0004)

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.

4

8 (0x0008)

Preserve this attribute in a tombstone object. This flag controls what attributes are kept when an object is deleted.

5

16 (0x0010)

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.

6

32 (0x0020)

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 search (drink=*coke) would match Cherry Coke, Diet Coke, etc. This flag requires Windows Server 2003 or ADAM V1.0.

7

64 (0x0040)

Create subtree index. This index is only available in ADAM R2 or newer and is designed to increase performance of VLV queries. See the section ADAM Schema” in Chapter 20.

8

128 (0x0080)

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.

9

256 (0x0100)

Never audit changes to this attribute. This flag is new in Windows Server 2008. Windows Server 2008 auditing enhancements are covered in Chapter 13.

10

512 (0x0200)

Include this attribute in the RODC filtered attribute set. RODCs and the filtered attribute set are covered in Chapter 7.

Indexed attributes

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 searchFlags 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 systemFlags or userAccountControl attributes.

  • 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 objectClass attribute 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, objectClass is indexed as part of this schema extension.

    Windows Server 2008 domain controllers implement a special behavior that indexes objectClass by default regardless of the searchFlags setting 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 objectclass when 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

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.

Preserve attribute in tombstone

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.

Note

Administrators can modify the tombstone lifetime for a forest by changing the tombstoneLifetime attribute of the CN=Directory Service, CN=Windows NT, CN=Services,CN=Configuration,DC=mycorp,DC=com object.

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 reanimated.

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.

Table 4-7. Tombstone lifetime values for new forests

Operating system

Tombstone lifetime

Windows 2000

60 days

Windows Server 2003

180 days

Windows Server 2003 R2

60 days (this was a regression bug in R2)

Windows Server 2003 SP2

180 days

Windows Server 2008

180 days

Tuple index

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.

Confidential

A new bit for the searchFlags 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.

Note

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.

Note

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.

Attribute change auditing

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.

Filtered attribute set

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 toggling bit 0x100, you should toggle bit 0x200.

Warning

You cannot include attributes that are defined as critical in the schemaFlagsEx attribute in the filtered attribute set.

Property Sets and attributeSecurityGUID

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 controlAccessRight 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 rightsGuid. The appliesTo attribute is the string representation of the schemaIDGUID attribute of the classSchema objects 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.

Linked Attributes

Microsoft allows distinguished name attributes with attributeSyntax values of 2.5.5.1, 2.5.5.7, and 2.5.5.14 to be linked to attributes with an attributeSyntax of 2.5.5.1. These are called linked attributes and consist of a forward link and a back link. An example of a pair of linked attributes is member and memberOf.

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 linkID 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 to request unique link IDs.

In order to auto-generate link ID pairs, there are four steps you must follow:

  1. Create the forward link attribute and populate the linkID attribute with the value 1.2.840.113556.1.2.50.

  2. Reload the schema cache.

  3. Create the back link attribute and populate the linkID attribute with the lDAPDisplayName of the forward link attribute you created in step 1.

  4. Reload the schema cache.

Classes (classSchema Objects)

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.

Object Class Category and Inheritance

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 the original 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.

Marketing and Finance subclasses

Figure 4-4. Marketing and Finance subclasses

Note

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 objectClassCategory: structural, abstract, and auxiliary:

Structural

If a class is structural, you can directly create objects of its type in Active Directory. The user and group classes are examples of structural classes.

Abstract

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.

Auxiliary

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.

Note

To comply with the X.500 standards, there are actually four types of objectClassCategory. While 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 88-Class.

Let’s take a look at the user and 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 Directory. The computer class inherits from the user class, so the computer class is a special type of user in a way. The user class 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 computer and user classes themselves, but also all the attributes that are inherited from the organizationalPerson class. The organizationalPerson class is a subclass of the person abstract class, which is a subclass of the abstract top class. Recall that there are no classes above top; it is the root class. This relationship is outlined in Figure 4-5.

The 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, securityPrincipal, posixAccount, and shadowAccount. 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 needed. The shadowAccount and posixAccount auxiliary classes were added in Windows Server 2003 R2 to support Microsoft Services for UNIX.

If you were to use a tool such as ADSI Edit, you could see the inheritance and class relationships quite clearly. For example, looking at the objectClass attribute of any user object, you would see that at a minimum, the values held in this attribute were top, person, organizationalPerson, and 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 top, person, organizationalPerson, user, and 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 indicates organizationalPerson, and so on. You can see this relationship in Figure 4-5.

The computer class

Figure 4-5. The computer class

Dissecting an Example Active Directory Class

Let’s now look at the user 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

adminDescription

CASE_IGNORE_STRING

User

adminDisplayName

CASE_IGNORE_STRING

User

auxiliaryClass

CASE_IGNORE_STRING

posixAccount shadowAccount

cn

CASE_IGNORE_STRING

User

defaultHidingValue

BOOLEAN

False

defaultSecurityDescriptor

CASE_IGNORE_STRING

SDDL text-encoded representation of the default security descriptor

governsID

CASE_IGNORE_STRING

1.2.840.113556.1.5.9

lDAPDisplayName

CASE_IGNORE_STRING

user

name

CASE_IGNORE_STRING

User

nTSecurityDescriptor

SECURITY_DESCRIPTOR

Binary representation of the Security Descriptor for the class

objectCategory

DN_STRING

cn=Class-Schema, cn=Schema, cn=Configuration, dc=mycorp, dc=com

objectClass

CASE_IGNORE_STRING

top; classSchema (two values of a multivalued attribute)

objectClassCategory

INTEGER

1

rDNAttID

CASE_IGNORE_STRING

cn

schemaIDGUID

OCTET_STRING

<GUID> that uniquely identifies this class

showInAdvancedViewOnly

BOOLEAN

True

subClassOf

CASE_IGNORE_STRING

organizationalPerson

systemAuxiliaryClass

CASE_IGNORE_STRING

securityPrincipal mailRecipient

systemMayContain

CASE_IGNORE_STRING

Various attributes. See discussion.

systemPossSuperiors

CASE_IGNORE_STRING

builtinDomain organizationalUnit domainDNS

You can learn the following about the user class by inspecting these attribute values:

  • The name of the class is User (adminDescription, adminDisplayName, cn, name).

  • It is an instance of the classSchema class (objectCategory and objectClass).

  • It inherits attributes from both top and classSchema (objectClass).

  • This object class has a security descriptor governing who can access and manipulate it (nTSecurityDescriptor).

  • A default Security Descriptor should be applied to new instances of the user class if one is not specified on creation (defaultSecurityDescriptor).

  • The instances of the user class are visible in normal browsing (defaultHidingValue).

  • The user class itself is not hidden from casual browsing (showInAdvancedViewOnly).

  • The user class has an OID of 1.2.840.113556.1.5.9 (governsID).

  • It inherits attributes not only from top and classSchema but also from security-Principal and mailRecipient (objectClass and systemAuxiliaryClass).

  • The shadowAccount and posixAccount auxiliary classes can be associated with user objects.

  • The user class is a direct subclass of the organizationalPerson class (subClassOf).

  • When connecting to instances of the class via LDAP, the two-letter prefix used should be cn (rDNAttID).

  • This class can be created directly under only three different parents in Active Directory (systemPossSuperiors).

  • The class is structural (objectClassCategory).

  • There are a large number of attributes that instances of the user class can have values for (systemMayContain).

How inheritance affects mustContain, mayContain, possSuperiors, and auxiliaryClass

Let’s look at the mustContain, mayContain, auxiliaryClass, possSuperiors, and their system attribute pairs. You can see that the only values set are systemPossSuperiors, systemMayContain, and 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 auxiliaryClass or 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 auxiliaryClass attribute:

  • msExchMailStorage

  • msExchCustomAttributes

  • msExchCertificateInformation

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 objectSID, sAMAccountName, and the other attributes are inherited from other classes that make up this one. The mustContain attributes can be defined directly in auxiliaryClass or systemAuxiliaryClass, or they can be defined on the classes inherited from further up the tree. Both sAMAccountName and objectSID, for example, are defined on the securityPrincipal class.

Warning

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 classes.

The possSuperiors attribute, 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 possSuperiors from itself, from the organizationalPerson class defined in the subClassOf attribute, from the person class (the organizationalPerson class’s subClassOf attribute), and from top (the person class’s subClassOf attribute).

Viewing the user class with the Active Directory Schema snap-in

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 data.

User class schema entry general settings

Figure 4-6. User class schema entry general settings

User class schema entry relationship settings

Figure 4-7. User class schema entry relationship settings

Notice that quite a bit of the user class is not configurable after the initial configuration, including:

  • governsID

  • subClassOf

  • schemaIDGUID

  • systemMustContain

  • rDNAttID

  • systemPossSuperiors

  • objectClassCategory

  • systemMayContain

  • systemOnly

  • systemAuxiliaryClass

  • objectClass

  • subClassOf

To see the so-called relationship settings (subClassOf, auxiliaryClass, possSuperiors, systemAuxiliaryClass, 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 shows the mustContain, systemMustContain, mayContain, and systemMayContain attributes of the user class.

Dynamically Linked Auxiliary Classes

With Windows 2000, auxiliary classes were statically linked to structural classes via the auxiliaryClass and 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 relationships.

User class schema entry attribute settings

Figure 4-8. User class schema entry attribute settings

Warning

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 mustContain and systemMustContain attributes 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 objectClass attribute.

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 2000.

Warning

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 objectClass listing. 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 objectClass attribute of the object itself.

Summary

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 attributeSchema objects, using the userPrincipalName attribute 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.



[3] 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.

Get Active Directory, 4th Edition now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.