TRIVIAL-LDAP v0.92
TRIVIAL-LDAP is a one file, all Common Lisp client implementation of
parts of RFC 2261.
WARNING:
This is beta software. While I believe the API
documented below is correct it is subject to change. Also, do
not run execute the example.lisp program against a production LDAP
directory, it will delete your entries.
Introduction
This LDAP client came about as a result of
some functionality I required for a different project altogether.
As a result it provides functionality that is general enough but
probably not in typical low-level API fashion. (For instance, a
"real" LDAP library would probably tackle the BER encoding
separately.) However, as there is a lack of Common Lisp LDAP
clients out there I thought I'd share.
I am open to both requests for features and suggestions for
improving my Lisp code. There are features I will be implementing
in the short term but for the sake of not creating false
expectations neither a comprehensive list nor timeframe is
available.
You can reach me at montuori@gmail.com.
Changes
- 2009-10-23 (v0.92)
- Applied a patch supplied by Faré to provide support for
XCVB
- 2009-08-16 (v0.91)
- Applied a patch supplied by Nick Dannenberg to fix UTF-8
handling for SBCL and CCL. My sincerest appreciation for taking
the time to generate and send the patch along!
- 2009-03-12 (v0.90)
- Applied patches kindly provided by Slawek Zak.
- Enable UTF-8 encoding for Allegro.
- Fixed a compilation failure on Allegro where a number
of constants were not properly defined.
- Fixed the dosearch macro for cases where the LDAP
variable is lexical.
Thanks to Slawek for taking the time to send the patches!
- 2007-01-12 (v0.80)
- Converted from trivial-socket to usocket: indications
were that trivial-socket has been deprecated.
- Added support for SSL with CL+SSL. Setting the ldap
object slot
sslflag
to T or
the port
slot to 636 will force an encrypted
connection. Do note that this is not TLS, just ldaps://
... I don't require TLS; if you do, drop me a line.
- Added functionality to ease the pain of short slapd
idletimeouts. The ldap object
slot
reuse-connection
may be set to NIL (the
default) to not attempt reopening connections, T to reopen
the connection before each request, or TRIVIAL-LDAP:REBIND
if the connection should be opened and a bind message sent
before each request (except, of course, the bind request
itself).
- A couple of documentation and logic bugs were corrected
Acknowledgments
I would like to thank Zach Beane for his
many helpful comments and suggestions. Thanks also to Ed Symanzik
for pointing out a number inconsistencies in the code and
documentation.
License
TRIVIAL-LDAP is distributed under the Clarified
Artistic License, a copy of which is included in the downloadable
package.
Requirements
TRIVIAL-LDAP has been tested under OpenMCL 1.0
(OS X/PPC), SBCL 0.9.7 (OS X/PPC), and SBCL 1.0 (OS X/Intel).
I would assume any CL that is supported by usockets and CL+SSL
would have no issues with this code. If you encounter problems
let me know.
Two external packages, usocket and CL+SSL, are required.
CL+SSL itself requires trivial-gray-streams, flexi-streams, and
cffi. These may be downloaded from:
The trivial-gray-streams project is part of the CL+SSL project.
(Note: to get CL+SSL working on OS X/Intel it was necessary to
re-compile openssl with the -m64 flag.)
Limitations
Missing functionality, as specified by RFC 2251, includes:
- UTF-8 is not implemented for all CL implementations
- SASL authentication is not implemented
- controls are not implemented
- extended DN searches are not implemented
- referrals are not followed
- extended request/response is not implemented
I do not require this functionality myself, but if there was
interest I would consider augmenting TRIVIAL-LDAP with some of
this missing functionality.
API
LDAP object and associated methods.
-
new-ldap &key (host "localhost")
(port 389) user pass base debug [function]
- Return an LDAP object.
-
host ldap-object
[method]
- Get/set the host slot value of
ldap-object. Slot value will be a string.
-
port ldap-object [method]
- Get/set the port slot value of
ldap-object. Slot value will be an integer. If the sslflag slot
is NIL, defaults to 389; if sslflag slot is T, defaults to 636.
If the port parameter is manually set to 636 an SSL connection is
used unless the sslflag is explicitly set to nil.
-
user ldap-object [method]
- Get/set the user DN to bind as. Slot
value will be a string.
-
pass ldap-object [method]
- Get/set the simple password to bind with.
Slot value will be a string.
-
base ldap-object [method]
- Get/set the default base DN for searches.
Slot value will be a string.
-
debug ldap-object
[method]
- Get/set the debug flag. Slot value will be T or NIL. When
value is T debug output will be written to *debug-io*.
-
sslflag ldap-object
[method]
- Get/set the SSL flag. When T the default port is 636 and a
CL+SSL stream is used. Defaults to nil. Note that if the port
slot is explicitly set to 636 an SSL connection is used unless the
sslflag slot is set to nil explicitly.
-
reuse-connection ldap-object
[method]
- Get/set the reuse-connection slot parameter. When T re-open
the stream before each reqest; when LDAP:REBIND open the stream
and send an (ldap:bind ldap-object) message; when nil, don't do
anything special. Set to NIL by default.
Entry object and associated methods
-
new-entry dn &key (attrs ())
(infer-rdn t) [function]
- Return a new entry object with the DN specified.
attrs
, if specified, will be an alist of
attribute/value pairs. If infer-rdn
is T the RDN
attribute and value will be appended to the attribute list.
-
dn entry-object
[method]
- Return the DN value for entry-object.
-
rdn entry-object
[method]
- Return the RDN value for entry-object
-
change-rdn entry-object
new-rdn [method]
- Change the RDN (and therefore DN) of an
entry-object. The RDN attribute and value will be updated in the
attribute list. No LDAP directory transactions will take place.
-
attr-list entry-object
[method]
- Return the list of attribute symbols
belonging to entry-object
-
attr-value entry-object
attr [method]
attr-value entry-object
attr-list [method]
- Return a list of values associated with
the attribute
attr
. Return NIL if the attribute does
not exist. If a list of attributes is passed, return a list of
lists of values.
-
add-attr entry-object attr
values [method]
- Add the specified attribute with the value
or values specified to the entry object's attribute list. Returns
the entire list of attributes/values. No LDAP directory transactions
will take place.
-
del-attr entry-object attr
&optional values [method]
- Delete the specified attribute (or values
for attribute) from the entry object's attribute list. Returns
the entire list of attributes/values. No LDAP directory
transactions will take place.
-
replace-attr entry-object attribute
values [method]
- Replace current attribute values with
values specified. Returns the entire list of attributes/values.
No LDAP directory transactions will take place.
-
ldif entry-object
[method]
- Return an LDIF representation of entry (as a string).
LDAP Commands
NB: Methods below that are specialized first on ldap-object will
return three values: T/NIL indicating success or failure, the LDAP
response code (these are exported from the TRIVIAL-LDAP package as
symbols), and third, any response message received from the LDAP
directory server (as a string).
Methods specialized first on entry-object will return T (or T/NIL
in the case of compare) and will throw an ldap-response-error if a
response from the LDAP directory server is other than succesful.
dn-or-entry can be either an entry-object or a DN string.
dn is a string. Generally if the method only requires the DN
either the entry or the DN will be acceptable arguments.
-
bind ldap-object
[method]
- Send a bind request to the LDAP directory server.
-
unbind ldap-object
[method]
- Send an unbind request to the LDAP
directory server and close the stream.
-
abandon ldap-object
[method]
- Send an abandon request to the LDAP
directory server and purge any data on the stream waiting to be
read.
-
add ldap-object entry-object
[method]
add entry-object ldap-object
- Add an entry described by entry-object to
the directory specified by ldap-object.
-
delete ldap-object
dn-or-entry [method]
delete entry-object
ldap-object
delete dn ldap-object
- Delete entry from directory specified by
ldap-object.
dn-or-entry
may be an entry object or a
DN string.
-
moddn ldap-object dn-or-entry
new-rdn &key delete-old new-sup [method]
moddn entry-object ldap-object
new-rdn &key delete-old new-sup
moddn dn ldap-object new-rdn &key
delete-old new-sup
- Modify the RDN specified by
dn-or-entry
to the replacement RDN
new-rdn
. dn-or-entry
may be either an
entry object or DN string. If an object is specified, the DN and
attribute associated with the RDN slot values are modified as well
as the directory specified by ldap-object.
-
compare ldap-object dn-or-entry
attribute value [method]
compare
entry-object ldap-object attribute value
- Send a compare message to the directory
server asserting that entry-obj (or DN) has an attribute
attribute
with a value value
. Returns
either T or NIL (as the only argument or as the first argument)
indicating a return code of compareTrue or compareFalse.
-
modify ldap-object dn-or-entry
list-of-mods [method]
modify entry-object ldap-object
list-of-mods
- Modify the entry specified by
dn-or-entry
or entry-object
.
list-of-mods
is a list of (type attribute value)
triples. Type will be one of ldap:add, ldap:delete, or
ldap:replace.
-
search ldap-object filter &key base
(scope 'sub) (deref 'never) (size-limit 0) (time-limit 0)
types-only attributes [method]
- Search the directory specified by
ldap-object.
filter
is an LDAP filter (as a string).
The outer parens on the filter are optional. The search base
defaults to the base slot-value of the ldap-object. This method
returns T or NIL, indicating results pending or not, respectively.
-
next-search-result ldap-object
[method]
- After an ldap:search is executed, this
method can be used to return each of the entry objects that search
resulted in. next-search-result will return NIL if no more
results are available.
-
dosearch var search-form &body
body [macro]
- Execute the ldap:search provided as
search-form
and iterate through the results binding
each resulting entry object to var
before evaluating
body.
Returns the number of entries processed.
NB: If the body of the loop involves LDAP transactions it
is probably best that a difference LDAP instance be employed.
-
ldif-search &rest
ldap-search-args [macro]
- Prints the results of a search in LDIF.
This macro is probably most useful in an interactive setting.
ldap-search-args
are passed directly to the search
method described above.
kevin montuori
Last modified: Sat Jan 13 09:01:44 EST 2007