Tải bản đầy đủ (.pdf) (10 trang)

Active Directory Cookbook for windows server 2003- P10 pps

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (36.43 KB, 10 trang )


101
Chapter 4. Searching and Manipulating
Objects
Introduction
Recipe 4.1. Viewing the RootDSE

Recipe 4.2. Viewing the Attributes of an Object
Recipe 4.3. Using LDAP Controls
Recipe 4.4. Using a Fast or Concurrent Bind
Recipe 4.5. Searching for Objects in a Domain
Recipe 4.6. Searching the Global Catalog
Recipe 4.7. Searching for a Large Number of Objects
Recipe 4.8. Searching with an Attribute-Scoped Query
Recipe 4.9. Searching with a Bitwise Filter
Recipe 4.10. Creating an Object
Recipe 4.11. Modifying an Object
Recipe 4.12. Modifying a Bit-Flag Attribute
Recipe 4.13. Dynamically Linking an Auxiliary Class
Recipe 4.14. Creating a Dynamic Object

Recipe 4.15. Refreshing a Dynamic Object
Recipe 4.16. Modifying the Default TTL Settings for Dynamic Objects
Recipe 4.17. Moving an Object to a Different OU or Container
Recipe 4.18. Moving an Object to a Different Domain
Recipe 4.19. Renaming an Object

102
Recipe 4.20. Deleting an Object
Recipe 4.21. Deleting a Container That Has Child Objects
Recipe 4.22. Viewing the Created and Last Modified Timestamp of an Object


Recipe 4.23. Modifying the Default LDAP Query Policy
Recipe 4.24. Exporting Objects to an LDIF File
Recipe 4.25. Importing Objects Using an LDIF File
Recipe 4.26. Exporting Objects to a CSV File
Recipe 4.27. Importing Objects Using a CSV File
Introduction
Active Directory is based on the Lightweight Directory Access Protocol (LDAP) and supports
the LDAP v3 specification defined in RFC 2251. And while many of the AD tools and interfaces,
such as ADSI, abstract and streamline LDAP operations to make things easier, any good AD
administrator or developer must have a thorough understanding of LDAP to fully utilize Active
Directory. This chapter will cover the some of the basic LDAP-related tasks you may need to do
with Active Directory, along with other items related to searching and manipulating objects in
the directory.
The Anatomy of an Object
The Active Directory schema is composed of a hierarchy of classes. These classes support
inheritance, which enables reuse of existing class definitions. At the top of the inheritance tree is
the top class, from which every class in the schema is derived. Table 4-1 contains a list of some
of the attributes that are available from the top class, and subsequently are defined on every
object that is created in Active Directory.
Table 4-1. Common attributes of objects
Attribute Description
cn
Relative distinguished name (RDN) attribute for most object classes
createTimestamp
Timestamp when the object was created. See Recipe 4.22 for more
information
description
Multivalued attribute that can be used as a generic field for storing a
description of the object


103
Table 4-1. Common attributes of objects
Attribute Description
displayName
Name of the object displayed in administrative interfaces
distinguishedName
Distinguished name of the object
modifyTimestamp
Timestamp when the object was last changed. See Recipe 4.22
for
more information
name
RDN of the object. The value of this attribute will mirror the naming
attribute (e.g., cn, ou, dc)
nTSecurityDescriptor
Security descriptor assigned to the object
objectCategory
Used as a grouping mechanism for objects with a similar purpose
(e.g., Person)
objectClass
List of classes from which the object's class was derived
objectGUID
Globally unique identifier for the object
uSNChanged
Update sequence number (USN) assigned by the local server after the
last change to the object (can include creation)
uSNCreated
USN assigned when the object was created
Recipe 4.1 Viewing the RootDSE
4.1.1 Problem

You want to view attributes of the RootDSE, which can be useful for discovering basic
information about a forest, domain, or domain controller.
4.1.2 Solution
4.1.2.1 Using a graphical user interface
1. Open LDP.
2. From the menu, select Connection Connect.
3. For Server, enter a domain controller, domain name, or leave blank to do a serverless
bind.
4. For Port, enter 389.
5. Click OK.
6. The contents of the RootDSE will be shown in the right pane.
4.1.2.2 Using a command-line interface
> enumprop "LDAP://RootDSE"

104
4.1.2.3 Using VBScript
' This code prints the attributes of the RootDSE
set objRootDSE = GetObject("LDAP://RootDSE")
objRootDSE.GetInfo
for i = 0 to objRootDSE.PropertyCount - 1
set strProp = objRootDSE.Item(i)
WScript.Echo strProp.Name & " "
for each strPropval in strProp.Values
WScript.Echo " " & strPropval.CaseIgnoreString
next
next
4.1.3 Discussion
The RootDSE was originally defined in RFC 2251 as part of the LDAPv3 specification. It is not
part of the Active Directory namespace per se. It is a synthetic object that is maintained
separately by each domain controller.

The RootDSE can be accessed anonymously, and in fact, none of the three solutions used
credentials. In the CLI and VBScript solutions, I used serverless binds against the RootDSE. In
that case, the DC Locator process is used to find a domain controller in the domain you
authenticate against. This can also be accomplished with LDP by not entering a server name
from the Connect dialog box.
The RootDSE is key to writing portable AD-enabled applications. It provides a mechanism to
programmatically determine the distinguished names of the various naming contexts among
other things, which means you do not need to hardcode that information in scripts and programs.
Here is an example from LDP when run against a Windows Server 2003-based domain controller:
ld = ldap_open("dc01", 389);
Established connection to dc01.
Retrieving base DSA information . . .
Result <0>: (null)
Matched DNs:
Getting 1 entries:
>> Dn:
1> currentTime: 05/26/2003 15:29:42 Pacific Standard Time Pacific Daylight
Time;

1>
subschemaSubentry:CN=Aggregate,CN=Schema,CN=Configuration,DC=rallencorp,DC=co
m;

1> dsServiceName: CN=NTDS Settings,CN=DC01,CN=Servers,CN=Default-First-Site-
Name,CN=Sites,CN=Configuration,DC=rallencorp,DC=com;

5> namingContexts: DC=rallencorp,DC=com;
CN=Configuration,DC=rallencorp,DC=com;
CN=Schema,CN=Configuration,DC=rallencorp,DC=com;
DC=DomainDnsZones,DC=rallencorp,DC=com;

DC=ForestDnsZones,DC=rallencorp,DC=com;


105
1> defaultNamingContext: DC=rallencorp,DC=com;

1> schemaNamingContext: CN=Schema,CN=Configuration,DC=rallencorp,DC=com;

1> configurationNamingContext: CN=Configuration,DC=rallencorp,DC=com;

1> rootDomainNamingContext: DC=rallencorp,DC=com;

21> supportedControl: 1.2.840.113556.1.4.319; 1.2.840.113556.1.4.801;
1.2.840.113556.
1.4.473; 1.2.840.113556.1.4.528; 1.2.840.113556.1.4.417;
1.2.840.113556.1.4.619; 1.2.
840.113556.1.4.841; 1.2.840.113556.1.4.529; 1.2.840.113556.1.4.805;
1.2.840.113556.1.
4.521; 1.2.840.113556.1.4.970; 1.2.840.113556.1.4.1338;
1.2.840.113556.1.4.474; 1.2.
840.113556.1.4.1339; 1.2.840.113556.1.4.1340; 1.2.840.113556.1.4.1413;
2.16.840.1.
113730.3.4.9; 2.16.840.1.113730.3.4.10; 1.2.840.113556.1.4.1504;
1.2.840.113556.1.4.
1852; 1.2.840.113556.1.4.802;

2> supportedLDAPVersion: 3; 2;

12> supportedLDAPPolicies: MaxPoolThreads; MaxDatagramRecv; MaxReceiveBuffer;
InitRecvTimeout; MaxConnections; MaxConnIdleTime; MaxPageSize;

MaxQueryDuration;
MaxTempTableSize; MaxResultSetSize; MaxNotificationPerConn; MaxValRange;

1> highestCommittedUSN: 53242;

4> supportedSASLMechanisms: GSSAPI; GSS-SPNEGO; EXTERNAL; DIGEST-MD5;

1> dnsHostName: dc01.rallencorp.com;

1> ldapServiceName: rallencorp.com:dc01$@RALLENCORP.COM;

1> serverName: CN=DC01,CN=Servers,CN=Default-First-Site-
Name,CN=Sites,CN=Configuration,DC=rallencorp,DC=com;

3> supportedCapabilities: 1.2.840.113556.1.4.800; 1.2.840.113556.1.4.1670;
1.2.840.
113556.1.4.1791;

1> isSynchronized: TRUE;

1> isGlobalCatalogReady: TRUE;

1> domainFunctionality: 0 = ( DS_BEHAVIOR_WIN2000 );

1> forestFunctionality: 0 = ( DS_BEHAVIOR_WIN2000 );

1> domainControllerFunctionality: 2 = ( DS_BEHAVIOR_WIN2003 );
4.1.3.1 Using VBScript

106

All attributes of the RootDSE were retrieved and displayed. Typically, you will need only a few
of the attributes; in which case, you'll want to use Get or GetEx as in the following example:
strDefaultNC = objRootDSE.Get("defaultNamingContext")
Or if want to get an object based on the distinguished name (DN) of one of the naming contexts,
you can call GetObject using an ADsPath:
set objUser = GetObject("LDAP://cn=administrator,cn=users," & _
objRootDSE.Get("defaultNamingContext") )
4.1.4 See Also
RFC 2251, MS KB 219005 (Windows 2000: LDAPv3 RootDSE), MSDN: IADsPropertyEntry,
MSDN: IADsProperty Value, MSDN: IADs::Get, and MSDN: IADs::GetEx
Recipe 4.2 Viewing the Attributes of an Object
4.2.1 Problem
You want to view one or more attributes of an object.
4.2.2 Solution
4.2.2.1 Using a graphical user interface
1. Open LDP.
2. From the menu, select Connection Connect.
3. For Server, enter the name of a domain controller or domain that contains the object.
4. For Port, enter 389.
5. Click OK.
6. From the menu, select Connection Bind.
7. Enter credentials of a user that can view the object (if necessary).
8. Click OK.
9. From the menu, select View Tree.
10. For BaseDN, type the DN of the object you want to view.
11. For Scope, select Base.
12. Click OK.
4.2.2.2 Using a command-line interface
> dsquery * "<ObjectDN>" -scope base -attr *
For Windows 2000, use this command:

> enumprop "LDAP://<ObjectDN>"
4.2.2.3 Using VBScript

107
' This code prints all attributes for the specified object.
' SCRIPT CONFIGURATION
strObjectDN = "<ObjectDN>" ' e.g. cn=jsmith,cn=users,dc=rallencorp,dc=com
' END CONFIGURATION

DisplayAttributes("LDAP://" & strObjectDN)

Function DisplayAttributes( strObjectADsPath )

set objObject = GetObject(strObjectADsPath)
objObject.GetInfo

'Declare the hash (dictionary), constants and variables
'Values taken from ADSTYPEENUM
set dicADsType = CreateObject("Scripting.Dictionary")
dicADsType.Add 0, "INVALID"
dicADsType.Add 1, "DN_STRING"
dicADsType.Add 2, "CASE_EXACT_STRING"
dicADsType.Add 3, "CASE_IGNORE_STRING"
dicADsType.Add 4, "PRINTABLE_STRING"
dicADsType.Add 5, "NUMERIC_STRING"
dicADsType.Add 6, "BOOLEAN"
dicADsType.Add 7, "INTEGER"
dicADsType.Add 8, "OCTET_STRING"
dicADsType.Add 9, "UTC_TIME"
dicADsType.Add 10, "LARGE_INTEGER"

dicADsType.Add 11, "PROV_SPECIFIC"
dicADsType.Add 12, "OBJECT_CLASS"
dicADsType.Add 13, "CASEIGNORE_LIST"
dicADsType.Add 14, "OCTET_LIST"
dicADsType.Add 15, "PATH"
dicADsType.Add 16, "POSTALADDRESS"
dicADsType.Add 17, "TIMESTAMP"
dicADsType.Add 18, "BACKLINK"
dicADsType.Add 19, "TYPEDNAME"
dicADsType.Add 20, "HOLD"
dicADsType.Add 21, "NETADDRESS"
dicADsType.Add 22, "REPLICAPOINTER"
dicADsType.Add 23, "FAXNUMBER"
dicADsType.Add 24, "EMAIL"
dicADsType.Add 25, "NT_SECURITY_DESCRIPTOR"
dicADsType.Add 26, "UNKNOWN"
dicADsType.Add 27, "DN_WITH_BINARY"
dicADsType.Add 28, "DN_WITH_STRING"

for intIndex = 0 To (objObject.PropertyCount - 1)
set objPropEntry = objObject.Item(intIndex)
for Each objPropValue In objPropEntry.Values
value = ""

if (dicADsType(objPropValue.ADsType) = "DN_STRING") then
value = objPropValue.DNString

elseIf (dicADsType(objPropValue.ADsType) = "CASE_EXACT_STRING") then
value = objPropValue.CaseExactString



108
elseIf (dicADsType(objPropValue.ADsType) = "CASE_IGNORE_STRING")
then
value = objPropValue.CaseIgnoreString

elseIf (dicADsType(objPropValue.ADsType) = "PRINTABLE_STRING") then
value = objPropValue.PrintableString

elseIf (dicADsType(objPropValue.ADsType) = "NUMERIC_STRING") then
value = objPropValue.NumericString

elseIf (dicADsType(objPropValue.ADsType) = "BOOLEAN") then
value = CStr(objPropValue.Boolean)

elseIf (dicADsType(objPropValue.ADsType) = "INTEGER") then
value = objPropValue.Integer

elseIf (dicADsType(objPropValue.ADsType) = "LARGE_INTEGER") then
set objLargeInt = objPropValue.LargeInteger
value = objLargeInt.HighPart * 2^32 + objLargeInt.LowPart

elseIf (dicADsType(objPropValue.ADsType) = "UTC_TIME") then
value = objPropValue.UTCTime

else
value = "<" & dicADsType.Item(objPropEntry.ADsType) & ">"

end if
WScript.Echo objPropEntry.Name & " : " & value

next
next
End Function
4.2.3 Discussion
Objects in Active Directory are made up of a collection of attributes. Attributes can be single- or
multivalued. Each attribute also has an associated syntax that is defined in the schema. See
Recipe 10.7 for a complete list of syntaxes.
4.2.3.1 Using a graphical user interface
You can customize the list of attributes returned from a search with LDP by modifying the
Attributes: field under Options Search. To include all attributes enter *. For a subset enter a
semicolon-separated list of attributes.
4.2.3.2 Using a command-line interface
The -
attr option for the dsquery command accepts a whitespace-separated list of attributes to
display. Using a
* will return all attributes.
For the
enumprop command, you can use the /ATTR option and a comma-separated list of
attributes to return. In the following example, only the name and whenCreated attributes would
be returned:

109
> enumprop /ATTR:name,whenCreated "LDAP://<ObjectDN>"
4.2.3.3 Using VBScript
The DisplayAttributes function prints the attributes that contain values for the object passed
in. After using GetObject to bind to the object, I used the IADs::GetInfo method to populate
the local property cache with all of the object's attributes from AD. In order to print each value of
a property, I have to know its type or syntax. The ADsType method returns an integer from the
ADSTYPEENUM enumeration that corresponds with a particular syntax (e.g., boolean). Based on the
syntax, I call a specific method (e.g., Boolean) that can properly print the value. If I didn't

incorporate this logic and tried to print all values using the CaseIgnoreString method for
example, an error would get generated when the script encountered an octet string because octet
strings (i.e., binary data) do not have a
CaseIgnoreString representation.
I stored the values from the
ADSTYPEENUM enumeration in key/value pairs in a dictionary object
(i.e., Scripting.Dictionary). In the dictionary object, the key for the dictionary is the
ADSTYPEENUM integer, and the value is a textual version of the syntax. I used the dictionary object
so I could print the textual syntax of each attribute. I iterated over all the properties in the
property cache using IADsPropertyList and IADsPropertyEntry objects, which are
instantiated with the IADsPropertyList::Item method.

The DisplayAttributes function is used throughout the book in examples
where the attributes for a given type of object are displayed.

4.2.4 See Also
Chapter 19, IADs and the Property Cache, from Active Directory, Second Edition, MSDN:
IADsPropertyEntry, MSDN: IADsPropertyList, MSDN: ADSTYPEENUM, and MSDN:
IADs::GetInfo
Recipe 4.3 Using LDAP Controls
4.3.1 Problem
You want to use an LDAP control as part of an LDAP operation.
4.3.2 Solution
4.3.2.1 Using a graphical user interface
1. Open LDP.
2. From the menu, select Options Controls.
3. For the Windows Server 2003 version of LDP, select the control you want to use under
Load Predefined. The control should automatically be added to the list of Active Controls.

110

For the Windows 2000 version of LDP, you'll need to type the object identifier (OID) of
the control under Object Identifier.
4. Enter the value for the control under Value.
5. Select whether the control is server- or client-side under Control Type.
6. Check the box beside Critical if the control is critical.
7. Click the Check-in button.
8. Click OK.
9. At this point, you will need to invoke the LDAP operation (for example, Search) that will
use the control. In the dialog box for any operation, be sure that the "Extended" option is
checked before initiating the operation.
4.3.2.2 Using VBScript
None of the ADSI automation interfaces directly expose LDAP controls. That means they cannot
be utilized from VBScript. On the other hand, many of the controls, such as paged searching or
deleting a subtree, are wrapped within their own ADSI methods that can be used within
VBScript.
Any LDAP-based API, such as the Perl Net::LDAP modules, can be used to set controls as part
of LDAP operations.
4.3.3 Discussion
LDAP controls were defined in the LDAPv3 specification as a way to extend LDAP and its
operations without breaking the protocol. Many controls have been implemented, some of which
are used when searching the directory (e.g., paged searching, VLV, finding deleted objects, and
attribute scoped query), and some are needed to do certain modifications to the directory (e.g.,
cross-domain object moves, tree delete, and permissive modify). Controls can be marked as
critical, which means they must be processed with the request, or an error is returned. If an
unsupported control is not flagged as critical, the server can continue to process the request and
ignore the control.
The complete list of controls supported by Active Directory is included in Table 4-2
.
Table 4-2. LDAP controls supported by Active Directory
Name OID Description

Paged Results 1.2.840.113556.1.4.319
Instructs the server to return search results in
"pages."
Cross Domain
Move
1.2.840.113556.1.4.521 Used to move objects between domains.
DIRSYNC 1.2.840.113556.1.4.841 Used to find objects that have changed over a

×