There are three basic "standard" tools that can be used for browsing Active Directory and editing the properties of directory objects.
ADSI Edit snap-in — from the Support Tools or Windows Administration Tools packs. This snap-in was discussed in Chapter 7, "Domain Manipulation Tools". It does not display all directory objects and attributes, but has a simple user interface and a flexible mechanism of custom query views. It provides you with access to all Active Directory partitions (including application partitions) as well as Global Catalog and offers a standard way of working with permissions on objects. Works with the LDAP protocol only.
Active Directory Browser (AdsVw.exe) — from the Active Directory Service Interfaces Software Development Kit (ADSI SDK). The only tool that is able to work with both the LDAP and WinNT protocols. It therefore allows you to work with AD- and Windows NT-based domains simultaneously. It is not well-documented and requires a solid understanding of Active Directory. Works with security descriptors.
Active Directory Administration Tool (Ldp.exe) — from the Support Tools. The most sophisticated tool for manipulating directory objects with the LDAP protocol. It requires extensive knowledge of LDAP basics (naming, queries, etc.) as well as Active Directory architecture. Works with security descriptors and Active Directory replication metadata.
These utilities can be regarded as "mandatory" tools set for troubleshooting various directory problems, and especially for composing your own administrative scripts or designing Active Directory-oriented applications.
In addition, Windows .NET-based domain controllers offer two powerful command-line utilities — DsGet.exe and DsMod.exe — that are useful for batch modifications of directory objects.
Unfortunately, among the above-mentioned tools, only the ADSI Edit snap-in works with non-Latin Unicode names of objects without any problems. The limitations of the other two tools are discussed in the appropriate sections.
If you need to work with objects' GUIDs (the objectGUID attribute), use Ldp.exe or DsQuery.exe, since the other two tools (AdsVw.exe and ADSI Edit) display a GUID as a binary value (octet string), which cannot be used for binding, referring, etc.
The Active Directory Browser is included in the ADSI SDK (also known as Active Directory SDK) that you can download from the Microsoft website (see links in Appendix A).
The main peculiarity of the Active Directory Browser is its ability to work with both Windows NT 4.0 and AD-based (Windows 2000 and Windows .NET) domains (see Figs. 12.1 and 12.2). Moreover, this is the only browsing tool that has multiple-document interface (MDI), which allows you to open separate windows for different objects or queries, organize them in the main window, and, therefore, simultaneously work with many directory objects, either in the same domain or in a few domains.
Fig. 12.1: Browsing the flat directory object namespace of a Windows NT 4.0 domain
Fig. 12.2: Browsing the object tree of a AD-based domain
Unfortunately, this tool is not documented. That is why we will consider some basic features in detail, since many of the tool's options are not obvious.
When AdsVw.exe runs on Windows 2000-based computers, it displays a non-Latin Unicode name as a sequence of the question (?) characters. If the LDAP provider is used, distinguished names as well as RDNs with non-Latin coding are also displayed as strings made up of "?". On Windows .NET-based computers, AdsVw.exe works properly within both Windows 2000 and Windows .NET domains.
The tool provides child windows of two types.
ObjectViewer — a two-pane window, in which you can navigate the object tree and view/edit their values (see Figs. 12.1 and 12.2). If the current user doesn't have permissions to access a property, the "???" string is displayed instead of the property's value.
Query — a table form (see Fig. 12.5) that consists of the selected attributes for the objects found in accordance with the specified query string (an LDAP filter or SQL query).
Fig. 12.5: A sample query
To open a new browsing window, press the <Ctrl>+<N> keys, select ObjectViewer in the opened window, and fill in the Enter ADs path field (Fig. 12.3). (Remember that you can include the name of a specific server in the directory path.)
Fig. 12.3: Basic information for a new browsing session
To use credentials different from those of the last connected user, check the Use OpenObject and Secure Authentication boxes, and fill in the Open As and Password fields.
Some attributes, such as primaryGroupToken, can be viewed only if you have checked the Use Extended Syntax box.
The mandatory attributes of an object are shown first in the Properties list (see Figs. 12.1 and 12.2) and are followed by the optional attributes in alphabetical order.
The results of a sample query are shown in Fig. 12.5. To start a query, press the <Ctrl>+<N+ keys, select Query in the opened window, and fill in all fields in the Edit Query window (Fig. 12.4). All attribute names must be explicitly specified. Click OK. You may leave all fields in the next window (Set Search Preferences) empty. (You will understand the meaning of the parameters presented in this window better if you read the section about the Ldp.exe tool later in this chapter, and about searching Active Directory in Chapter 16, "Active Directory Service Interfaces (ADSI).")
Fig. 12.4: Preparing a sample query: finding all OUs in the domain
You may use the privileges of the currently logged user when browsing directory objects (using either protocol), but you must always provide valid credentials while creating a new query. Otherwise the query will be unauthenticated (and therefore very restricted), and the result set will most probably be empty.
The window with the result set for the sample query is shown in Fig. 12.5.
If the result set does not fit the window, you must scroll down all lines (using the down arrow button) to see the entire set for the first time.
Active Directory Administration Tool (Ldp.exe) is a GUI tool, which allows you to query, browse, and modify LDAP-compliant directories (servers) via the LDAP protocol. The tool allows an administrator to access information that cannot be derived with the help of other tools, as well as to compose sophisticated and powerful queries with various scopes.
The Windows .NET version of Ldp.exe works properly within both Windows 2000- and Windows .NET-based domains, but cannot run on Windows 2000 systems. The Windows 2000 version of Ldp.exe fails to display Unicode names in non-Latin coding and the contents of directory containers with similar names. Both in tree-browsing mode and when search operations are performed, Ldp.exe always displays all non-Latin Unicode values of attributes in string format in the form of <ldp: Binary blob>.
To work with an LDAP server, the user must perform two primary operations — connecting and binding. (Connectionless operations and operations without binding (authenticating) are extremely restricted.) The information necessary for both operations is shown in Fig. 12.6.
Fig. 12.6: Connecting and binding to a LDAP server
The Server field in the Connect window can contain a server's DNS name or IP address as well as a domain DNS name. By default, port 389 is used for the LDAP protocol, and port 3268 is designated for Global Catalog. If you leave the Server field blank when working on an AD-based domain client computer, a connection is made to your logon DC (LOGONSERVER). (To work with Ldp.exe in an AD-based environment, you must be logged onto a forest.) If the User and Password fields in the Bind window are left blank, the credentials of the user who is currently logged on are used.
If the connection is successful, the information about the RootDSE object — base DSA information — is displayed. After binding, you can make queries and/or browse the object tree (click Tree in the View menu) (Fig. 12.7).
Fig. 12.7: Connecting to an Active Directory server (Windows 2000- or Windows .NET-based domain controller) and viewing the object tree of the domain
As shown in Fig. 12.7, the tool's window is divided into two panes: the tree pane (left) and the result pane (right). To explode a node in the object tree, simply click on it twice. Which objects are displayed in the result pane depends on the privileges of the user whose credentials you entered while binding to the server.
The tool's basic options are defined in the General Options window. To open it, click General in the Options menu (Fig. 12.8).
Fig. 12.8: Default general options
In some specific cases, you may want the values of found attributes to be displayed in binary format. Select the Binary switch and, instead of the default string representation of an attribute, you will get its "low-level" value. For instance, the string format may look like:
1> whenCreated: 3/15/2002 8:38:45 Central Standard Time Central Daylight Time;
The binary format will be:
1> whenCreated: 32 30 30 32 30 33 31 35 31 34 33 38 34 35 2e 30 20020315143845.0 5a Z
You can select the version of LDAP protocol only before the connection is made. After this, both switches in the LDAP Version group are grayed.
Checking this box enables the display of the RootDSE information when connecting to a LDAP server. Besides, if this box is checked, the current domain context name is automatically used as the base DN when the tree view is selected. Otherwise, you must always specify a DN of a container.
Virtual List View is a new feature of Windows .NET systems that support a pair of appropriate LDAP controls (namely, 2.16.840.1.1137188.8.131.52 and 2.16.840.1.1137184.108.40.206). The feature is designed for retrieving information from queries that produce very large result sets. The user can only obtain a predefined number of sorted rows produced by a query rather than the entire result set that can count thousands of rows. Depending on the data received, the user can re-define the query and repeat the search until the necessary information will be obtained. In the Ldp tool, this feature is realized as a special window that can be opened either automatically (if you check the Auto VLV browse when box) or manually (if you select the Virtual List View command in the Browse menu). In the former case, the Virtual List View window opens when you try to view (in tree mode) contents of a directory object that comprises more child objects than is specified (by default, 100). The methods of working with this window do not depend on how it is opened. An example of the window is shown in Fig. 12.9.
Fig. 12.9: An example view of the Virtual List View window
The Virtual List View window resembles the Search window except for the data pane that displays specified attributes of found objects in a tabular form. The new portions of data will be requested as you scroll down the table rows. The Type Name or Select from List field allows you to enter an object name, which the requested server will try to find within the defined query. A few rows before that object and a few rows after that object will only be sent to the client and displayed in the table. To see the children of a found object, click twice on the corresponding row. You can right click on an object and select for it a standard LDAP operation in the context menu (see Fig. 12.9).
In the DN Processing group you can indicate how the tool will display the distinguished names of the objects found. All options are listed below with sample strings.
>> Dn: CN=Administrator, OU=ADMINs, DC=net, DC=dom >> Dn: CN=Certificate Templates, CN=Public Key Services, CN=Services, CN=Configuration, DC=net, DC=dom
>> Dn: CN=Administrator; OU=ADMINs; DC=net; DC=dom; >> Dn: CN=Certificate Templates; CN=Public Key Services; CN=Services; CN=Configuration; DC=net; DC=dom;
>> Dn: Administrator; ADMINs; net; dom; >> Dn: Certificate Templates; Public Key Services; Services; Configration; net; dom;
>> Dn: CN=Administrator, OU=ADMINs, DC=net, DC=dom >> Dn: CN=CertificateTemplates, CN=PublicKeyServices, CN=Services, CN=Configuration, DC=net, DC=dom
Notice that in the last case there are no spaces in RDNs.
The Number of lines parameter sets the number of rows displayed in the result pane before wrapping begins. Do not forget that you cannot obtain more rows in a query than the MaxPageSize value in the query policy permits.
The Chars per line parameter sets the maximum number of characters displayed in a line. Lines whose length exceeds this value are truncated!
In practice, referrals are very important in search operations, as they may greatly influence the results. The Chase referrals box in the Search Options window (see Fig. 12.12, left) determines whether or not the server generates LDAP referrals when trying to find objects. (By default, the box is not checked, since this improves the performance of the search.) However, in some cases, if this box is checked, an error can occur:
Error: Search: Referral. <10> Result <10>: 0000202B: RefErr: ...
Some other scenarios in which you may get an unexpected result are also possible. Therefore, it is necessary to select the status of this checkbox carefully. Let us discuss this issue using two examples.
Suppose you are logged onto a computer joined to a child domain, and want to search the parent domain (or a domain from another domain tree) by entering its DN as the base of the search. You must either make an LDAP connection to a DC in the parent domain or enable chasing referrals. (Otherwise, the referral error will be reported.) Why referrals should help in such a situation will become clear a bit later. (Maybe you already understand what happens.)
Let us go to the second example. Suppose, for instance, you are searching your own domain for referrals objects or DSA objects. The (objectClass=crossRef) or (cn=NTDS Settings) filter strings, respectively, can be used for this purpose. The domain DN is specified as the base of the search.
Without the Chase referrals box checked, you will get an empty result set. Maybe you have forgotten, or did not initially know, that required objects are stored in the Configuration namespace (directory partition). Furthermore, remember that the search is performed in one namespace only unless you enable generating referrals. The above-described search operation will be successful if you have done one of the following: either directly specified the appropriate name context as the base of the search or enabled generation of referrals.
If the Chase referrals box is checked, the search is performed:
Within all partitions stored on a server
Within the domain partitions of all child domains, to which the referrals are directed
(There are also other search options, but it is more difficult to configure them. You can find additional information in the MSDN Library — look for "Extended Controls".)
Turning to the first example, it is clear now that if a server finds an object that refers to another domain and cannot (is not allowed to) connect to the server that stores the corresponding partition, it will generate a referral error message.
The problem of cross-domain (cross-partition, and cross-tree) searching can also be resolved by using a connection over the Global Catalog (3268) port. This might even be a more appropriate way. Do not forget, however, that not all attributes are replicated to GC.
Sometimes, a requested server can return a number of rows that exceed the MaxPageSize value. (Do not confuse the number of rows returned by a server on a request and the number of rows that the tool can display in the result pane — the Number of lines parameter.) The following error will be reported:
Error: Search: Size Limit Exceeded. <4> Result <4>: [null]
In such a case, it is necessary to use paging search results. You can request the results in pages of a specific size. Open the Search Options window (see Fig. 12.12; left) and select the Paged switch in the Search Call Type group. The Page size value defines the length of the page. Now you will get the results of a search operation in 16- row pages (by default):
Result <0>: Matched DNs: Getting 16 entries: ... -=>> 'Run' for more, 'Close' to abandon <<=-
Fig. 12.12: Configuring the search options for deleted objects
You can continue searching by clicking Run, or you can terminate the operation at any moment. When paging is used, you need not worry about how long the result of a search is.
The Windows .NET version of Ldp.exe has a new option that allows you to obtain additional information about some LDAP operation errors. Suppose you try to connect to a DC and see the following messages:
1d = ldap_open("netdc2.net.dom", 389); Error <0x51>: Fail to connect to netdc2.net.dom.
If you select the GetLastError command in the Browse menu, the tool will display the message:
0x51=LdapGetLastError () Server Down
Sometimes this additional information can be valuable for understanding an error that has occurred.
To clear the result pane before a new operation, click New on the Connection menu or press <Ctrl>+<N+ keys. Any information displayed in this pane can be copied- and-pasted.
At any moment, you may save the contents of the result pane by selecting Save or Save As from the Connection menu. (You need not close the Search window.) The latter option always asks you for a file name. The former option allows you to save information in the current output file, and asks for a file name only after the tool starts or a New command has been performed.
You may look up all domains and DCs in the forest in tree form. Click Enterprise Configuration in the View menu. Click Refresh in the window that is open. After some time, the actual configuration of your enterprise will be displayed in the window (Fig. 12.10). You can get the configuration only after binding to a DC.
Fig. 12.10: In this window, you can see the entire domain structure (the forest) and the state of all DCs
As Fig. 12.10 shows, two DCs (NETDC2, NETDC3) in the forest are online, and one DC (NETDC1) is offline. Knowledge of the network's real state will help you to select servers for connecting and making queries.
For clarity and simplicity, we will discuss the procedure involved in finding objects in Active Directory (or any other LDAP-compatible directory) using a few specific scenarios.
Remember that every DC in a domain stores, at minimum, three Active Directory partitions (see the RootDSE object's information when a connection is established). Although these partitions (including application partitions) have contiguous DNS names — and this may seem a little confusing — they are absolutely different namespaces when it comes to performing a search.
Deleted Active Directory objects (so called tombstones) are stored in a hidden Deleted Objects container for a pre-configured period of time, and then permanently purged during garbage collection. This container cannot be accessed by using standard snap-ins. The Show Deleted Object control (controlType = 1.2.840.1135220.127.116.117) and search command allow you to retrieve the tombstones. (You must have administrative privileges.)
Start Ldp.exe and carry out the following operations:
Connect to a DC, and bind to it using the credentials of an administrator.
Click Search in the Browse menu, and enter the distinguished name of the domain and the filter string (isDeleted=*). Select the Subtree switch and click Options (Fig. 12.11).
Fig. 12.11: Primary search parameters
Click Extended in the Search Call Type group, and enter the attributes of the deleted objects that you wish to view (see Fig. 12.12, left). (You may also need to increase the default Timeout (s) from zero to a bigger number. The value can be determined by experimenting.) Click Controls.
If you receive the following error message, increase the timeout value:
Error: Search: Timeout. <85> Error<94>: ldap_parse_result failed: No result present in message Getting 0 entries:
You can enter the type of the control directly into the Object Identifier field and click Check in (make sure that the Server switch in the Control Type group is selected), or simply select the Return deleted objects option in the Load Predefined list (see Fig. 12.12, right). To delete (deactivate) a control, select it in the Active Controls window and click Check Out.
You can combine a number of various controls in the same query.
To view and activate/deactivate the controls, you can open the Controls window at any moment by clicking Controls in the Options menu.
Close the Controls and Search Options windows.
Click Run and execute the search.
As you know, the name (e.g., the cn attribute) of a directory object can be changed by a rename object operation. If, for instance, an application uses the name for referring to the object, it will "lose" this object after its renaming. A more appropriate way would be to use the object GUID, which remains the same throughout the entire lifetime of the object.
The question is thus how to find the object GUID. You might search the directory for the object and specify the objectGUID attribute in the Search Options window. However, it is possible to get the GUID of each object found in a search operation immediately or to get it while browsing the directory tree. You need to activate the Return Extended Distinguished Names LDAP control (controlType = = 1.2.840.113518.104.22.1689).
It is also possible to get the GUID of an object by using the ADSI Edit snap-in. However, that may be inconvenient, since the objectGUID attribute (as well as objectSID) is in Octet-String format (e.g., "0x73 0xa5 0xe1 0xdd …" — 16 bytes in all). You cannot directly substitute such a string in a search or bind command. The Dsquery.exe utility would be a better choice.
The GUID search preparation steps are similar to those for deleted objects described above. Let us find the GUIDs of the OUs that are contained in a domain. Enter the following information:
Base DN — domain DN
Filter — (ou=*)
Search Call Type —Extended
Attributes — ADsPath
Active Controls — 1.2.840.113522.214.171.1249 (the Extended DN option in the Load Predefined list)
You will get a list of OUs in a format similar to the following:
Dn: <GUID=079760441fb9d948afdeacab994997cb>; OU=Domain Controllers, DC=net, DC=dom
The new component (marked here in bold) appears in the distinguished name. The found GUID can be verified by using Search.vbs (see "Searching for an Object using its GUID" at the beginning of this chapter), or you may use the entire string (between and including the angle brackets) in a script in a bind operation.
For directory objects that represent security principals (user, group, and computer accounts) output strings also contain object SIDs, for example:
Dn: <GUID=a6ead32063e11a40924e57f9107a14ec>; <SID=0105000000000005150000002fd5ec6ddde8e41c8aa7323feb030000>; CN=NETDC1, OU=Domain Controllers, DC=net, DC=dom
You might notice that the result sets of search operations contain rows in a quite random order. To obtain sorted results, you can use the Return Sorted Results LDAP control (controlType = 1.2.840.1135126.96.36.1993). To obtain sorted results in any search operations, perform the following steps:
Add the "1.2.840.1135188.8.131.523" value to the Active Controls list (see Fig. 12.12; right).
Click Options | Sort Keys.
In the Sort Keys window (Fig. 12.13), enter OID of a sort key in the Attribute Type field and click Check In and OK. You can obtain the attribute's OID using the Active Directory Schema Manager snap-in. The name attribute (1.2.840.1135184.108.40.206) has been selected in our example.
Fig. 12.13: Sorting search results on the name attribute
Select all search parameters and click Extended in the Search Call Type group in the Search Options window (see Fig. 12.12; left).
After all this, any search operations will produce sorted result sets unless the select Sync in the Search Call Type group or delete the Return Sorted Results control from the list of LDAP controls.
The LDAP update operations include the following: Add, Modify, Modify RDN, and Delete. On the one hand (regarding the user interface), they are quite simple and obvious; on the other hand, they require a rather keen understanding of Active Directory architecture (particularly the schema, classes, and attributes). That is why other tools, such as administrative snap-ins (ADSI Edit, Active Directory Users and Computers, and so on), are more suitable for modifying Active Directory objects. In an example below, we will discuss the most common steps involved in using Ldp.exe for this purpose.
The Modify RDN operation is equivalent to renaming or moving an object. The Cross Domain Move LDAP control (1.2.840.1135220.127.116.111) enables you to perform move operations over domain boundaries.
Let us change a user's UPN. First, click Modify in the Browse menu. In the opened window, enter the user's DN, the attribute name, and its new value. Then select Replace from the Operation group (because the attribute already exists), and click Enter to add the data to the Entry List. No checks are performed at this time, so be careful. You may correct the entered data by clicking Edit (and then editing the information) or Remove. A sample window is shown in Fig. 12.14.
Fig. 12.14: The information necessary to change the UPN of a user
When everything is ready, click Run. The server will verify all entered data (syntax rules, acceptable values, etc.), and perform the operation if all requirements have been met. The result message may be similar to the following:
***Call Modify... ldap_modify_s(ld, 'CN=John Smith, OU=Staff, DC=net, DC=dom',  attrs); Modified "CN=John Smith, OU=Staff, DC=net, DC=dom".
If an error occurs while at some step of executing an operation, the tool reports an error message, which is determined by the kind of error (such as a syntax error in the entered data, or an error with the directory database, etc.). The message contains a description of the error.
***Call Modify... ldap_modify_s(ld, 'CN=John Smith, OU=Staff, DC=net, DC=dom',  attrs); Error: Modify: No Such Object. <32>
The delete operation is also fairly obvious and simple. However, a problem may arise when you want to delete an object that has one or more child objects, for example, an OU with user accounts. The following error may be reported:
Error: Delete: Not allowed on Non-leaf. <66>
To perform such an operation, you must use the Tree Delete LDAP control (controlType = 1.2.840.113518.104.22.1685). This control allows you to delete an entire subtree, if you have sufficient permissions.
To delete a non-leaf object (i.e., a container), perform the following operations:
Add the Tree Delete control to the list of active controls (select the Subtree Delete option in the Load Predefined list — see Fig. 12.12; right).
Click Delete in the Browse menu.
In the Delete window, enter the distinguished name of the container and check the Extended box. (An example window is shown in Fig. 12.15.)
Fig. 12.15: Deleting a non-empty container (an OU in this case)
Be extremely careful when deleting an entire container! No warnings are generated.
Ldp.exe allows you to view the security descriptor of any directory object. This feature is intended for solving problems related to the accounts' permissions on directory objects (e.g., when moving the security principals to another domain) and can be especially useful when you are debugging scripts or applications that work with security descriptors (see Chapter 17, "Scripting Administrative Tasks"). Using this feature requires a sound understanding of the Active Directory security model (access control lists (ACL) and access control elements (ACE), their inheritance, etc.).
To view the security descriptor for a directory object, select the Security | Security Descriptor command from the Browse menu and specify the distinguished name of the object. If you want to see the directly specified or inherited audit settings (the system ACLs) of this object, check the SACL box. A sample output produced by this command is shown in Fig. 12.16. The command also displays the descriptor in the SDDL (Security Descriptor Definition Language) string format (not shown in the figure). As Fig. 12.16 shows, you can see all the information about the descriptor (some of its elements are circled in the figure). That information includes, in particular, control flags, the owner of the object, the number of ACEs, and elements of each ACE, such as the ACE's type, the access mask, and the name and SID of the security principal that was granted this right. You can retrieve all described information from a descriptor by using a script (Chapter 17, "Scripting Administrative Tasks", contains an example of such a script). You can also programmatically manipulate the ACEs, i.e., grant or revoke permissions on directory objects.
Fig. 12.16: A fragment of a security descriptor shown by using Ldp.exe
Ldp.exe can display the directory object's metadata information (the replProperty-MetaData attribute) that is used in replication. You can also view this information by using the RepAdmin.exe command with the /showmeta parameter (see Chapter 11, "Verifying Network and Distributed Services").
To view the metadata for an object, select the Replication | View Metadata command from the Browse menu and enter the object's distinguished name. A sample output is presented in Fig. 12.17.
Fig. 12.17: Viewing the replication metadata for a directory object
When troubleshooting replication issues, you can connect to various domain controllers and compare the metadata for the stored replicas of the desired object.