comparison src/eldap.c @ 371:cc15677e0335 r21-2b1

Import from CVS: tag r21-2b1
author cvs
date Mon, 13 Aug 2007 11:03:08 +0200
parents 7347b34c275b
children bbff43aa5eb7
comparison
equal deleted inserted replaced
370:bd866891f083 371:cc15677e0335
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 - Netscape's LDAP SDK 1.0 (http://developer.netscape.com) */
30 - Netscape's LDAP SDK (http://developer.netscape.com/) */
31 30
32 31
33 #include <config.h> 32 #include <config.h>
34 #include "lisp.h" 33 #include "lisp.h"
35 #include "opaque.h" 34 #include "opaque.h"
36 #include "sysdep.h" 35 #include "sysdep.h"
37 #include "buffer.h"
38 36
39 #include <errno.h> 37 #include <errno.h>
40 38
41 #include "eldap.h" 39 #include "eldap.h"
40
41 #ifdef HAVE_NS_LDAP
42 # define HAVE_LDAP_SET_OPTION 1
43 # define HAVE_LDAP_GET_ERRNO 1
44 #else
45 # undef HAVE_LDAP_SET_OPTION
46 # undef HAVE_LDAP_GET_ERRNO
47 #endif
42 48
43 static int ldap_default_port; 49 static int ldap_default_port;
44 static Lisp_Object Vldap_default_base; 50 static Lisp_Object Vldap_default_base;
45 51
46 /* Needed by the lrecord definition */ 52 /* Needed by the lrecord definition */
59 /************************************************************************/ 65 /************************************************************************/
60 /* Utility Functions */ 66 /* Utility Functions */
61 /************************************************************************/ 67 /************************************************************************/
62 68
63 static void 69 static void
64 signal_ldap_error (LDAP *ld, LDAPMessage *res, int ldap_err) 70 signal_ldap_error (LDAP *ld)
65 { 71 {
66 if (ldap_err <= 0) 72 #ifdef HAVE_LDAP_GET_ERRNO
67 { 73 signal_simple_error
68 #if defined HAVE_LDAP_PARSE_RESULT 74 ("LDAP error",
69 int err; 75 build_string (ldap_err2string (ldap_get_lderrno (ld, NULL, NULL))));
70 ldap_err = ldap_parse_result (ld, res,
71 &err,
72 NULL, NULL, NULL, NULL, 0);
73 if (ldap_err == LDAP_SUCCESS)
74 ldap_err = err;
75 #elif defined HAVE_LDAP_GET_LDERRNO
76 ldap_err = ldap_get_lderrno (ld, NULL, NULL);
77 #elif defined HAVE_LDAP_RESULT2ERROR
78 ldap_err = ldap_result2error (ld, res, 0);
79 #else 76 #else
80 ldap_err = ld->ld_errno; 77 signal_simple_error ("LDAP error",
78 build_string (ldap_err2string (ld->ld_errno)));
81 #endif 79 #endif
82 }
83 signal_simple_error ("LDAP error",
84 build_string (ldap_err2string (ldap_err)));
85 } 80 }
86 81
87 82
88 /************************************************************************/ 83 /************************************************************************/
89 /* ldap lrecord basic functions */ 84 /* ldap lrecord basic functions */
114 error ("printing unreadable object #<ldap %s>", 109 error ("printing unreadable object #<ldap %s>",
115 XSTRING_DATA (ldap->host)); 110 XSTRING_DATA (ldap->host));
116 111
117 write_c_string ("#<ldap ", printcharfun); 112 write_c_string ("#<ldap ", printcharfun);
118 print_internal (ldap->host, printcharfun, 1); 113 print_internal (ldap->host, printcharfun, 1);
119 if (!ldap->ld) 114 if (!ldap->livep)
120 write_c_string ("(dead) ",printcharfun); 115 write_c_string ("(dead) ",printcharfun);
121 sprintf (buf, " 0x%x>", (unsigned int)ldap); 116 sprintf (buf, " 0x%x>", (unsigned int)ldap);
122 write_c_string (buf, printcharfun); 117 write_c_string (buf, printcharfun);
123 } 118 }
124 119
128 struct Lisp_LDAP *ldap = 123 struct Lisp_LDAP *ldap =
129 alloc_lcrecord_type (struct Lisp_LDAP, lrecord_ldap); 124 alloc_lcrecord_type (struct Lisp_LDAP, lrecord_ldap);
130 125
131 ldap->ld = NULL; 126 ldap->ld = NULL;
132 ldap->host = Qnil; 127 ldap->host = Qnil;
128 ldap->livep = 0;
133 return ldap; 129 return ldap;
134 } 130 }
135 131
136 static void 132 static void
137 finalize_ldap (void *header, int for_disksave) 133 finalize_ldap (void *header, int for_disksave)
140 136
141 if (for_disksave) 137 if (for_disksave)
142 signal_simple_error ("Can't dump an emacs containing LDAP objects", 138 signal_simple_error ("Can't dump an emacs containing LDAP objects",
143 make_ldap (ldap)); 139 make_ldap (ldap));
144 140
145 if (ldap->ld) 141 if (ldap->livep)
146 ldap_unbind (ldap->ld); 142 ldap_unbind (ldap->ld);
147 ldap->ld = NULL;
148 } 143 }
149 144
150 DEFINE_LRECORD_IMPLEMENTATION ("ldap", ldap, 145 DEFINE_LRECORD_IMPLEMENTATION ("ldap", ldap,
151 mark_ldap, print_ldap, finalize_ldap, 146 mark_ldap, print_ldap, finalize_ldap,
152 NULL, NULL, struct Lisp_LDAP); 147 NULL, NULL, struct Lisp_LDAP);
179 Return t if LDAP is an active LDAP connection. 174 Return t if LDAP is an active LDAP connection.
180 */ 175 */
181 (ldap)) 176 (ldap))
182 { 177 {
183 CHECK_LDAP (ldap); 178 CHECK_LDAP (ldap);
184 return (XLDAP (ldap))->ld ? Qt : Qnil; 179 return (XLDAP (ldap))->livep ? Qt : Qnil;
185 } 180 }
186 181
187 /************************************************************************/ 182 /************************************************************************/
188 /* Opening/Closing a LDAP connection */ 183 /* Opening/Closing a LDAP connection */
189 /************************************************************************/ 184 /************************************************************************/
247 } 242 }
248 /* Bind DN */ 243 /* Bind DN */
249 else if (EQ (keyword, Qbinddn)) 244 else if (EQ (keyword, Qbinddn))
250 { 245 {
251 CHECK_STRING (value); 246 CHECK_STRING (value);
252 GET_C_STRING_OS_DATA_ALLOCA (value, ldap_binddn); 247 ldap_binddn = alloca (XSTRING_LENGTH (value) + 1);
248 strcpy (ldap_binddn, (char *)XSTRING_DATA (value));
253 } 249 }
254 /* Password */ 250 /* Password */
255 else if (EQ (keyword, Qpasswd)) 251 else if (EQ (keyword, Qpasswd))
256 { 252 {
257 CHECK_STRING (value); 253 CHECK_STRING (value);
258 GET_C_STRING_OS_DATA_ALLOCA (value, ldap_passwd); 254 ldap_passwd = alloca (XSTRING_LENGTH (value) + 1);
255 strcpy (ldap_passwd, (char *)XSTRING_DATA (value));
259 } 256 }
260 /* Deref */ 257 /* Deref */
261 else if (EQ (keyword, Qderef)) 258 else if (EQ (keyword, Qderef))
262 { 259 {
263 if (EQ (value, Qnever)) 260 if (EQ (value, Qnever))
289 { 286 {
290 ldap_port = ldap_default_port; 287 ldap_port = ldap_default_port;
291 } 288 }
292 289
293 /* Connect to the server and bind */ 290 /* Connect to the server and bind */
294 slow_down_interrupts ();
295 ld = ldap_open ((char *)XSTRING_DATA (host), ldap_port); 291 ld = ldap_open ((char *)XSTRING_DATA (host), ldap_port);
296 speed_up_interrupts ();
297
298 if (ld == NULL ) 292 if (ld == NULL )
299 signal_simple_error_2 ("Failed connecting to host", 293 signal_simple_error_2 ("Failed connecting to host",
300 host, 294 host,
301 lisp_strerror (errno)); 295 lisp_strerror (errno));
302 296
303 297
304 #ifdef HAVE_LDAP_SET_OPTION 298 #ifdef HAVE_LDAP_SET_OPTION
305 if ((err = ldap_set_option (ld, LDAP_OPT_DEREF, 299 if (ldap_set_option (ld, LDAP_OPT_DEREF, (void *)&ldap_deref) != LDAP_SUCCESS)
306 (void *)&ldap_deref)) != LDAP_SUCCESS) 300 signal_ldap_error (ld);
307 signal_ldap_error (ld, NULL, err); 301 if (ldap_set_option (ld, LDAP_OPT_TIMELIMIT,
308 if ((err = ldap_set_option (ld, LDAP_OPT_TIMELIMIT, 302 (void *)&ldap_timelimit) != LDAP_SUCCESS)
309 (void *)&ldap_timelimit)) != LDAP_SUCCESS) 303 signal_ldap_error (ld);
310 signal_ldap_error (ld, NULL, err); 304 if (ldap_set_option (ld, LDAP_OPT_SIZELIMIT,
311 if ((err = ldap_set_option (ld, LDAP_OPT_SIZELIMIT, 305 (void *)&ldap_sizelimit) != LDAP_SUCCESS)
312 (void *)&ldap_sizelimit)) != LDAP_SUCCESS) 306 signal_ldap_error (ld);
313 signal_ldap_error (ld, NULL, err); 307 if (ldap_set_option (ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON) != LDAP_SUCCESS)
314 if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS, 308 signal_ldap_error (ld);
315 LDAP_OPT_ON)) != LDAP_SUCCESS)
316 signal_ldap_error (ld, NULL, err);
317 if ((err = ldap_set_option (ld, LDAP_OPT_RESTART,
318 LDAP_OPT_ON)) != LDAP_SUCCESS)
319 signal_ldap_error (ld, NULL, err);
320 #else /* not HAVE_LDAP_SET_OPTION */ 309 #else /* not HAVE_LDAP_SET_OPTION */
321 ld->ld_deref = ldap_deref; 310 ld->ld_deref = ldap_deref;
322 ld->ld_timelimit = ldap_timelimit; 311 ld->ld_timelimit = ldap_timelimit;
323 ld->ld_sizelimit = ldap_sizelimit; 312 ld->ld_sizelimit = ldap_sizelimit;
324 #ifdef LDAP_REFERRALS 313 #ifdef LDAP_REFERRALS
325 ld->ld_options = LDAP_OPT_REFERRALS; 314 ld->ld_options = LDAP_OPT_REFERRALS;
326 #else /* not LDAP_REFERRALS */ 315 #else /* not LDAP_REFERRALS */
327 ld->ld_options = 0; 316 ld->ld_options = 0;
328 #endif /* not LDAP_REFERRALS */ 317 #endif /* not LDAP_REFERRALS */
329 /* XEmacs uses interrupts (SIGIO,SIGALRM), LDAP calls need to ignore them */
330 ld->ld_options |= LDAP_OPT_RESTART;
331 #endif /* not HAVE_LDAP_SET_OPTION */ 318 #endif /* not HAVE_LDAP_SET_OPTION */
332 319
320 /* ldap_bind_s calls select and may be wedged by SIGIO. */
321 slow_down_interrupts ();
333 err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth); 322 err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth);
323 speed_up_interrupts ();
334 if (err != LDAP_SUCCESS) 324 if (err != LDAP_SUCCESS)
335 signal_simple_error ("Failed binding to the server", 325 signal_simple_error ("Failed binding to the server",
336 build_string (ldap_err2string (err))); 326 build_string (ldap_err2string (err)));
337 327
338 ldap = allocate_ldap (); 328 ldap = allocate_ldap ();
339 ldap->ld = ld; 329 ldap->ld = ld;
340 ldap->host = host; 330 ldap->host = host;
331 ldap->livep = 1;
341 332
342 return make_ldap (ldap); 333 return make_ldap (ldap);
343 } 334 }
344 335
345 336
351 { 342 {
352 struct Lisp_LDAP *lldap; 343 struct Lisp_LDAP *lldap;
353 CHECK_LIVE_LDAP (ldap); 344 CHECK_LIVE_LDAP (ldap);
354 lldap = XLDAP (ldap); 345 lldap = XLDAP (ldap);
355 ldap_unbind (lldap->ld); 346 ldap_unbind (lldap->ld);
356 lldap->ld = NULL; 347 lldap->livep = 0;
357 return Qnil; 348 return Qnil;
358 } 349 }
359 350
360 351
361 352
363 /* Working on a LDAP connection */ 354 /* Working on a LDAP connection */
364 /************************************************************************/ 355 /************************************************************************/
365 struct ldap_unwind_struct 356 struct ldap_unwind_struct
366 { 357 {
367 LDAPMessage *res; 358 LDAPMessage *res;
368 struct berval **vals; 359 char **vals;
369 }; 360 };
361
370 362
371 static Lisp_Object 363 static Lisp_Object
372 ldap_search_unwind (Lisp_Object unwind_obj) 364 ldap_search_unwind (Lisp_Object unwind_obj)
373 { 365 {
374 struct ldap_unwind_struct *unwind = 366 struct ldap_unwind_struct *unwind =
375 (struct ldap_unwind_struct *) get_opaque_ptr (unwind_obj); 367 (struct ldap_unwind_struct *) get_opaque_ptr (unwind_obj);
376 if (unwind->res) 368 if (unwind->res)
377 ldap_msgfree (unwind->res); 369 ldap_msgfree (unwind->res);
378 if (unwind->vals) 370 if (unwind->vals)
379 ldap_value_free_len (unwind->vals); 371 ldap_value_free (unwind->vals);
380 return Qnil; 372 return Qnil;
381 } 373 }
382 374
383 DEFUN ("ldap-search-internal", Fldap_search_internal, 2, 6, 0, /* 375 DEFUN ("ldap-search-internal", Fldap_search_internal, 2, 6, 0, /*
384 Perform a search on an open LDAP connection. 376 Perform a search on an open LDAP connection.
401 /* Vars for query */ 393 /* Vars for query */
402 LDAP *ld; 394 LDAP *ld;
403 LDAPMessage *e; 395 LDAPMessage *e;
404 BerElement *ptr; 396 BerElement *ptr;
405 char *a; 397 char *a;
406 int i, rc, rc2; 398 int i, rc;
407 int matches; 399 int matches;
408 struct ldap_unwind_struct unwind; 400 struct ldap_unwind_struct unwind;
409 401
410 int ldap_scope = LDAP_SCOPE_SUBTREE; 402 int ldap_scope = LDAP_SCOPE_SUBTREE;
411 char **ldap_attributes = NULL; 403 char **ldap_attributes = NULL;
460 i = 0; 452 i = 0;
461 EXTERNAL_LIST_LOOP (attrs, attrs) 453 EXTERNAL_LIST_LOOP (attrs, attrs)
462 { 454 {
463 Lisp_Object current = XCAR (attrs); 455 Lisp_Object current = XCAR (attrs);
464 CHECK_STRING (current); 456 CHECK_STRING (current);
465 GET_C_STRING_OS_DATA_ALLOCA (current, ldap_attributes[i]); 457 ldap_attributes[i] =
458 alloca_array (char, 1 + XSTRING_LENGTH (current));
459 /* XSTRING_LENGTH is increased by one in order to copy the final 0 */
460 memcpy (ldap_attributes[i],
461 XSTRING_DATA (current), 1 + XSTRING_LENGTH (current));
466 ++i; 462 ++i;
467 } 463 }
468 ldap_attributes[i] = NULL; 464 ldap_attributes[i] = NULL;
469 } 465 }
470 466
476 NILP (base) ? "" : (char *) XSTRING_DATA (base), 472 NILP (base) ? "" : (char *) XSTRING_DATA (base),
477 ldap_scope, 473 ldap_scope,
478 NILP (filter) ? "" : (char *) XSTRING_DATA (filter), 474 NILP (filter) ? "" : (char *) XSTRING_DATA (filter),
479 ldap_attributes, 475 ldap_attributes,
480 NILP (attrsonly) ? 0 : 1) 476 NILP (attrsonly) ? 0 : 1)
481 == -1) 477 == -1)
482 { 478 {
483 signal_ldap_error (ld, NULL, 0); 479 signal_ldap_error (ld);
484 } 480 }
485 481
486 /* Ensure we don't exit without cleaning up */ 482 /* Ensure we don't exit without cleaning up */
487 record_unwind_protect (ldap_search_unwind, 483 record_unwind_protect (ldap_search_unwind,
488 make_opaque_ptr (&unwind)); 484 make_opaque_ptr (&unwind));
489 485
490 /* Build the results list */ 486 /* Build the results list */
491 matches = 0; 487 matches = 0;
492 488
489 /* ldap_result calls select() and can get wedged by EINTR signals */
490 slow_down_interrupts ();
493 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res); 491 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res);
494 492 speed_up_interrupts ();
495 while (rc == LDAP_RES_SEARCH_ENTRY) 493 while (rc == LDAP_RES_SEARCH_ENTRY)
496 { 494 {
497 QUIT; 495 QUIT;
498 matches ++; 496 matches ++;
499 e = ldap_first_entry (ld, unwind.res); 497 e = ldap_first_entry (ld, unwind.res);
503 restore the old echo area contents later. */ 501 restore the old echo area contents later. */
504 message ("Parsing ldap results... %d", matches); 502 message ("Parsing ldap results... %d", matches);
505 entry = Qnil; 503 entry = Qnil;
506 for (a= ldap_first_attribute (ld, e, &ptr); 504 for (a= ldap_first_attribute (ld, e, &ptr);
507 a != NULL; 505 a != NULL;
508 a = ldap_next_attribute (ld, e, ptr) ) 506 a= ldap_next_attribute (ld, e, ptr) )
509 { 507 {
510 list = Fcons (build_ext_string (a, FORMAT_OS), Qnil); 508 list = Fcons (build_ext_string (a, FORMAT_OS), Qnil);
511 unwind.vals = ldap_get_values_len (ld, e, a); 509 unwind.vals = ldap_get_values (ld, e, a);
512 if (unwind.vals != NULL) 510 if (unwind.vals != NULL)
513 { 511 {
514 for (i = 0; unwind.vals[i] != NULL; i++) 512 for (i = 0; unwind.vals[i] != NULL; i++)
515 { 513 {
516 list = Fcons (make_ext_string (unwind.vals[i]->bv_val, 514 list = Fcons (build_ext_string (unwind.vals[i], FORMAT_OS),
517 unwind.vals[i]->bv_len,
518 FORMAT_OS),
519 list); 515 list);
520 } 516 }
521 } 517 }
522 entry = Fcons (Fnreverse (list), 518 entry = Fcons (Fnreverse (list),
523 entry); 519 entry);
524 ldap_value_free_len (unwind.vals); 520 ldap_value_free (unwind.vals);
525 unwind.vals = NULL; 521 unwind.vals = NULL;
526 } 522 }
527 result = Fcons (Fnreverse (entry), 523 result = Fcons (Fnreverse (entry),
528 result); 524 result);
529 ldap_msgfree (unwind.res); 525 ldap_msgfree (unwind.res);
530 unwind.res = NULL; 526 unwind.res = NULL;
531 527
528 slow_down_interrupts ();
532 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res)); 529 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res));
533 } 530 speed_up_interrupts ();
534 531 }
535 #if defined HAVE_LDAP_PARSE_RESULT
536 rc2 = ldap_parse_result (ld, unwind.res,
537 &rc,
538 NULL, NULL, NULL, NULL, 0);
539 if (rc2 != LDAP_SUCCESS)
540 rc = rc2;
541 #else
542 if (rc == 0)
543 signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED);
544 532
545 if (rc == -1) 533 if (rc == -1)
546 signal_ldap_error (ld, unwind.res, (unwind.res==NULL) ? ld->ld_errno : 0); 534 {
547 535 signal_ldap_error (ld);
548 #if defined HAVE_LDAP_RESULT2ERROR 536 }
549 rc = ldap_result2error (ld, unwind.res, 0); 537 rc = ldap_result2error (ld, unwind.res, 0);
550 #endif 538 if ((rc != LDAP_SUCCESS) &&
551 #endif 539 (rc != LDAP_SIZELIMIT_EXCEEDED))
552 540 {
553 if (rc != LDAP_SUCCESS) 541 signal_ldap_error (ld);
554 signal_ldap_error (ld, NULL, rc); 542 }
555 543
556 ldap_msgfree (unwind.res); 544 ldap_msgfree (unwind.res);
557 unwind.res = (LDAPMessage *)NULL; 545 unwind.res = (LDAPMessage *)NULL;
558
559 /* #### See above for calling message(). */ 546 /* #### See above for calling message(). */
560 message ("Parsing ldap results... done"); 547 message ("Parsing ldap results... done");
561 548
562 unbind_to (speccount, Qnil); 549 unbind_to (speccount, Qnil);
563 UNGCPRO; 550 UNGCPRO;
578 } 565 }
579 566
580 void 567 void
581 vars_of_eldap (void) 568 vars_of_eldap (void)
582 { 569 {
570 Fprovide (intern ("ldap"));
583 571
584 ldap_default_port = LDAP_PORT; 572 ldap_default_port = LDAP_PORT;
585 Vldap_default_base = Qnil; 573 Vldap_default_base = Qnil;
586 574
587 DEFVAR_INT ("ldap-default-port", &ldap_default_port /* 575 DEFVAR_INT ("ldap-default-port", &ldap_default_port /*