311 Table 10-2. Attributes of attributeSchema objects Attribute Description indexed and if it is used in ANR searches. systemFlags Integer representing additional properties of the attribute. Recipe 10.1 Registering the Active Directory Schema MMC Snap-in 10.1.1 Problem You want to use the Active Directory Schema snap-in for the first time on a computer. 10.1.2 Solution Before you can use the Active Directory Schema snap-in, you have to register the dynamic link library (DLL) associated with it. This can be done with the regsvr32 utility using the following command: > regsvr32 schmmgmt.dll If the command is successful, you'll see the following message: DllRegisterServer in schmmgmt.dll succeeded. 10.1.3 Discussion Most of the Active Directory MMC snap-ins do not require that you manually register the associated DLL. Microsoft requires this with the Active Directory Schema snap-in due to the sensitive nature of modifying the schema. This doesn't actually do much to prevent users from using it, but at least it isn't available by default. And regardless, only members of the Schema Admins group have permission to modify the schema anyway, so making this snap-in available should not pose much of a risk. The schmmgmt.dll file is installed as part of adminpak.msi or when a domain controller is promoted. If you want to use the Schema snap-in on a non-domain controller machine and you have not installed the adminpak.msi package, you'll need to specify the full path to schmmgmt.dll when using regsvr32, which can be found in the \i386 directory of a Windows Server CD. 312 10.1.4 See Also MS KB 320337 (HOW TO: Manage the Active Directory Schema in Windows 2000), and MS KB 326310 (HOW TO: Manage the Active Directory Schema in Windows Server 2003 Enterprise Edition) Recipe 10.2 Enabling Schema Updates This is necessary only when the Schema FSMO role owner is running Windows 2000. 10.2.1 Problem You want to enable schema modifications on the Schema FSMO. This is a necessary first step before you can extend the schema. 10.2.2 Solution 10.2.2.1 Using a graphical user interface 1. Open the Active Directory Schema snap-in. 2. Click on Active Directory Schema in the left pane. 3. Right-click on Active Directory Schema and select Operations Master. 4. Check the box beside Allow schema modifications. 5. Click OK. 10.2.2.2 Using a command-line interface To enable modifications to the schema, use the following command: > reg add HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTDS\Parameters /t[RETURN] REG_DWORD /v "Schema Update Allowed" /d 1 To disable modifications to the schema, use the following command: > reg delete HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTDS\Parameters /v[RETURN] "Schema Update Allowed" /f 10.2.2.3 Using VBScript ' This code enables or disables schema mods on Schema FSMO. ' SCRIPT CONFIGURATION ' TRUE to enable schema mods and FALSE to disable boolSetReg = TRUE 313 ' Name of the Schema FSMO or "." to run locally strDC = "<SchemaFSMOName>" ' END CONFIGURATION const HKEY_LOCAL_MACHINE = &H80000002 set objReg = GetObject("winmgmts:\\" & strDC & "\root\default:StdRegProv") strKeyPath = "System\CurrentControlSet\Services\NTDS\Parameters" strValueName = "Schema Update Allowed" if boolSetReg = TRUE then strValue = 1 intRC = objReg.SetDWORDValue(HKEY_LOCAL_MACHINE,strKeyPath, _ strValueName,strValue) if intRC > 0 then WScript.Echo "Error occurred: " & intRC else WScript.Echo strValueName & " value set to " & strValue end if else intRC = objReg.DeleteValue(HKEY_LOCAL_MACHINE,strKeyPath,strValueName) if intRC > 0 then WScript.Echo "Error occurred: " & intRC else WScript.Echo strValueName & " value deleted" end if end if 10.2.3 Discussion When the Schema FSMO role owner is running Windows 2000, you must explicitly enable schema modifications on the server before extending the schema. To enable this, you need to create a key value called Schema Update Allowed with a value of 1 under the following key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTDS\Parameters To disable schema modifications, set the value to 0 or delete it from the registry. This is no longer necessary when the Schema FSMO owner is running Windows Server 2003. Microsoft removed this registry hack as a requirement for extending the schema. 10.2.4 See Also MS KB 285172 (Schema Updates Require Write Access to Schema in Active Directory) 314 Recipe 10.3 Generating an OID to Use for a New Class or Attribute 10.3.1 Problem You want to generate an OID to use with a new class or attribute you intend to add to the schema. 10.3.2 Solution You have two options for generating an OID. First, you can generate a base OID off of the Microsoft OID tree. This can be done with the Oidgen.exe utility from the Resource Kit: > oidgen Attribute Base OID: 1.2.840.113556.1.4.7000.233.28688.28684.8.2849.956347.1967079.334190 Class Base OID: 1.2.840.113556.1.5.7000.111.28688.28684.8.370553.291204.940269.113484 Using Oidgen is really easy, but if you want to implement schema extensions for production use, I strongly suggest you consider using an OID from your company or organization's OID branch. To determine if your company already has an assigned OID, see these sites: http://www.iana.org/assignments/enterprise-numbers http://www.alvestrand.no/objectid/ If your organization does not have an assigned OID, go to your country's national registry to request one. The list of registries can be found at the following site: http://www.iso.ch/iso/en/aboutiso/isomembers/index.html. Once you have a base OID, you can create branches from that OID however you want. For example, if you had a base OID of 1.2.3.4, you could start new class OIDs under 1.2.3.4.1 and new attributes under 1.2.3.4.2. In that case, the first class OID you would create would be 1.2.3.4.1.1 and the first attribute OID would be 1.2.3.4.2.1. 10.3.3 Discussion An OID is nothing more than a string of numbers separated by dots (.). OIDs were initially defined by the ITU-T in X.208 and have been used to uniquely identify a variety of things including SNMP MIB objects and LDAP schema classes and attributes. OIDs are hierarchical, and the national registries are responsible for managing and assigning OID branches. 315 Recipe 10.4 Generating a GUID to Use for a New Class or Attribute 10.4.1 Problem You want to generate a GUID to use for the schemaIDGUID attribute of a new class or attribute you intend to add to the schema. 10.4.2 Solution There are several ways to go about generating a GUID. If you do not specify the schemaIDGUID when initially creating a class or attribute, one will automatically be generated for you. So you could add the class or attribute to the schema of a test forest, and then use the schemaIDGUID that was generated in that forest. You can also programmatically generate a GUID using Perl, VB, C++, or C#, but you cannot do it natively within VBScript. The Windows API supports a CoCreateGUID method that can be used to generate a GUID. If you are stuck with VBScript, you can wrap the CoCreateGUID method in an ActiveX DLL using VB and then use that DLL from within VBScript. Finally, you can use a tool such as uuidgen.exe, which is available in the Microsoft Platform SDK to generate GUIDs. Uuidgen doesn't require any parameters (although there are a few options that can be seen by running uuidgen -h), and it can generate as many GUIDs as you need. If you intend to use LDIF files for extending the schema (highly recommended), then you need to encode any GUIDs in base64 notation. This is necessary because GUIDs are stored as octet strings (binary data) in Active Directory. The LDIF specification requires any binary data to be encoded in base64. Again, VBScript does not support base64 encoding natively, but other languages like Perl have modules available that do. Here is an example Perl script that uses a combination of the uuidgen utility to generate a GUID, the Win32::Lanman module to convert the GUID to binary, and the MIME::Base64 module to encode it: #!perl use MIME::Base64; use Win32::Lanman; # Get the string GUID my $str_guid = `uuidgen.exe`; chomp $str_guid; # Convert to a binary GUID my $bin_guid = Win32::Lanman::StringToGuid($str_guid); # Base64 encode binary GUID my $b64_guid = encode_base64($bin_guid); print "$b64_guid\n"; 316 You can avoid using uuidgen.exe altogether by using the Win32::Guidgen module or Data::UUID (for Unix), both of which can generate text-based GUIDs. 10.4.3 Discussion The schemaIDGUID attribute defines the GUID or unique identifier for classes and attributes in the schema. It is a good practice to define this attribute in your schema extensions when creating new classes or attributes. This is especially true if the new class or attribute will be associated with any extended rights or property sets, which reference schema objects by GUID. If you do not explicitly set that value, the method you use for creating or modifying extended rights to use that class will have to dynamically determine the schemaIDGUID for each forest it is implemented in, which is not very clean. Recipe 10.5 Extending the Schema 10.5.1 Problem You want to extend the schema to support new classes and attributes in Active Directory. 10.5.2 Solution Extending the schema is a straightforward process, which consists of adding new classes or attributes, or modifying existing ones in the schema. While extending the schema is not hard, due to the sensitive nature of the schema, you should implement a schema extension process that thoroughly tests any extensions before you put them in your production forest. Here is a suggested summary of what your schema extension process should be: 1. Meet with clients and determine if there is a business justification for integrating their application with Active Directory. 2. Examine the extensions and determine what impact, if any, it will have on your Active Directory environment (e.g., adding an attribute to the global catalog). 3. Try out the extensions in a test environment. Observe any peculiarities. 4. Document the extensions. 5. Extend the schema in your production Active Directory. For more information on defining a schema extension process, see Chapter 12 of Active Directory, Second Edition (O'Reilly). 10.5.3 Discussion One thing to be cautious of when developing a schema extension process is not to make it an overly bureaucratic process that can require several weeks to complete. If that is the type of process you implement, you'll find that fewer people will want to integrate their applications with your Active Directory infrastructure. While some organizations may want to strictly limit 317 schema extensions, there is nothing inherently bad about extending the schema and it is one of the core features and advantages over Active Directory's predecessor—Windows NT 4.0. 10.5.4 See Also Recipe 10.7 for adding a new attribute, Recipe 10.9 for adding a new class, and MS KB 283791 (How to Modify Schema Information Using the Ldifde Utility) Recipe 10.6 Documenting Schema Extensions 10.6.1 Problem You want to document your schema extensions. 10.6.2 Solution There are several different ways you can document schema extensions. If you require LDIF files of the schema extensions before you extend the schema, you could use the files themselves as a simple self-documenting system. You can put comments in LDIF files by putting # at the beginning of a line. I personally prefer this option and recommend that any company that needs to extend the schema of their customer's Active Directory should include LDIF files, regardless of whether you use that method to actually extend the schema. Another fairly easy mechanism for documenting schema extensions is with the SchemaDoc program developed by Microsoft. SchemaDoc is a simple GUI program that lets you document classes and attributes that have already been added to Active Directory. The output for SchemaDoc is XML, which you can then use to create your own management interface for viewing the contents. SchemaDoc can be downloaded from the following site: http://www.microsoft.com/downloads/details.aspx?FamilyId=BEF87B1D-D2F1-4795- 88C5-CA66CFC3AB29&displaylang=en More information on SchemaDoc can be found here: http://www.microsoft.com/technet/prodtechnol/ad/windows2000/maintain/schema.asp 10.6.3 Discussion There are no hard and fast rules for documenting schema extensions. Documenting schema extensions in some fashion, even if rudimentary, should be a requirement of any schema extension process you adopt. If you have the resources and time, you can even develop a much more elaborate documentation system using the web or even an object-modeling system. 318 10.6.4 See Also RFC 2849 (The LDAP Data Interchange Format (LDIF)—Technical Specification) Recipe 10.7 Adding a New Attribute 10.7.1 Problem You want to add a new attribute to the schema. 10.7.2 Solution For Windows 2000 Active Directory you need to enable schema modifications before proceeding. See Recipe 10.2 for more information. 10.7.2.1 Using a graphical user interface 1. Open the Active Directory Schema snap-in. 2. In the left pane, right-click on the Attributes folder and select Create Attribute. 3. Click the Continue button to confirm that you want to extend the schema. 4. Enter the information for the new attribute. 5. Click OK. 10.7.2.2 Using a command-line interface You can create new attributes by using ldifde and an LDIF file that contains the properties to be set on the attribute. The following text shows an example LDIF file called create_attr.ldf that creates an attribute called rallencorp-LanguagesSpoken: dn: cn=rallencorp-LanguagesSpoken,cn=schema,cn=configuration,<ForestRootDN> changetype: add objectclass: attributeSchema lDAPDisplayName: rallencorp-LanguagesSpoken attributeId: 1.3.6.1.4.1.999.1.1.28.3 oMSyntax: 20 attributeSyntax: 2.5.5.4 isSingleValued: FALSE searchFlags: 1 description: "Languages a user speaks" Then run the following command: > ldifde -v -i -f create_attr.ldf 10.7.2.3 Using VBScript ' This code illustrates how to create an attribute ' called rallencorp-LanguagesSpoken 319 set objRootDSE = GetObject("LDAP://RootDSE") set objSchemaCont = GetObject("LDAP://" & _ objRootDSE.Get("schemaNamingContext") ) set objAttr = objSchemaCont.Create("attributeSchema", _ "cn=rallencorp-LanguagesSpoken") objAttr.Put "lDAPDisplayName", "rallencorp-LanguagesSpoken" objAttr.Put "attributeId", "1.3.6.1.4.1.999.1.1.28.3" objAttr.Put "oMSyntax", 20 objAttr.Put "attributeSyntax", "2.5.5.4" objAttr.Put "isSingleValued", FALSE objAttr.Put "description", "Languages a user speaks" objAttr.Put "searchFlags", 1 ' index the attribute objAttr.SetInfo WScript.Echo "Attribute created" 10.7.3 Discussion To create an attribute, you need to add an attributeSchema object to the Schema container. Typically, when you extend the schema, you perform several additions or modifications at once. The order of your extensions is very important. You can't create a class, assign an attribute, and then create the attribute; you obviously need to create the attribute before it can be assigned to the class. Even if you create the attribute before you assign it to a class, you must reload the schema before doing the class assignment. Reloading the schema is described in more detail in Recipe 10.22. Most of the attributes that can be set on attributeSchema objects are pretty straightforward, but a couple of them take a little explanation. The attributeSyntax and oMSyntax attributes together define the syntax, or the type of data that can be contained in the attribute. Table 10-3 shows the possible combinations of these two attributes and the resulting syntax. Table 10-3. attributeSyntax and oMSyntax combinations Name attributeSyntax oMSyntax Description AccessPointDN 2.5.5.14 127 Type of distinguished name taken from X.500. Boolean 2.5.5.8 1 TRUE or FALSE value. CaseExactString 2.5.5.3 27 Case-sensitive string. CaseIgnoreString 2.5.5.4 20 Case-insensitive string. DirectoryString 2.5.5.12 64 Case-insensitive Unicode string. DN 2.5.5.1 127 String representing a distinguished name. DNWithBinary 2.5.5.7 127 Octet string that has the following format: B:CharCount:BinaryValue:ObjectDN 320 Table 10-3. attributeSyntax and oMSyntax combinations Name attributeSyntax oMSyntax Description where CharCount is the number of hexadecimal digits in BinaryValue, BinaryValue is the hexadecimal representation of the binary value, and ObjectDN is a distinguished name. DNWithString 2.5.5.14 127 Octet string that contains a string value and a DN. A value with this syntax has the following format: S:CharCount:StringValue:ObjectDN where CharCount is the number of characters in the StringValue string, and ObjectDN is a distinguished name of an object in Active Directory. Enumeration 2.5.5.9 10 Defined in X.500 and treated as an integer. GeneralizedTime 2.5.5.11 24 Time string format defined by ASN.1 standards. See ISO 8601 and X.680. IA5String 2.5.5.5 22 Case-sensitive string containing characters from the IA5 character set. Integer 2.5.5.9 2 32-bit integer. Integer8 2.5.5.16 65 64-bit integer, also known as a large integer. NTSecurityDescriptor 2.5.5.15 66 Octet string that contains a security descriptor. NumericString 2.5.5.6 18 String that contains digits. OctetString 2.5.5.10 4 Array of bytes used to store binary data. OID 2.5.5.2 6 String that contains digits (0-9) and decimal points (.). ORName 2.5.5.7 127 Taken from X.400; used for X.400 to RFC 822 mapping. PresentationAddress 2.5.5.13 127 String that contains OSI presentation addresses. . the Active Directory Schema MMC Snap-in 10.1.1 Problem You want to use the Active Directory Schema snap-in for the first time on a computer. 10.1.2 Solution Before you can use the Active Directory. i386 directory of a Windows Server CD. 312 10.1.4 See Also MS KB 320337 (HOW TO: Manage the Active Directory Schema in Windows 2000), and MS KB 326310 (HOW TO: Manage the Active Directory. extensions. 5. Extend the schema in your production Active Directory. For more information on defining a schema extension process, see Chapter 12 of Active Directory, Second Edition (O'Reilly).