comparison src/eldap.c @ 400:a86b2b5e0111 r21-2-30

Import from CVS: tag r21-2-30
author cvs
date Mon, 13 Aug 2007 11:14:34 +0200
parents 74fd4e045ea6
children 2f8bb876ab1d
comparison
equal deleted inserted replaced
399:376370fb5946 400:a86b2b5e0111
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
314 (void *)&ldap_sizelimit)) != LDAP_SUCCESS) 317 (void *)&ldap_sizelimit)) != LDAP_SUCCESS)
315 signal_ldap_error (ld, NULL, err); 318 signal_ldap_error (ld, NULL, err);
316 if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS, 319 if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS,
317 LDAP_OPT_ON)) != LDAP_SUCCESS) 320 LDAP_OPT_ON)) != LDAP_SUCCESS)
318 signal_ldap_error (ld, NULL, err); 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);
319 #else /* not HAVE_LDAP_SET_OPTION */ 325 #else /* not HAVE_LDAP_SET_OPTION */
320 ld->ld_deref = ldap_deref; 326 ld->ld_deref = ldap_deref;
321 ld->ld_timelimit = ldap_timelimit; 327 ld->ld_timelimit = ldap_timelimit;
322 ld->ld_sizelimit = ldap_sizelimit; 328 ld->ld_sizelimit = ldap_sizelimit;
323 #ifdef LDAP_REFERRALS 329 #ifdef LDAP_REFERRALS
324 ld->ld_options = LDAP_OPT_REFERRALS; 330 ld->ld_options = LDAP_OPT_REFERRALS;
325 #else /* not LDAP_REFERRALS */ 331 #else /* not LDAP_REFERRALS */
326 ld->ld_options = 0; 332 ld->ld_options = 0;
327 #endif /* not LDAP_REFERRALS */ 333 #endif /* not LDAP_REFERRALS */
334 /* XEmacs uses interrupts (SIGIO,SIGALRM), LDAP calls need to ignore them */
335 ld->ld_options |= LDAP_OPT_RESTART;
328 #endif /* not HAVE_LDAP_SET_OPTION */ 336 #endif /* not HAVE_LDAP_SET_OPTION */
329 337
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); 338 err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth);
333 speed_up_interrupts ();
334 if (err != LDAP_SUCCESS) 339 if (err != LDAP_SUCCESS)
335 signal_simple_error ("Failed binding to the server", 340 signal_simple_error ("Failed binding to the server",
336 build_string (ldap_err2string (err))); 341 build_string (ldap_err2string (err)));
337 342
338 ldap = allocate_ldap (); 343 ldap = allocate_ldap ();
365 struct ldap_unwind_struct 370 struct ldap_unwind_struct
366 { 371 {
367 LDAPMessage *res; 372 LDAPMessage *res;
368 struct berval **vals; 373 struct berval **vals;
369 }; 374 };
370
371 375
372 static Lisp_Object 376 static Lisp_Object
373 ldap_search_unwind (Lisp_Object unwind_obj) 377 ldap_search_unwind (Lisp_Object unwind_obj)
374 { 378 {
375 struct ldap_unwind_struct *unwind = 379 struct ldap_unwind_struct *unwind =
379 if (unwind->vals) 383 if (unwind->vals)
380 ldap_value_free_len (unwind->vals); 384 ldap_value_free_len (unwind->vals);
381 return Qnil; 385 return Qnil;
382 } 386 }
383 387
384 DEFUN ("ldap-search-internal", Fldap_search_internal, 2, 7, 0, /* 388 /* The following function is called `ldap-search-basic' instead of */
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, /*
385 Perform a search on an open LDAP connection. 394 Perform a search on an open LDAP connection.
386 LDAP is an LDAP connection object created with `ldap-open'. 395 LDAP is an LDAP connection object created with `ldap-open'.
387 FILTER is a filter string for the search as described in RFC 1558. 396 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. 397 BASE is the distinguished name at which to start the search.
389 SCOPE is one of the symbols `base', `onelevel' or `subtree' indicating 398 SCOPE is one of the symbols `base', `onelevel' or `subtree' indicating
390 the scope of the search. 399 the scope of the search.
391 ATTRS is a list of strings indicating which attributes to retrieve 400 ATTRS is a list of strings indicating which attributes to retrieve
392 for each matching entry. If nil return all available attributes. 401 for each matching entry. If nil return all available attributes.
393 If ATTRSONLY is non-nil then only the attributes are retrieved, not 402 If ATTRSONLY is non-nil then only the attributes are retrieved, not
394 the associated values. 403 the associated values.
395 If WITHDN is non-nil each entry in the result will be prepennded with 404 If WITHDN is non-nil each entry in the result will be prepended with
396 its distinguished name DN. 405 its distinguished name DN.
406 If VERBOSE is non-nil progress messages will be echoed.
397 The function returns a list of matching entries. Each entry is itself 407 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 408 an alist of attribute/value pairs optionally preceded by the DN of the
399 entry according to the value of WITHDN. 409 entry according to the value of WITHDN.
400 */ 410 */
401 (ldap, filter, base, scope, attrs, attrsonly, withdn)) 411 (ldap, filter, base, scope, attrs, attrsonly, withdn, verbose))
402 { 412 {
403 /* This function can GC */ 413 /* This function can GC */
404 414
405 /* Vars for query */ 415 /* Vars for query */
406 LDAP *ld; 416 LDAP *ld;
494 make_opaque_ptr (&unwind)); 504 make_opaque_ptr (&unwind));
495 505
496 /* Build the results list */ 506 /* Build the results list */
497 matches = 0; 507 matches = 0;
498 508
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); 509 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res);
502 speed_up_interrupts (); 510
503 while (rc == LDAP_RES_SEARCH_ENTRY) 511 while (rc == LDAP_RES_SEARCH_ENTRY)
504 { 512 {
505 QUIT; 513 QUIT;
506 matches ++; 514 matches ++;
507 e = ldap_first_entry (ld, unwind.res); 515 e = ldap_first_entry (ld, unwind.res);
508 /* #### This call to message() is pretty fascist, because it 516 /* #### This call to message() is pretty fascist, because it
509 destroys the current echo area contents, even when invoked 517 destroys the current echo area contents, even when invoked
510 from Lisp. It should use echo_area_message() instead, and 518 from Lisp. It should use echo_area_message() instead, and
511 restore the old echo area contents later. */ 519 restore the old echo area contents later. */
512 message ("Parsing ldap results... %d", matches); 520 if (! NILP (verbose))
521 message ("Parsing ldap results... %d", matches);
513 entry = Qnil; 522 entry = Qnil;
514 /* Get the DN if required */ 523 /* Get the DN if required */
515 if (! NILP (withdn)) 524 if (! NILP (withdn))
516 { 525 {
517 dn = ldap_get_dn (ld, e); 526 dn = ldap_get_dn (ld, e);
543 result = Fcons (Fnreverse (entry), 552 result = Fcons (Fnreverse (entry),
544 result); 553 result);
545 ldap_msgfree (unwind.res); 554 ldap_msgfree (unwind.res);
546 unwind.res = NULL; 555 unwind.res = NULL;
547 556
548 slow_down_interrupts ();
549 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res)); 557 rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res));
550 speed_up_interrupts (); 558 }
551 }
552
553 if (rc == -1)
554 signal_ldap_error (ld, unwind.res, 0);
555
556 if (rc == 0)
557 signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED);
558 559
559 #if defined HAVE_LDAP_PARSE_RESULT 560 #if defined HAVE_LDAP_PARSE_RESULT
560 rc2 = ldap_parse_result (ld, unwind.res, 561 rc2 = ldap_parse_result (ld, unwind.res,
561 &rc, 562 &rc,
562 NULL, NULL, NULL, NULL, 0); 563 NULL, NULL, NULL, NULL, 0);
563 if (rc2 != LDAP_SUCCESS) 564 if (rc2 != LDAP_SUCCESS)
564 rc = rc2; 565 rc = rc2;
565 #elif defined HAVE_LDAP_RESULT2ERROR 566 #else
567 if (rc == 0)
568 signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED);
569
570 if (rc == -1)
571 signal_ldap_error (ld, unwind.res, (unwind.res==NULL) ? ld->ld_errno : 0);
572
573 #if defined HAVE_LDAP_RESULT2ERROR
566 rc = ldap_result2error (ld, unwind.res, 0); 574 rc = ldap_result2error (ld, unwind.res, 0);
567 #endif 575 #endif
568 if ((rc != LDAP_SUCCESS) && (rc != LDAP_SIZELIMIT_EXCEEDED)) 576 #endif
577
578 if (rc != LDAP_SUCCESS)
569 signal_ldap_error (ld, NULL, rc); 579 signal_ldap_error (ld, NULL, rc);
570 580
571 ldap_msgfree (unwind.res); 581 ldap_msgfree (unwind.res);
572 unwind.res = (LDAPMessage *)NULL; 582 unwind.res = (LDAPMessage *)NULL;
583
573 /* #### See above for calling message(). */ 584 /* #### See above for calling message(). */
574 message ("Parsing ldap results... done"); 585 if (! NILP (verbose))
586 message ("Parsing ldap results... done");
575 587
576 unbind_to (speccount, Qnil); 588 unbind_to (speccount, Qnil);
577 UNGCPRO; 589 UNGCPRO;
578 return Fnreverse (result); 590 return Fnreverse (result);
579 } 591 }
580 592
593 DEFUN ("ldap-add", Fldap_add, 3, 3, 0, /*
594 Add an entry to an LDAP directory.
595 LDAP is an LDAP connection object created with `ldap-open'.
596 DN is the distinguished name of the entry to add.
597 ENTRY is an entry specification, i.e., a list of cons cells
598 containing attribute/value string pairs.
599 */
600 (ldap, dn, entry))
601 {
602 LDAP *ld;
603 LDAPMod *ldap_mods, **ldap_mods_ptrs;
604 struct berval *bervals;
605 int rc;
606 int i, j;
607
608 Lisp_Object current, values;
609 struct gcpro gcpro1, gcpro2;
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 ldap_mods = alloca_array (LDAPMod, XINT (Flength (entry)));
626 ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + XINT (Flength (entry)));
627 i = 0;
628 EXTERNAL_LIST_LOOP (entry, entry)
629 {
630 current = XCAR (entry);
631 CHECK_CONS (current);
632 CHECK_STRING (XCAR (current));
633 ldap_mods_ptrs[i] = &(ldap_mods[i]);
634 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (current),
635 C_STRING_ALLOCA, ldap_mods[i].mod_type,
636 Qnative);
637 ldap_mods[i].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
638 values = XCDR (current);
639 if (CONSP (values))
640 {
641 bervals =
642 alloca_array (struct berval, XINT (Flength (values)));
643 ldap_mods[i].mod_vals.modv_bvals =
644 alloca_array (struct berval *, 1 + XINT (Flength (values)));
645 j = 0;
646 EXTERNAL_LIST_LOOP (values, values)
647 {
648 current = XCAR (values);
649 CHECK_STRING (current);
650 ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]);
651 TO_EXTERNAL_FORMAT (LISP_STRING, current,
652 ALLOCA, (bervals[j].bv_val,
653 bervals[j].bv_len),
654 Qnative);
655 j++;
656 }
657 ldap_mods[i].mod_vals.modv_bvals[j] = NULL;
658 }
659 else
660 {
661 CHECK_STRING (values);
662 bervals = alloca_array (struct berval, 1);
663 ldap_mods[i].mod_vals.modv_bvals = alloca_array (struct berval *, 2);
664 ldap_mods[i].mod_vals.modv_bvals[0] = &(bervals[0]);
665 TO_EXTERNAL_FORMAT (LISP_STRING, values,
666 ALLOCA, (bervals[0].bv_val,
667 bervals[0].bv_len),
668 Qnative);
669 ldap_mods[i].mod_vals.modv_bvals[1] = NULL;
670 }
671 i++;
672 }
673 ldap_mods_ptrs[i] = NULL;
674 rc = ldap_add_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs);
675 if (rc != LDAP_SUCCESS)
676 signal_ldap_error (ld, NULL, rc);
677
678 UNGCPRO;
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
698 Lisp_Object current, mod_op, values;
699 struct gcpro gcpro1, gcpro2;
700
701 GCPRO2 (current, values);
702
703 /* Do all the parameter checking */
704 CHECK_LIVE_LDAP (ldap);
705 ld = XLDAP (ldap)->ld;
706
707 /* Check the DN */
708 CHECK_STRING (dn);
709
710 /* Check the entry */
711 CHECK_CONS (mods);
712 if (NILP (mods))
713 return Qnil;
714
715 /* Build the ldap_mods array */
716 ldap_mods = alloca_array (LDAPMod, XINT (Flength (mods)));
717 ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + XINT (Flength (mods)));
718 i = 0;
719 EXTERNAL_LIST_LOOP (mods, mods)
720 {
721 current = XCAR (mods);
722 CHECK_CONS (current);
723 CHECK_SYMBOL (XCAR (current));
724 mod_op = XCAR (current);
725 ldap_mods_ptrs[i] = &(ldap_mods[i]);
726 ldap_mods[i].mod_op = LDAP_MOD_BVALUES;
727 if (EQ (mod_op, Qadd))
728 ldap_mods[i].mod_op |= LDAP_MOD_ADD;
729 else if (EQ (mod_op, Qdelete))
730 ldap_mods[i].mod_op |= LDAP_MOD_DELETE;
731 else if (EQ (mod_op, Qreplace))
732 ldap_mods[i].mod_op |= LDAP_MOD_REPLACE;
733 else
734 signal_simple_error ("Invalid LDAP modification type", mod_op);
735 current = XCDR (current);
736 CHECK_STRING (XCAR (current));
737 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (current),
738 C_STRING_ALLOCA, ldap_mods[i].mod_type,
739 Qnative);
740 values = XCDR (current);
741 bervals = alloca_array (struct berval, XINT (Flength (values)));
742 ldap_mods[i].mod_vals.modv_bvals =
743 alloca_array (struct berval *, 1 + XINT (Flength (values)));
744 j = 0;
745 EXTERNAL_LIST_LOOP (values, values)
746 {
747 current = XCAR (values);
748 CHECK_STRING (current);
749 ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]);
750 TO_EXTERNAL_FORMAT (LISP_STRING, current,
751 ALLOCA, (bervals[j].bv_val,
752 bervals[j].bv_len),
753 Qnative);
754 j++;
755 }
756 ldap_mods[i].mod_vals.modv_bvals[j] = NULL;
757 i++;
758 }
759 ldap_mods_ptrs[i] = NULL;
760 rc = ldap_modify_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs);
761 if (rc != LDAP_SUCCESS)
762 signal_ldap_error (ld, NULL, rc);
763
764 UNGCPRO;
765 }
766
767
768 DEFUN ("ldap-delete", Fldap_delete, 2, 2, 0, /*
769 Delete an entry to an LDAP directory.
770 LDAP is an LDAP connection object created with `ldap-open'.
771 DN is the distinguished name of the entry to delete.
772 */
773 (ldap, dn))
774 {
775 LDAP *ld;
776 int rc;
777
778 /* Check parameters */
779 CHECK_LIVE_LDAP (ldap);
780 ld = XLDAP (ldap)->ld;
781 CHECK_STRING (dn);
782
783 rc = ldap_delete_s (ld, (char *) XSTRING_DATA (dn));
784 if (rc != LDAP_SUCCESS)
785 signal_ldap_error (ld, NULL, rc);
786 }
581 787
582 void 788 void
583 syms_of_eldap (void) 789 syms_of_eldap (void)
584 { 790 {
791 INIT_LRECORD_IMPLEMENTATION (ldap);
792
585 defsymbol (&Qldapp, "ldapp"); 793 defsymbol (&Qldapp, "ldapp");
586 defsymbol (&Qport, "port"); 794 defsymbol (&Qport, "port");
587 defsymbol (&Qauth, "auth"); 795 defsymbol (&Qauth, "auth");
588 defsymbol (&Qbinddn, "binddn"); 796 defsymbol (&Qbinddn, "binddn");
589 defsymbol (&Qpasswd, "passwd"); 797 defsymbol (&Qpasswd, "passwd");
596 defsymbol (&Qkrbv41, "krbv41"); 804 defsymbol (&Qkrbv41, "krbv41");
597 defsymbol (&Qkrbv42, "krbv42"); 805 defsymbol (&Qkrbv42, "krbv42");
598 defsymbol (&Qnever, "never"); 806 defsymbol (&Qnever, "never");
599 defsymbol (&Qalways, "always"); 807 defsymbol (&Qalways, "always");
600 defsymbol (&Qfind, "find"); 808 defsymbol (&Qfind, "find");
809 defsymbol (&Qadd, "add");
810 defsymbol (&Qreplace, "replace");
601 811
602 DEFSUBR (Fldapp); 812 DEFSUBR (Fldapp);
603 DEFSUBR (Fldap_host); 813 DEFSUBR (Fldap_host);
604 DEFSUBR (Fldap_status); 814 DEFSUBR (Fldap_status);
605 DEFSUBR (Fldap_open); 815 DEFSUBR (Fldap_open);
606 DEFSUBR (Fldap_close); 816 DEFSUBR (Fldap_close);
607 DEFSUBR (Fldap_search_internal); 817 DEFSUBR (Fldap_search_basic);
818 DEFSUBR (Fldap_add);
819 DEFSUBR (Fldap_modify);
820 DEFSUBR (Fldap_delete);
608 } 821 }
609 822
610 void 823 void
611 vars_of_eldap (void) 824 vars_of_eldap (void)
612 { 825 {