Mercurial > hg > xemacs-beta
diff 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 |
line wrap: on
line diff
--- a/src/eldap.c Mon Aug 13 11:19:22 2007 +0200 +++ b/src/eldap.c Mon Aug 13 11:20:41 2007 +0200 @@ -26,8 +26,8 @@ conforming to the API defined in RFC 1823. It has been tested with: - UMich LDAP 3.3 (http://www.umich.edu/~dirsvcs/ldap/) - - OpenLDAP 1.2 (http://www.openldap.org/) - - Netscape's LDAP SDK (http://developer.netscape.com/) */ + - OpenLDAP 1.0.3 (http://www.openldap.org/) + - Netscape's LDAP SDK 1.0 (http://developer.netscape.com/) */ #include <config.h> @@ -40,6 +40,14 @@ #include "eldap.h" +#ifdef HAVE_NS_LDAP +# define HAVE_LDAP_SET_OPTION 1 +# define HAVE_LDAP_GET_ERRNO 1 +#else +# undef HAVE_LDAP_SET_OPTION +# undef HAVE_LDAP_GET_ERRNO +#endif + static int ldap_default_port; static Lisp_Object Vldap_default_base; @@ -47,43 +55,30 @@ Lisp_Object Qldapp; /* ldap-open plist keywords */ -static Lisp_Object Qport, Qauth, Qbinddn, Qpasswd, Qderef, Qtimelimit, Qsizelimit; +extern Lisp_Object Qport, Qauth, Qbinddn, Qpasswd, Qderef, Qtimelimit, + Qsizelimit; /* Search scope limits */ -static Lisp_Object Qbase, Qonelevel, Qsubtree; +extern Lisp_Object Qbase, Qonelevel, Qsubtree; /* Authentication methods */ -static Lisp_Object Qkrbv41, Qkrbv42; +extern Lisp_Object Qkrbv41, Qkrbv42; /* Deref policy */ -static Lisp_Object Qnever, Qalways, Qfind; -/* Modification types (Qdelete is defined in general.c) */ -static Lisp_Object Qadd, Qreplace; - +extern Lisp_Object Qnever, Qalways, Qfind; /************************************************************************/ /* Utility Functions */ /************************************************************************/ static void -signal_ldap_error (LDAP *ld, LDAPMessage *res, int ldap_err) +signal_ldap_error (LDAP *ld) { - if (ldap_err <= 0) - { -#if defined HAVE_LDAP_PARSE_RESULT - int err; - ldap_err = ldap_parse_result (ld, res, - &err, - NULL, NULL, NULL, NULL, 0); - if (ldap_err == LDAP_SUCCESS) - ldap_err = err; -#elif defined HAVE_LDAP_GET_LDERRNO - ldap_err = ldap_get_lderrno (ld, NULL, NULL); -#elif defined HAVE_LDAP_RESULT2ERROR - ldap_err = ldap_result2error (ld, res, 0); +#ifdef HAVE_LDAP_GET_ERRNO + signal_simple_error + ("LDAP error", + build_string (ldap_err2string (ldap_get_lderrno (ld, NULL, NULL)))); #else - ldap_err = ld->ld_errno; + signal_simple_error ("LDAP error", + build_string (ldap_err2string (ld->ld_errno))); #endif - } - signal_simple_error ("LDAP error", - build_string (ldap_err2string (ldap_err))); } @@ -92,7 +87,7 @@ /************************************************************************/ static Lisp_Object -make_ldap (Lisp_LDAP *ldap) +make_ldap (struct Lisp_LDAP *ldap) { Lisp_Object lisp_ldap; XSETLDAP (lisp_ldap, ldap); @@ -100,7 +95,7 @@ } static Lisp_Object -mark_ldap (Lisp_Object obj) +mark_ldap (Lisp_Object obj, void (*markobj) (Lisp_Object)) { return XLDAP (obj)->host; } @@ -110,7 +105,7 @@ { char buf[32]; - Lisp_LDAP *ldap = XLDAP (obj); + struct Lisp_LDAP *ldap = XLDAP (obj); if (print_readably) error ("printing unreadable object #<ldap %s>", @@ -118,39 +113,40 @@ write_c_string ("#<ldap ", printcharfun); print_internal (ldap->host, printcharfun, 1); - if (!ldap->ld) + if (!ldap->livep) write_c_string ("(dead) ",printcharfun); sprintf (buf, " 0x%x>", (unsigned int)ldap); write_c_string (buf, printcharfun); } -static Lisp_LDAP * +static struct Lisp_LDAP * allocate_ldap (void) { - Lisp_LDAP *ldap = alloc_lcrecord_type (Lisp_LDAP, &lrecord_ldap); + struct Lisp_LDAP *ldap = + alloc_lcrecord_type (struct Lisp_LDAP, &lrecord_ldap); ldap->ld = NULL; ldap->host = Qnil; + ldap->livep = 0; return ldap; } static void finalize_ldap (void *header, int for_disksave) { - Lisp_LDAP *ldap = (Lisp_LDAP *) header; + struct Lisp_LDAP *ldap = (struct Lisp_LDAP *) header; if (for_disksave) signal_simple_error ("Can't dump an emacs containing LDAP objects", make_ldap (ldap)); - if (ldap->ld) + if (ldap->livep) ldap_unbind (ldap->ld); - ldap->ld = NULL; } DEFINE_LRECORD_IMPLEMENTATION ("ldap", ldap, mark_ldap, print_ldap, finalize_ldap, - NULL, NULL, 0, Lisp_LDAP); + NULL, NULL, struct Lisp_LDAP); @@ -182,7 +178,7 @@ (ldap)) { CHECK_LDAP (ldap); - return (XLDAP (ldap))->ld ? Qt : Qnil; + return (XLDAP (ldap))->livep ? Qt : Qnil; } /************************************************************************/ @@ -207,7 +203,7 @@ (host, plist)) { /* This function can GC */ - Lisp_LDAP *ldap; + struct Lisp_LDAP *ldap; LDAP *ld; int ldap_port = 0; int ldap_auth = LDAP_AUTH_SIMPLE; @@ -250,17 +246,13 @@ else if (EQ (keyword, Qbinddn)) { CHECK_STRING (value); - TO_EXTERNAL_FORMAT (LISP_STRING, value, - C_STRING_ALLOCA, ldap_binddn, - Qnative); + GET_C_STRING_OS_DATA_ALLOCA (value, ldap_binddn); } /* Password */ else if (EQ (keyword, Qpasswd)) { CHECK_STRING (value); - TO_EXTERNAL_FORMAT (LISP_STRING, value, - C_STRING_ALLOCA, ldap_passwd, - Qnative); + GET_C_STRING_OS_DATA_ALLOCA (value, ldap_passwd); } /* Deref */ else if (EQ (keyword, Qderef)) @@ -307,21 +299,16 @@ #ifdef HAVE_LDAP_SET_OPTION - if ((err = ldap_set_option (ld, LDAP_OPT_DEREF, - (void *)&ldap_deref)) != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, err); - if ((err = ldap_set_option (ld, LDAP_OPT_TIMELIMIT, - (void *)&ldap_timelimit)) != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, err); - if ((err = ldap_set_option (ld, LDAP_OPT_SIZELIMIT, - (void *)&ldap_sizelimit)) != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, err); - if ((err = ldap_set_option (ld, LDAP_OPT_REFERRALS, - LDAP_OPT_ON)) != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, err); - if ((err = ldap_set_option (ld, LDAP_OPT_RESTART, - LDAP_OPT_ON)) != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, err); + if (ldap_set_option (ld, LDAP_OPT_DEREF, (void *)&ldap_deref) != LDAP_SUCCESS) + signal_ldap_error (ld); + if (ldap_set_option (ld, LDAP_OPT_TIMELIMIT, + (void *)&ldap_timelimit) != LDAP_SUCCESS) + signal_ldap_error (ld); + if (ldap_set_option (ld, LDAP_OPT_SIZELIMIT, + (void *)&ldap_sizelimit) != LDAP_SUCCESS) + signal_ldap_error (ld); + if (ldap_set_option (ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON) != LDAP_SUCCESS) + signal_ldap_error (ld); #else /* not HAVE_LDAP_SET_OPTION */ ld->ld_deref = ldap_deref; ld->ld_timelimit = ldap_timelimit; @@ -331,11 +318,12 @@ #else /* not LDAP_REFERRALS */ ld->ld_options = 0; #endif /* not LDAP_REFERRALS */ - /* XEmacs uses interrupts (SIGIO,SIGALRM), LDAP calls need to ignore them */ - ld->ld_options |= LDAP_OPT_RESTART; #endif /* not HAVE_LDAP_SET_OPTION */ + /* ldap_bind_s calls select and may be wedged by SIGIO. */ + slow_down_interrupts (); err = ldap_bind_s (ld, ldap_binddn, ldap_passwd, ldap_auth); + speed_up_interrupts (); if (err != LDAP_SUCCESS) signal_simple_error ("Failed binding to the server", build_string (ldap_err2string (err))); @@ -343,6 +331,7 @@ ldap = allocate_ldap (); ldap->ld = ld; ldap->host = host; + ldap->livep = 1; return make_ldap (ldap); } @@ -354,11 +343,11 @@ */ (ldap)) { - Lisp_LDAP *lldap; + struct Lisp_LDAP *lldap; CHECK_LIVE_LDAP (ldap); lldap = XLDAP (ldap); ldap_unbind (lldap->ld); - lldap->ld = NULL; + lldap->livep = 0; return Qnil; } @@ -373,6 +362,7 @@ struct berval **vals; }; + static Lisp_Object ldap_search_unwind (Lisp_Object unwind_obj) { @@ -385,12 +375,7 @@ return Qnil; } -/* The following function is called `ldap-search-basic' instead of */ -/* plain `ldap-search' to maintain compatibility with the XEmacs 21.1 */ -/* API where `ldap-search' was the name of the high-level search */ -/* function */ - -DEFUN ("ldap-search-basic", Fldap_search_basic, 2, 8, 0, /* +DEFUN ("ldap-search-internal", Fldap_search_internal, 2, 7, 0, /* Perform a search on an open LDAP connection. LDAP is an LDAP connection object created with `ldap-open'. FILTER is a filter string for the search as described in RFC 1558. @@ -401,14 +386,13 @@ for each matching entry. If nil return all available attributes. If ATTRSONLY is non-nil then only the attributes are retrieved, not the associated values. -If WITHDN is non-nil each entry in the result will be prepended with +If WITHDN is non-nil each entry in the result will be prepennded with its distinguished name DN. -If VERBOSE is non-nil progress messages will be echoed. The function returns a list of matching entries. Each entry is itself an alist of attribute/value pairs optionally preceded by the DN of the entry according to the value of WITHDN. */ - (ldap, filter, base, scope, attrs, attrsonly, withdn, verbose)) + (ldap, filter, base, scope, attrs, attrsonly, withdn)) { /* This function can GC */ @@ -426,11 +410,10 @@ int speccount = specpdl_depth (); - Lisp_Object list = Qnil; - Lisp_Object entry = Qnil; - Lisp_Object result = Qnil; + Lisp_Object list, entry, result; struct gcpro gcpro1, gcpro2, gcpro3; + list = entry = result = Qnil; GCPRO3 (list, entry, result); unwind.res = NULL; @@ -477,9 +460,7 @@ { Lisp_Object current = XCAR (attrs); CHECK_STRING (current); - TO_EXTERNAL_FORMAT (LISP_STRING, current, - C_STRING_ALLOCA, ldap_attributes[i], - Qnative); + GET_C_STRING_OS_DATA_ALLOCA (current, ldap_attributes[i]); ++i; } ldap_attributes[i] = NULL; @@ -490,14 +471,14 @@ /* Perform the search */ if (ldap_search (ld, - NILP (base) ? (char *) "" : (char *) XSTRING_DATA (base), + NILP (base) ? "" : (char *) XSTRING_DATA (base), ldap_scope, - NILP (filter) ? (char *) "" : (char *) XSTRING_DATA (filter), + NILP (filter) ? "" : (char *) XSTRING_DATA (filter), ldap_attributes, NILP (attrsonly) ? 0 : 1) - == -1) + == -1) { - signal_ldap_error (ld, NULL, 0); + signal_ldap_error (ld); } /* Ensure we don't exit without cleaning up */ @@ -507,8 +488,10 @@ /* Build the results list */ matches = 0; + /* ldap_result calls select() and can get wedged by EINTR signals */ + slow_down_interrupts (); rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &unwind.res); - + speed_up_interrupts (); while (rc == LDAP_RES_SEARCH_ENTRY) { QUIT; @@ -518,30 +501,31 @@ destroys the current echo area contents, even when invoked from Lisp. It should use echo_area_message() instead, and restore the old echo area contents later. */ - if (! NILP (verbose)) - message ("Parsing ldap results... %d", matches); + message ("Parsing ldap results... %d", matches); entry = Qnil; /* Get the DN if required */ if (! NILP (withdn)) { dn = ldap_get_dn (ld, e); if (dn == NULL) - signal_ldap_error (ld, e, 0); - entry = Fcons (build_ext_string (dn, Qnative), Qnil); + { + signal_ldap_error (ld); + } + entry = Fcons (build_ext_string (dn, FORMAT_OS), Qnil); } for (a= ldap_first_attribute (ld, e, &ptr); a != NULL; a = ldap_next_attribute (ld, e, ptr) ) { - list = Fcons (build_ext_string (a, Qnative), Qnil); + list = Fcons (build_ext_string (a, FORMAT_OS), Qnil); unwind.vals = ldap_get_values_len (ld, e, a); if (unwind.vals != NULL) { for (i = 0; unwind.vals[i] != NULL; i++) { - list = Fcons (make_ext_string ((Extbyte *) unwind.vals[i]->bv_val, + list = Fcons (make_ext_string (unwind.vals[i]->bv_val, unwind.vals[i]->bv_len, - Qnative), + FORMAT_OS), list); } } @@ -555,285 +539,43 @@ ldap_msgfree (unwind.res); unwind.res = NULL; + slow_down_interrupts (); rc = ldap_result (ld, LDAP_RES_ANY, 0, NULL, &(unwind.res)); + speed_up_interrupts (); } -#if defined HAVE_LDAP_PARSE_RESULT - { - int rc2 = ldap_parse_result (ld, unwind.res, - &rc, - NULL, NULL, NULL, NULL, 0); - if (rc2 != LDAP_SUCCESS) - rc = rc2; - } -#else - if (rc == 0) - signal_ldap_error (ld, NULL, LDAP_TIMELIMIT_EXCEEDED); - if (rc == -1) - signal_ldap_error (ld, unwind.res, (unwind.res==NULL) ? ld->ld_errno : 0); - -#if defined HAVE_LDAP_RESULT2ERROR + { + signal_ldap_error (ld); + } rc = ldap_result2error (ld, unwind.res, 0); -#endif -#endif - - if (rc != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, rc); + if ((rc != LDAP_SUCCESS) && + (rc != LDAP_SIZELIMIT_EXCEEDED)) + { + signal_ldap_error (ld); + } ldap_msgfree (unwind.res); unwind.res = (LDAPMessage *)NULL; - /* #### See above for calling message(). */ - if (! NILP (verbose)) - message ("Parsing ldap results... done"); + message ("Parsing ldap results... done"); unbind_to (speccount, Qnil); UNGCPRO; return Fnreverse (result); } -DEFUN ("ldap-add", Fldap_add, 3, 3, 0, /* -Add an entry to an LDAP directory. -LDAP is an LDAP connection object created with `ldap-open'. -DN is the distinguished name of the entry to add. -ENTRY is an entry specification, i.e., a list of cons cells -containing attribute/value string pairs. -*/ - (ldap, dn, entry)) -{ - LDAP *ld; - LDAPMod *ldap_mods, **ldap_mods_ptrs; - struct berval *bervals; - int rc; - int i, j; - size_t len; - - Lisp_Object current = Qnil; - Lisp_Object values = Qnil; - struct gcpro gcpro1, gcpro2; - - GCPRO2 (current, values); - - /* Do all the parameter checking */ - CHECK_LIVE_LDAP (ldap); - ld = XLDAP (ldap)->ld; - - /* Check the DN */ - CHECK_STRING (dn); - - /* Check the entry */ - CHECK_CONS (entry); - if (NILP (entry)) - signal_simple_error ("Cannot add void entry", entry); - - /* Build the ldap_mods array */ - len = XINT (Flength (entry)); - ldap_mods = alloca_array (LDAPMod, len); - ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len); - i = 0; - EXTERNAL_LIST_LOOP (entry, entry) - { - current = XCAR (entry); - CHECK_CONS (current); - CHECK_STRING (XCAR (current)); - ldap_mods_ptrs[i] = &(ldap_mods[i]); - TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (current), - C_STRING_ALLOCA, ldap_mods[i].mod_type, - Qnative); - ldap_mods[i].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; - values = XCDR (current); - if (CONSP (values)) - { - len = XINT (Flength (values)); - bervals = alloca_array (struct berval, len); - ldap_mods[i].mod_vals.modv_bvals = - alloca_array (struct berval *, 1 + len); - j = 0; - EXTERNAL_LIST_LOOP (values, values) - { - current = XCAR (values); - CHECK_STRING (current); - ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]); - TO_EXTERNAL_FORMAT (LISP_STRING, current, - ALLOCA, (bervals[j].bv_val, - bervals[j].bv_len), - Qnative); - j++; - } - ldap_mods[i].mod_vals.modv_bvals[j] = NULL; - } - else - { - CHECK_STRING (values); - bervals = alloca_array (struct berval, 1); - ldap_mods[i].mod_vals.modv_bvals = alloca_array (struct berval *, 2); - ldap_mods[i].mod_vals.modv_bvals[0] = &(bervals[0]); - TO_EXTERNAL_FORMAT (LISP_STRING, values, - ALLOCA, (bervals[0].bv_val, - bervals[0].bv_len), - Qnative); - ldap_mods[i].mod_vals.modv_bvals[1] = NULL; - } - i++; - } - ldap_mods_ptrs[i] = NULL; - rc = ldap_add_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs); - if (rc != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, rc); - - UNGCPRO; - return Qnil; -} - -DEFUN ("ldap-modify", Fldap_modify, 3, 3, 0, /* -Add an entry to an LDAP directory. -LDAP is an LDAP connection object created with `ldap-open'. -DN is the distinguished name of the entry to modify. -MODS is a list of modifications to apply. -A modification is a list of the form (MOD-OP ATTR VALUE1 VALUE2 ...) -MOD-OP and ATTR are mandatory, VALUEs are optional depending on MOD-OP. -MOD-OP is the type of modification, one of the symbols `add', `delete' -or `replace'. ATTR is the LDAP attribute type to modify. -*/ - (ldap, dn, mods)) -{ - LDAP *ld; - LDAPMod *ldap_mods, **ldap_mods_ptrs; - struct berval *bervals; - int i, j, rc; - Lisp_Object mod_op; - size_t len; - - Lisp_Object current = Qnil; - Lisp_Object values = Qnil; - struct gcpro gcpro1, gcpro2; - - GCPRO2 (current, values); - - /* Do all the parameter checking */ - CHECK_LIVE_LDAP (ldap); - ld = XLDAP (ldap)->ld; - - /* Check the DN */ - CHECK_STRING (dn); - - /* Check the entry */ - CHECK_CONS (mods); - if (NILP (mods)) - return Qnil; - - /* Build the ldap_mods array */ - len = XINT (Flength (mods)); - ldap_mods = alloca_array (LDAPMod, len); - ldap_mods_ptrs = alloca_array (LDAPMod *, 1 + len); - i = 0; - EXTERNAL_LIST_LOOP (mods, mods) - { - current = XCAR (mods); - CHECK_CONS (current); - CHECK_SYMBOL (XCAR (current)); - mod_op = XCAR (current); - ldap_mods_ptrs[i] = &(ldap_mods[i]); - ldap_mods[i].mod_op = LDAP_MOD_BVALUES; - if (EQ (mod_op, Qadd)) - ldap_mods[i].mod_op |= LDAP_MOD_ADD; - else if (EQ (mod_op, Qdelete)) - ldap_mods[i].mod_op |= LDAP_MOD_DELETE; - else if (EQ (mod_op, Qreplace)) - ldap_mods[i].mod_op |= LDAP_MOD_REPLACE; - else - signal_simple_error ("Invalid LDAP modification type", mod_op); - current = XCDR (current); - CHECK_STRING (XCAR (current)); - TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (current), - C_STRING_ALLOCA, ldap_mods[i].mod_type, - Qnative); - values = XCDR (current); - len = XINT (Flength (values)); - bervals = alloca_array (struct berval, len); - ldap_mods[i].mod_vals.modv_bvals = - alloca_array (struct berval *, 1 + len); - j = 0; - EXTERNAL_LIST_LOOP (values, values) - { - current = XCAR (values); - CHECK_STRING (current); - ldap_mods[i].mod_vals.modv_bvals[j] = &(bervals[j]); - TO_EXTERNAL_FORMAT (LISP_STRING, current, - ALLOCA, (bervals[j].bv_val, - bervals[j].bv_len), - Qnative); - j++; - } - ldap_mods[i].mod_vals.modv_bvals[j] = NULL; - i++; - } - ldap_mods_ptrs[i] = NULL; - rc = ldap_modify_s (ld, (char *) XSTRING_DATA (dn), ldap_mods_ptrs); - if (rc != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, rc); - - UNGCPRO; - return Qnil; -} - - -DEFUN ("ldap-delete", Fldap_delete, 2, 2, 0, /* -Delete an entry to an LDAP directory. -LDAP is an LDAP connection object created with `ldap-open'. -DN is the distinguished name of the entry to delete. -*/ - (ldap, dn)) -{ - LDAP *ld; - int rc; - - /* Check parameters */ - CHECK_LIVE_LDAP (ldap); - ld = XLDAP (ldap)->ld; - CHECK_STRING (dn); - - rc = ldap_delete_s (ld, (char *) XSTRING_DATA (dn)); - if (rc != LDAP_SUCCESS) - signal_ldap_error (ld, NULL, rc); - - return Qnil; -} void syms_of_eldap (void) { - INIT_LRECORD_IMPLEMENTATION (ldap); - defsymbol (&Qldapp, "ldapp"); - defsymbol (&Qport, "port"); - defsymbol (&Qauth, "auth"); - defsymbol (&Qbinddn, "binddn"); - defsymbol (&Qpasswd, "passwd"); - defsymbol (&Qderef, "deref"); - defsymbol (&Qtimelimit, "timelimit"); - defsymbol (&Qsizelimit, "sizelimit"); - defsymbol (&Qbase, "base"); - defsymbol (&Qonelevel, "onelevel"); - defsymbol (&Qsubtree, "subtree"); - defsymbol (&Qkrbv41, "krbv41"); - defsymbol (&Qkrbv42, "krbv42"); - defsymbol (&Qnever, "never"); - defsymbol (&Qalways, "always"); - defsymbol (&Qfind, "find"); - defsymbol (&Qadd, "add"); - defsymbol (&Qreplace, "replace"); - DEFSUBR (Fldapp); DEFSUBR (Fldap_host); DEFSUBR (Fldap_status); DEFSUBR (Fldap_open); DEFSUBR (Fldap_close); - DEFSUBR (Fldap_search_basic); - DEFSUBR (Fldap_add); - DEFSUBR (Fldap_modify); - DEFSUBR (Fldap_delete); + DEFSUBR (Fldap_search_internal); } void