comparison src/eldap.c @ 361:7347b34c275b r21-1-10

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