Chapter 4. Searching and Manipulating Objects

Introduction

Active Directory is based on Lightweight Directory Access Protocol (LDAP) and supports the LDAP version 3 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 some of the LDAP-related tasks you may need to perform when working with Active Directory, along with other tasks related to searching and manipulating objects within the directory.

The Anatomy of an Object

The Active Directory schema is composed of a hierarchy of classes that define the types of objects that can be created within Active Directory, as well as the different attributes they can possess. These classes support inheritance, which enables developers to reuse existing class definitions for more than one type of object; for example, the description attribute is available with every type of AD object, but the attribute itself is defined only once within the schema. 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

RDN attribute for most object classes, also referred to as the common name.

whenCreated

Timestamp when the object was created. See Viewing the Created and Last-Modified Timestamp of an Object for more information.

description

Multivalued attribute that can be used as a generic field for storing a description of the object. Although this attribute is multivalued, objects such as users and groups can have only one value populated due to legacy support requirements.

displayName

Name of the object displayed in administrative interfaces.

distinguishedName

Distinguished name of the object.

whenChanged

Timestamp when the object was last changed by the local server. See Viewing the Created and Last-Modified Timestamp of an Object 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 by the local server when the object was created.

Viewing the RootDSE

Problem

You want to view attributes of the RootDSE, which can be useful for discovering basic information about a forest, domain, or domain controller without hardcoding the name of a particular naming context into a query.

Solution

Using a graphical user interface

  1. Open LDP.

  2. From the menu, select Connection→Connect.

  3. For Server, enter a domain controller or domain name, or leave it 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.

Using a command-line interface

To display the RootDSE of a domain controller using AdFind, use the following syntax:

> adfind -rootdse

Using PowerShell

Get-ADRootDSE

You’ll see results similar to the following (truncated for readability):

configurationNamingContext: cn=Configuration,dc= adatum,dc=com
currentTime: 10/9/2012 9:27:38 AM
defaultNamingContext: dc=adatum,dc=com
dnsHostName: dc1.adatum.com
domainControllerFunctionality: Windows2012
domainFunctionality: Windows2012Domain
dsServiceName: cn=NTDS Settings,cn=DC1,cn=Servers,cn=Default-First-Site-Name,↵
cn=Sites,cn=Configuration,dc=adatum,dc=com
forestFunctionality: Windows2012Forest
highestCommittedUSN: 28013
isGlobalCatalogReady: {TRUE}
isSynchronized: {TRUE}
ldapServiceName: adatum.com:dc1$@ADATUM.COM
namingContexts: {dc=adatum,dc=com, cn=Configuration,dc=adatum,dc=com,
cn=Schema,cn=Configuration,dc=adatum,dc=com,dc=DomainDnsZones,dc=adatum,↵
dc=com...}
rootDomainNamingContext: dc=adatum,dc=com
schemaNamingContext: cn=Schema,cn=Configuration,dc=adatum,dc=com
serverName: cn=dc1,cn=Servers,cn=Default-First-Site-Name,cn=Sites,↵
cn=Configuration,dc=adatum,dc=com
subschemaSubentry: cn=Aggregate,cn=Schema,cn=Configuration,dc=adatum,dc=com
supportedCapabilities: {1.2.840.113556.1.4.800 (LDAP_CAP_ACTIVE_DIRECTORY_OID),;1.2.840.113556.1.4.1670(LDAP_CAP_ACTIVE_DIRECTORY_V51_OID),;1.2.840.113556.1.4.1791(LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID),;1.2.840.113556.1.4.1935(LDAP_CAP_ACTIVE_DIRECTORY_V61_OID)...}
supportedControl: {1.2.840.113556.1.4.319(LDAP_PAGED_RESULT_OID_STRING),;1.2.840.113556.1.4.801(LDAP_SERVER_SD_FLAGS_OID),;1.2.840.113556.1.4.473(LDAP_SERVER_SORT_OID),;1.2.840.113556.1.4.528(LDAP_SERVER_NOTIFICATION_OID)...}
supportedLDAPPolicies: {MaxPoolThreads, MaxDatagramRecv, MaxReceiveBuffer,; InitRecvTimeout...}
supportedLDAPVersion: {3, 2}
supportedSASLMechanisms: {GSSAPI, GSS-SPNEGO, EXTERNAL, DIGEST-MD5}

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 using LDP; the command-line and PowerShell solutions use the credentials of the currently logged-on user unless you specify an alternate username and password. In the CLI and PowerShell solutions, serverless binds were used 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 that you do not need to hardcode that information in scripts and programs.

See Also

RFC 2251; MS KB 219005 (Windows 2000: LDAPv3 RootDSE); MSDN: IADsPropertyEntry; MSDN: IADsProperty Value; MSDN: IADs::Get MSDN: IADs::GetEx

Viewing the Attributes of an Object

Problem

You want to view one or more attributes of an object.

Solution

Using a graphical user interface

  1. Open LDP.

  2. From the menu, select Connection→Connect.

  3. For Server, enter the name or IP address 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. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  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.

Using a command-line interface

To obtain a list of attributes for a particular object using DSQuery, use the following syntax:

> dsquery * "<ObjectDN>" -scope base -attr *

To query for an object using AdFind, use the following syntax:

> adfind -b <Parent Container DN> -f cn=<Object CN> -tdcgt

Using PowerShell

To get the attributes of the built-in Administrator account, run the following PowerShell command:

Get-ADUser -Identity Administrator -Properties *

An example of the output is shown here:

AccountExpirationDate                :
accountExpires                       : 0
AccountLockoutTime                   :
AccountNotDelegated                  : False
adminCount                           : 1
AllowReversiblePasswordEncryption    : False
BadLogonCount                        : 0
badPasswordTime                      : 129934507947486667
badPwdCount                          : 0
CannotChangePassword                 : False
CanonicalName                        : adatum.com/Users/Administrator
Certificates                         : {}
City                                 :
CN                                   : Administrator
codePage                             : 0
Company                              :
CompoundIdentitySupported            : {}
Country                              :
countryCode                          : 0
Created                              : 9/27/2012 11:16:45 AM
createTimeStamp                      : 9/27/2012 11:16:45 AM
Deleted                              :
Department                           :
Description                          : Built-in account for administering the
                                       computer/domain
DisplayName                          :
DistinguishedName                    : cn=Administrator,cn=Users,dc=adatum,dc=com
Division                             :
DoesNotRequirePreAuth                : False
dSCorePropagationData                : {9/27/2012 11:34:42 AM,↵
                                        9/27/2012 11:34:42 AM,↵
                                        9/27/2012 11:19:31 AM,↵
                                        1/1/1601 10:12:16 AM}
EmailAddress                         :
EmployeeID                           :
EmployeeNumber                       :
Enabled                              : True
Fax                                  :
GivenName                            :
HomeDirectory                        :
HomedirRequired                      : False
HomeDrive                            :
HomePage                             :
HomePhone                            :
Initials                             :
instanceType                         : 4
isCriticalSystemObject               : True
isDeleted                            :
KerberosEncryptionType               : {}
LastBadPasswordAttempt               : 9/29/2012 8:53:14 PM
LastKnownParent                      :
lastLogoff                           : 0
lastLogon                            : 129942736428265971
LastLogonDate                        : 10/9/2012 9:27:17 AM
lastLogonTimestamp                   : 129942736379503412
LockedOut                            : False
logonCount                           : 29
logonHours                           : {255, 255, 255, 255...}
LogonWorkstations                    :
Manager                              :
MemberOf                             : {cn=Group Policy Creator                                        
              Owners,cn=Users,dc=adatum,dc=com, cn=Domain
              Admins,cn=Users,dc=adatum,dc=com, cn=Enterprise
              Admins,cn=Users,dc=adatum,dc=com, cn=Schema
              Admins,cn=Users,dc=adatum,dc=com...}
MNSLogonAccount                      : False
MobilePhone                          :
Modified                             : 10/9/2012 9:27:17 AM
modifyTimeStamp                      : 10/9/2012 9:27:17 AM
msDS-AuthenticatedAtDC               : {cn=2012-DC05,OU=Domain                                        
                                        Controllers,dc=adatum,dc=com}
msDS-User-Account-Control-Computed   : 0
Name                                 : Administrator
nTSecurityDescriptor                 : System.DirectoryServices.↵                                       
                                       ActiveDirectorySecurity
ObjectCategory                       : cn=Person,cn=Schema,cn=Configuration,↵                                       
                                       dc=adatum,dc=com
ObjectClass                          : user
ObjectGUID                           : c897bc0a-b5d4-4025-8c10-b696e45ce780
objectSid                            : S-1-5-21-3384837461-4027165227-↵
                                       453512602-500
Office                               :
OfficePhone                          :
Organization                         :
OtherName                            :
PasswordExpired                      : False
PasswordLastSet                      : 9/27/2012 10:18:17 AM
PasswordNeverExpires                 : False
PasswordNotRequired                  : False
POBox                                :
PostalCode                           :
PrimaryGroup                         : cn=Domain Users,cn=Users,dc=adatum,dc=com
primaryGroupID                       : 513
PrincipalsAllowedToDelegateToAccount : {}
ProfilePath                          :
ProtectedFromAccidentalDeletion      : False
pwdLastSet                           : 129932398979898472
SamAccountName                       : Administrator
sAMAccountType                       : 805306368
ScriptPath                           :
sDRightsEffective                    : 15
ServicePrincipalNames                : {}
SID                                  : S-1-5-21-3384837461-4027165227-↵
                                       453512602-500
SIDHistory                           : {}
SmartcardLogonRequired               : False
State                                :
StreetAddress                        :
Surname                              :
Title                                :
TrustedForDelegation                 : False
TrustedToAuthForDelegation           : False
UseDESKeyOnly                        : False
userAccountControl                   : 512
userCertificate                      : {}
UserPrincipalName                    :
uSNChanged                           : 28008
uSNCreated                           : 8196
whenChanged                          : 10/9/2012 9:27:17 AM
whenCreated                          : 9/27/2012 11:16:45 AM

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 Adding a New Attribute for a complete list of syntaxes.

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 an asterisk (*). To modify the default subset of attributes that are returned, enter a semicolon-separated list of attributes. You can also use the numeric attribute ID instead of the attribute name, such as using 1.1 in place of distinguishedName.

Using a command-line interface

The -attr option for the dsquery command accepts a whitespace-separated list of attributes to display. Using an asterisk (*) will return all default attributes.

When using AdFind, you have several shortcut switches to reduce the amount of typing you need to do. If you are searching for an object in the default container, you can use the –default switch rather than something like –b dc=contoso,dc=com. Likewise, if you are querying the Configuration NC, you can use the –config switch, -root for the root partition, or –schema for the Schema partition. If you want to query a subcontainer of one of these partitions, you can add the –rb switch, which stands for Relative Base.

See Also

Adding a New Attribute; MSDN: IADsPropertyEntry; MSDN: IADsPropertyList; MSDN: ADSTYPEENUM; MSDN: IADs::GetInfo; Active Directory, Fifth Edition, by Brian Desmond et al. (O’Reilly)

Counting Objects in Active Directory

Problem

You want to retrieve the number of directory objects that meet the result of an LDAP query.

Solution

Using a graphical user interface

  1. Open LDP.

  2. From the menu, select Connection→Connect.

  3. For Server, enter the name or IP address of a domain controller or the domain that contains the object.

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. From the menu, select Browse→Search.

  10. Enter the base DN, scope, and LDAP filter of the objects that you’re looking for.

  11. Click Options and remove the checkmark next to Display Results. This will display the number of objects returned by the query without displaying the details of the items that are returned.

  12. Click OK and then click Run to perform the query.

Using a command-line interface

To retrieve a count of objects that match a particular query, use the following syntax:

> adfind -b <Search Base> -s <Scope> -f <Search Filter> -c

For example, retrieving the number of user objects in the adatum.com domain would use the following syntax:

> adfind -default -f "(&(objectclass=user)(objectcategory=person))" -c
>
> AdFind V01.46.00cpp Joe Richards (joe@joeware.net) March 2012
>
> Using server: dc1.adatum.com:389
> Directory: Windows Server 8
> Base DN: dc=adatum,dc=com
>
> 5 Objects returned

Using PowerShell

The following example will query Active Directory for a list of user objects in the current domain and return the count:

Get-ADObject -Filter {(objectClass -eq "user") -and (objectCategory -eq "person")} | Measure-Object | FL Count

To retrieve a count of all of the computer objects in the current domain, run the following command:

Get-ADObject -Filter {(objectClass -eq "user") -and (objectCategory -eq "computer")} | Measure-Object | FL Count

Discussion

Using PowerShell

The PowerShell commands can target a specific container or OU, as follows:

Get-ADObject -SearchBase "OU=Branches,dc=adatum,dc=com" -Filter {(objectClass -eq "user") -and (objectCategory -eq "person")} | Measure-Object | FL Count

Be careful with the filtering. The class and category of the object must be combined to accurately target user objects.

There are other ways to filter, too. In this recipe, we’ve used an efficient filtering method while keeping the commands easy to use. However, in large environments, using LDAP filtering can be a bit faster than standard filtering. The following command counts all of the user objects in the current domain and uses LDAP filtering:

Get-ADObject -LDAPFilter "(&(objectCategory=Person)(objectClass=User)) " | Measure-Object | FL Count

Using LDAP Controls

Problem

You want to use an LDAP control as part of an LDAP operation.

Solution

Using a graphical user interface

  1. Open LDP.

  2. From the menu, select Options→Controls.

  3. Under Load Predefined, select the control you want to use. The control should automatically be added to the list of Active Controls.

  4. Under Value, enter the value for the control.

  5. Under Control Type, select whether the control is server-side or client-side.

  6. Check the box beside Critical if the control is critical.

  7. Click OK.

  8. At this point, you will need to invoke the LDAP operation (such as Search) that will use the control. In the dialog box for any operation, click Options and ensure that the Extended option is checked before initiating the operation.

Using a command-line interface

The AdFind and AdMod utilities will enable a number of LDAP controls, either by default or through the use of various command-line switches. For example, the –showdel switch will invoke the Show Deleted Objects LDAP control, and -stats will invoke the Show Stats control.

Using PowerShell

PowerShell leverages LDAP controls in some built-in parameters of various cmdlets. For example, the Get-ADObject cmdlet has a parameter to include deleted objects in searches. The –IncludeDeletedObjects parameter uses LDAP controls as part of the command.

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, Virtual List View [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

Permit No-Opt Modify

1.2.840.113556.1.4.1413

Allows duplicate adds of the same value for an attribute or deletion of an attribute that has no values to succeed (normally, it would fail in that situation).

Return Deleted Objects

1.2.840.113556.1.4.417

Used to inform the server to return any deleted objects that matched the search criteria.

Cross Domain Move

1.2.840.113556.1.4.521

Used to move objects between domains.

Set change notifications

1.2.840.113556.1.4.528

Used by clients to register for notification of when changes occur in the directory.

Delayed Write

1.2.840.113556.1.4.619

Used to inform the server to return after directory modifications have been written to memory, but before they have been written to disk. This can speed up processing of a lot of modifications.

Security Descriptor Flags

1.2.840.113556.1.4.801

Used to pass flags to the server to control certain security descriptor options.

Subtree Delete

1.2.840.113556.1.4.805

Used to delete portions of the directory tree, including any child objects.

Verify Name Existence

1.2.840.113556.1.4.1338

Used to target a specific GC server that is used to verify DN-valued attributes that are processed during addition or modification operations.

No referrals generated

1.2.840.113556.1.4.1339

Informs the server not to generate any referrals in a search response.

Domain or phantom scope

1.2.840.113556.1.4.1340

Used to pass flags to the server to control search options.

Search Stats

1.2.840.113556.1.4.970

Used to return statistics about an LDAP query. See Using the STATS Control to View LDAP Query Statistics for an example.

Attribute Scoped Query

1.2.840.113556.1.4.1504

Used to force a query to be based on a specific DN-valued attribute. This control is new to Windows Server 2003. See Searching for Objects in a Domain for an example.

Extended DN

1.2.840.113556.1.4.529

Used to return an object’s GUID and SID (for security principals) as part of its distinguished name.

Quota SID

1.2.840.113566.1.4.1852

Used to pass the SID of a security principal in order to query constructed attributes such as ms-DS-Quota-Effective and ms-DS-Quota-Used.

Paged Results

1.2.840.113556.1.4.319

Instructs the server to return search results in “pages.”

DIRSYNC

1.2.840.113556.1.4.841

Used to find objects that have changed over a period of time.

Server-side Sort Request

1.2.840.113556.1.4.473

Used to inform the server to sort the results of a search.

Server-side Sort Response

1.2.840.113556.1.4.474

Returned by the server in response to a sort request.

Show deactivated links

1.2.840.113556.1.4.2065

Used to request deactivated links to be included in a search.

Show deleted objects

1.2.840.113556.1.4.417

Used to request deleted objects to be included in a search.

VLV Request

2.16.840.1.113730.3.4.9

Used to request a virtual list view of results from a search. This control is new to Windows Server 2003.

VLV Response

2.16.840.1.113730.3.4.10

Response from a server returning a virtual list view of results from a search. This control is new to Windows Server 2003.

See Also

Searching for Objects in a Domain; Using the STATS Control to View LDAP Query Statistics; RFC 2251 (Lightweight Directory Access Protocol [v3]) for a description of LDAP controls; 3.1.1.3.4.1 LDAP Extended Controls; MSDN: Using Controls

Using a Fast or Concurrent Bind

Problem

You want to perform an LDAP bind using a concurrent bind, also known as a fast bind. Concurrent binds are typically used in situations where you need to authenticate a lot of users, and either those users do not need to directly access the directory or the directory access is done with another account.

Solution

Using a graphical user interface

  1. Open LDP.

  2. From the menu, select Connection→Connect.

  3. For Server, enter the name of a DC.

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Options→Connection Options.

  7. Under Option Name:, select LDAP_OPT_FAST_CONCURRENT_BIND.

  8. Click the Set button. Then click the Close button.

  9. From the menu, select Connection→Bind.

  10. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  11. Click OK.

Discussion

Unlike simple binding, concurrent binding does not generate a security token or determine a user’s group memberships during the authentication process. It determines only whether the authenticating user has a valid enabled account and password, which makes it much faster than a typical bind. This is usually used programmatically for AD-enabled applications to improve the speed of AD authentication; it’s not something that you’ll typically do on the fly. Concurrent binding is implemented as a session option that is set after you establish a connection to a domain controller, but before any bind attempts are made. After the option has been set, any bind attempt made with the connection will be a concurrent bind.

There are a couple of caveats when using concurrent binds. First, you cannot enable signing or encryption, which means that all data for concurrent binds will be sent over the network in clear text. Second, because the user’s security token is not generated, access to the directory is done anonymously and access restrictions are based on the ANONYMOUS LOGON principal.

It is worth mentioning that there is another type of fast bind that is completely different from the procedure just described. This fast bind is implemented within ADSI, and it simply means that when you fast-bind to an object, the objectClass attribute for the object is not retrieved; therefore, the object-specific IADs class interfaces are not available. For example, if you bind to a user object using an ADSI fast bind, then only the basic IADs interfaces will be available, not the IADsUser interfaces.

This is the complete list of interfaces that are available for objects retrieved with fast binds:

  • IADs

  • IADsContainer

  • IDirectoryObject

  • IDirectorySearch

  • IADsPropertyList

  • IADsObjectOptions

  • ISupportErrorInfo

  • IADsDeleteOps

You must use the IADsOpenDSObject::OpenDSObject interface to enable fast binds. If you call IADsContainer::GetObject on a child object of a parent you used a fast bind with, the same fast bind behavior applies. Unlike concurrent binds, ADSI fast binds do not impose any restrictions on the authenticating user. This means that the object-specific IADs interfaces will not be available. Also, no check is done to verify the object exists when you call OpenDSObject.

ADSI fast binds are useful when you need to make a lot of updates to objects that you know exist (perhaps from an ADO query that returned a list of DNs) and you do not need any IADs-specific interfaces. Instead of two trips over the network per object binding, there would be only one.

See Also

MSDN: Using Concurrent Binding; MSDN: ADS_AUTHENTICATION_ENUM

Connecting to an Object GUID

Problem

You want to bind to a container using its globally unique identifier (GUID).

Solution

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 leave it blank to do a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. From the menu, select Browse→Search.

  10. For BaseDN, enter the GUID of the object that you’re searching for in the following format:

    <GUID=758A39F4A44A0C48A16016457C1AE9E9>
  11. For Scope, select the appropriate scope.

  12. For Filter, enter an LDAP filter.

  13. Click Run.

Discussion

Each object in Active Directory has a GUID associated with it, stored in the objectGUID attribute. The GUID is, for most purposes, a unique identifier that retains its value even if an object is updated, renamed, or moved. This makes the GUID the preferable means of binding to an object, rather than hardcoding a reference to an object name that might change or by using a potentially complex LDAP query.

See Also

“‘GUIDs’ or ‘Having unique in the name doesn’t make it so...’” for a more in-depth discussion of the objectGUID attribute; MSDN: IADs.GUID; MSDN: Using objectGUID to Bind to an Object; Connecting to a Well-Known GUID

Connecting to a Well-Known GUID

Problem

You want to connect to LDAP using one of the well-known GUIDs in Active Directory.

Solution

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 leave it blank to do a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. From the menu, select View→Tree.

  10. For the DN, enter:

    <WKGUID=<WKGUID>,<DomainDN>>

    where <WKGUID> is the well-known GUID that you want to connect to, and <DomainDN> is the distinguished name of a domain.

  11. Click OK. In the lefthand menu, you can now browse the container corresponding to the well-known GUID that you specified.

Using a command-line interface

To enumerate the well-known GUIDs in the Domain NC, use the following syntax:

> adfind -default -s base wellknownObjects

To display the WKGUIDs in the Configuration NC, replace –default with –config in the previous syntax.

To connect to a well-known GUID in the Domain NC using AdFind, use the following syntax:

> adfind -b "<WKGUID=<WKGUID>,<DomainDN>>" -s base -dn

Note

Because of additional security settings attached to the Deleted Objects container, if you specify the GUID you must also use the –showdel switch in AdFind.

Using PowerShell

Get-ADObject (Get-ADRootDSE).DefaultNamingContext -Properties wellKnownObjects | Select wellKnownObjects -ExpandProperty wellknownobjects

Discussion

The Domain NC in Active Directory contains a number of well-known GUIDs that correspond to containers that exist in every AD implementation. These GUIDs are stored as wellKnownObjects attributes within the <DomainDN> object, and they allow administrators and developers to consistently connect to critical containers even if they are moved or renamed. The <DomainDN> container possesses the following objects that correspond to well-known GUIDs:

  • cn=NTDS Quotas,<DomainDN>

  • cn=Microsoft,cn=Program Data,<DomainDN>

  • cn=Program Data,<DomainDN>

  • cn=ForeignSecurityPrincipals,<DomainDN>

  • cn=Deleted Objects,<DomainDN>

  • cn=Infrastructure,<DomainDN>

  • cn=LostAndFound,<DomainDN>

  • cn=System,<DomainDN>

  • OU=Domain Controllers,<DomainDN>

  • cn=Computers,<DomainDN>

  • cn=Users,<DomainDN>

The Configuration NC adds these additional WKGUIDs:

  • cn=NTDS Quotas,cn=Configuration,<ForestRootDN>

  • cn=LostAndFoundConfig,cn=Configuration,<ForestRootDN>

  • cn=Deleted Objects,cn=Configuration,<ForestRootDN>

See Also

MSDN: Binding to Well-Known Objects Using WKGUID

Searching for Objects in a Domain

Problem

You want to find objects in a domain that match certain criteria.

Solution

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 leave it blank to do a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. From the menu, select Browse→Search.

  10. For BaseDN, type the base distinguished name where the search will start. (You can leave this blank if you wish to connect to the Domain NC as the base DN.)

  11. For Scope, select the appropriate scope.

  12. For Filter, enter an LDAP filter.

  13. Click Run.

Using a command-line interface

To run a query using the built-in DSQuery tool, use the following syntax:

> dsquery * <BaseDN> -scope <Scope> -filter "<Filter>" -attr "<AttrList>"

To retrieve the SAM account name for all user objects within the adatum.com domain, for example, use the following syntax:

> dsquery * dc=adatum,dc=com -filter
"(&(objectclass=user)(objectcategory=person))" -attr sAMAccountName

To run a query using adfind, use the following syntax:

> adfind -b <BaseDN> -s <Scope> -f <Filter> <Attributes>

Querying for SAM account names of user objects with adfind takes the following syntax:

> adfind -b dc=adatum,dc=com -f "(&(objectclass=user)(objectcategory=person))" sAMAccountName

Note

Both DSQuery and AdFind assume a default search scope of subtrees; you need only to specify the search scope if you want to use a different one.

Using PowerShell

The following example will search for user objects within the current Active Directory domain:

Get-ADObject -Filter {(objectClass -eq "user") -and (objectCategory -eq "person")}

Discussion

Most tools that can be used to search Active Directory require a basic understanding of how to perform LDAP searches using a base DN, search scope, and search filter, as described in RFC 2251 and RFC 2254. The base DN is where the search begins in the directory tree. The search scope defines how far down in the tree to search from the base DN. The search filter is a prefix notation string that contains equality comparisons of attribute and value pairs.

The scope can be base, onelevel (or one), or subtree (or sub). A base scope will match only the base DN, onelevel will match only objects that are contained directly under the base DN, and subtree will match everything from the base DN and any objects beneath it.

Note

There are no LDAP query scopes that will walk backward “up” the tree.

The search filter syntax is a powerful way to represent simple and complex queries. For example, a filter that matches all of the user objects would be (&(objectclass=user)(objectcategory=Person)). For more information on filters, see RFC 2254.

Using a graphical user interface

To customize the list of attributes returned for each matching object, look at the GUI discussion in Viewing the Attributes of an Object.

Using a command-line interface

<AttrList> should be a space-separated list of attributes to return. To return all attributes that have been populated with a value, leave this field blank or use an asterisk (*).

See Also

Viewing the Attributes of an Object for viewing attributes of objects; Searching the Global Catalog for setting advanced ADO options; RFC 2251 (Lightweight Directory Access Protocol [v3]); RFC 2254 (Lightweight Directory Access Protocol [v3]); “LDAP Query Basics”

Searching the Global Catalog

Problem

You want to perform a forest-wide search using the global catalog.

Solution

Using a graphical user interface

  1. Open LDP.

  2. From the menu, select Connection→Connect.

  3. For Server, enter the name of a global catalog server.

  4. For Port, enter 3268.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. From the menu, select Browse→Search.

  10. For BaseDN, type the base distinguished name of where to start the search.

  11. For Scope, select the appropriate scope.

  12. For Filter, enter an LDAP filter.

  13. Click Run.

Using a command-line interface

To query the global catalog using DSQuery, use the following syntax:

> dsquery * <BaseDN> -gc -scope <Scope> -filter "<Filter>" -attr "<AttrList>"

To run a query using AdFind, use the following syntax:

> adfind -gc -b <BaseDN> -s <Scope> -f <Filter> <Attributes>

Using PowerShell

To query the global catalog server named dc1.adatum.com for all computer objects in the adatum.com domain, run the following command:

Get-ADObject -Filter {ObjectClass -eq "computer"} -Server dc1.adatum.com:3268 -SearchBase "dc=adatum,dc=com" -Properties Name | FT Name

Discussion

The global catalog facilitates forest-wide searches. When you perform a normal LDAP search over port 389, you are searching against a particular partition within Active Directory, whether that is the Domain naming context, Configuration naming context, Schema naming context, or an application partition. If you have multiple domains in your forest, this type of search will not search against all domains; it will search only the domain that you specify.

The global catalog, by contrast, contains a subset of the attributes for all objects in the forest (excluding objects in application partitions). Think of it as a subset of all the naming contexts combined. Every object in the directory will be contained in the global catalog (except for objects contained within application partitions), but only some of the attributes of those objects will be available. For that reason, if you perform a global catalog search and do not get values for attributes you were expecting to, make sure those attributes are included in the global catalog, also known as the partial attribute set (PAS). See Modifying the Set of Attributes Stored on a Global Catalog for more information on adding information to the PAS. As an alternative, you can query a DC within the domain containing the object to return a list of all attributes configured for that object. Note that the Active Directory Administrative Center provides a method to easily change the scope of a search to be a global catalog search.

Using a graphical user interface

The only difference between this solution and the one in Searching for Objects in a Domain is that the port has changed to 3268, which is the standard GC port.

Using a command-line interface

The only difference between this solution and the one in Searching for Objects in a Domain, both for DSQuery and AdFind, is the addition of the -gc flag.

Searching for a Large Number of Objects

Problem

Your search is returning exactly 1,000 objects, which is only a subset of the objects you expected, and you want it to return all matching objects.

Solution

You might notice, when using some tools, that searches with large numbers of matches stop displaying after 1,000. By default, domain controllers return a maximum of 1,000 entries from a search unless paging is enabled. This is done to prevent queries from consuming excessive resources on domain controllers by retrieving the results all at once instead of in pages or batches. The following examples are variations of Searching for Objects in a Domain, which will show how to enable paging and return all matching entries.

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 leave it blank to do a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. From the menu, select Browse→Search.

  10. For BaseDN, type the base distinguished name of where the search will start. (You can leave this blank if you wish to connect to the domain NC as the base DN.)

  11. For Scope, select the appropriate scope.

  12. For Filter, enter an LDAP filter.

  13. Click Options to customize the options for this query.

  14. For “Time limit,” enter a value such as 120.

  15. For “Size limit,” enter the number of objects to be returned with each page (e.g., 1,000).

  16. Under Search Call Type, select Paged.

  17. Click OK and then Run to perform the query. A page of results (i.e., 1,000 entries) will be displayed each time you click Run until all results have been returned.

Using a command-line interface

> dsquery * <BaseDN> -limit 0 -scope <Scope> -filter "<Filter>" -attr "<AttrList>"

Using PowerShell

The following PowerShell command will search the default Users container and return all objects while limiting results to 12,000 objects:

Get-ADObject -SearchBase "cn=users,dc=adatum,dc=com" -Filter * -ResultSetSize 12000

Discussion

Paged searching support is implemented via an LDAP control. LDAP controls were defined in RFC 2251 and the Paged control in RFC 2696. Controls are extensions to LDAP that were not built into the protocol, so not all directory vendors support the same ones.

Note

In Active Directory, you can change the default maximum page size of 1,000 by modifying the LDAP query policy. See Modifying the Default LDAP Query Policy for more information.

Active Directory will return a maximum of 256 KB of data even when paged searching is enabled. This value is defined in the LDAP query policy and can be modified like the maximum page size (see Modifying the Default LDAP Query Policy).

Using a graphical user interface

A word of caution when using LDP to display a large number of entries: by default, only 2,048 lines will be displayed in the right pane. To change that value, go to Options→General and change the number of lines under Buffer Size to a larger number. Note that newer tools aren’t as limited as some of the tools that have been around a long time. For example, the Active Directory Administrative Center displays up to 20,000 objects in a search by default.

Using a command-line interface

The only difference between this solution and the one in Searching for Objects in a Domain is the addition of the -limit 0 flag. With -limit set to 0, paging will be enabled according to the default LDAP query policy; matching objects will be returned within those parameters. If -limit is not specified, a maximum of 100 entries will be returned.

Note

AdFind enables paged searches by default; it will return any number of objects from a query without any modification.

See Also

Searching for Objects in a Domain for searching for objects; Modifying the Default LDAP Query Policy for viewing the default LDAP policy; RFC 2251 (Lightweight Directory Access Protocol [v3]); RFC 2696 (LDAP Control Extension for Simple Paged Results Manipulation)

Searching with an Attribute-Scoped Query

Problem

You want to perform a search using an individual value within a multivalued attribute as part of the search criteria. An attribute-scoped query can do this in a single query, instead of the previous method, which required multiple queries.

Solution

Using a graphical user interface

  1. Follow the steps in Using LDAP Controls to enable an LDAP control.

  2. Select the Attribute Scoped Query control.

  3. For Value, enter the multivalued attribute name (e.g., member).

  4. Click the “Check in” button.

  5. Click OK.

  6. From the menu, select Browse→Search.

  7. For BaseDN, type the DN of the object that contains the multivalued attributes.

  8. For Scope, select Base.

  9. For Filter, enter an LDAP filter to match against the objects that are part of the multivalued DN attribute.

  10. Click Run.

Warning

Attribute-scoped queries can only be performed using a Base scope.

Using a command-line interface

AdFind allows attribute-scoped queries by using the -asq switch. For example:

adfind -b cn=somegroup,cn=users,dc=domain,dc=group -asq member -f objectclass=user
samaccountname

Using PowerShell

The PowerShell pipeline will allow you to perform an attribute-scoped query as follows:

Get-ADGroup "Domain Admins" | Get-ADGroupMember |Get-ADUser -Properties sAMAccountName | Select samaccountname

Discussion

When dealing with group objects, you may have encountered the problem where you wanted to search against the members of a group to find a subset or to retrieve certain attributes about each member. This normally involved performing a query to retrieve all of the members, and additional queries to retrieve whatever attributes you needed for each member. This was less than ideal, so an alternative was developed.

With an attribute-scoped query, you can perform a single query against the group object and return whatever properties you need from the member’s object, or return only a subset of the members based on certain criteria. Let’s look at the LDAP search parameters for an attribute-scoped query:

Attribute-scoped query control value

The value to set for this control should be the DN attribute that you want to iterate over (for example, member).

Base DN

This must be the DN of the object that contains the DN attribute (e.g., cn=Domain Admins,cn=users,dc=adatum,dc=com).

Scope

This must be set to Base to query only the group object itself.

Filter

The filter will match against objects defined in the Control Value. For example, a filter of (objectClass=computer) would match computer objects only. You can also use any other attributes that are available with those objects. The following filter would match all computer objects that have a Description attribute equal to “Sales”:

(&(objectclass=computer)(Description=Sales))
Attributes

This should contain the list of attributes to return for the objects matched in the DN attribute.

When performing an attribute-scoped query against a member attribute, it’s important to remember that primary group membership is handled as a special case; as such you may experience unpredictable results in this situation.

See Also

Using LDAP Controls; MSDN: Performing an Attribute Scoped Query

Searching with a Bitwise Filter

Problem

You want to search against an attribute that contains a bit flag, which requires you to use a bitwise filter to perform the search.

Solution

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 leave it blank to do a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. From the menu, select Browse→Search.

  10. For Base DN, type the base distinguished name of where the search will start. (You can leave this blank if you wish to connect to the domain NC as the base DN.)

  11. For Scope, select the appropriate scope.

  12. For the Filter, enter the bitwise expression, such as the following, which will find all universal groups:

    (&(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=8))
  13. Click Run.

Using a command-line interface

The following query finds universal groups in the adatum.com domain by using a bitwise AND filter:

> dsquery * dc=adatum,dc=com -scope subtree -attr "name" -filter"(&(objectclass=group)(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=8) )"

The following query finds disabled user accounts in the adatum.com domain by using a bitwise AND filter:

> dsquery * dc=adatum,dc=com -attr name -scope subtree -filter
"(&(objectclass=user)(objectcategory=person)(useraccountcontrol:1.2.840.113556.1.4.
803:=2))"

You can also perform queries that use bitwise filters using AdFind. The following will find all disabled user accounts in the adatum.com domain:

> adfind -default -bit -f useraccountcontrol:AND:=2

Similarly, the following will return all universal groups in the adatum.com domain using a bitwise filter:

> adfind -default -bit -f groupType:AND:=8

Using PowerShell

The following command will find all universal groups in the current domain:

Get-ADObject -LDAPFilter {(groupType:1.2.840.113556.1.4.803:=8)} | Select Name

Discussion

Many attributes in Active Directory are composed of bit flags. A bit flag is often used to encode properties about an object into a single attribute. For example, the groupType attribute on group objects is a bit flag that is used to determine the group scope and type.

The userAccountControl attribute on user and computer objects is used to describe a whole series of properties, including account status (i.e., enabled or disabled), account lockout, password not required, smartcard authentication required, and so on.

The searchFlags and systemFlags attributes on attributeSchema objects define, among other things, whether an attribute is constructed, indexed, and included as part of Ambiguous Name Resolution (ANR).

To search against these types of attributes, you need to use bitwise search filters. There are two types of bitwise search filters you can use, one that represents a logical OR and one that represents a logical AND. This is implemented within a search filter as a matching rule. A matching rule is simply a way to inform the LDAP server (in this case, a domain controller) to treat part of the filter differently. Here is an example of what a matching rule looks like:

(userAccountControl:1.2.840.113556.1.4.803:=514)

The format is (attributename:MatchingRuleOID:=value), though AdFind allows you to use an easier syntax for bitwise queries. As mentioned, there are two bitwise matching rules, which are defined by OIDs. The logical AND matching rule OID is 1.2.840.113556.1.4.803, and the logical OR matching rule OID is 1.2.840.113556.1.4.804. These OIDs instruct the server to perform special processing on the filter. A logical OR filter will return success if any bit specified by value is stored in attributename. Alternatively, the logical AND filter will return success if all bits specified by value match the value of attributename. Perhaps an example will help clarify this.

To create a normal user account, you have to set userAccountControl to 514. The number 514 was calculated by adding the normal user account flag of 512 together with the disabled account flag of 2 (512 + 2 = 514). If you use the following logical OR matching rule against the 514 value, as shown here:

(useraccountcontrol:1.2.840.113556.1.4.804:=514)

then all normal user accounts (flag 512) OR disabled accounts (flag 2) would be returned. This would include enabled user accounts (from flag 512), disabled computer accounts (from flag 2), and disabled user accounts (from flag 2). In the case of userAccountControl, flag 2 can apply to both user and computer accounts, which is why both would be included in the returned entries.

One of the benefits of bitwise matching rules is that they allow you to combine a bunch of comparisons into a single filter. In fact, it may help to think that the OR filter could also be written using two expressions:

(|(useraccountcontrol:1.2.840.113556.1.4.804:=2)
(useraccountcontrol:1.2.840.113556.1.4.804:=512))

Just as before, this will match userAccountControl attributes that contain either the 2 or 512 flag; we’re performing two OR operations against the same value, first ORing the value against 2, then against 512.

For the logical AND operator, similar principles apply. Instead of any of the bits in the flag being a possible match, all of the bits in the flag must match for it to return a success. If the userAccountControl example was changed to use logical AND, it would look like this:

(useraccountcontrol:1.2.840.113556.1.4.803:=514)

In this case, only normal user accounts that are also disabled would be returned. The same filter could be rewritten using the & operator instead of | as in the following:

(&(useraccountcontrol:1.2.840.113556.1.4.803:=2)
(useraccountcontrol:1.2.840.113556.1.4.803:=512))

An important subtlety to note is that when you are comparing only a single bit-flag value, the logical OR and logical AND matching rules would return the same result. So, if you wanted to find any normal user accounts, you could search on the single bit flag of 512 using either of the following:

(useraccountcontrol:1.2.840.113556.1.4.803:=512)

(useraccountcontrol:1.2.840.113556.1.4.804:=512)

Using PowerShell

Searching on a bitwise operator in PowerShell is done using the appropriate LDAP filter, as you can see. In other chapters we will look at individual AD cmdlets that mask the bitwise search into a more human-readable operation, such as the Enable-ADAccount and Disable-ADAccount cmdlets.

See Also

MSDN: Enumerating Groups by Scope or Type in a Domain; MSDN: Determining Which Properties Are Non-Replicated, Constructed, Global Catalog, and Indexed; MS KB 305144 (How to Use the UserAccountControl Flags to Manipulate User Account Properties)

Creating an Object

Problem

You want to create an object.

Solution

In each solution in this recipe, an example of adding a user object is shown. Modify the examples as needed to include whatever class and attributes you need to create.

Using a graphical user interface

  1. Open ADSI Edit.

  2. If an entry for the naming context you want to browse is not already displayed, do the following:

    1. Right-click on ADSI Edit in the right pane and click “Connect to.”

    2. Fill in the information for the naming context, container, or OU you want to add an object to. Click on the Advanced button if you need to enter alternate credentials.

  3. In the left pane, browse to the container or OU you want to add the object to. Once you’ve found the parent container, right-click on it and select New→Object.

  4. Under Select a Class, select user.

  5. For the cn, enter jsmith and click Next.

  6. For sAMAccountName, enter jsmith and click Next.

  7. Click the More Attributes button to enter additional attributes.

  8. Click Finish.

Using a command-line interface

Create an LDAP Data Interchange Format (LDIF) file called create_object.ldf with the following contents:

dn: cn=jsmith,cn=users,dc=adatum,dc=com
changetype: add
objectClass: user
samaccountname: jsmith

Then run the following command:

> ldifde -v -i -f create_object.ldf

It is also worth noting that you can add a limited number of object types with the dsadd command. Run dsadd /? from a command line for more details.

You can also create objects using AdMod; to create a new user object in the adatum.com domain use the following syntax:

> admod -b "cn=Joe Smith,cn=users,dc=adatum,dc=com" objectclass::user samaccountname::jsmith -add

Using PowerShell

To create a new computer object named Kiosk2 in the Workstations OU, use the following PowerShell command:

New-ADObject -Path "OU=Workstations,dc=adatum,dc=com" -Type Computer -Name "Kiosk2" -Description "Computer in lobby" -OtherAttributes @{SamAccountName="Kiosk2"}

Discussion

To create an object in Active Directory, you have to specify the objectClass, RDN value, and any other mandatory attributes that are not automatically set by Active Directory. Some of the automatically generated attributes include objectGUID, instanceType, and objectCategory.

In the jsmith example, the object class was user, the RDN value was jsmith, and the only other attribute set was sAMAccountName. Admittedly, this user object is unusable in its current state because it will be disabled by default and no password was set, but it should give you an idea of how to create an object. In the case of a user object, you’ll need to configure a password that meets any existing password complexity requirements before enabling the user.

Using a graphical user interface

Other tools, such as Active Directory Administrative Center and AD Users and Computers, could be used to do the same thing, but ADSI Edit is useful as a generic object editor.

One attribute that you will not be able to set via ADSI Edit is the password (unicodePwd attribute). It is stored in binary form and needs to be edited using a secure connection. If you want to set the password for a user through a GUI, you can do it with the AD Users and Computers snap-in or Active Directory Administrative Center.

Using a command-line interface

For more on ldifde, see Exporting Objects to an LDIF File.

With DSAdd, you can set numerous attributes when creating an object. The downside is that you can create only the following object types: computer, contact, group, OU, quota, and user.

See Also

Exporting Objects to an LDIF File; Importing Objects Using an LDIF File for importing objects with LDIF; MSDN: IADsContainer::GetObject; MSDN: IADsContainer::Create; MSDN: IADs::Put; MSDN: IADs::SetInfo

Modifying an Object

Problem

You want to modify one or more attributes of an object.

Solution

The following example sets the employeeID attribute for a user object.

Using a graphical user interface

  1. Open Active Directory Administrative Center.

  2. In the bottom-right pane, enter the search criteria of the desired object and then click the Search button.

  3. In the search results, locate the object, right-click it, and then click Properties.

  4. Scroll down to the Extensions section and then click the Attribute Editor tab.

  5. Scroll down and click the employeeID attribute and then click the Edit button.

  6. Enter the value and then click OK.

  7. Click OK again to close the object properties.

Using a command-line interface

Create an LDIF file called modify_object.ldf with the following contents:

dn: cn=jsmith,cn=users,dc=adatum,dc=com
changetype: modify
replace: employeeID
employeeID: 17320
-

Then run the following command:

> ldifde -v -i -f modify_object.ldf

To modify an object using AdMod, you’ll use the following general syntax:

> admod -b <ObjectDN> <attribute>:<operation>:<value>

For example, you can add a description to a user object using the following syntax:

> admod -b cn="Joe Smith,cn=Users,dc=adatum,dc=com" description::Consultant

You can modify a limited number of object types with the dsmod command. Run dsmod /? from a command line for more details.

Using PowerShell

To modify an object using PowerShell, use the following syntax:

Set-ADObject -Identity <"ObjectDN"> -Replace @{<property>=<"value">}

Discussion

Using a command-line interface

For more on ldifde, see Exporting Objects to an LDIF File.

As of the publication of this book, the only types of objects you can modify with DSMod are the following: computer, contact, group, OU, server, quota, partition, and user.

As you saw in this recipe, the basic format of the AdMod command when used to modify an attribute is as follows:

> admod -b <ObjectDN> <attribute>:<operation>:<value>

The value used for <operation> can be any one of the following:

<blank>

Updates the attribute with the new value. (In practical terms, this leads to a syntax of <attribute>::<value>, with nothing included between the two colons.)

+

Adds a value to an attribute.

Clears an attribute.

++

Adds multiple values to an attribute.

−−

Removes multiple values from an attribute.

Note

To change a user’s password via AdMod, encrypt the connection by using the -kerbenc switch and then modify the unicodepwd attribute.

See Also

MSDN: IADs::Put; MSDN: IADs::PutEx; MSDN: IADs::SetInfo; MSDN: ADS_ PROPERTY_OPERATION_ENUM

Modifying a Bit-Flag Attribute

Problem

You want to safely modify an attribute that contains a bit flag, without blindly overwriting its existing contents. The solutions in this recipe modify a new attribute named adatum-UserProperties that was previously added to the schema.

Solution

Using VBScript

' This code safely modifies a bit flag attribute
' ------ SCRIPT CONFIGURATION ------
strObject = "<ObjectDN>" ' e.g. cn=jsmith,cn=users,dc=adatum,dc=com
strAttr = "<AttrName>" ' e.g. adatum-UserProperties
boolEnableBit = <TRUEorFALSE> ' e.g. FALSE
intBit = <BitValue> ' e.g. 16
' ------ END CONFIGURATION --------

set objObject = GetObject("LDAP://" & strObject)
intBitsOrig = objObject.Get(strAttr)
intBitsCalc = CalcBit(intBitsOrig, intBit, boolEnableBit)

if intBitsOrig <> intBitsCalc then
   objObject.Put strAttr, intBitsCalc
   objObject.SetInfo
   WScript.Echo "Changed " & strAttr & " from " & intBitsOrig &↵
" to " & intBitsCalc
else
   WScript.Echo "Did not need to change " & strAttr & " (" & intBitsOrig & ")"
end if

Function CalcBit(intValue, intBit, boolEnable)

   CalcBit = intValue

   if boolEnable = TRUE then
      CalcBit = intValue Or intBit
   else
      if intValue And intBit then
         CalcBit = intValue Xor intBit
      end if
   end if

End Function

Using PowerShell

To set the adatum-UserProperties value using PowerShell, use the following example script:

$user = Get-ADObject "cn=jsmith,cn=users,dc=adatum,dc=com" -Properties adatum-UserProperties
if (!$user.adatum-UserProperties) {
Set-ADObject $user -Add @{"adatum-UserProperties"=4}
Write-Host "Changed from NULL to 4."
} else {
$value = $user.adatum-UserProperties + 4
Set-ADObject $user -Replace @{"adatum-UserProperties"=$value}
Write-Host "Changed value from" $user.adatum-UserProperties "to" $value"."
}

Discussion

Searching with a Bitwise Filter described how to search against attributes that contain a bit flag, which is used to encode various settings about an object in a single attribute. As a quick recap, you need to use a logical OR operation to match any bits being searched against, and a logical AND to match a specific set of bits. If you want to set an attribute that is a bit flag, you need to take special precautions to ensure that you don’t overwrite an existing bit. Let’s consider an example. Adatum wants to secretly store some politically incorrect information about their users, such as whether the user is really old or has big feet. They don’t want to create attributes such as adatum-UserHasBigFeet, so they decide to encode the properties in a single bit-flag attribute. They decide to call the attribute adatum-UserProperties with the possible bit values shown in Table 4-3.

Table 4-3. Sample bit-flag attribute values

Value

Description

1

User is overweight.

2

User is very tall.

4

User has big feet.

8

User is very old.

After they extend the schema to include the new attribute, Adatum needs to initially populate the attribute for all their users. To do so they can simply logically OR the values together that apply to each user. So, if settings 4 and 8 apply to the jsmith user, his adatum-UserProperties would be set to 12 (4 OR 8). No big deal so far. The issue comes in when they need to modify the attribute in the future.

Note

You will, however, find that searching for information based on a bit-flag attribute is not terribly efficient. This is because bit flags cannot be indexed; you need to calculate the value for every object populated with the bit-flag attribute in question.

They later find out that jsmith was a former basketball player and is 6′8″. They need to set the 2 bit (for being tall) in his adatum-UserProperties attribute. To set the 2 bit they need to first determine whether it has already been set. If it has already been set, then there is nothing to do. If the 2 bit hasn’t been set, they need to logical OR 2 with the existing value of jsmith’s adatum-UserProperties attribute. If they simply set the attribute to 2, it would overwrite the 4 and 8 bits that had been set previously. In the VBScript solution, they could use the CalcBit function to determine the new value:

intBitsCalc = CalcBit(intBitsOrig, 2, TRUE)

The result would be 14 (12 OR 2).

The same logic applies if they want to remove a bit, except the XOR logical operator is used.

Warning

Active Directory contains numerous bit-flag attributes, most notably options (which is used on several different object classes) and userAccountControl (which is used on user objects). We do not recommend blindly setting those attributes unless you know what you are doing. It is preferable to use a script from this recipe so that it calculates the new value based on the existing value.

You should note that it’s certainly possible to modify bitwise attributes using a GUI tool like ADSI Edit or a command-line tool like DSMod. However, it will require a certain amount of manual effort, as you’ll first need to make note of the existing attribute value and then calculate the new value using a calculator or some other method. The VBScript solution presented here simply automates that process by performing the lookup and calculations for you.

Using PowerShell

The PowerShell solution looks at the existing adatum-UserProperties attribute value. If it is null, it changes it to 4. If it contains a value already, it takes that value and adds 4 to it, and then replaces the existing value with the new value.

See Also

Searching with a Bitwise Filter for searching with a bitwise filter

Dynamically Linking an Auxiliary Class

Problem

You want to dynamically link an auxiliary class to an existing object instance.

Solution

In each solution in this recipe, an example of adding the custom adatum-SalesUser auxiliary class to the jsmith user object will be described.

Using a graphical user interface

  1. Open ADSI Edit.

  2. If an entry for the naming context you want to browse is not already displayed, do the following:

    1. Right-click on ADSI Edit in the right pane and click “Connect to.”

    2. Fill in the information for the naming context, container, or OU you want to add an object to. Click the Advanced button if you need to enter alternate credentials.

  3. In the left pane, browse to the container or OU that contains the object you want to modify. Once you’ve found the object, right-click on it and select Properties.

  4. Edit the values for the objectClass attribute.

  5. For “Value to add,” enter adatum-SalesUser.

  6. Click Add.

  7. Click OK twice.

Using a command-line interface

Create an LDIF file called dynamically_link_class.ldf with the following contents:

dn: cn=jsmith,cn=users,dc=adatum,dc=com
changetype: modify
add: objectClass
objectClass: adatum-SalesUser
-

Then run the following command:

> ldifde -v -i -f dynamically_link_class.ldf

Alternatively, you can use AdMod as follows:

> admod -b <ObjectDN> objectClass:+:<Dynamic Object Class>

Using PowerShell

Set-ADObject -Identity "cn=jsmith,cn=users,dc=adatum,dc=com" -Add @{ObjectClass="adatum-SalesUser"}

Discussion

Dynamically linking an auxiliary class to an object is an easy way to use new attributes without modifying the existing object class definition in the schema.

A situation in which it makes more sense to dynamically link auxiliary classes than to link them statically is when several organizations or divisions within a company maintain their own user objects and want to add new attributes to the user class.

It is also worth mentioning that extensive use of dynamically linked auxiliary classes can lead to problems. If several groups are using different auxiliary classes, it might become hard to determine what attributes you can expect on your user objects. Essentially, you could end up with many variations of a user class that each group has implemented through the use of dynamic auxiliary classes. For this reason, use of dynamic auxiliary classes should be closely monitored. In addition, some tools that access Active Directory may not work properly with auxiliary classes.

See Also

Modifying an Object for modifying an object

Creating a Dynamic Object

Problem

You want to create an object that is automatically expired and removed from the directory after a period of time.

Solution

Using a graphical user interface

  1. Open LDP.

  2. Click Connection→Connect and click OK.

  3. Click Connection→Bind.

  4. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  5. Click View→Tree. Enter the DN of the parent container of the object you want to create and then click OK.

  6. Click Browse→Add Child. The Add window will appear.

  7. In the DN text box, enter the DN of the new object.

  8. In the Attribute text box, enter objectClass. In the Values text box, enter the object class of the object you are creating, such as 'user'. Click Enter. In the Values text box, type dynamicObject and click Enter.

  9. In the Attribute text box, type entryTTL. In the Values text box, enter the time to live (TTL) of the object you are creating, such as '3600'. Click Enter.

  10. Enter any other attributes and values that you wish to populate in the Attribute and Values text boxes.

  11. Click Run.

Using a command-line interface

Create an LDIF file called create_dynamic_object.ldf with the following contents:

dn: cn=jsmith,cn=users,dc=adatum,dc=com
changetype: add
objectClass: user
objectClass: dynamicObject
entryTTL: 1800
sAMAccountName: jsmith

Then run the following command:

> ldifde -v -i -f create_dynamic_object.ldf

Discussion

The ability to create dynamic objects allows you to create objects that have a limited lifespan before they are automatically removed from the directory. To create a dynamic object, you simply need to specify the objectClass to have a value of dynamicObject in addition to its structural objectClass (e.g., user) value when instantiating the object. The entryTTL attribute can also be set to the number of seconds before the object is automatically deleted. If entryTTL is not set, the object will use the dynamicObjectDefaultTTL attribute specified in the domain. The entryTTL cannot be lower than the dynamicObjectMinTTL for the domain. See Modifying the Default TTL Settings for Dynamic Objects for more information on how to view and modify these default values.

Dynamic objects have a few special properties worth noting:

  • A static object cannot be turned into a dynamic object. The object must be marked as dynamic when it is created.

  • Dynamic objects cannot be created in the Configuration NC and Schema NC.

  • Dynamic objects do not leave behind tombstone objects.

  • Dynamic objects that are containers cannot have static child objects.

  • A dynamic container will not expire prior to any child objects contained within it. If the dynamic container has a lower TTL value than any of the children, once the container’s TTL expires it will be reset to the highest TTL value of the children plus one second.

See Also

Refreshing a Dynamic Object for refreshing a dynamic object; Modifying the Default TTL Settings for Dynamic Objects for modifying the default dynamic object properties

Refreshing a Dynamic Object

Problem

You want to refresh a dynamic object to keep it from expiring and getting deleted from Active Directory.

Solution

In each solution in this recipe, an example of adding a user object is used. Modify the examples as needed to refresh whatever object is needed.

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 leave it blank to do a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. Select Browse→Modify.

  10. For DN, enter the DN of the dynamic object you want to refresh.

  11. For Attribute, enter entryTTL.

  12. For Values, enter the new time to live (TTL) for the object in seconds.

  13. Under Operation, select Replace.

  14. Click Enter.

  15. Click Run.

Using a command-line interface

Create an LDIF file called refresh_dynamic_object.ldf with the following contents:

dn: cn=jsmith,cn=users,dc=adatum,dc=com
changetype: modify
replace: entryTTL
entryTTL: 1800
-

Then run the following command:

> ldifde -v -i -f refresh_dynamic_object.ldf

You can also use AdMod with the following syntax:

> admod -b <ObjectDN> entryTTL::<TTL in Seconds>

Using PowerShell

To refresh a dynamic object using PowerShell, use the following command:

Set-ADObject -Identity "cn=jsmith,cn=users,dc=adatum,dc=com" -Replace @{entryTTL="1800"}

Discussion

Dynamic objects expire after their TTL becomes 0. You can determine when a dynamic object will expire by looking at the current value of an object’s entryTTL attribute or by querying msDS-Entry-Time-To-Die, which contains the seconds remaining until expiration. If you’ve created a dynamic object and need to refresh it so that it will not get deleted, you must reset the entryTTL attribute to a new value. There is no limit to the number of times you can refresh a dynamic object. As long as the entryTTL value does not reach 0, the object will remain in Active Directory.

See Also

Modifying an Object for modifying an object; “Dynamic Objects (Windows)”; Creating a Dynamic Object for creating a dynamic object

Modifying the Default TTL Settings for Dynamic Objects

Problem

You want to modify the minimum and default TTLs for dynamic objects.

Solution

In each solution in this recipe, we’ll show how to set the DynamicObjectDefaultTTL setting to 172800. Modifying the DynamicObjectMinTTL can be done in the same manner.

Using a graphical user interface

  1. Open ADSI Edit.

  2. If an entry for the Configuration naming context is not already displayed, do the following:

    1. Right-click on ADSI Edit in the right pane and click “Connect to.”

    2. Fill in the information for the naming context for your forest. Click on the Advanced button if you need to enter alternate credentials.

  3. In the left pane, browse to the following path under the Configuration naming context: Services→Windows NT→Directory Service.

  4. Right-click cn=Directory Service and select Properties.

  5. Edit the msDS-Other-Settings attribute.

  6. Click on DynamicObjectDefaultTTL= <xxxxx> and click Remove.

  7. The attribute/value pair should have been populated in the “Value to add” field.

  8. Edit the number part of the value to be 172800.

  9. Click Add.

  10. Click OK twice.

Using a command-line interface

The following ntdsutil command connects to <DomainControllerName>, displays the current values for the dynamic object TTL settings, sets the DynamicObjectDefaultTTL to 172800, commits the change, and displays the results:

> ntdsutil "config settings" connections "connect to server <DomainControllerName>" q "show values" "set DynamicObjectDefaultTTL to 172800""commit changes"
"show values" q q

Discussion

Two configuration settings apply to dynamic objects:

dynamicObjectDefaultTTL

Defines the default TTL that is set for a dynamic object at creation time unless another one is set via entryTTL

dynamicObjectMinTTL

Defines the smallest TTL that can be configured for a dynamic object

Unfortunately, these two settings are not stored as discrete attributes. Instead, they are stored as attribute value assertions (AVAs) in the msDS-Other-Settings attribute on the cn=DirectoryServices,cn=WindowsNT,cn=Configuration,<ForestRootDN> object. AVAs are used occasionally in Active Directory on multivalued attributes, in which the values take the form of Setting1=Value1,Setting2=Value2, and so on.

For this reason, you cannot simply manipulate AVA attributes as you would another attribute. You have to be sure to add or replace values with the same format, as they existed previously.

Using a command-line interface

You can use ntdsutil in interactive mode or in single-command mode. In this solution, we’ve included all the necessary commands on a single line. You can, of course, step through each command by simply running ntdsutil in interactive mode and entering each command one by one.

See Also

Modifying an Object for modifying an object; MSDN: Regular Expression (RegExp) Object

Moving an Object to a Different OU or Container

Problem

You want to move an object to a different container or OU.

Solution

Using a graphical user interface

  1. Open Active Directory Administrative Center.

  2. In the bottom-right pane, enter the search criteria of the desired object and then click the Search button.

  3. In the search results, locate the object, right-click it, and then click Move.

  4. In the dialog box, browse to the destination container, click to highlight it, and then click OK to move the object.

    Note

    You can also move objects by using the ADSI Edit tool or the Active Directory Users and Computers snap-in.

Using a command-line interface

To move an object to a new parent container within the same domain, you can use either dsmove or admod, as follows:

> dsmove "<ObjectDN>" -newparent "<NewParentDN>"

or:

> admod -b <ObjectDN> -move "<NewParentDN>"

Using PowerShell

To move an Active Directory object using PowerShell, use the following syntax:

Move-ADObject -Identity <ObjectDN> -TargetPath <NewParentDN>

Discussion

Using a command-line interface

The DSMove utility can work against any type of object (it has no limitations, as with DSAdd and DSMod). The first parameter is the DN of the object to be moved. The second parameter is the new parent container of the object. The -s parameter can additionally be used to designate a specific server to work against.

Note

Regardless of the method you use to move objects, you need to ensure that the user who is performing the move has the appropriate permissions to create objects in the destination container and delete objects from the source container.

See Also

Renaming an Object; MSDN: IADsContainer::MoveHere

Moving an Object to a Different Domain

Problem

You want to move an object to a different domain.

Solution

Using a graphical user interface (ADMT 3.2)

To migrate a computer object between domains in the same forest, use the following steps:

  1. Open the ADMT MMC snap-in.

  2. Right-click on the Active Directory Migration Tool folder and select the Computer Migration Wizard.

  3. On the Welcome screen, click Next.

  4. On the Domain Selection page, enter the DNS or NetBIOS name of the source and target domains. Click Next.

  5. On the Computer Selection Option screen, select the option to select computer from the domain and then click Next.

  6. On the Computer Selection screen, click Add and use the object picker to select a computer object. Click OK to return to the Computer Selection screen and then click Next.

  7. On the Organizational Unit Selection screen, enter the destination OU in the new domain and then click Next.

  8. On the Translate Objects screen, specify which objects should have new ACLs applied in the new domain. Select any, none, or all of the following, and then click Next to continue:

    • Files and folders

    • Local groups

    • Printers

    • Registry

    • Shares

    • User profiles

    • User rights

  9. On the Computer Options screen, click Next to maintain the default reboot time of 5 minutes.

  10. On the Object Property Exclusion screen, select any object properties that you do not want to migrate and then click Next.

  11. On the Conflict Management screen, click Next to accept the default that will not migrate the computer if there is a conflict.

  12. On the Completing the Computer Migration Wizard screen, review the migration settings and then click Finish to complete the move.

Using PowerShell

In the following example, the cn=jsmith object in the amer.adatum.com domain will be moved to the emea.adatum.com domain:

Move-ADObject -Identity "cn=jsmith,cn=users,dc=amer,dc=adatum,dc=com" -TargetPath "ou=MigratedUsers,dc=emea,dc=adatum,dc=com" -TargetServer dc-emea1.emea.adatum.com -Credential "emea\Administrator"

Discussion

At the time of this writing, the current version of ADMT, version 3.2, is not supported on Windows Server 2012. Therefore, you should install it on a previous version of Windows Server as part of the migration to Windows Server 2012. You can move objects between domains assuming you follow a few guidelines:

  • The user performing the move operation must have permission to modify objects in the parent container of both domains.

  • You need to explicitly specify the target DC (serverless binds usually do not work). This is necessary because the “Cross Domain Move” LDAP control is being used behind the scenes. For more information on controls, see Using LDAP Controls.

  • The move operation must be performed against the RID master for both domains.

  • When you move a user object to a different domain, its objectSID is replaced with a new SID (based on the new domain), and the old SID is optionally added to the sIDHistory attribute.

See Also

Using LDAP Controls for more information on LDAP controls; MS KB 238394 (How to Use the MoveTree Utility to Move Objects Between Domains in a Single Forest); MSDN: IADsContainer::MoveHere; “ADMT Guide: Migrating and Restructuring Active Directory Domains”

Referencing an External Domain

Problem

You need to create a reference to an external Active Directory domain.

Solution

Using a graphical user interface

  1. Open ADSI Edit.

  2. If an entry for the naming context you want to browse is not already displayed, do the following:

    1. Right-click on ADSI Edit in the right pane and click “Connect to.”

    2. Fill in the information for the naming context, container, or OU you want to add an object to. Click on the Advanced button if you need to enter alternate credentials.

  3. Right-click on the top-level node and open a connection to the Configuration NC.

  4. Right-click on the Partitions container and select New→Object. Click Next.

  5. Right-click on crossRef and click Next.

  6. For the cn attribute, enter the FQDN of the external domain—othercorp.com, for example. Click Next.

  7. For the nCName attribute, enter the DN of the external domain, such as dc=othercorp,dc=com. Click Next.

  8. For the dnsRoot attribute, enter the DNS name of a server that can respond to LDAP queries about the domain in question, such as dc1.othercorp.com.

  9. Click Next and then Finish to create the crossRef object.

Using a command-line interface

Create an LDIF file called create_crossref.ldf with the following contents:

dn: cn=othercorp.com,cn=partitions,cn=configuration,dc=adatum,dc=com
changetype: add
objectClass: crossRef
cn: othercorp.com
nCName: dc=othercorp,dc=com
dnsRoot: dc1.othercorp.com

Then run the following command:

> ldifde -v -i -f create_crossref.ldf

You can also create a crossRef using AdMod as follows:

> admod -config -rb cn=othercorp.com,cn=partitions↵
objectClass::crossRef cn::othercorp.com nCName::dc=othercorp,dc=com↵
dnsRoot::dc1.othercorp.com -add

Discussion

Similar to the way in which DNS servers use iterative queries to resolve hostnames that can be resolved only by remote servers, LDAP uses referrals to resolve queries for objects contained in naming contexts that are not hosted by the local DC. When a DC receives any query, it will search the Partitions container for a crossRef object containing the DN that’s being used as the Base DN of the query. If the DC locates a crossRef that matches the search base of the query, and that crossRef indicates a naming context that’s hosted by the domain controller itself, then the DC will perform the search locally. If the crossRef refers to an NC that’s hosted on a remote server, the DC generates a referral to the server that is pointed to by the crossRef object. If the DC can’t locate a relevant crossRef object, it will use DNS to attempt to generate an additional location to refer the client to.

In most cases, Active Directory will generate LDAP referrals automatically. However, you should manually create a crossRef object to generate LDAP referrals for an external domain, such as referrals to othercorp.com that are generated by the adatum.com domain.

See Also

MS KB 241737 (How to Create a Cross-Reference to an External Domain in Active Directory); MS KB 817872 (How to Create crossRef Objects for a DNS Namespace Subordinate of an Existing Active Directory Forest); MSDN: Referrals [Active Directory]; MSDN: When Referrals Are Generated [Active Directory]

Renaming an Object

Problem

You want to rename an object and keep it in its current container or OU.

Solution

Using a graphical user interface

  1. Open ADSI Edit.

  2. If an entry for the naming context you want to browse is not already displayed, do the following:

    1. Right-click on ADSI Edit in the right pane and click “Connect to.”

    2. Fill in the information for the naming context, container, or OU that contains the object you want to rename. Click on the Advanced button if you need to enter alternate credentials.

  3. In the left pane, browse to the container or OU that contains the object you want to modify. Once you’ve found the object, right-click on it and select Rename.

  4. Enter the new name and click OK.

You can also rename a leaf object by using LDP as follows:

  1. Open LDP.

  2. From the menu, select Connection→Connect.

  3. For Server, enter the name of a domain controller (or leave it blank for a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. Click Browse→Modify RDN. For Old DN, enter the Distinguished Name of the object that you want to rename. For New DN, enter the object’s new name.

  10. Click Run to rename the object.

Using a command-line interface

To rename an object using the built-in DSMove utility, use the following syntax:

> dsmove "<ObjectDN>" -newname "<NewName>"

To use AdMod, use the following:

> admod -b "<ObjectDN>" -rename "<NewName>"

Using PowerShell

To rename an object using PowerShell, use the following syntax:

Rename-ADObject -Identity "<Object DN>" -NewName "<New Value of 'name'
attribute>"

Discussion

Before you rename an object, you should ensure that no applications reference it by name. You can make objects rename-safe by requiring all applications that must store a reference to an object to use the GUID of the object, rather than the name.

The GUID (stored in the objectGUID attribute) is effectively unique and does not change when an object is renamed.

Note

Keep in mind that you may wish to perform other cleanup tasks when renaming an object. In the case of a user who is changing her name, you may wish to update her Display Name and sn attributes to match the new CN.

Using a graphical user interface

If the parent container of the object you want to rename has a lot of objects in it, you may want to add a new connection entry for the DN of the object you want to rename. This may save you time searching through the list of objects in the container. You can do this by right-clicking ADSI Edit and selecting “Connect to” under Connection Point; select Distinguished Name and enter the DN of the object you want to rename.

You can also rename most objects within the Active Directory Users and Computers MMC snap-in (dsa.msc) by navigating to the object in question, right-clicking on it, and selecting Rename.

Using a command-line interface

The two parameters that are needed to rename an object are the original DN of the object and the new RDN (-newname). The -s option can also be used to specify a server name to work against.

See Also

MSDN: IADsContainer::MoveHere

Deleting an Object

Problem

You want to delete an individual object.

Solution

Using a graphical user interface

  1. Open ADSI Edit.

  2. If an entry for the naming context you want to browse is not already displayed, do the following:

    1. Right-click on ADSI Edit in the right pane and click “Connect to.”

    2. Fill in the information for the naming context, container, or OU that contains the object you want to delete. Click on the Advanced button if you need to enter alternate credentials.

  3. In the left pane, browse to the object you want to delete.

  4. Right-click on the object and select Delete.

  5. Click Yes to confirm.

You can also delete an object using LDP, as follows:

  1. Open LDP.

  2. From the menu, select Connection→Connect.

  3. For Server, enter the name of a domain controller (or leave it blank for a serverless bind).

  4. For Port, enter 389.

  5. Click OK.

  6. From the menu, select Connection→Bind.

  7. Accept the default and bind as the currently logged on user or select the option to bind with credentials and then enter the credentials.

  8. Click OK.

  9. Click Browse→Delete. For DN, enter the Distinguished Name of the object that you want to delete.

  10. Click Run to delete the object.

Using a command-line interface

You can delete an object using the built-in dsrm utility, as well as AdMod. For dsrm, use the following syntax:

> dsrm "<ObjectDN>"

For AdMod, enter the following:

> admod -b "<ObjectDN>" -del

Using PowerShell

To delete the “Branches” OU in the adatum.com domain, use the following command:

Remove-ADObject -Identity "ou=Branches,dc=adatum,dc=com" -Confirm:$false

Discussion

This recipe covers deleting individual objects. If you want to delete a container or OU and all the objects in it, take a look at Deleting a Container That Has Child Objects.

Using a graphical user interface

If the parent container of the object you want to delete has a lot of objects in it, you may want to add a new connection entry for the DN of the object you want to delete. This can save you time searching through the list of objects in the container and could help avoid accidental deletions. You can do this by right-clicking ADSI Edit and selecting “Connect to.” Under Connection Point, select Distinguished Name and enter the DN of the object you want to delete.

You can also delete most objects within the Active Directory Users and Computers MMC snap-in (dsa.msc) by navigating to the object in question, right-clicking on it, and selecting Delete.

Using a command-line interface

The dsrm utility can be used to delete any type of object (there are no limitations based on object type, as with dsadd and dsmod). The only required parameter is the DN of the object to delete. You can also specify -noprompt to keep it from asking for confirmation before deleting. The -s parameter can be used as well to designate a specific server to target. AdMod will not prompt you in this manner.

See Also

Deleting a Container That Has Child Objects for deleting a container; MS KB 258310 (Viewing Deleted Objects in Active Directory); MSDN: IADsContainer::Delete; MSDN: IADsDeleteOps:: DeleteObject

Deleting a Container That Has Child Objects

Problem

You want to delete a container or organizational unit and all child objects contained within.

Solution

Using a graphical user interface

Open ADSI Edit and follow the same steps as in Deleting an Object. The only difference is that you’ll be prompted to confirm twice instead of once before the deletion occurs.

Using a command-line interface

You can delete a container and its child objects using the built-in dsrm utility, as well as AdMod. For dsrm, use the following syntax:

> dsrm "<ObjectDN>" -subtree

For AdMod, enter the following:

> admod -b "<ObjectDN>" -del -treedelete

Using PowerShell

The “Branches” OU in the adatum.com domain contains child objects. To delete it without a confirmation prompt, use the following command:

Remove-ADObject -Identity "ou=Branches,dc=adatum,dc=com" -Recursive↵
 -Confirm:$false

Discussion

As you can see from the solutions, there is not much difference between deleting a leaf node and deleting a container that has child objects. However, there is a distinction in what is happening in the background.

Deleting an object that has no children can be done with a simple LDAP delete operation. On the other hand, to delete a container and its children, the tree-delete LDAP control has to be used. If you were to do the deletion from an LDAP-based tool like LDP (the Active Directory Administration Tool), you would first need to enable the Subtree Delete control, which has an OID of 1.2.840.113556.1.4.805. LDP provides another option to do a Recursive Delete from the client side. That will essentially iterate through all the objects in the container, deleting them one by one. The Subtree Delete is much more efficient, especially when dealing with large containers.

As with the other operations we’ve discussed in this chapter (create, rename, move, and so on), the user performing the delete operation needs to have the necessary permissions to delete the object or objects in question. Active Directory permissions are discussed more extensively in Chapter 14.

See Also

Deleting an Object for information about deleting objects; Protecting a Computer Against Accidental Deletion; Protecting a User Against Accidental Deletion; MSDN: IADsDeleteOps::DeleteObject

Viewing the Created and Last-Modified Timestamp of an Object

Problem

You want to determine when an object was either created or last updated.

Solution

Using a graphical user interface

  1. Follow the steps in Viewing the Attributes of an Object.

  2. Ensure that createTimestamp and modifyTimestamp are included in the list of attributes to be returned by looking at Attributes under Options→Search.

Using a command-line interface

You can view the created and modified timestamps using the built-in DSQuery utility, as well as AdFind. For DSQuery, use the following syntax:

> dsquery * "<ObjectDN>" -attr name createTimestamp modifyTimestamp

For AdFind, use the following:

> adfind -default -rb cn=Users -f "cn=Joe Smith"↵
createTimestamp modifyTimestamp

Using PowerShell

The following command gets the creation date and the last-modified date for a user object:

Get-ADUser <sAMAccountName> -Properties * | Select Name,whenCreated,Modified

Discussion

When an object is created or modified in Active Directory, the createTimestamp and modifyTimestamp attributes get set with the current time. The createTimestamp attribute is replicated between domain controllers, so assuming the latest modification of the object in question has replicated to all domain controllers, they will all contain the timestamp when the object was created. whenChanged and modifyTimestamp are not replicated, which means that their values will be local to an individual domain controller. Additionally, modifyTimestamp is a constructed attribute.

See Also

Viewing the Attributes of an Object for viewing the attributes of an object; Chapter 12 for a more detailed description of the Active Directory replication process

Modifying the Default LDAP Query Policy

Problem

You want to view or modify the default LDAP query policy of a forest. The query policy contains settings that restrict search behavior, such as the maximum number of entries that can be returned from a search.

Solution

Using a graphical user interface

  1. Open ADSI Edit.

  2. In the Configuration partition, browse to Services→Windows NT→Directory Service→Query Policies.

  3. In the left pane, click on the Query Policies container, then right-click on the Default Query Policy object in the right pane and select Properties.

  4. Double-click on the lDAPAdminLimits attribute.

  5. Click on the attribute you want to modify and click Remove.

  6. Modify the value in the “Value to add” box and click Add.

  7. Click OK twice.

Using a command-line interface

To view the current settings, use the following command:

> ntdsutil "ldap pol" conn "con to server <DomainControllerName>" q "show values"

To change the MaxPageSize value to 2,000, you can do the following:

> ntdsutil "ldap pol" conn "con to server <DomainControllerName>" q
ldap policy: set MaxPageSize to 2000
ldap policy: Commit Changes

Discussion

The LDAP query policy contains several settings that control how domain controllers handle searches. By default, one query policy is defined for all domain controllers in a forest, but you can create additional ones and apply them to a specific domain controller or even at the site level (so that all domain controllers in the site use that policy).

Query policies are stored in the Configuration NC as queryPolicy objects. The default query policy is located at cn=Default Query Policy,cn=Query-Policies,cn=Directory Service,cn=Windows NT,cn=Services, <ConfigurationPartitionDN>. The attribute lDAPAdminLimits of a queryPolicy object is multivalued and contains each setting for the policy in name/value pairs. Table 4-4 contains the available settings.

Table 4-4. LDAP query policy settings

Name

Default value

Description

MaxPoolThreads

4 per proc

Maximum number of threads that are created by the DC for query execution.

MaxDatagramRecv

4096

Maximum number of datagrams that can be simultaneously processed by the DC.

MaxReceiveBuffer

10485760

Maximum size in bytes for an LDAP request that the server will attempt to process. If the server receives a request that is larger than this value, it will close the connection.

InitRecvTimeout

120 secs

Initial receive timeout.

MaxConnections

5000

Maximum number of open connections.

MaxConnIdleTime

900 secs

Maximum amount of time a connection can be idle.

MaxPageSize

1000

Maximum number of records that will be returned by LDAP responses.

MaxQueryDuration

120 secs

Maximum length of time the domain controller can execute a query.

MaxTempTableSiz

10000

Maximum size of temporary storage that is allocated to execute queries.

MaxResultSetSize

262144

Controls the total amount of data that the domain controller stores for this kind of search. When this limit is reached, the domain controller discards the oldest of these intermediate results to make room to store new intermediate results.

MaxNotificationPerConn

5

Maximum number of notifications that a client can request for a given connection.

Instead of modifying the default LDAP query policy, you can create a new one from scratch. In the Query Policies container (where the default query policy object is located), create a new queryPolicy object and set the lDAPAdminLimits attribute as just described based on the settings you want configured. Then modify the attribute queryPolicyObject on the nTDSDSA object of a domain controller you want to apply the new policy to. This can be done via the Active Directory Sites and Services snap-in by browsing to the nTDSDSA object of a domain controller (cn=NTDS Settings), right-clicking on it, and selecting Properties. You can then select the new policy from a drop-down menu beside Query Policy. Click OK to apply the new policy.

Warning

You should not change the default query policy in production unless you’ve done plenty of testing. Changing some of the settings may result in unexpected application or domain controller behavior, such as a significant failure of your Active Directory domain controllers.

See Also

Modifying the Default TTL Settings for Dynamic Objects; MS KB 315071 (How to View and Set LDAP Policy in Active Directory by Using Ntdsutil.exe)

Exporting Objects to an LDIF File

Problem

You want to export objects to an LDIF file.

Solution

Using a graphical user interface

None of the standard Microsoft tools support exporting LDIF from a GUI.

Using a command-line interface

> ldifde -f output.ldf -l <AttrList> -p <Scope> -r "<Filter>" -d "<BaseDN>"

Discussion

The LDIF specification defined in RFC 2849 describes a well-defined file-based format for representing directory entries. The format is intended to be both human- and machine-parseable, which adds to its usefulness. LDIF is the de facto standard for importing and exporting a large number of objects in a directory and is supported by virtually every directory vendor, including Microsoft.

Using a command-line interface

The -f switch specifies the name of the file to use to save the entries to, -s is the DC to query, -l is the comma-separated list of attributes to include, -p is the search scope, -r is the search filter, and -d is the base DN. If you encounter any problems using ldifde, the -v switch enables verbose mode and can help identify problems.

See Also

Importing Objects Using an LDIF File for importing objects using LDIF; RFC 2849 (The LDAP Data Interchange Format [LDIF]—Technical Specification); MS KB 237677 (Using LDIFDE to Import and Export Directory Objects to Active Directory)

Importing Objects Using an LDIF File

Problem

You want to import objects into Active Directory using an LDIF file. The file could contain object additions, modifications, and deletions.

Solution

Using a command-line interface

To import objects using the ldifde utility, you must first create an LDIF file with the objects to add, modify, or delete. Here is an example LDIF file that adds a user:

dn: cn=jsmith,cn=users,dc=adatum,dc=com
changetype: add
objectClass: user
samaccountname: jsmith
sn: JSmith

Once you’ve created the LDIF file, you just need to run the ldifde command to import the new objects:

> ldifde -i -f input.ldf

Discussion

For more information on the LDIF format, check RFC 2849.

Using a command-line interface

To import with ldifde, simply specify the -i switch to turn on import mode and -f <filename> for the file. It can also be beneficial to use the -v switch to turn on verbose mode to get more information in case of errors. The Windows Server 2003 version of ldifde also includes the –j switch that will create a logfile for troubleshooting purposes. The LDIF file can specify a deletion or a modification instead of an addition. To modify a user, set the changetype to modify. To delete a user, set the changetype to delete.

See Also

Exporting Objects to an LDIF File for information on LDIF; RFC 2849 (The LDAP Data Interchange Format [LDIF]—Technical Specification); MS KB 237677 (Using LDIFDE to Import and Export Directory Objects to Active Directory)

Exporting Objects to a CSV File

Problem

You want to export objects to a comma-separated values (CSV) file. The CSV file can then be opened and manipulated from a spreadsheet application or with a text editor.

Solution

Using a graphical user interface

You can export objects to a CSV file using Active Directory Users and Computers, as follows:

  1. Open Active Directory Users and Computers.

  2. Browse to the desired container or OU.

  3. Right-click on the container or OU and click Export List.

  4. Choose the CSV file type, name the file, and then click Save to save the file.

Using a command-line interface

You can export objects to a CSV file using the built-in csvde utility, as well as AdFind. For csvde, use the following syntax:

> csvde -f output.csv -l <AttrList> -p <Scope> -r "<Filter>" -d "<BaseDN>"

You can also export information to a CSV file using adfind:

> adfind -b <SearchBase> -f <Filter> -csv <Attr1> <Attr2> <Attr3>

Using PowerShell

You can also export objects to a CSV file by using PowerShell. In the following command, all user objects in the Users OU in the adatum.com domain will be exported to c:\temp\users.csv:

Get-ADUser -SearchBase "cn=users,dc=adatum,dc=com" -Filter * | Select Name,UserPrincipalName,samAccountName | Export-Csv c:\temp\users.csv

Discussion

Once you have a CSV file containing entries, you can use a spreadsheet application such as Excel to view, sort, and manipulate the data.

Using a graphical user interface

Before performing the export, add any needed columns to the view in Active Directory Users and Computers. To add columns, click on View and then click Add/Remove Columns.

Using a command-line interface

The parameters used by csvde are nearly identical to those used by ldifde. The -f switch specifies the name of the file to use to save the entries to, -s is the DC to query, -l is the comma-separated list of attributes to include, -p is the search scope (base, onelevel, or subtree), -r is the search filter, and -d is the base DN. If you encounter any issues, the -v switch enables verbose mode and can help identify problems.

AdFind offers a number of additional switches to customize the behavior of CSV file output, including the following:

-csv xxx

CSV output. xxx is an optional string that specifies the value to use for empty attributes.

-csvdelim x

Delimiter to use for separating attributes in CSV output. The default is (,).

-csvmvdelim x

Delimiter to use for separating multiple values in output. The default is (;).

-csvq x

Character to use for quoting attributes. The default is (").

See Also

Importing Objects Using PowerShell and a CSV File for importing objects using a CSV file

Importing Objects Using PowerShell and a CSV File

Problem

You want to import objects into Active Directory using a CSV file.

Solution

Using PowerShell

You must first create a CSV file containing the objects to add. The first line of the file should contain a comma-separated list of attributes you want to set, with DN being the first attribute. Here is an example:

DN,objectClass,cn,sn,userAccountControl,sAMAccountName,userPrincipalName

The rest of the lines should contain entries to add. If you want to leave one of the attributes unset, then leave the value blank (followed by a comma). Here is a sample CSV file that would add two user objects:

DN,objectClass,sn,userAccountControl,sAMAccountName,userPrincipalName
"cn=jim,cn=users,dc=adatum,dc=com",user,Smith,512,jim,jim@adatum.com
"cn=john,cn=users,dc=adatum,dc=com",user,,512,john,john@adatum.com

Once you’ve created the CSV file, you just need to import the new objects by using PowerShell:

> -Import-CSV c:\temp\input.csv | New-ADUser

Discussion

Prior to the New-ADUser cmdlet, CSVDE was often used to import objects from a CSV file. However, starting with Windows Server 2008, it became much more difficult to use CSVDE due to the inability to meet password complexity requirements of a domain. CSVDE creates users with a blank password, which usually doesn’t meet password complexity requirements of a domain. With the New-ADUser cmdlet, new disabled users can be created without a password, even if there is a password complexity requirement.

Get Active Directory Cookbook, 4th 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.