Nick Randell
Nick Randell

Reputation: 18305

How to extract TNSNames from an LDAP directory

I've been trying to query an LDAP directory server to retrieve a tnsnames entry. I have the following code working, but it doesn't smell right. Is it because it is wrong, or because querying ldap involves a few levels of indirection

   let identifier = LdapDirectoryIdentifier(server, port)
   use connection = new LdapConnection (identifier)
   connection.AuthType <- AuthType.Anonymous
   let request = System.DirectoryServices.Protocols.SearchRequest(defaultAdminContext, "cn=" + sid, SearchScope.OneLevel, "orclnetdescstring")
   let response = connection.SendRequest request :?> SearchResponse

   Seq.init response.Entries.Count (fun i -> response.Entries.[i])
   |> Seq.collect (fun entry ->
       let value = entry.Attributes.["orclnetdescstring"]
       Seq.init value.Count (fun i -> value.[i])
       |> Seq.map (fun v -> Some (v :?> string))
       )

I was hoping for a simple call that basically does 'query the directory and return the result', but there seems to be a lot of 'stuff' I have to do in order to read the real values.

Upvotes: 3

Views: 1201

Answers (1)

Terry Gardner
Terry Gardner

Reputation: 11132

Once the client is connected to the directory server, the client can make requests and read the responses. Requests take the form of LDAP operations such as bind, search, add, modify, delete, and others.

When the directory server accepts a connection, that connection (or LDAP session if you prefer) has an anonymous identity (RFC4513). Depending on the configuration of the directory server and the type of request, it may be necessary for the client to bind the connection to an authorization identity - this is done with a bind request which can be a 'simple' type or a SASL type. Dialog with the directory server administrator to determine if your client must bind connections to an authorization identity - the administrator might allow certain requests without authentication, though this is generally a bad practice and unusual.

A search for data requires the following parameters:

  • a 'search base', or base object
  • a 'search scope', which is base only, one level below the base object, or the entire subtree below the base object
  • a 'search filter', which the directory server uses to select matching entries from the list of candidate entries to return to the client
  • a list of attributes to return (the client can use the special attribute '1.1' to get just the entry distinguished name, which can be useful to determine whether an entry exists)

There are other parameters which are optional, for example, a size limit (a limit on the number of entries to return), and time limit (a limit on the time the search can take), whether to return just attributes, or attributes and values, and some others. Generally speaking, all search requests should provide a time limit to ensure that the search will timeout - because the directory server may not be configured with a time limit on LDAP requests from clients.

The response from the directory server to a search request will always contain a result code. This result code should be zero (0), if the search was successful, or it might be a code indicating that the number entries that could have been returned exceeded the number of entries that were allowed to be returned (the number of entries that are allowed to be returned is capped by the size limit in the search request or the servers' limit), or it may be a result code indicating that an error has occurred.

Assuming the error code was zero, a sequence of SearchResultEntries or SearchResultReferences then follows, and finally a SearchResultDone - a good API will manage this part for the client and simply present the entries returned as an array or a list.

Finally, the answer to your question, is 'yes, there is some stuff to be done' before entries can be read. A good API will reduce the amount of 'stuff' to a dull roar.

Upvotes: 1

Related Questions