comparison src/eldap.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
52 static Lisp_Object Qbase, Qonelevel, Qsubtree; 52 static Lisp_Object Qbase, Qonelevel, Qsubtree;
53 /* Authentication methods */ 53 /* Authentication methods */
54 static Lisp_Object Qkrbv41, Qkrbv42; 54 static Lisp_Object Qkrbv41, Qkrbv42;
55 /* Deref policy */ 55 /* Deref policy */
56 static Lisp_Object Qnever, Qalways, Qfind; 56 static Lisp_Object Qnever, Qalways, Qfind;
57 /* Modification types (Qdelete is defined in general.c) */
58 static Lisp_Object Qadd, Qreplace;
59
57 60
58 /************************************************************************/ 61 /************************************************************************/
59 /* Utility Functions */ 62 /* Utility Functions */
60 /************************************************************************/ 63 /************************************************************************/
61 64
213 int ldap_deref = LDAP_DEREF_NEVER; 216 int ldap_deref = LDAP_DEREF_NEVER;
214 int ldap_timelimit = 0; 217 int ldap_timelimit = 0;
215 int ldap_sizelimit = 0; 218 int ldap_sizelimit = 0;
216 int err; 219 int err;
217 220
218 Lisp_Object list, keyword, value;
219
220 CHECK_STRING (host); 221 CHECK_STRING (host);
221 222
222 EXTERNAL_PROPERTY_LIST_LOOP (list, keyword, value, plist) 223 {
223 { 224 EXTERNAL_PROPERTY_LIST_LOOP_3 (keyword, value, plist)
224 /* TCP Port */ 225 {
225 if (EQ (keyword, Qport)) 226 /* TCP Port */
226 { 227 if (EQ (keyword, Qport))
227 CHECK_INT (value); 228 {
228 ldap_port = XINT (value); 229 CHECK_INT (value);
229 } 230 ldap_port = XINT (value);
230 /* Authentication method */ 231 }
231 if (EQ (keyword, Qauth)) 232 /* Authentication method */
232 { 233 if (EQ (keyword, Qauth))
233 if (EQ (value, Qsimple)) 234 {
234 ldap_auth = LDAP_AUTH_SIMPLE; 235 if (EQ (value, Qsimple))
236 ldap_auth = LDAP_AUTH_SIMPLE;
235 #ifdef LDAP_AUTH_KRBV41 237 #ifdef LDAP_AUTH_KRBV41
236 else if (EQ (value, Qkrbv41)) 238 else if (EQ (value, Qkrbv41))
237 ldap_auth = LDAP_AUTH_KRBV41; 239 ldap_auth = LDAP_AUTH_KRBV41;
238 #endif 240 #endif
239 #ifdef LDAP_AUTH_KRBV42 241 #ifdef LDAP_AUTH_KRBV42
240 else if (EQ (value, Qkrbv42)) 242 else if (EQ (value, Qkrbv42))
241 ldap_auth = LDAP_AUTH_KRBV42; 243 ldap_auth = LDAP_AUTH_KRBV42;
242 #endif 244 #endif
243 else 245 else
244 signal_simple_error ("Invalid authentication method", value); 246 signal_simple_error ("Invalid authentication method", value);
245 } 247 }
246 /* Bind DN */ 248 /* Bind DN */
247 else if (EQ (keyword, Qbinddn)) 249 else if (EQ (keyword, Qbinddn))
248 { 250 {
249 CHECK_STRING (value); 251 CHECK_STRING (value);
250 TO_EXTERNAL_FORMAT (LISP_STRING, value, 252 LISP_STRING_TO_EXTERNAL (value, ldap_binddn, Qnative);
251 C_STRING_ALLOCA, ldap_binddn, 253 }
252 Qnative); 254 /* Password */
253 } 255 else if (EQ (keyword, Qpasswd))
254 /* Password */ 256 {
255 else if (EQ (keyword, Qpasswd)) 257 CHECK_STRING (value);
256 { 258 LISP_STRING_TO_EXTERNAL (value, ldap_passwd, Qnative);
257 CHECK_STRING (value); 259 }
258 TO_EXTERNAL_FORMAT (LISP_STRING, value, 260 /* Deref */
259 C_STRING_ALLOCA, ldap_passwd, 261 else if (EQ (keyword, Qderef))
260 Qnative); 262 {
261 } 263 if (EQ (value, Qnever))
262 /* Deref */ 264 ldap_deref = LDAP_DEREF_NEVER;
263 else if (EQ (keyword, Qderef)) 265 else if (EQ (value, Qsearch))
264 { 266 ldap_deref = LDAP_DEREF_SEARCHING;
265 if (EQ (value, Qnever)) 267 else if (EQ (value, Qfind))
266 ldap_deref = LDAP_DEREF_NEVER; 268 ldap_deref = LDAP_DEREF_FINDING;
267 else if (EQ (value, Qsearch)) 269 else if (EQ (value, Qalways))
268 ldap_deref = LDAP_DEREF_SEARCHING; 270 ldap_deref = LDAP_DEREF_ALWAYS;
269 else if (EQ (value, Qfind)) 271 else
270 ldap_deref = LDAP_DEREF_FINDING; 272 signal_simple_error ("Invalid deref value", value);
271 else if (EQ (value, Qalways)) 273 }
272 ldap_deref = LDAP_DEREF_ALWAYS; 274 /* Timelimit */
273 else 275 else if (EQ (keyword, Qtimelimit))
274 signal_simple_error ("Invalid deref value", value); 276 {
275 } 277 CHECK_INT (value);
276 /* Timelimit */ 278 ldap_timelimit = XINT (value);
277 else if (EQ (keyword, Qtimelimit)) 279 }
278 { 280 /* Sizelimit */
279 CHECK_INT (value); 281 else if (EQ (keyword, Qsizelimit))
280 ldap_timelimit = XINT (value); 282 {
281 } 283 CHECK_INT (value);
282 /* Sizelimit */ 284 ldap_sizelimit = XINT (value);
283 else if (EQ (keyword, Qsizelimit)) 285 }
284 { 286 }
285 CHECK_INT (value); 287 }
286 ldap_sizelimit = XINT (value);
287 }
288 }
289 288
290 if (ldap_port == 0) 289 if (ldap_port == 0)
291 { 290 {
292 ldap_port = ldap_default_port; 291 ldap_port = ldap_default_port;
293 } 292 }
294 293
295 /* Connect to the server and bind */ 294 /* Connect to the server and bind */
296 slow_down_interrupts (); 295 slow_down_interrupts ();
297 ld = ldap_open ((char *)XSTRING_DATA (host), ldap_port); 296 ld = ldap_open ((char *) XSTRING_DATA (host), ldap_port);
298 speed_up_interrupts (); 297 speed_up_interrupts ();
299 298
300 if (ld == NULL ) 299 if (ld == NULL )
301 signal_simple_error_2 ("Failed connecting to host", 300 signal_simple_error_2 ("Failed connecting to host",
302 host, 301 host,
314 (void *)&ldap_sizelimit)) != LDAP_SUCCESS) 313 (void *)&ldap_sizelimit)) != LDAP_SUCCESS)
315 signal_ldap_error (ld, NULL, err); 314 signal_ldap_error (ld, NULL, err);
316 if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS, 315 if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS,
317 LDAP_OPT_ON)) != LDAP_SUCCESS) 316 LDAP_OPT_ON)) != LDAP_SUCCESS)
318 signal_ldap_error (ld, NULL, err); 317 signal_ldap_error (ld, NULL, err);
318 if ((err = ldap_set_option (ld, LDAP_OPT_RESTART,
319 LDAP_OPT_ON)) != LDAP_SUCCESS)
320 signal_ldap_error (ld, NULL, err);
319 #else /* not HAVE_LDAP_SET_OPTION */ 321 #else /* not HAVE_LDAP_SET_OPTION */
320 ld->ld_deref = ldap_deref; 322 ld->ld_deref = ldap_deref;
321 ld->ld_timelimit = ldap_timelimit; 323 ld->ld_timelimit = ldap_timelimit;
322 ld->ld_sizelimit = ldap_sizelimit; 324 ld->ld_sizelimit = ldap_sizelimit;
323 #ifdef LDAP_REFERRALS 325 #ifdef LDAP_REFERRALS
324 ld->ld_options = LDAP_OPT_REFERRALS; 326 ld->ld_options = LDAP_OPT_REFERRALS;
325 #else /* not LDAP_REFERRALS */ 327 #else /* not LDAP_REFERRALS */
326 ld->ld_options = 0; 328 ld->ld_options = 0;
327 #endif /* not LDAP_REFERRALS */ 329 #endif /* not LDAP_REFERRALS */
330 /* XEmacs uses interrupts (SIGIO,SIGALRM), LDAP calls need to ignore them */
331 ld->ld_options |= LDAP_OPT_RESTART;
328 #endif /* not HAVE_LDAP_SET_OPTION */ 332 #endif /* not HAVE_LDAP_SET_OPTION */
329 333
330 /* ldap_bind_s calls select and may be wedged by SIGIO. */
331 slow_down_interrupts ();
332 err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth); 334 err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth);
333 speed_up_interrupts ();
334 if (err != LDAP_SUCCESS) 335 if (err != LDAP_SUCCESS)
335 signal_simple_error ("Failed binding to the server", 336 signal_simple_error ("Failed binding to the server",
336 build_string (ldap_err2string (err))); 337 build_string (ldap_err2string (err)));
337 338
338 ldap = allocate_ldap (); 339 ldap = allocate_ldap ();
365 struct ldap_unwind_struct 366 struct ldap_unwind_struct
366 { 367 {
367 LDAPMessage *res; 368 LDAPMessage *res;
368 struct berval **vals; 369 struct berval **vals;
369 }; 370 };
370
371 371
372 static Lisp_Object 372 static Lisp_Object
373 ldap_search_unwind (Lisp_Object unwind_obj) 373 ldap_search_unwind (Lisp_Object unwind_obj)
374 { 374 {
375 struct ldap_unwind_struct *unwind = 375 struct ldap_unwind_struct *unwind =
379 if (unwind->vals) 379 if (unwind->vals)
380 ldap_value_free_len (unwind->vals); 380 ldap_value_free_len (unwind->vals);
381 return Qnil; 381 return Qnil;
382 } 382 }
383 383
384 DEFUN ("ldap-search-internal", Fldap_search_internal, 2, 7, 0, /* 384 /* The following function is called `ldap-search-basic' instead of */
385 /* plain `ldap-search' to maintain compatibility with the XEmacs 21.1 */
386 /* API where `ldap-search' was the name of the high-level search */
387 /* function */
388
389 DEFUN ("ldap-search-basic", Fldap_search_basic, 2, 8, 0, /*
385 Perform a search on an open LDAP connection. 390 Perform a search on an open LDAP connection.
386 LDAP is an LDAP connection object created with `ldap-open'. 391 LDAP is an LDAP connection object created with `ldap-open'.
387 FILTER is a filter string for the search as described in RFC 1558. 392 FILTER is a filter string for the search as described in RFC 1558.
388 BASE is the distinguished name at which to start the search. 393 BASE is the distinguished name at which to start the search.
389 SCOPE is one of the symbols `base', `onelevel' or `subtree' indicating 394 SCOPE is one of the symbols `base', `onelevel' or `subtree' indicating
390 the scope of the search. 395 the scope of the search.
391 ATTRS is a list of strings indicating which attributes to retrieve 396 ATTRS is a list of strings indicating which attributes to retrieve
392 for each matching entry. If nil return all available attributes. 397 for each matching entry. If nil return all available attributes.
393 If ATTRSONLY is non-nil then only the attributes are retrieved, not 398 If ATTRSONLY is non-nil then only the attributes are retrieved, not
394 the associated values. 399 the associated values.
395 If WITHDN is non-nil each entry in the result will be prepennded with 400 If WITHDN is non-nil each entry in the result will be prepended with
396 its distinguished name DN. 401 its distinguished name DN.
402 If VERBOSE is non-nil progress messages will be echoed.
397 The function returns a list of matching entries. Each entry is itself 403 The function returns a list of matching entries. Each entry is itself
398 an alist of attribute/value pairs optionally preceded by the DN of the 404 an alist of attribute/value pairs optionally preceded by the DN of the
399 entry according to the value of WITHDN. 405 entry according to the value of WITHDN.
400 */ 406 */
401 (ldap, filter, base, scope, attrs, attrsonly, withdn)) 407 (ldap, filter, base, scope, attrs, attrsonly, withdn, verbose))
402 { 408 {
403 /* This function can GC */ 409 /* This function can GC */
404 410
405 /* Vars for query */ 411 /* Vars for query */
406 LDAP *ld; 412 LDAP *ld;
407 LDAPMessage *e; 413 LDAPMessage *e;
408 BerElement *ptr; 414 BerElement *ptr;
409 char *a, *dn; 415 char *a, *dn;
410 int i, rc, rc2; 416 int i, rc;
411 int matches; 417 int matches;
412 struct ldap_unwind_struct unwind; 418 struct ldap_unwind_struct unwind;
413 419
414 int ldap_scope = LDAP_SCOPE_SUBTREE; 420 int ldap_scope = LDAP_SCOPE_SUBTREE;
415 char **ldap_attributes = NULL; 421 char **ldap_attributes = NULL;
416 422
417 int speccount = specpdl_depth (); 423 int speccount = specpdl_depth ();
418 424
419 Lisp_Object list, entry, result; 425 Lisp_Object list = Qnil;
426 Lisp_Object entry = Qnil;
427 Lisp_Object result = Qnil;
420 struct gcpro gcpro1, gcpro2, gcpro3; 428 struct gcpro gcpro1, gcpro2, gcpro3;
421 429
422 list = entry = result = Qnil;
423 GCPRO3 (list, entry, result); 430 GCPRO3 (list, entry, result);
424 431
425 unwind.res = NULL; 432 unwind.res = NULL;
426 unwind.vals = NULL; 433 unwind.vals = NULL;
427 434
464 i = 0; 471 i = 0;
465 EXTERNAL_LIST_LOOP (attrs, attrs) 472 EXTERNAL_LIST_LOOP (attrs, attrs)
466 { 473 {
467 Lisp_Object current = XCAR (attrs); 474 Lisp_Object current = XCAR (attrs);
468 CHECK_STRING (current); 475 CHECK_STRING (current);
469 TO_EXTERNAL_FORMAT (LISP_STRING, current, 476 LISP_STRING_TO_EXTERNAL (current, ldap_attributes[i], Qnative);
470 C_STRING_ALLOCA, ldap_attributes[i],
471 Qnative);
472 ++i; 477 ++i;
473 } 478 }
474 ldap_attributes[i] = NULL; 479 ldap_attributes[i] = NULL;
475 } 480 }
476 481
477 /* Attributes only ? */ 482 /* Attributes only ? */
478 CHECK_SYMBOL (attrsonly); 483 CHECK_SYMBOL (attrsonly);
479 484
480 /* Perform the search */ 485 /* Perform the search */
481 if (ldap_search (ld, 486 if (ldap_search (ld,
482 NILP (base) ? "" : (char *) XSTRING_DATA (base), 487 NILP (base) ? (char *) "" : (char *) XSTRING_DATA (base),
483 ldap_scope, 488 ldap_scope,
484 NILP (filter) ? "" : (char *) XSTRING_DATA (filter), 489 NILP (filter) ? (char *) "" : (char *) XSTRING_DATA (filter),
485 ldap_attributes, 490 ldap_attributes,
486 NILP (attrsonly) ? 0 : 1) 491 NILP (attrsonly) ? 0 : 1)
487 == -1) 492 == -1)
488 { 493 {
489 signal_ldap_error (ld, NULL, 0); 494 signal_ldap_error (ld, NULL, 0);
494 make_opaque_ptr (&unwind)); 499 make_opaque_ptr (&unwind));
495 500
496 /* Build the results list */ 501 /* Build the results list */
497 matches = 0; 502 matches = 0;
498 503
499 /* ldap_result calls select() and can get wedged by EINTR signals */
500 slow_down_interrupts ();
501 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res); 504 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res);
502 speed_up_interrupts (); 505
503 while (rc == LDAP_RES_SEARCH_ENTRY) 506 while (rc == LDAP_RES_SEARCH_ENTRY)
504 { 507 {
505 QUIT; 508 QUIT;
506 matches ++; 509 matches ++;
507 e = ldap_first_entry (ld, unwind.res); 510 e = ldap_first_entry (ld, unwind.res);
508 /* #### This call to message() is pretty fascist, because it 511 /* #### This call to message() is pretty fascist, because it
509 destroys the current echo area contents, even when invoked 512 destroys the current echo area contents, even when invoked
510 from Lisp. It should use echo_area_message() instead, and 513 from Lisp. It should use echo_area_message() instead, and
511 restore the old echo area contents later. */ 514 restore the old echo area contents later. */
512 message ("Parsing ldap results... %d", matches); 515 if (! NILP (verbose))
516 message ("Parsing ldap results... %d", matches);
513 entry = Qnil; 517 entry = Qnil;
514 /* Get the DN if required */ 518 /* Get the DN if required */
515 if (! NILP (withdn)) 519 if (! NILP (withdn))
516 { 520 {
517 dn = ldap_get_dn (ld, e); 521 dn = ldap_get_dn (ld, e);
527 unwind.vals = ldap_get_values_len (ld, e, a); 531 unwind.vals = ldap_get_values_len (ld, e, a);
528 if (unwind.vals != NULL) 532 if (unwind.vals != NULL)
529 { 533 {
530 for (i = 0; unwind.vals[i] != NULL; i++) 534 for (i = 0; unwind.vals[i] != NULL; i++)
531 { 535 {
532 list = Fcons (make_ext_string (unwind.vals[i]->bv_val, 536 list = Fcons (make_ext_string ((Extbyte *) unwind.vals[i]->bv_val,
533 unwind.vals[i]->bv_len, 537 unwind.vals[i]->bv_len,
534 Qnative), 538 Qnative),
535 list); 539 list);
536 } 540 }
537 } 541 }
543 result = Fcons (Fnreverse (entry), 547 result = Fcons (Fnreverse (entry),
544 result); 548 result);
545 ldap_msgfree (unwind.res); 549 ldap_msgfree (unwind.res);
546 unwind.res = NULL; 550 unwind.res = NULL;
547 551
548 slow_down_interrupts ();
549 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res)); 552 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res));
550 speed_up_interrupts (); 553 }
551 } 554
552 555 #if defined HAVE_LDAP_PARSE_RESULT
553 if (rc == -1) 556 {
554 signal_ldap_error (ld, unwind.res, 0); 557 int rc2 = ldap_parse_result (ld, unwind.res,
555 558 &rc,
559 NULL, NULL, NULL, NULL, 0);
560 if (rc2 != LDAP_SUCCESS)
561 rc = rc2;
562 }
563 #else
556 if (rc == 0) 564 if (rc == 0)
557 signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED); 565 signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED);
558 566
559 #if defined HAVE_LDAP_PARSE_RESULT 567 if (rc == -1)
560 rc2 = ldap_parse_result (ld, unwind.res, 568 signal_ldap_error (ld, unwind.res, (unwind.res==NULL) ? ld->ld_errno : 0);
561 &rc, 569
562 NULL, NULL, NULL, NULL, 0); 570 #if defined HAVE_LDAP_RESULT2ERROR
563 if (rc2 != LDAP_SUCCESS)
564 rc = rc2;
565 #elif defined HAVE_LDAP_RESULT2ERROR
566 rc = ldap_result2error (ld, unwind.res, 0); 571 rc = ldap_result2error (ld, unwind.res, 0);
567 #endif 572 #endif
568 if ((rc != LDAP_SUCCESS) && (rc != LDAP_SIZELIMIT_EXCEEDED)) 573 #endif
574
575 if (rc != LDAP_SUCCESS)
569 signal_ldap_error (ld, NULL, rc); 576 signal_ldap_error (ld, NULL, rc);
570 577
571 ldap_msgfree (unwind.res); 578 ldap_msgfree (unwind.res);
572 unwind.res = (LDAPMessage *)NULL; 579 unwind.res = (LDAPMessage *)NULL;
580
573 /* #### See above for calling message(). */ 581 /* #### See above for calling message(). */
574 message ("Parsing ldap results... done"); 582 if (! NILP (verbose))
583 message ("Parsing ldap results... done");
575 584
576 unbind_to (speccount, Qnil); 585 unbind_to (speccount, Qnil);
577 UNGCPRO; 586 UNGCPRO;
578 return Fnreverse (result); 587 return Fnreverse (result);
579 } 588 }
580 589
590 DEFUN ("ldap-add", Fldap_add, 3, 3, 0, /*
591 Add an entry to an LDAP directory.
592 LDAP is an LDAP connection object created with `ldap-open'.
593 DN is the distinguished name of the entry to add.
594 ENTRY is an entry specification, i.e., a list of cons cells
595 containing attribute/value string pairs.
596 */
597 (ldap, dn, entry))
598 {
599 LDAP *ld;
600 LDAPMod *ldap_mods, **ldap_mods_ptrs;
601 struct berval *bervals;
602 int rc;
603 int i, j;
604 size_t len;
605
606 Lisp_Object current = Qnil;
607 Lisp_Object values = Qnil;
608 struct gcpro gcpro1, gcpro2;
609
610 GCPRO2 (current, values);
611
612 /* Do all the parameter checking */
613 CHECK_LIVE_LDAP (ldap);
614 ld = XLDAP (ldap)->ld;
615
616 /* Check the DN */
617 CHECK_STRING (dn);
618
619 /* Check the entry */
620 CHECK_CONS (entry);
621 if (NILP (entry))
622 signal_simple_error ("Cannot add void entry", entry);
623
624 /* Build the ldap_mods array */
625 len = XINT (Flength (entry));
626 ldap_mods = alloca_array (LDAPMod, len);
627 ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len);
628 i = 0;
629 EXTERNAL_LIST_LOOP (entry, entry)
630 {
631 current = XCAR (entry);
632 CHECK_CONS (current);
633 CHECK_STRING (XCAR (current));
634 ldap_mods_ptrs[i] = &(ldap_mods[i]);
635 LISP_STRING_TO_EXTERNAL (XCAR (current), ldap_mods[i].mod_type, Qnative);
636 ldap_mods[i].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
637 values = XCDR (current);
638 if (CONSP (values))
639 {
640 len = XINT (Flength (values));
641 bervals = alloca_array (struct berval, len);
642 ldap_mods[i].mod_vals.modv_bvals =
643 alloca_array (struct berval *, 1 + len);
644 j = 0;
645 EXTERNAL_LIST_LOOP (values, values)
646 {
647 current = XCAR (values);
648 CHECK_STRING (current);
649 ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]);
650 TO_EXTERNAL_FORMAT (LISP_STRING, current,
651 ALLOCA, (bervals[j].bv_val,
652 bervals[j].bv_len),
653 Qnative);
654 j++;
655 }
656 ldap_mods[i].mod_vals.modv_bvals[j] = NULL;
657 }
658 else
659 {
660 CHECK_STRING (values);
661 bervals = alloca_array (struct berval, 1);
662 ldap_mods[i].mod_vals.modv_bvals = alloca_array (struct berval *, 2);
663 ldap_mods[i].mod_vals.modv_bvals[0] = &(bervals[0]);
664 TO_EXTERNAL_FORMAT (LISP_STRING, values,
665 ALLOCA, (bervals[0].bv_val,
666 bervals[0].bv_len),
667 Qnative);
668 ldap_mods[i].mod_vals.modv_bvals[1] = NULL;
669 }
670 i++;
671 }
672 ldap_mods_ptrs[i] = NULL;
673 rc = ldap_add_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs);
674 if (rc != LDAP_SUCCESS)
675 signal_ldap_error (ld, NULL, rc);
676
677 UNGCPRO;
678 return Qnil;
679 }
680
681 DEFUN ("ldap-modify", Fldap_modify, 3, 3, 0, /*
682 Add an entry to an LDAP directory.
683 LDAP is an LDAP connection object created with `ldap-open'.
684 DN is the distinguished name of the entry to modify.
685 MODS is a list of modifications to apply.
686 A modification is a list of the form (MOD-OP ATTR VALUE1 VALUE2 ...)
687 MOD-OP and ATTR are mandatory, VALUEs are optional depending on MOD-OP.
688 MOD-OP is the type of modification, one of the symbols `add', `delete'
689 or `replace'. ATTR is the LDAP attribute type to modify.
690 */
691 (ldap, dn, mods))
692 {
693 LDAP *ld;
694 LDAPMod *ldap_mods, **ldap_mods_ptrs;
695 struct berval *bervals;
696 int i, j, rc;
697 Lisp_Object mod_op;
698 size_t len;
699
700 Lisp_Object current = Qnil;
701 Lisp_Object values = Qnil;
702 struct gcpro gcpro1, gcpro2;
703
704 GCPRO2 (current, values);
705
706 /* Do all the parameter checking */
707 CHECK_LIVE_LDAP (ldap);
708 ld = XLDAP (ldap)->ld;
709
710 /* Check the DN */
711 CHECK_STRING (dn);
712
713 /* Check the entry */
714 CHECK_CONS (mods);
715 if (NILP (mods))
716 return Qnil;
717
718 /* Build the ldap_mods array */
719 len = XINT (Flength (mods));
720 ldap_mods = alloca_array (LDAPMod, len);
721 ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len);
722 i = 0;
723 EXTERNAL_LIST_LOOP (mods, mods)
724 {
725 current = XCAR (mods);
726 CHECK_CONS (current);
727 CHECK_SYMBOL (XCAR (current));
728 mod_op = XCAR (current);
729 ldap_mods_ptrs[i] = &(ldap_mods[i]);
730 ldap_mods[i].mod_op = LDAP_MOD_BVALUES;
731 if (EQ (mod_op, Qadd))
732 ldap_mods[i].mod_op |= LDAP_MOD_ADD;
733 else if (EQ (mod_op, Qdelete))
734 ldap_mods[i].mod_op |= LDAP_MOD_DELETE;
735 else if (EQ (mod_op, Qreplace))
736 ldap_mods[i].mod_op |= LDAP_MOD_REPLACE;
737 else
738 signal_simple_error ("Invalid LDAP modification type", mod_op);
739 current = XCDR (current);
740 CHECK_STRING (XCAR (current));
741 LISP_STRING_TO_EXTERNAL (XCAR (current), ldap_mods[i].mod_type, Qnative);
742 values = XCDR (current);
743 len = XINT (Flength (values));
744 bervals = alloca_array (struct berval, len);
745 ldap_mods[i].mod_vals.modv_bvals =
746 alloca_array (struct berval *, 1 + len);
747 j = 0;
748 EXTERNAL_LIST_LOOP (values, values)
749 {
750 current = XCAR (values);
751 CHECK_STRING (current);
752 ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]);
753 TO_EXTERNAL_FORMAT (LISP_STRING, current,
754 ALLOCA, (bervals[j].bv_val,
755 bervals[j].bv_len),
756 Qnative);
757 j++;
758 }
759 ldap_mods[i].mod_vals.modv_bvals[j] = NULL;
760 i++;
761 }
762 ldap_mods_ptrs[i] = NULL;
763 rc = ldap_modify_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs);
764 if (rc != LDAP_SUCCESS)
765 signal_ldap_error (ld, NULL, rc);
766
767 UNGCPRO;
768 return Qnil;
769 }
770
771
772 DEFUN ("ldap-delete", Fldap_delete, 2, 2, 0, /*
773 Delete an entry to an LDAP directory.
774 LDAP is an LDAP connection object created with `ldap-open'.
775 DN is the distinguished name of the entry to delete.
776 */
777 (ldap, dn))
778 {
779 LDAP *ld;
780 int rc;
781
782 /* Check parameters */
783 CHECK_LIVE_LDAP (ldap);
784 ld = XLDAP (ldap)->ld;
785 CHECK_STRING (dn);
786
787 rc = ldap_delete_s (ld, (char *) XSTRING_DATA (dn));
788 if (rc != LDAP_SUCCESS)
789 signal_ldap_error (ld, NULL, rc);
790
791 return Qnil;
792 }
581 793
582 void 794 void
583 syms_of_eldap (void) 795 syms_of_eldap (void)
584 { 796 {
797 INIT_LRECORD_IMPLEMENTATION (ldap);
798
585 defsymbol (&Qldapp, "ldapp"); 799 defsymbol (&Qldapp, "ldapp");
586 defsymbol (&Qport, "port"); 800 defsymbol (&Qport, "port");
587 defsymbol (&Qauth, "auth"); 801 defsymbol (&Qauth, "auth");
588 defsymbol (&Qbinddn, "binddn"); 802 defsymbol (&Qbinddn, "binddn");
589 defsymbol (&Qpasswd, "passwd"); 803 defsymbol (&Qpasswd, "passwd");
596 defsymbol (&Qkrbv41, "krbv41"); 810 defsymbol (&Qkrbv41, "krbv41");
597 defsymbol (&Qkrbv42, "krbv42"); 811 defsymbol (&Qkrbv42, "krbv42");
598 defsymbol (&Qnever, "never"); 812 defsymbol (&Qnever, "never");
599 defsymbol (&Qalways, "always"); 813 defsymbol (&Qalways, "always");
600 defsymbol (&Qfind, "find"); 814 defsymbol (&Qfind, "find");
815 defsymbol (&Qadd, "add");
816 defsymbol (&Qreplace, "replace");
601 817
602 DEFSUBR (Fldapp); 818 DEFSUBR (Fldapp);
603 DEFSUBR (Fldap_host); 819 DEFSUBR (Fldap_host);
604 DEFSUBR (Fldap_status); 820 DEFSUBR (Fldap_status);
605 DEFSUBR (Fldap_open); 821 DEFSUBR (Fldap_open);
606 DEFSUBR (Fldap_close); 822 DEFSUBR (Fldap_close);
607 DEFSUBR (Fldap_search_internal); 823 DEFSUBR (Fldap_search_basic);
824 DEFSUBR (Fldap_add);
825 DEFSUBR (Fldap_modify);
826 DEFSUBR (Fldap_delete);
608 } 827 }
609 828
610 void 829 void
611 vars_of_eldap (void) 830 vars_of_eldap (void)
612 { 831 {