comparison src/eldap.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents 2f8bb876ab1d
children e804706bfb8c
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
24 24
25 /* This file provides lisp primitives for access to an LDAP library 25 /* This file provides lisp primitives for access to an LDAP library
26 conforming to the API defined in RFC 1823. 26 conforming to the API defined in RFC 1823.
27 It has been tested with: 27 It has been tested with:
28 - UMich LDAP 3.3 (http://www.umich.edu/~dirsvcs/ldap/) 28 - UMich LDAP 3.3 (http://www.umich.edu/~dirsvcs/ldap/)
29 - OpenLDAP 1.2 (http://www.openldap.org/) 29 - OpenLDAP 1.0.3 (http://www.openldap.org/)
30 - Netscape's LDAP SDK (http://developer.netscape.com/) */ 30 - Netscape's LDAP SDK 1.0 (http://developer.netscape.com/) */
31 31
32 32
33 #include <config.h> 33 #include <config.h>
34 #include "lisp.h" 34 #include "lisp.h"
35 #include "opaque.h" 35 #include "opaque.h"
38 38
39 #include <errno.h> 39 #include <errno.h>
40 40
41 #include "eldap.h" 41 #include "eldap.h"
42 42
43 #ifdef HAVE_NS_LDAP
44 # define HAVE_LDAP_SET_OPTION 1
45 # define HAVE_LDAP_GET_ERRNO 1
46 #else
47 # undef HAVE_LDAP_SET_OPTION
48 # undef HAVE_LDAP_GET_ERRNO
49 #endif
50
43 static int ldap_default_port; 51 static int ldap_default_port;
44 static Lisp_Object Vldap_default_base; 52 static Lisp_Object Vldap_default_base;
45 53
46 /* Needed by the lrecord definition */ 54 /* Needed by the lrecord definition */
47 Lisp_Object Qldapp; 55 Lisp_Object Qldapp;
48 56
49 /* ldap-open plist keywords */ 57 /* ldap-open plist keywords */
50 static Lisp_Object Qport, Qauth, Qbinddn, Qpasswd, Qderef, Qtimelimit, Qsizelimit; 58 extern Lisp_Object Qport, Qauth, Qbinddn, Qpasswd, Qderef, Qtimelimit,
59 Qsizelimit;
51 /* Search scope limits */ 60 /* Search scope limits */
52 static Lisp_Object Qbase, Qonelevel, Qsubtree; 61 extern Lisp_Object Qbase, Qonelevel, Qsubtree;
53 /* Authentication methods */ 62 /* Authentication methods */
54 static Lisp_Object Qkrbv41, Qkrbv42; 63 extern Lisp_Object Qkrbv41, Qkrbv42;
55 /* Deref policy */ 64 /* Deref policy */
56 static Lisp_Object Qnever, Qalways, Qfind; 65 extern Lisp_Object Qnever, Qalways, Qfind;
57 /* Modification types (Qdelete is defined in general.c) */
58 static Lisp_Object Qadd, Qreplace;
59
60 66
61 /************************************************************************/ 67 /************************************************************************/
62 /* Utility Functions */ 68 /* Utility Functions */
63 /************************************************************************/ 69 /************************************************************************/
64 70
65 static void 71 static void
66 signal_ldap_error (LDAP *ld, LDAPMessage *res, int ldap_err) 72 signal_ldap_error (LDAP *ld)
67 { 73 {
68 if (ldap_err <= 0) 74 #ifdef HAVE_LDAP_GET_ERRNO
69 { 75 signal_simple_error
70 #if defined HAVE_LDAP_PARSE_RESULT 76 ("LDAP error",
71 int err; 77 build_string (ldap_err2string (ldap_get_lderrno (ld, NULL, NULL))));
72 ldap_err = ldap_parse_result (ld, res,
73 &err,
74 NULL, NULL, NULL, NULL, 0);
75 if (ldap_err == LDAP_SUCCESS)
76 ldap_err = err;
77 #elif defined HAVE_LDAP_GET_LDERRNO
78 ldap_err = ldap_get_lderrno (ld, NULL, NULL);
79 #elif defined HAVE_LDAP_RESULT2ERROR
80 ldap_err = ldap_result2error (ld, res, 0);
81 #else 78 #else
82 ldap_err = ld->ld_errno; 79 signal_simple_error ("LDAP error",
80 build_string (ldap_err2string (ld->ld_errno)));
83 #endif 81 #endif
84 }
85 signal_simple_error ("LDAP error",
86 build_string (ldap_err2string (ldap_err)));
87 } 82 }
88 83
89 84
90 /************************************************************************/ 85 /************************************************************************/
91 /* ldap lrecord basic functions */ 86 /* ldap lrecord basic functions */
92 /************************************************************************/ 87 /************************************************************************/
93 88
94 static Lisp_Object 89 static Lisp_Object
95 make_ldap (Lisp_LDAP *ldap) 90 make_ldap (struct Lisp_LDAP *ldap)
96 { 91 {
97 Lisp_Object lisp_ldap; 92 Lisp_Object lisp_ldap;
98 XSETLDAP (lisp_ldap, ldap); 93 XSETLDAP (lisp_ldap, ldap);
99 return lisp_ldap; 94 return lisp_ldap;
100 } 95 }
101 96
102 static Lisp_Object 97 static Lisp_Object
103 mark_ldap (Lisp_Object obj) 98 mark_ldap (Lisp_Object obj, void (*markobj) (Lisp_Object))
104 { 99 {
105 return XLDAP (obj)->host; 100 return XLDAP (obj)->host;
106 } 101 }
107 102
108 static void 103 static void
109 print_ldap (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 104 print_ldap (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
110 { 105 {
111 char buf[32]; 106 char buf[32];
112 107
113 Lisp_LDAP *ldap = XLDAP (obj); 108 struct Lisp_LDAP *ldap = XLDAP (obj);
114 109
115 if (print_readably) 110 if (print_readably)
116 error ("printing unreadable object #<ldap %s>", 111 error ("printing unreadable object #<ldap %s>",
117 XSTRING_DATA (ldap->host)); 112 XSTRING_DATA (ldap->host));
118 113
119 write_c_string ("#<ldap ", printcharfun); 114 write_c_string ("#<ldap ", printcharfun);
120 print_internal (ldap->host, printcharfun, 1); 115 print_internal (ldap->host, printcharfun, 1);
121 if (!ldap->ld) 116 if (!ldap->livep)
122 write_c_string ("(dead) ",printcharfun); 117 write_c_string ("(dead) ",printcharfun);
123 sprintf (buf, " 0x%x>", (unsigned int)ldap); 118 sprintf (buf, " 0x%x>", (unsigned int)ldap);
124 write_c_string (buf, printcharfun); 119 write_c_string (buf, printcharfun);
125 } 120 }
126 121
127 static Lisp_LDAP * 122 static struct Lisp_LDAP *
128 allocate_ldap (void) 123 allocate_ldap (void)
129 { 124 {
130 Lisp_LDAP *ldap = alloc_lcrecord_type (Lisp_LDAP, &lrecord_ldap); 125 struct Lisp_LDAP *ldap =
126 alloc_lcrecord_type (struct Lisp_LDAP, &lrecord_ldap);
131 127
132 ldap->ld = NULL; 128 ldap->ld = NULL;
133 ldap->host = Qnil; 129 ldap->host = Qnil;
130 ldap->livep = 0;
134 return ldap; 131 return ldap;
135 } 132 }
136 133
137 static void 134 static void
138 finalize_ldap (void *header, int for_disksave) 135 finalize_ldap (void *header, int for_disksave)
139 { 136 {
140 Lisp_LDAP *ldap = (Lisp_LDAP *) header; 137 struct Lisp_LDAP *ldap = (struct Lisp_LDAP *) header;
141 138
142 if (for_disksave) 139 if (for_disksave)
143 signal_simple_error ("Can't dump an emacs containing LDAP objects", 140 signal_simple_error ("Can't dump an emacs containing LDAP objects",
144 make_ldap (ldap)); 141 make_ldap (ldap));
145 142
146 if (ldap->ld) 143 if (ldap->livep)
147 ldap_unbind (ldap->ld); 144 ldap_unbind (ldap->ld);
148 ldap->ld = NULL;
149 } 145 }
150 146
151 DEFINE_LRECORD_IMPLEMENTATION ("ldap", ldap, 147 DEFINE_LRECORD_IMPLEMENTATION ("ldap", ldap,
152 mark_ldap, print_ldap, finalize_ldap, 148 mark_ldap, print_ldap, finalize_ldap,
153 NULL, NULL, 0, Lisp_LDAP); 149 NULL, NULL, struct Lisp_LDAP);
154 150
155 151
156 152
157 153
158 /************************************************************************/ 154 /************************************************************************/
180 Return t if LDAP is an active LDAP connection. 176 Return t if LDAP is an active LDAP connection.
181 */ 177 */
182 (ldap)) 178 (ldap))
183 { 179 {
184 CHECK_LDAP (ldap); 180 CHECK_LDAP (ldap);
185 return (XLDAP (ldap))->ld ? Qt : Qnil; 181 return (XLDAP (ldap))->livep ? Qt : Qnil;
186 } 182 }
187 183
188 /************************************************************************/ 184 /************************************************************************/
189 /* Opening/Closing a LDAP connection */ 185 /* Opening/Closing a LDAP connection */
190 /************************************************************************/ 186 /************************************************************************/
205 `sizelimit' is the maximum number of matches to return. 201 `sizelimit' is the maximum number of matches to return.
206 */ 202 */
207 (host, plist)) 203 (host, plist))
208 { 204 {
209 /* This function can GC */ 205 /* This function can GC */
210 Lisp_LDAP *ldap; 206 struct Lisp_LDAP *ldap;
211 LDAP *ld; 207 LDAP *ld;
212 int ldap_port = 0; 208 int ldap_port = 0;
213 int ldap_auth = LDAP_AUTH_SIMPLE; 209 int ldap_auth = LDAP_AUTH_SIMPLE;
214 char *ldap_binddn = NULL; 210 char *ldap_binddn = NULL;
215 char *ldap_passwd = NULL; 211 char *ldap_passwd = NULL;
248 } 244 }
249 /* Bind DN */ 245 /* Bind DN */
250 else if (EQ (keyword, Qbinddn)) 246 else if (EQ (keyword, Qbinddn))
251 { 247 {
252 CHECK_STRING (value); 248 CHECK_STRING (value);
253 TO_EXTERNAL_FORMAT (LISP_STRING, value, 249 GET_C_STRING_OS_DATA_ALLOCA (value, ldap_binddn);
254 C_STRING_ALLOCA, ldap_binddn,
255 Qnative);
256 } 250 }
257 /* Password */ 251 /* Password */
258 else if (EQ (keyword, Qpasswd)) 252 else if (EQ (keyword, Qpasswd))
259 { 253 {
260 CHECK_STRING (value); 254 CHECK_STRING (value);
261 TO_EXTERNAL_FORMAT (LISP_STRING, value, 255 GET_C_STRING_OS_DATA_ALLOCA (value, ldap_passwd);
262 C_STRING_ALLOCA, ldap_passwd,
263 Qnative);
264 } 256 }
265 /* Deref */ 257 /* Deref */
266 else if (EQ (keyword, Qderef)) 258 else if (EQ (keyword, Qderef))
267 { 259 {
268 if (EQ (value, Qnever)) 260 if (EQ (value, Qnever))
305 host, 297 host,
306 lisp_strerror (errno)); 298 lisp_strerror (errno));
307 299
308 300
309 #ifdef HAVE_LDAP_SET_OPTION 301 #ifdef HAVE_LDAP_SET_OPTION
310 if ((err = ldap_set_option (ld, LDAP_OPT_DEREF, 302 if (ldap_set_option (ld, LDAP_OPT_DEREF, (void *)&ldap_deref) != LDAP_SUCCESS)
311 (void *)&ldap_deref)) != LDAP_SUCCESS) 303 signal_ldap_error (ld);
312 signal_ldap_error (ld, NULL, err); 304 if (ldap_set_option (ld, LDAP_OPT_TIMELIMIT,
313 if ((err = ldap_set_option (ld, LDAP_OPT_TIMELIMIT, 305 (void *)&ldap_timelimit) != LDAP_SUCCESS)
314 (void *)&ldap_timelimit)) != LDAP_SUCCESS) 306 signal_ldap_error (ld);
315 signal_ldap_error (ld, NULL, err); 307 if (ldap_set_option (ld, LDAP_OPT_SIZELIMIT,
316 if ((err = ldap_set_option (ld, LDAP_OPT_SIZELIMIT, 308 (void *)&ldap_sizelimit) != LDAP_SUCCESS)
317 (void *)&ldap_sizelimit)) != LDAP_SUCCESS) 309 signal_ldap_error (ld);
318 signal_ldap_error (ld, NULL, err); 310 if (ldap_set_option (ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON) != LDAP_SUCCESS)
319 if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS, 311 signal_ldap_error (ld);
320 LDAP_OPT_ON)) != LDAP_SUCCESS)
321 signal_ldap_error (ld, NULL, err);
322 if ((err = ldap_set_option (ld, LDAP_OPT_RESTART,
323 LDAP_OPT_ON)) != LDAP_SUCCESS)
324 signal_ldap_error (ld, NULL, err);
325 #else /* not HAVE_LDAP_SET_OPTION */ 312 #else /* not HAVE_LDAP_SET_OPTION */
326 ld->ld_deref = ldap_deref; 313 ld->ld_deref = ldap_deref;
327 ld->ld_timelimit = ldap_timelimit; 314 ld->ld_timelimit = ldap_timelimit;
328 ld->ld_sizelimit = ldap_sizelimit; 315 ld->ld_sizelimit = ldap_sizelimit;
329 #ifdef LDAP_REFERRALS 316 #ifdef LDAP_REFERRALS
330 ld->ld_options = LDAP_OPT_REFERRALS; 317 ld->ld_options = LDAP_OPT_REFERRALS;
331 #else /* not LDAP_REFERRALS */ 318 #else /* not LDAP_REFERRALS */
332 ld->ld_options = 0; 319 ld->ld_options = 0;
333 #endif /* not LDAP_REFERRALS */ 320 #endif /* not LDAP_REFERRALS */
334 /* XEmacs uses interrupts (SIGIO,SIGALRM), LDAP calls need to ignore them */
335 ld->ld_options |= LDAP_OPT_RESTART;
336 #endif /* not HAVE_LDAP_SET_OPTION */ 321 #endif /* not HAVE_LDAP_SET_OPTION */
337 322
323 /* ldap_bind_s calls select and may be wedged by SIGIO. */
324 slow_down_interrupts ();
338 err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth); 325 err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth);
326 speed_up_interrupts ();
339 if (err != LDAP_SUCCESS) 327 if (err != LDAP_SUCCESS)
340 signal_simple_error ("Failed binding to the server", 328 signal_simple_error ("Failed binding to the server",
341 build_string (ldap_err2string (err))); 329 build_string (ldap_err2string (err)));
342 330
343 ldap = allocate_ldap (); 331 ldap = allocate_ldap ();
344 ldap->ld = ld; 332 ldap->ld = ld;
345 ldap->host = host; 333 ldap->host = host;
334 ldap->livep = 1;
346 335
347 return make_ldap (ldap); 336 return make_ldap (ldap);
348 } 337 }
349 338
350 339
352 DEFUN ("ldap-close", Fldap_close, 1, 1, 0, /* 341 DEFUN ("ldap-close", Fldap_close, 1, 1, 0, /*
353 Close an LDAP connection. 342 Close an LDAP connection.
354 */ 343 */
355 (ldap)) 344 (ldap))
356 { 345 {
357 Lisp_LDAP *lldap; 346 struct Lisp_LDAP *lldap;
358 CHECK_LIVE_LDAP (ldap); 347 CHECK_LIVE_LDAP (ldap);
359 lldap = XLDAP (ldap); 348 lldap = XLDAP (ldap);
360 ldap_unbind (lldap->ld); 349 ldap_unbind (lldap->ld);
361 lldap->ld = NULL; 350 lldap->livep = 0;
362 return Qnil; 351 return Qnil;
363 } 352 }
364 353
365 354
366 355
370 struct ldap_unwind_struct 359 struct ldap_unwind_struct
371 { 360 {
372 LDAPMessage *res; 361 LDAPMessage *res;
373 struct berval **vals; 362 struct berval **vals;
374 }; 363 };
364
375 365
376 static Lisp_Object 366 static Lisp_Object
377 ldap_search_unwind (Lisp_Object unwind_obj) 367 ldap_search_unwind (Lisp_Object unwind_obj)
378 { 368 {
379 struct ldap_unwind_struct *unwind = 369 struct ldap_unwind_struct *unwind =
383 if (unwind->vals) 373 if (unwind->vals)
384 ldap_value_free_len (unwind->vals); 374 ldap_value_free_len (unwind->vals);
385 return Qnil; 375 return Qnil;
386 } 376 }
387 377
388 /* The following function is called `ldap-search-basic' instead of */ 378 DEFUN ("ldap-search-internal", Fldap_search_internal, 2, 7, 0, /*
389 /* plain `ldap-search' to maintain compatibility with the XEmacs 21.1 */
390 /* API where `ldap-search' was the name of the high-level search */
391 /* function */
392
393 DEFUN ("ldap-search-basic", Fldap_search_basic, 2, 8, 0, /*
394 Perform a search on an open LDAP connection. 379 Perform a search on an open LDAP connection.
395 LDAP is an LDAP connection object created with `ldap-open'. 380 LDAP is an LDAP connection object created with `ldap-open'.
396 FILTER is a filter string for the search as described in RFC 1558. 381 FILTER is a filter string for the search as described in RFC 1558.
397 BASE is the distinguished name at which to start the search. 382 BASE is the distinguished name at which to start the search.
398 SCOPE is one of the symbols `base', `onelevel' or `subtree' indicating 383 SCOPE is one of the symbols `base', `onelevel' or `subtree' indicating
399 the scope of the search. 384 the scope of the search.
400 ATTRS is a list of strings indicating which attributes to retrieve 385 ATTRS is a list of strings indicating which attributes to retrieve
401 for each matching entry. If nil return all available attributes. 386 for each matching entry. If nil return all available attributes.
402 If ATTRSONLY is non-nil then only the attributes are retrieved, not 387 If ATTRSONLY is non-nil then only the attributes are retrieved, not
403 the associated values. 388 the associated values.
404 If WITHDN is non-nil each entry in the result will be prepended with 389 If WITHDN is non-nil each entry in the result will be prepennded with
405 its distinguished name DN. 390 its distinguished name DN.
406 If VERBOSE is non-nil progress messages will be echoed.
407 The function returns a list of matching entries. Each entry is itself 391 The function returns a list of matching entries. Each entry is itself
408 an alist of attribute/value pairs optionally preceded by the DN of the 392 an alist of attribute/value pairs optionally preceded by the DN of the
409 entry according to the value of WITHDN. 393 entry according to the value of WITHDN.
410 */ 394 */
411 (ldap, filter, base, scope, attrs, attrsonly, withdn, verbose)) 395 (ldap, filter, base, scope, attrs, attrsonly, withdn))
412 { 396 {
413 /* This function can GC */ 397 /* This function can GC */
414 398
415 /* Vars for query */ 399 /* Vars for query */
416 LDAP *ld; 400 LDAP *ld;
424 int ldap_scope = LDAP_SCOPE_SUBTREE; 408 int ldap_scope = LDAP_SCOPE_SUBTREE;
425 char **ldap_attributes = NULL; 409 char **ldap_attributes = NULL;
426 410
427 int speccount = specpdl_depth (); 411 int speccount = specpdl_depth ();
428 412
429 Lisp_Object list = Qnil; 413 Lisp_Object list, entry, result;
430 Lisp_Object entry = Qnil;
431 Lisp_Object result = Qnil;
432 struct gcpro gcpro1, gcpro2, gcpro3; 414 struct gcpro gcpro1, gcpro2, gcpro3;
433 415
416 list = entry = result = Qnil;
434 GCPRO3 (list, entry, result); 417 GCPRO3 (list, entry, result);
435 418
436 unwind.res = NULL; 419 unwind.res = NULL;
437 unwind.vals = NULL; 420 unwind.vals = NULL;
438 421
475 i = 0; 458 i = 0;
476 EXTERNAL_LIST_LOOP (attrs, attrs) 459 EXTERNAL_LIST_LOOP (attrs, attrs)
477 { 460 {
478 Lisp_Object current = XCAR (attrs); 461 Lisp_Object current = XCAR (attrs);
479 CHECK_STRING (current); 462 CHECK_STRING (current);
480 TO_EXTERNAL_FORMAT (LISP_STRING, current, 463 GET_C_STRING_OS_DATA_ALLOCA (current, ldap_attributes[i]);
481 C_STRING_ALLOCA, ldap_attributes[i],
482 Qnative);
483 ++i; 464 ++i;
484 } 465 }
485 ldap_attributes[i] = NULL; 466 ldap_attributes[i] = NULL;
486 } 467 }
487 468
488 /* Attributes only ? */ 469 /* Attributes only ? */
489 CHECK_SYMBOL (attrsonly); 470 CHECK_SYMBOL (attrsonly);
490 471
491 /* Perform the search */ 472 /* Perform the search */
492 if (ldap_search (ld, 473 if (ldap_search (ld,
493 NILP (base) ? (char *) "" : (char *) XSTRING_DATA (base), 474 NILP (base) ? "" : (char *) XSTRING_DATA (base),
494 ldap_scope, 475 ldap_scope,
495 NILP (filter) ? (char *) "" : (char *) XSTRING_DATA (filter), 476 NILP (filter) ? "" : (char *) XSTRING_DATA (filter),
496 ldap_attributes, 477 ldap_attributes,
497 NILP (attrsonly) ? 0 : 1) 478 NILP (attrsonly) ? 0 : 1)
498 == -1) 479 == -1)
499 { 480 {
500 signal_ldap_error (ld, NULL, 0); 481 signal_ldap_error (ld);
501 } 482 }
502 483
503 /* Ensure we don't exit without cleaning up */ 484 /* Ensure we don't exit without cleaning up */
504 record_unwind_protect (ldap_search_unwind, 485 record_unwind_protect (ldap_search_unwind,
505 make_opaque_ptr (&unwind)); 486 make_opaque_ptr (&unwind));
506 487
507 /* Build the results list */ 488 /* Build the results list */
508 matches = 0; 489 matches = 0;
509 490
491 /* ldap_result calls select() and can get wedged by EINTR signals */
492 slow_down_interrupts ();
510 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res); 493 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res);
511 494 speed_up_interrupts ();
512 while (rc == LDAP_RES_SEARCH_ENTRY) 495 while (rc == LDAP_RES_SEARCH_ENTRY)
513 { 496 {
514 QUIT; 497 QUIT;
515 matches ++; 498 matches ++;
516 e = ldap_first_entry (ld, unwind.res); 499 e = ldap_first_entry (ld, unwind.res);
517 /* #### This call to message() is pretty fascist, because it 500 /* #### This call to message() is pretty fascist, because it
518 destroys the current echo area contents, even when invoked 501 destroys the current echo area contents, even when invoked
519 from Lisp. It should use echo_area_message() instead, and 502 from Lisp. It should use echo_area_message() instead, and
520 restore the old echo area contents later. */ 503 restore the old echo area contents later. */
521 if (! NILP (verbose)) 504 message ("Parsing ldap results... %d", matches);
522 message ("Parsing ldap results... %d", matches);
523 entry = Qnil; 505 entry = Qnil;
524 /* Get the DN if required */ 506 /* Get the DN if required */
525 if (! NILP (withdn)) 507 if (! NILP (withdn))
526 { 508 {
527 dn = ldap_get_dn (ld, e); 509 dn = ldap_get_dn (ld, e);
528 if (dn == NULL) 510 if (dn == NULL)
529 signal_ldap_error (ld, e, 0); 511 {
530 entry = Fcons (build_ext_string (dn, Qnative), Qnil); 512 signal_ldap_error (ld);
513 }
514 entry = Fcons (build_ext_string (dn, FORMAT_OS), Qnil);
531 } 515 }
532 for (a= ldap_first_attribute (ld, e, &ptr); 516 for (a= ldap_first_attribute (ld, e, &ptr);
533 a != NULL; 517 a != NULL;
534 a = ldap_next_attribute (ld, e, ptr) ) 518 a = ldap_next_attribute (ld, e, ptr) )
535 { 519 {
536 list = Fcons (build_ext_string (a, Qnative), Qnil); 520 list = Fcons (build_ext_string (a, FORMAT_OS), Qnil);
537 unwind.vals = ldap_get_values_len (ld, e, a); 521 unwind.vals = ldap_get_values_len (ld, e, a);
538 if (unwind.vals != NULL) 522 if (unwind.vals != NULL)
539 { 523 {
540 for (i = 0; unwind.vals[i] != NULL; i++) 524 for (i = 0; unwind.vals[i] != NULL; i++)
541 { 525 {
542 list = Fcons (make_ext_string ((Extbyte *) unwind.vals[i]->bv_val, 526 list = Fcons (make_ext_string (unwind.vals[i]->bv_val,
543 unwind.vals[i]->bv_len, 527 unwind.vals[i]->bv_len,
544 Qnative), 528 FORMAT_OS),
545 list); 529 list);
546 } 530 }
547 } 531 }
548 entry = Fcons (Fnreverse (list), 532 entry = Fcons (Fnreverse (list),
549 entry); 533 entry);
553 result = Fcons (Fnreverse (entry), 537 result = Fcons (Fnreverse (entry),
554 result); 538 result);
555 ldap_msgfree (unwind.res); 539 ldap_msgfree (unwind.res);
556 unwind.res = NULL; 540 unwind.res = NULL;
557 541
542 slow_down_interrupts ();
558 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res)); 543 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res));
559 } 544 speed_up_interrupts ();
560 545 }
561 #if defined HAVE_LDAP_PARSE_RESULT
562 {
563 int rc2 = ldap_parse_result (ld, unwind.res,
564 &rc,
565 NULL, NULL, NULL, NULL, 0);
566 if (rc2 != LDAP_SUCCESS)
567 rc = rc2;
568 }
569 #else
570 if (rc == 0)
571 signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED);
572 546
573 if (rc == -1) 547 if (rc == -1)
574 signal_ldap_error (ld, unwind.res, (unwind.res==NULL) ? ld->ld_errno : 0); 548 {
575 549 signal_ldap_error (ld);
576 #if defined HAVE_LDAP_RESULT2ERROR 550 }
577 rc = ldap_result2error (ld, unwind.res, 0); 551 rc = ldap_result2error (ld, unwind.res, 0);
578 #endif 552 if ((rc != LDAP_SUCCESS) &&
579 #endif 553 (rc != LDAP_SIZELIMIT_EXCEEDED))
580 554 {
581 if (rc != LDAP_SUCCESS) 555 signal_ldap_error (ld);
582 signal_ldap_error (ld, NULL, rc); 556 }
583 557
584 ldap_msgfree (unwind.res); 558 ldap_msgfree (unwind.res);
585 unwind.res = (LDAPMessage *)NULL; 559 unwind.res = (LDAPMessage *)NULL;
586
587 /* #### See above for calling message(). */ 560 /* #### See above for calling message(). */
588 if (! NILP (verbose)) 561 message ("Parsing ldap results... done");
589 message ("Parsing ldap results... done");
590 562
591 unbind_to (speccount, Qnil); 563 unbind_to (speccount, Qnil);
592 UNGCPRO; 564 UNGCPRO;
593 return Fnreverse (result); 565 return Fnreverse (result);
594 } 566 }
595 567
596 DEFUN ("ldap-add", Fldap_add, 3, 3, 0, /*
597 Add an entry to an LDAP directory.
598 LDAP is an LDAP connection object created with `ldap-open'.
599 DN is the distinguished name of the entry to add.
600 ENTRY is an entry specification, i.e., a list of cons cells
601 containing attribute/value string pairs.
602 */
603 (ldap, dn, entry))
604 {
605 LDAP *ld;
606 LDAPMod *ldap_mods, **ldap_mods_ptrs;
607 struct berval *bervals;
608 int rc;
609 int i, j;
610 size_t len;
611
612 Lisp_Object current = Qnil;
613 Lisp_Object values = Qnil;
614 struct gcpro gcpro1, gcpro2;
615
616 GCPRO2 (current, values);
617
618 /* Do all the parameter checking */
619 CHECK_LIVE_LDAP (ldap);
620 ld = XLDAP (ldap)->ld;
621
622 /* Check the DN */
623 CHECK_STRING (dn);
624
625 /* Check the entry */
626 CHECK_CONS (entry);
627 if (NILP (entry))
628 signal_simple_error ("Cannot add void entry", entry);
629
630 /* Build the ldap_mods array */
631 len = XINT (Flength (entry));
632 ldap_mods = alloca_array (LDAPMod, len);
633 ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len);
634 i = 0;
635 EXTERNAL_LIST_LOOP (entry, entry)
636 {
637 current = XCAR (entry);
638 CHECK_CONS (current);
639 CHECK_STRING (XCAR (current));
640 ldap_mods_ptrs[i] = &(ldap_mods[i]);
641 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (current),
642 C_STRING_ALLOCA, ldap_mods[i].mod_type,
643 Qnative);
644 ldap_mods[i].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
645 values = XCDR (current);
646 if (CONSP (values))
647 {
648 len = XINT (Flength (values));
649 bervals = alloca_array (struct berval, len);
650 ldap_mods[i].mod_vals.modv_bvals =
651 alloca_array (struct berval *, 1 + len);
652 j = 0;
653 EXTERNAL_LIST_LOOP (values, values)
654 {
655 current = XCAR (values);
656 CHECK_STRING (current);
657 ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]);
658 TO_EXTERNAL_FORMAT (LISP_STRING, current,
659 ALLOCA, (bervals[j].bv_val,
660 bervals[j].bv_len),
661 Qnative);
662 j++;
663 }
664 ldap_mods[i].mod_vals.modv_bvals[j] = NULL;
665 }
666 else
667 {
668 CHECK_STRING (values);
669 bervals = alloca_array (struct berval, 1);
670 ldap_mods[i].mod_vals.modv_bvals = alloca_array (struct berval *, 2);
671 ldap_mods[i].mod_vals.modv_bvals[0] = &(bervals[0]);
672 TO_EXTERNAL_FORMAT (LISP_STRING, values,
673 ALLOCA, (bervals[0].bv_val,
674 bervals[0].bv_len),
675 Qnative);
676 ldap_mods[i].mod_vals.modv_bvals[1] = NULL;
677 }
678 i++;
679 }
680 ldap_mods_ptrs[i] = NULL;
681 rc = ldap_add_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs);
682 if (rc != LDAP_SUCCESS)
683 signal_ldap_error (ld, NULL, rc);
684
685 UNGCPRO;
686 return Qnil;
687 }
688
689 DEFUN ("ldap-modify", Fldap_modify, 3, 3, 0, /*
690 Add an entry to an LDAP directory.
691 LDAP is an LDAP connection object created with `ldap-open'.
692 DN is the distinguished name of the entry to modify.
693 MODS is a list of modifications to apply.
694 A modification is a list of the form (MOD-OP ATTR VALUE1 VALUE2 ...)
695 MOD-OP and ATTR are mandatory, VALUEs are optional depending on MOD-OP.
696 MOD-OP is the type of modification, one of the symbols `add', `delete'
697 or `replace'. ATTR is the LDAP attribute type to modify.
698 */
699 (ldap, dn, mods))
700 {
701 LDAP *ld;
702 LDAPMod *ldap_mods, **ldap_mods_ptrs;
703 struct berval *bervals;
704 int i, j, rc;
705 Lisp_Object mod_op;
706 size_t len;
707
708 Lisp_Object current = Qnil;
709 Lisp_Object values = Qnil;
710 struct gcpro gcpro1, gcpro2;
711
712 GCPRO2 (current, values);
713
714 /* Do all the parameter checking */
715 CHECK_LIVE_LDAP (ldap);
716 ld = XLDAP (ldap)->ld;
717
718 /* Check the DN */
719 CHECK_STRING (dn);
720
721 /* Check the entry */
722 CHECK_CONS (mods);
723 if (NILP (mods))
724 return Qnil;
725
726 /* Build the ldap_mods array */
727 len = XINT (Flength (mods));
728 ldap_mods = alloca_array (LDAPMod, len);
729 ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len);
730 i = 0;
731 EXTERNAL_LIST_LOOP (mods, mods)
732 {
733 current = XCAR (mods);
734 CHECK_CONS (current);
735 CHECK_SYMBOL (XCAR (current));
736 mod_op = XCAR (current);
737 ldap_mods_ptrs[i] = &(ldap_mods[i]);
738 ldap_mods[i].mod_op = LDAP_MOD_BVALUES;
739 if (EQ (mod_op, Qadd))
740 ldap_mods[i].mod_op |= LDAP_MOD_ADD;
741 else if (EQ (mod_op, Qdelete))
742 ldap_mods[i].mod_op |= LDAP_MOD_DELETE;
743 else if (EQ (mod_op, Qreplace))
744 ldap_mods[i].mod_op |= LDAP_MOD_REPLACE;
745 else
746 signal_simple_error ("Invalid LDAP modification type", mod_op);
747 current = XCDR (current);
748 CHECK_STRING (XCAR (current));
749 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (current),
750 C_STRING_ALLOCA, ldap_mods[i].mod_type,
751 Qnative);
752 values = XCDR (current);
753 len = XINT (Flength (values));
754 bervals = alloca_array (struct berval, len);
755 ldap_mods[i].mod_vals.modv_bvals =
756 alloca_array (struct berval *, 1 + len);
757 j = 0;
758 EXTERNAL_LIST_LOOP (values, values)
759 {
760 current = XCAR (values);
761 CHECK_STRING (current);
762 ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]);
763 TO_EXTERNAL_FORMAT (LISP_STRING, current,
764 ALLOCA, (bervals[j].bv_val,
765 bervals[j].bv_len),
766 Qnative);
767 j++;
768 }
769 ldap_mods[i].mod_vals.modv_bvals[j] = NULL;
770 i++;
771 }
772 ldap_mods_ptrs[i] = NULL;
773 rc = ldap_modify_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs);
774 if (rc != LDAP_SUCCESS)
775 signal_ldap_error (ld, NULL, rc);
776
777 UNGCPRO;
778 return Qnil;
779 }
780
781
782 DEFUN ("ldap-delete", Fldap_delete, 2, 2, 0, /*
783 Delete an entry to an LDAP directory.
784 LDAP is an LDAP connection object created with `ldap-open'.
785 DN is the distinguished name of the entry to delete.
786 */
787 (ldap, dn))
788 {
789 LDAP *ld;
790 int rc;
791
792 /* Check parameters */
793 CHECK_LIVE_LDAP (ldap);
794 ld = XLDAP (ldap)->ld;
795 CHECK_STRING (dn);
796
797 rc = ldap_delete_s (ld, (char *) XSTRING_DATA (dn));
798 if (rc != LDAP_SUCCESS)
799 signal_ldap_error (ld, NULL, rc);
800
801 return Qnil;
802 }
803 568
804 void 569 void
805 syms_of_eldap (void) 570 syms_of_eldap (void)
806 { 571 {
807 INIT_LRECORD_IMPLEMENTATION (ldap);
808
809 defsymbol (&Qldapp, "ldapp"); 572 defsymbol (&Qldapp, "ldapp");
810 defsymbol (&Qport, "port");
811 defsymbol (&Qauth, "auth");
812 defsymbol (&Qbinddn, "binddn");
813 defsymbol (&Qpasswd, "passwd");
814 defsymbol (&Qderef, "deref");
815 defsymbol (&Qtimelimit, "timelimit");
816 defsymbol (&Qsizelimit, "sizelimit");
817 defsymbol (&Qbase, "base");
818 defsymbol (&Qonelevel, "onelevel");
819 defsymbol (&Qsubtree, "subtree");
820 defsymbol (&Qkrbv41, "krbv41");
821 defsymbol (&Qkrbv42, "krbv42");
822 defsymbol (&Qnever, "never");
823 defsymbol (&Qalways, "always");
824 defsymbol (&Qfind, "find");
825 defsymbol (&Qadd, "add");
826 defsymbol (&Qreplace, "replace");
827
828 DEFSUBR (Fldapp); 573 DEFSUBR (Fldapp);
829 DEFSUBR (Fldap_host); 574 DEFSUBR (Fldap_host);
830 DEFSUBR (Fldap_status); 575 DEFSUBR (Fldap_status);
831 DEFSUBR (Fldap_open); 576 DEFSUBR (Fldap_open);
832 DEFSUBR (Fldap_close); 577 DEFSUBR (Fldap_close);
833 DEFSUBR (Fldap_search_basic); 578 DEFSUBR (Fldap_search_internal);
834 DEFSUBR (Fldap_add);
835 DEFSUBR (Fldap_modify);
836 DEFSUBR (Fldap_delete);
837 } 579 }
838 580
839 void 581 void
840 vars_of_eldap (void) 582 vars_of_eldap (void)
841 { 583 {