-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtrivial-ldap.html
556 lines (450 loc) · 18.3 KB
/
trivial-ldap.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!--
(defun add-api-entry ()
(interactive)
(let ((function (read-string "Function/Method name: "))
(args (read-string "Argument list: "))
(type (read-string "Function, Method, or Macro? ")))
(insert (format "
<dt>
<span class=\"term\"><b>%s</b> <i>%s</i></span>
<span class=\"type\">[%s]</span>
</dt>
<br class=\"both\" />
<dd>
</dd>" function args type))
(previous-line 1)))
-->
<html>
<head>
<title>TRIVIAL-LDAP v0.92</title>
<style type="text/css">
.leftcontent {float: left; width: 75%; padding-left: 12px;}
div.head {background-color: #aeffee;}
span.term {float: left; text-align: left;}
span.type {float: right; text-align: right; font-weight: bold;}
br.both {clear: both;}
dd {font-style: normal; padding-bottom: 8px;}
</style>
</head>
<body class="leftcontent">
<h3>TRIVIAL-LDAP v0.92</h3>
TRIVIAL-LDAP is a one file, all Common Lisp client implementation of
parts of RFC 2261.
<h4>WARNING:</h4> This is beta software. While I believe the API
documented below is correct it is subject to change. Also, <b>do
not run execute the example.lisp program against a production LDAP
directory, it will delete your entries.</b>
<h4>Introduction</h4> 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. <p/>
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. <p />
You can reach me at [email protected].
<h4>Changes</h4>
<dl>
<dt>2009-10-23 (v0.92)</dt>
<dd>Applied a patch supplied by Faré to provide support for
XCVB</dd>
<dt>2009-08-16 (v0.91)</dt>
<dd>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!</dd>
<dt>2009-03-12 (v0.90)</dt>
<dd>Applied patches kindly provided by Slawek Zak.
<ul>
<li>Enable UTF-8 encoding for Allegro.</li>
<li>Fixed a compilation failure on Allegro where a number
of constants were not properly defined.</li>
<li>Fixed the dosearch macro for cases where the LDAP
variable is lexical.</li>
</ul>
Thanks to Slawek for taking the time to send the patches!
</dd>
<dt>2007-01-12 (v0.80)</dt>
<dd><ul>
<li>Converted from trivial-socket to usocket: indications
were that trivial-socket has been deprecated.</li>
<li>Added support for SSL with CL+SSL. Setting the ldap
object slot <code>sslflag</code> to T or
the <code>port</code> 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.</li>
<li>Added functionality to ease the pain of short slapd
idletimeouts. The ldap object
slot <code>reuse-connection</code> 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). </li>
<li>A couple of documentation and logic bugs were corrected</li>
</ul></dd>
</dl>
<p>
<h4>Acknowledgments</h4> 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.
<p>
<h4>License</h4> TRIVIAL-LDAP is distributed under the Clarified
Artistic License, a copy of which is included in the downloadable
package.
<h4>Requirements</h4> 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).
<p>
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.
<p/>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:
<ul>
<li><a href="http://common-lisp.net/project/usocket/">
http://common-lisp.net/project/usocket/</a></li>
<li><a href="http://common-lisp.net/project/cl-plus-ssl/">
http://common-lisp.net/project/cl-plus-ssl/</a></li>
<li><a href="http://common-lisp.net/project/cffi/">
http://common-lisp.net/project/cffi/</a></li>
<li><a href="http://weitz.de/flexi-streams/">
http://weitz.de/flexi-streams/</a></li>
</ul>
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.)
<p>
<h4>Limitations</h4>
Missing functionality, as specified by RFC 2251, includes:
<ul>
<li>UTF-8 is not implemented for all CL implementations</li>
<li>SASL authentication is not implemented</li>
<li>controls are not implemented</li>
<li>extended DN searches are not implemented</li>
<li>referrals are not followed</li>
<li>extended request/response is not implemented</li>
</ul>
I do not require this functionality myself, but if there was
interest I would consider augmenting TRIVIAL-LDAP with some of
this missing functionality.
<p/>
<h4>API</h4>
<dl>
<p><b>LDAP object and associated methods.</b></p>
<dt>
<span class="term"><b>new-ldap</b> <i>&key (host "localhost")
(port 389) user pass base debug</i></span> <span
class="type">[function]</span>
</dt>
<br class="both" />
<dd>Return an LDAP object.</dd>
<dt>
<span class="term"><b>host</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" /> <dd>Get/set the host slot value of
ldap-object. Slot value will be a string.</dd>
<dt>
<span class="term"><b>port</b> <i>ldap-object</i></span> <span
class="type">[method]</span>
</dt>
<br class="both" /> <dd>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.
</dd>
<dt>
<span class="term"><b>user</b> <i>ldap-object</i></span> <span
class="type">[method]</span>
</dt>
<br class="both" /> <dd>Get/set the user DN to bind as. Slot
value will be a string.
</dd>
<dt>
<span class="term"><b>pass</b> <i>ldap-object</i></span> <span
class="type">[method]</span>
</dt>
<br class="both" /> <dd>Get/set the simple password to bind with.
Slot value will be a string.
</dd>
<dt>
<span class="term"><b>base</b> <i>ldap-object</i></span> <span
class="type">[method]</span>
</dt>
<br class="both" /> <dd>Get/set the default base DN for searches.
Slot value will be a string.
</dd>
<dt>
<span class="term"><b>debugflag</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" />
<dd>Get/set the debug flag. Slot value will be T or NIL. When
value is T debug output will be written to *debug-io*.
</dd>
<dt>
<span class="term"><b>sslflag</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" />
<dd>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.
</dd>
<dt>
<span class="term"><b>reuse-connection</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" />
<dd>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.
</dd>
<p><b>Entry object and associated methods</b></p>
<dt>
<span class="term"><b>new-entry</b> <i>dn &key (attrs ())
(infer-rdn t)</i></span> <span class="type">[function]</span>
</dt>
<br class="both" />
<dd>Return a new entry object with the DN specified.
<code>attrs</code>, if specified, will be an alist of
attribute/value pairs. If <code>infer-rdn</code> is T the RDN
attribute and value will be appended to the attribute list.
</dd>
<dt>
<span class="term"><b>dn</b> <i>entry-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" />
<dd>Return the DN value for entry-object.
</dd>
<dt>
<span class="term"><b>rdn</b> <i>entry-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" />
<dd>Return the RDN value for entry-object
</dd>
<dt>
<span class="term"><b>change-rdn</b> <i>entry-object
new-rdn</i></span> <span class="type">[method]</span>
</dt>
<br class="both" /> <dd>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.
</dd>
<dt>
<span class="term"><b>attr-list</b> <i>entry-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" /> <dd>Return the list of attribute symbols
belonging to entry-object
</dd>
<dt>
<span class="term"><b>attr-value</b> <i>entry-object
attr</i></span> <span class="type">[method]</span>
<br class="both" />
<span class="term"><b>attr-value</b> <i>entry-object
attr-list</i></span> <span class="type">[method]</span>
</dt>
<br class="both" /> <dd>Return a list of values associated with
the attribute <code>attr</code>. Return NIL if the attribute does
not exist. If a list of attributes is passed, return a list of
lists of values.
</dd>
<dt>
<span class="term"><b>add-attr</b> <i>entry-object attr
values</i></span> <span class="type">[method]</span>
</dt>
<br class="both" /> <dd>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.
</dd>
<dt>
<span class="term"><b>del-attr</b> <i>entry-object attr
&optional values</i></span> <span class="type">[method]</span>
</dt>
<br class="both" /> <dd>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.
</dd>
<dt>
<span class="term"><b>replace-attr</b> <i>entry-object attribute
values</i></span> <span class="type">[method]</span>
</dt>
<br class="both" /> <dd>Replace current attribute values with
values specified. Returns the entire list of attributes/values.
No LDAP directory transactions will take place.
</dd>
<dt>
<span class="term"><b>ldif</b> <i>entry-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" />
<dd>Return an LDIF representation of entry (as a string).
</dd>
<p><b>LDAP Commands</b></p>
<p>
<b>NB:</b> 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).
</p>
<p>
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.
</p>
<p>
<i>dn-or-entry</i> can be either an entry-object or a DN string.
<i>dn</i> is a string. Generally if the method only requires the DN
either the entry or the DN will be acceptable arguments.
</p>
<dt>
<span class="term"><b>bind</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" />
<dd>Send a bind request to the LDAP directory server.
</dd>
<dt>
<span class="term"><b>unbind</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" /> <dd>Send an unbind request to the LDAP
directory server and close the stream.
</dd>
<dt>
<span class="term"><b>abandon</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" /> <dd>Send an abandon request to the LDAP
directory server and purge any data on the stream waiting to be
read. </dd>
<dt>
<span class="term"><b>add</b> <i>ldap-object entry-object</i></span>
<span class="type">[method]</span>
<br class="both" />
<span class="term"><b>add</b> <i>entry-object ldap-object</i></span>
</dt>
<br class="both" /> <dd>Add an entry described by entry-object to
the directory specified by ldap-object.
</dd>
<dt>
<span class="term"><b>delete</b> <i>ldap-object
dn-or-entry</i></span> <span class="type">[method]</span>
<br class="both" />
<span class="term"><b>delete</b> <i>entry-object
ldap-object</i></span>
<br class="both" />
<span class="term"><b>delete</b> <i>dn ldap-object</i></span>
</dt>
<br class="both" /> <dd>Delete entry from directory specified by
ldap-object. <code>dn-or-entry</code> may be an entry object or a
DN string.
</dd>
<dt>
<span class="term"><b>moddn</b> <i>ldap-object dn-or-entry
new-rdn &key delete-old new-sup</i></span> <span
class="type">[method]</span>
<br class="both" />
<span class="term"><b>moddn</b> <i>entry-object ldap-object
new-rdn &key delete-old new-sup</i></span>
<br class="both" />
<span class="term"><b>moddn</b> <i>dn ldap-object new-rdn &key
delete-old new-sup</i></span>
</dt>
<br class="both" /> <dd>Modify the RDN specified by
<code>dn-or-entry</code> to the replacement RDN
<code>new-rdn</code>. <code>dn-or-entry</code> 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.
</dd>
<dt>
<span class="term"><b>compare</b> <i>ldap-object dn-or-entry
attribute value</i></span> <span class="type">[method]</span>
<br class="both" /> <span class="term"><b>compare</b>
<i>entry-object ldap-object attribute value</i>
</dt>
<br class="both" /> <dd>Send a compare message to the directory
server asserting that entry-obj (or DN) has an attribute
<code>attribute</code> with a value <code>value</code>. Returns
either T or NIL (as the only argument or as the first argument)
indicating a return code of compareTrue or compareFalse.
</dd>
<dt>
<span class="term"><b>modify</b> <i>ldap-object dn-or-entry
list-of-mods</i></span> <span class="type">[method]</span>
<br class="both" />
<span class="term"><b>modify</b> <i>entry-object ldap-object
list-of-mods</i></span>
</dt>
<br class="both" /> <dd>Modify the entry specified by
<code>dn-or-entry</code> or <code>entry-object</code>.
<code>list-of-mods</code> is a list of (type attribute value)
triples. Type will be one of ldap:add, ldap:delete, or
ldap:replace.
</dd>
<dt>
<span class="term"><b>search</b> <i>ldap-object filter &key base
(scope 'sub) (deref 'never) (size-limit 0) (time-limit 0)
types-only attributes</i></span> <span
class="type">[method]</span>
</dt>
<br class="both" /> <dd>Search the directory specified by
ldap-object. <code>filter</code> 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.
</dd>
<dt>
<span class="term"><b>next-search-result</b> <i>ldap-object</i></span>
<span class="type">[method]</span>
</dt>
<br class="both" /> <dd>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.
</dd>
<dt>
<span class="term"><b>dosearch</b> <i>var search-form &body
body</i></span> <span class="type">[macro]</span>
</dt>
<br class="both" /> <dd>Execute the ldap:search provided as
<code>search-form</code> and iterate through the results binding
each resulting entry object to <code>var</code> before evaluating
<code>body.</code> Returns the number of entries processed.
<b>NB: </b>If the body of the loop involves LDAP transactions it
is probably best that a difference LDAP instance be employed.
</dd>
<dt>
<span class="term"><b>ldif-search</b> <i>&rest
ldap-search-args</i></span> <span class="type">[macro]</span>
</dt>
<br class="both" /> <dd>Prints the results of a search in LDIF.
This macro is probably most useful in an interactive setting.
<code>ldap-search-args</code> are passed directly to the search
method described above.
</dd>
</dl>
<hr>
<address><a href="mailto:[email protected]">kevin montuori</a></address>
<!-- Created: Sun Jan 22 14:36:42 EST 2006 -->
<!-- hhmts start -->
Last modified: Sat Jan 13 09:01:44 EST 2007
<!-- hhmts end -->
</body>
</html>