Schema classes are defined as instances of the classSchema
class. Table 4-6 shows the most important attributes that you may wish to set.
Table 4-6. The defining attributes of a classSchema object instance
Attribute |
Syntax |
Mandatory |
Multivalued |
Description |
---|---|---|---|---|
|
OID |
No |
Yes |
The list of Auxiliary (or 88-Class) classes that this object inherits attributes from. |
|
Unicode |
Yes |
No |
The Relative Distinguished Name (RDN). |
|
Boolean |
No |
No |
Whether the object should be hidden or displayed within the MMCs by default. |
|
Octet string |
No |
No |
The Security Descriptor to assign to new instances of this class. Note that this SD is applied to new instances of the class if and only if an SD is not specifically provided and set during the creation of the instance. |
|
Unicode string |
No |
No |
A description of the attribute. |
|
OID |
Yes |
No |
The OID that uniquely identifies objects of this class. |
|
Unicode |
No |
No |
The name by which LDAP clients identify this class. |
|
OID |
No |
Yes |
The list of attributes that are optional for this class. |
|
OID |
No |
Yes |
The list of attributes that are mandatory for this class. |
|
NT-Security Descriptor |
Yes |
Yes |
Security Descriptor on the |
|
Object |
Yes |
Yes |
The class that this object is an instance of; i.e., |
|
Integer |
Yes |
No |
0 = 88-Class 1 = Structural 2 = Abstract 3 = Auxiliary |
|
OID |
No |
Yes |
The list of classes that this object can be created within; e.g., user objects can be created within Organizational Unit objects. |
|
OID |
No |
No |
The attribute that indicates what two-letter-prefix ( |
|
Octet string |
Yes |
No |
Globally Unique Identifier (GUID) to uniquely identify this class. |
|
OID |
Yes |
No |
The class that this one inherits from; the default is |
|
OID |
No |
Yes |
System version of |
|
Integer |
No |
No |
Integer with bit flags that define additional properties for the class. |
|
OID |
No |
Yes |
System version of |
|
OID |
No |
Yes |
System version of |
|
Boolean |
No |
No |
If True, once the initial value has been set, only the system can create and modify instances of this class. The default is False. |
|
OID |
No |
Yes |
System version of |
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 seven special attributes, while the marketing user needs three. 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. It really is that simple.
Tip
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 spec. 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. For example, let's say that the Marketing-User and Finance-User were to be the first of a number of structural classes that had a common structure. In that case, you could create an abstract class to be used as the basis of other structural classes. Abstract classes can inherit from other classes, can have attributes defined on them directly, and in all other ways act like structural classes, except that instances of them cannot be directly created as objects in Active Directory.
- 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. It is 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.
Tip
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, which are used to create user and computer accounts, respectively, within Active Directory. The computer
class (OID: 1.2.840.113556.1.3.30) and user
class (OID: 1.2.840.113556.1.5.9) 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
abstract class (OID: 2.5.6.7). 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 (OID: 2.5.6.6), which is a subclass of the abstract top
class (OID: 2.5.6.0). There are no classes above top
; it is the root class.
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
and securityPrincipal
. 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.
Figure 4-4 indicates how the computer
class is made up from a number of other classes.
If you were to use a tool such as ADSIEdit, 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 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.
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-7 contains the attributes and values.
Table 4-7. Attributes and values for the user class
User attribute's LDAP-Display-Name |
User attribute's syntax |
Value contained in user's attribute |
---|---|---|
|
CASE_ IGNORE_ STRING |
User |
|
CASE_ IGNORE_ STRING |
User |
|
CASE_ IGNORE_ STRING |
User |
|
BOOLEAN |
False |
|
DN_STRING |
cn=person, cn=schema, cn=configuration, dc=mycorp, dc=com |
|
CASE_ IGNORE_ STRING |
SDDL text-encoded representation of the default security descriptor |
|
DN_STRING |
cn=User, cn=Schema, cn=Configuration, dc=mycorp, dc=com |
|
CASE_ IGNORE_ STRING |
1.2.840.113556.1.5.9 |
|
INTEGER |
4 |
|
CASE_ IGNORE_ STRING |
|
|
CASE_ IGNORE_ STRING |
User |
|
SECURITY_ DESCRIPTOR |
Binary representation of the Security Descriptor for the class |
|
DN_STRING |
cn=Class-Schema, cn=Schema, cn=Configuration, dc=mycorp, dc=com |
|
CASE_ IGNORE_ STRING |
|
|
INTEGER |
1 |
|
OCTET_ STRING |
<GUID> |
|
CASE_ IGNORE_ STRING |
|
|
OCTET_ STRING |
<GUID> that uniquely identifies this class |
|
BOOLEAN |
True |
|
CASE_ IGNORE_ STRING |
|
|
CASE_ IGNORE_ STRING |
|
|
INTEGER |
16 (Category 1 class) |
|
CASE_ IGNORE_ STRING |
Various attributes. See discussion. |
|
BOOLEAN |
False |
|
CASE_ IGNORE_ STRING |
|
|
LARGE_INTEGER |
USN when last changed |
|
LARGE_INTEGER |
USN when created |
|
UTC_TIME |
Time when last changed |
|
UTC_TIME |
Time when created |
You can see the following about the user class:
The name of the class is User (
adminDescription
,adminDisplayName
,cn
,name
).It is an instance of the
classSchema
class (objectCategory
andobjectClass
).It inherits attributes from both
top
andclassSchema
(objectClass
).This object class has a security descriptor governing who can access and manipulate it (
nTSecurityDescriptor
).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 can have instances created by anyone (
systemOnly
).It inherits attributes not only from
top
andclassSchema
but also fromsecurity-Principal
andmailRecipient
(objectClass
andsystemAuxiliaryClass
).When connecting to instances of the class via LDAP, the two-letter prefix used should be
cn
(rDNAttID
).The user class is a direct subclass of the
organizationalPerson
class (subClassOf
).This class can be created directly under only three different parents in Active Directory (
systemPossSuperiors
).The class is structural (
objectClassCategory
).A default Security Descriptor should be applied to new instances of the user class if one is not specified on creation (
defaultSecurityDescriptor
).There are a large number of attributes that instances of the user class can have values for (
systemMayContain
). Values include:
accountExpires
|
msDS-User-Account-Control-Computed
|
aCSPolicyName
|
msIIS-FTPDir
|
adminCount
|
msIIS-FTPRoot
|
badPasswordTime
|
mSMQDigests
|
badPwdCount
|
mSMQDigestsMig
|
businessCategory
|
mSMQSignCertificates
|
codePage
|
mSMQSignCertificatesMig
|
controlAccessRights
|
msNPAllowDialin
|
dBCSPwd
|
msNPCallingStationID
|
defaultClassStore
|
msNPSavedCallingStationID
|
desktopProfile
|
msRADIUSCallbackNumber
|
dynamicLDAPServer
|
msRADIUSFramedIPAddress
|
groupMembershipSAM
|
msRADIUSFramedRoute
|
groupPriority
|
msRADIUSServiceType
|
groupsToIgnore
|
msRASSavedCallbackNumber
|
homeDirectory
|
msRASSavedFramedIPAddress
|
homeDrive
|
msRASSavedFramedRoute
|
homePhone
|
networkAddress
|
initials
|
ntPwdHistory
|
lastLogoff
|
o
|
lastLogon
|
operatorCount
|
lastLogonTimestamp
|
otherLoginWorkstations
|
lmPwdHistory
|
pager
|
localeID
|
preferredOU
|
lockoutTime
|
primaryGroupID
|
logonCount
|
profilePath
|
logonHours
|
pwdLastSet
|
logonWorkstation
|
scriptPath
|
mail
|
servicePrincipalName
|
manager
|
terminalServer
|
maxStorage
|
unicodePwd
|
mobile
|
userAccountControl
|
mS-DS-CreatorSID
|
userCertificate
|
msCOM-UserPartitionSetLink
|
userParameters
|
msDRM-IdentityCertificate
|
userPrincipalName
|
msDS-Cached-Membership
|
userSharedFolder
|
msDS-Cached-Membership-Time-Stamp
|
userSharedFolderOther
|
msDS-Site-Affinity
|
userWorkstations
|
Let's look at the mustContain
, mayContain
, auxiliaryClass
, possSuperiors
, and their system attribute pairs. You can see that the only values that are 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 systemMustContain
attribute 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 use the Active Directory Connector (ADC
) to link your Active Directory and a Microsoft Exchange 5.5 schema. When you install the ADC for the first time in a forest, it extends the schema to include new Exchange objects and attributes, as well as modifying existing Active Directory objects to include new Exchange-relevant attributes. 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
, and msExchCertificateInformation
. The ADC is discussed more fully in Chapter 17.
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
, systemAuxiliaryClass
, or subClassOf
, 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 ADAM 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).
Take a look at Figure 4-5. This shows the user
class viewed with the Active Directory Schema snap-in. You can see the relevant general user data.
Notice that quite a bit of it 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
, systemAuxili-aryClass
, possSuperiors
, systemPossSuperiors
), look at Figure 4-6. In this screen, you can see that the user class in this schema is inheriting attributes from the two auxiliary classes.
The third and final screen is the Attributes tab for the user
class and is displayed in Figure 4-7. This shows the mustContain
, systemMustContain
, mayContain
, and system-MayContain
attributes of the user
class.
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 typically allowed 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.
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. 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
listing 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.
Get Active Directory, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.