LDAP class
The LDAP class simplifies public searches of an organization's LDAP (Lightweight Directory Access Protocol) directory. The LDAP class is a high level, object oriented interface to client sockets that lets you write a User Language LDAP request without knowledge of socket level programming or the format of LDAP requests and responses.
The LDAP class methods allow a User Language program to act as an LDAP client to access and retrieve directory information through an LDAP server. The LDAP server may be running on any platform to which the LDAP client online can make a TCP/IP connection.
You use JANUS commands (DEFINE, START, NAMESERVER) to define and start a TCP/IP CLSOCK port for the LDAP client to use.
Note: To use LDAP class objects, you must have licensed Janus Sockets and Janus SOAP. The Sirius object-oriented alternative to $functions is designed for Janus SOAP applications only, and information about using Sirius objects is provided in "Janus SOAP User Language Interface".
The "List of LDAP methods" lists all the methods in this class.
Feature summary
The LDAP class provides the following capabilities:
- Read access to X.500 and LDAP v2 directory services.
- One-step connection and login to an LDAP server (with user ID and password passing as well as also anonymous logins).
- Multiple search filters, each in a separate method.
- Text-only retrieval: all returned data is automatically converted from ASCII to EBCDIC. UTF-8 encoding is not supported.
- Automatic deserializing of returned data into XML in an XmlDoc object.
- A limit of approximately 1300 bytes to the data sent in or returned from a single query of the server.
- Optional retrieval of only the directory entry attribute names, that is, the names without the corresponding attribute values.
- Optional SSL (Secure Sockets Layer) data transmission.
The following LDAP features are not currently supported by the LDAP class:
- Kerberos user logins.
- Modifying, deleting, or adding directory content.
- Full compliance with LDAP v3 (for example, UTF-8 is not supported)
- Arbitrary, user-constructed search queries (RFC 1960 syntax featuring boolean operators is not supported).
- Restart of aborted transfers.
- Limiting the quantity of the server data returned or the number of entries returned.
LDAP overview
A directory is a repository for the storage and retrieval of information, and LDAP (Lightweight Directory Access Protocol) is a vendor- and platform-independent standard for accessing computerized directories. LDAP is a subset of X.500, a more complex enterprise directory system. LDAP, like X.500, is both an information model (with namespace) and a protocol for querying and manipulating directory data. Unlike X.500, LDAP is designed to run directly over the TCP/IP stack, and it has a smaller set of query and update functions.
An LDAP directory server runs on a host computer on the Internet, and it provides directory access to client programs that understand the LDAP protocol and can log into the server and look up information. The information is stored in units known as entries. For example, all the data for a particular person is typically contained in a single entry.
Entries are used to store attributes, each of which has
an associated type and one or more values.
An entry for a person may have a firstname
attribute type
whose value is Byron
, for example.
The type determines the
attribute's syntax, which defines what kind of
information is allowed in the values.
The entries are arranged in a tree structure.
LDAP servers index all the data in their entries, and filters are used to select a matching entry or group of entries. A filter specifies attribute types, assertion values, and matching criteria. The LDAP model also defines operations for adding, removing, or changing entries in the directory.
For more information about the LDAP protocol, hear are some relevant Internet RFCs:
- RFC 1777 The best place for detailed information about LDAP is Internet RFC 1777 (http://www.ietf.org/rfc/rfc1777.txt), which specifies the protocol. An excerpt follows: "The protocol described in this document is designed to provide access to the X.500 Directory while not incurring the resource requirements of the Directory Access Protocol (DAP). This protocol is specifically targeted at simple management applications and browser applications that provide simple read/write interactive access to the X.500 Directory, and is intended to be a complement to the DAP itself."
- RFC 2256 This RFC (http://www.ietf.org/rfc/rfc2256.txt), provides a summary of the attribute types and object classes defined for use by LDAP/X.500 directory clients. Although the attribute types implemented by an LDAP server are server-specific, many of the standard types are typically used.
- RFC 2849 This RFC (http://www.ietf.org/rfc/rfc2849.txt) specifies the format of a directory entry that is returned by the LDAP server. The LDAP Data Interchange Format (LDIF) “consists of a series of records separated by line separators. A record consists of a sequence of lines describing a directory entry, or a sequence of lines describing a set of changes to a directory entry. An LDIF file specifies a set of directory entries, or a set of changes to be applied to directory entries, but not both.” The LDAP class reformats LDAP server responses in an XML document, as described in "Working with returned values". This Janus XML formatting does not follow the “DSML” model described in http://www.worldspot.com/dsmlgw-xml-rpc/DSMLGateway.html.
- RFC 1960 This RFC (http://www.ietf.org/rfc/rfc1960.txt) provides a grammar that can be used to do arbitrary LDAP queries. This grammar is not currently supported by the LDAP class.
Using the LDAP class
The LDAP class makes the information in LDAP directories more easily accessible by removing LDAP protocol concerns from the programmer. To retrieve data from an LDAP server, applications must:
- Define a Janus CLSOCK port.
- Use the JANUS DEFINE command to
- Create a TCP/IP port for your Model 204 LDAP client application.
- Indicate the remote LDAP server identifier and port number (or a pattern that allows the specific server to be specified by an LDAP class method).
- Set a timeout value for the LDAP connections.
- Use the JANUS NAMESERVER command to let you reference remote hosts by name rather than IP address.
- Use a JANUS CLSOCK command to specify access rules for your port.
- Use the JANUS START command to start your port.
- Use the JANUS DEFINE command to
- Bind a connection and log in to an LDAP server. In your User Language request, a single Bind method statement performs these actions.
- Send a search query to the LDAP server. Use one of the multiple Find methods, which provide a variety of search filters. See "Using the Find methods".
- Optionally, extract particular data from the returned value. See "Working with returned values".
- End your session when ready. The Unbind method logs off the LDAP user, and it deactivates the connection.
Working with returned values
The directory information returned from an LDAP server in response to a Janus LDAP Find call is stored in a Janus system XmlDoc object. This object contains exactly the data strings sent from the server, in whatever case.
The XML structure of such an XmlDoc is shown in this sample fragment, whose features are described after the example:
<result> <entry objectName="cn: Sildar, John R, id=X479, c=US"> <cn> <value>Sildar, John R</value> </cn> <sn> <value>Sildar</value> </sn> </entry> </result>
- The top element is named
result
. If no matches were found, only an empty result element (<result/>
) is present. - The
result
element has zero or moreentry
children. - Each
entry
element has one or more child elements, each named for the LDAP attribute type whose returned data it contains. (for example,cn
,sn
,telephonenumber
). - Each attribute-type element has zero or more
value
child elements that contain that LDAP attribute's value(s). If the Find call specified anAttributesOnly=True
argument, anyvalue
children are not displayed. - The
entry
element in this example has an (XML) attribute namedobjectName
that contains identifying information for the entry (this is the LDAP Distinguished Name field for the entry).
Using XPath to search returned values
In the XmlDoc returned from an LDAP query, the LDAP attribute names themselves are the XmlDoc element names. One consequence of this is that you can use Janus SOAP XmlDoc API method calls with relatively simple XPath-expression arguments to extract particular “fields” from a returned value.
For example, to extract the first value of attribute sn
in the
first found entry in the returned XmlDoc %doc
, you can use the
Value property with a straightforward XPath argument:
Print %doc:Value('result/entry/sn/value')
Or, alternatively:
%entry = %doc:selectSingleNode('/result/entry') Print %doc:Value('sn')
For more information about selecting nodes from an XmlDoc, see SelectSingleNode.
To return the first value of sn
in the second found entry,
in a case where multiple entries were found, you can use:
Print doc:Value('result/entry[2]/sn/value')
And to return the first value of sn
in the third (or greater)
found entry:
Print doc:Value('result/entry[position()>=3]/sn/value')
LDAP class example
The procedure below, which exercises many of the LDAP methods, does the following:
- Defines a Janus port for an LDAP client.
- Creates an LDAP object, then connects to an LDAP server.
- Performs an equality search using a traditional
attribute type (
sn
) to return the names of the attribute types implemented by this LDAP server. This informs the user for the next step. - In a repeating loop, prompts the user for an attribute type and search value, performs an equality search with the user-specified values, then searches the returned XmlDoc for the value of a particular attribute.
- Disconnects from the LDAP server.
UTABLE LPDLST 8000 * JANUS NAMESERVER 198.142.144.8 43 JANUS DRAIN LDSOCK1 JANUS FORCE LDSOCK1 JANUS DELETE LDSOCK1 JANUS DEFINE LDSOCK1 * CLSOCK 5 TIMEOUT 180 MASTER REMOTE * * JANUS START LDSOCK1 JANUS STATUS * Begin %ld Object Ldap %doc Object XmlDoc Auto New %status float %Attrib string len 255 %SearchString string len 255 %PortNumber float %val is longstring *************** %ld = New %status = %ld:Bind(JanusPort='LDSOCK1', - LDAPServer='ldap.college.edu') If %status then Print 'Bad status from Ldap:Bind: ' %status Print ' LDERRNO: ' %ld:ErrorNumber Print ' LDERRMS: <' %ld:ErrorText '>' Stop End If *************** Print 'AttributesOnly result: ' %status = %ld:FindEQ('sn', 'Sildar', %doc, - AttributesOnly=True) If %status then Print 'Bad status from Ldap:FindOP: ' %status Print ' LDERRNO: ' %ld:ErrorNumber Print ' LDERRMS: <' %ld:ErrorText '>' Stop End If %doc:Print * Must clear XmlDoc %doc = New *************** * Ask user for attrib and value for FindEQ test * Either string empty breaks out of the loop Repeat Forever %Attrib = $READ ('What attribute for an EQ search?') If (%Attrib EQ ) then Loop End End If %SearchString = $READ ('What value?') If (%SearchString EQ ) then Loop End End If Print 'Searching for <' %Attrib ' EQ ' %SearchString '>' %status = %ld:FindEQ(%Attrib, %SearchString, %doc) If %status then Print 'Bad status from Ldap:FindEQ: ' %status Print ' LDERRNO: ' %ld:ErrorNumber Print ' LDERRMS: <' %ld:ErrorText '>' Stop End If %doc:Print * Print the email address %val = %doc:Value('result/entry/mail/value') Print 'found value is ' %val %doc = New End Repeat *************** %status = %ld:Unbind If %status then Print 'Bad status from Ldap:Unbind: ' %status Print ' LDERRNO: ' %ld:ErrorNumber Print ' LDERRMS: <' %ld:ErrorText '>' End If End
Instantiating and discarding LDAP objects
The LDAP class has no explicit constructor or destructor methods. To create or discard an LDAP object instance, you use the system New and Discard methods that are available to all Janus classes.
The New Constructor allocates and initializes storage for a new LDAP object instance. It takes no arguments. A separate method (Bind) establishes a connection to an LDAP server.
When an LDAP client no longer wants to query the LDAP server, the LDAP Unbind method unauthenticates the LDAP user and severs the connection to the server host. The LDAP object instance remains available for reuse. If no further references to it exist, it gets discarded automatically (“implicitly”). You can also use the generic (Object class) Discard method to discard an LDAP object:
%ldapObject:Discard
The Discard method does not set the ErrorNumber and ErrorText properties.