Directory Services Markup Language (DSML) provides a means of representing directory structural information and directory operations as an XML document. DSML was created to allow XML-based enterprise applications to leverage profile and resource information from a directory in their native XML environment. DSML allows XML and directories to work together because it is based on standards such as XML, SOAP, and HTTP. It is approved by the Organization for the Advancement of Structural Information Standards (OASIS). DSML can run on Windows 2000 or Windows Server 2003.
DSML in Windows includes the following components :
SOAP listener component This component intercepts DSMLv2 requests and sends back corresponding DSMLv2 responses.
Support for equivalent LDAP operations This service performs equivalent LDAP operations such as addRequest , modifyRequest , and searchRequest . It also supports advanced operations such as LDAP controls and extended requests.
Session support DSML was designed and based on the request/response protocol; DSML Services for Windows allows users to keep the state between requests by specifying the session ID in the SOAP header. This is useful for some LDAP control operations that might span multiple requests, such as a page- size control when browsing through a directory.
IIS security support This service supports all IIS security configurations, including integrated Windows authentication, Basic authentication, Basic authentication over SSL, and Digest authentication.
Connection pooling This service manages incoming requests and promotes scalability by sharing connections from a common pool.
Multiple configuration options DSML supports many different configuration options to optimize performance, including the ability to customize ports, virtual directories, connections, timeouts, and other configuration parameters.
DSML is SOAP-based, so you send your requests using a SOAP envelope with a LDAP payload; you get back a SOAP envelope with the response payload. We won't go through all the supported schema and methods in DSML in this section ”you should look at the DSML documentation. Instead, we will look at some of the most common operations with DSML that you will implement with ADSI.
The following SOAP envelope contains a blank DSML request to the server:
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest/> </se:Body> </se:Envelope>
As you can see in the request, you pass in the DSML namespace and then pass in a batchRequest element. batchRequest elements are different from authRequest elements and other request types. batchRequest elements are queries or modifications to the server. You can send multiple commands in a batchRequest and have the server process them in parallel or sequentially.
When you send this request, you get the following response from the DSML server (formatted for clarity):
<soap:Envelope xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body> <batchResponse xmlns="urn:oasis:names:tc:DSML:2:0:core" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </batchResponse> </soap:Body> </soap:Envelope>
This response contains a batchResponse element, which includes any response from the server for your batchRequest .
All of this is over HTTP, so you can leverage XMLHTTP , ServerXMLHTTP , or, in .NET, the WebRequest class to send and receive your DSML requests and responses.
The following samples show some of the basic operations you can perform with DSML, along with the SOAP requests that perform the operations. To run these samples, get the sample DSML query application from the DSML SDK. These samples use XMLHTTP to send and receive its HTTP commands.
The following request includes a searchRequest object, which searches Active Directory. The filter in the request is on the objectclass . In this case, the response will be all attributes on the object specified in the DN for the search request.
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest> <searchRequestdn="cn=thomas rizzo,cn=users, dc=thomriznt5dom2, dc=extest,dc=microsoft,dc=com" scope="baseObject" derefAliases="neverDerefAliases" sizeLimit="1000"> <filter> <present name="objectclass"/> </filter> </searchRequest> </batchRequest> </se:Body> </se:Envelope>
To add an object, you use the addRequest element in your payload. The following example adds a new OU to your Active Directory. You can see the use of the attr element for setting attributes.
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest xmlns="urn:oasis:names:tc:DSML:2:0:core" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <addRequest dn="ou=MyNewOU,dc=thomriznt5dom2,dc=extest, dc=microsoft,dc=com"> <attr name="objectClass"> <value>organizationalUnit</value> </attr> </addRequest> </batchRequest> </se:Body> </se:Envelope>
To modify an object, you send a modifyRequest element and also a modification element, which includes the name of the attribute you want to modify and the type of modification, which can be add, replace, or delete. The following example changes the OU description we created in the previous example and also replaces the telephone number for a user :
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest> <modifyRequest dn="ou=MyNewOU,dc=thomriznt5dom2,dc=extest, dc=microsoft,dc=com"> <modification name="description" operation="replace"> <value>This is a sample OU</value> </modification> </modifyRequest> <modifyRequest dn="cn=Thomas Rizzo,cn=Users,dc=thomriznt5dom2, dc=extest,dc=microsoft,dc=com"> <modification name="telephoneNumber" operation="replace"> <value>555-1234</value> </modification> </modifyRequest> </batchRequest> </se:Body> </se:Envelope>
To delete an object, you send a delRequest to the server with the DN of the object you want to delete. The following deletes the OU we created earlier:
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest> <delRequest dn="ou=MyNewOU,dc=thomriznt5dom2,dc=extest,dc=microsoft, dc=com"/> </batchRequest> </se:Body> </se:Envelope>
To perform a simple search, you send a searchRequest element. As part of this XML structure, you must pass a filter, which is the filter that Active Directory will filter the responses on. Also, you can pass an attribute structure that will be the set of attributes from Active Directory that you want returned in your response.
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest> <searchRequest dn="cn=users,dc=thomriznt5dom2,dc=extest,dc=microsoft, dc=com" scope="singleLevel" derefAliases="neverDerefAliases" sizeLimit="1000"> <filter> <present name="objectclass"/> </filter> <attributes> <attribute name="name"/> <attribute name="description"/> <attribute name="whenCreated"/> <attribute name="sAMAccountName"/> </attributes> </searchRequest> </batchRequest> </se:Body> </se:Envelope>
You can perform more advanced searches using the searchRequest structure. The following example shows searching for all contacts with a last name that starts with R . You can do equality or substring searches, and you can use not elements to negate search terms in your searches. Finally, you can also use matching rules that are defined in LDAP.
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/"> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest> <searchRequest dn="cn=users,dc=thomriznt5dom2,dc=extest,dc=microsoft, dc=com" scope="wholeSubtree" derefAliases="neverDerefAliases" sizeLimit="10"> <filter> <and> <equalityMatch name="objectCategory"> <value>contact</value> </equalityMatch> <substrings name="sn"> <initial>R</initial> </substrings> </and> </filter> <attributes> <attribute name="name"/> <attribute name="dn"/> </attributes> </searchRequest> </batchRequest> </se:Body> </se:Envelope>
The final topic we will look at for DSML is session support. You might want to maintain authentication or responses across multiple, separate requests. You can begin, use, and end a session using DSML. The following code begins a session:
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/" se:encoding Style="http://schemas.xmlsoap.org/soap/encoding/"> <se:Header> <ad:BeginSession xmlns:ad="urn:schema-microsoft-com:activedirec tory:dsmlv2" se:mustUnderstand="1"/> </se:Header> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest xmlns="urn:oasis:names:tc:DSML:2:0:core" xmlns:xsd="http: //www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance"/> </se:Body> </se:Envelope>
In the response to the BeginSession request, you get a SessionID . In your subsequent requests to the server, you should pass a header that specifies the SessionID as part of a Session element, as shown here:
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/" se:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <se:Header> <ad:Session xmlns:ad="urn:schema-microsoft-com:activedirectory:dsmlv2" ad:SessionID="duZ0kbF+buULEdIlWR3S6P29" se:mustUnderstand="1"/> </se:Header> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest xmlns="urn:oasis:names:tc:DSML:2:0:core" xmlns:xsd="http: //www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance"/> </se:Body> </se:Envelope>
To end your session, you must pass an EndSession header with the SessionID of the session you want to end:
<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/" se:encoding Style="http://schemas.xmlsoap.org/soap/encoding/"> <se:Header> <ad:EndSession xmlns:ad="urn:schema-microsoft-com:activedirec tory:dsmlv2" ad:SessionID="duZ0kbF+buULEdIlWR3S6P29" se:mustUnderstand="1"/> </se:Header> <se:Body xmlns="urn:oasis:names:tc:DSML:2:0:core"> <batchRequest xmlns="urn:oasis:names:tc:DSML:2:0:core" xmlns:xsd="http: //www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/> </se:Body> </se:Envelope>