diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2013-12-28 10:51:06 +0100 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2014-01-05 22:08:40 +0100 |
commit | 15ee2fce08794ec82d2a08b9c01339c0db0a4725 (patch) | |
tree | 2df67515ff3ad323dce50983b87bba681dc1d744 | |
parent | 547e4792c580b67ec14595e23a08836825424171 (diff) |
Provide replacement ldap_create_deref_control()
This adds a test for a bug in OpenLDAP that allocated a
LDAP_CONTROL_PAGEDRESULTS control instead of a LDAP_CONTROL_X_DEREF
control.
-rw-r--r-- | compat/Makefile.am | 1 | ||||
-rw-r--r-- | compat/derefctrl.c | 50 | ||||
-rw-r--r-- | compat/ldap_compat.h | 13 | ||||
-rw-r--r-- | configure.ac | 62 |
4 files changed, 123 insertions, 3 deletions
diff --git a/compat/Makefile.am b/compat/Makefile.am index 361c9be..bc8e4cc 100644 --- a/compat/Makefile.am +++ b/compat/Makefile.am @@ -29,6 +29,7 @@ EXTRA_DIST = getopt_long.c getopt_long.h \ nss_compat.h socket.h \ ldap_compat.h pagectrl.c ldap_passwd_s.c ldap_initialize.c \ ldap_parse_passwordpolicy_control.c ldap_passwordpolicy_err2txt.c \ + derefctrl.c \ pam_compat.h pam_get_authtok.c pam_prompt.c libcompat_a_SOURCES = getpeercred.c getpeercred.h diff --git a/compat/derefctrl.c b/compat/derefctrl.c new file mode 100644 index 0000000..9676c55 --- /dev/null +++ b/compat/derefctrl.c @@ -0,0 +1,50 @@ +/* + derefctrl.c - replacement function + + Copyright (C) 2013 Arthur de Jong + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "config.h" + +#include <stdlib.h> +#include <lber.h> +#include <ldap.h> +#include <string.h> + +#include "compat/ldap_compat.h" +#include "compat/attrs.h" + +#ifdef REPLACE_LDAP_CREATE_DEREF_CONTROL +int replacement_ldap_create_deref_control(LDAP *ld, LDAPDerefSpec *ds, + int iscritical, LDAPControl **ctrlp) +{ + int rc; + struct berval value; + if (ctrlp == NULL) + return LDAP_PARAM_ERROR; + rc = ldap_create_deref_control_value(ld, ds, &value); + if (rc != LDAP_SUCCESS) + return rc; + rc = ldap_control_create(LDAP_CONTROL_X_DEREF, iscritical, &value, 0, ctrlp); + if (rc != LDAP_SUCCESS) + { + ber_memfree(value.bv_val); + } + return rc; +} +#endif /* REPLACE_LDAP_CREATE_DEREF_CONTROL */ diff --git a/compat/ldap_compat.h b/compat/ldap_compat.h index 6e9c6b1..b69974f 100644 --- a/compat/ldap_compat.h +++ b/compat/ldap_compat.h @@ -1,7 +1,7 @@ /* ldap_compat.h - provide a replacement definitions for some ldap functions - Copyright (C) 2009, 2010, 2012, 2013 Arthur de Jong + Copyright (C) 2009-2013 Arthur de Jong This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -80,6 +80,14 @@ int ldap_parse_passwordpolicy_control(LDAP *ld, LDAPControl *ctrl, const char *ldap_passwordpolicy_err2txt(LDAPPasswordPolicyError error); #endif /* HAVE_LDAP_PASSWORDPOLICY_ERR2TXT */ +#ifdef REPLACE_LDAP_CREATE_DEREF_CONTROL +/* provide a replacement implementation of ldap_create_deref_control() */ +int replacement_ldap_create_deref_control(LDAP *ld, LDAPDerefSpec *ds, + int iscritical, LDAPControl **ctrlp); +#define ldap_create_deref_control(ld, dc, iscritical, ctrlp) \ + replacement_ldap_create_deref_control(ld, dc, iscritical, ctrlp) +#endif /* REPLACE_LDAP_CREATE_DEREF_CONTROL */ + /* compatibility definition */ #ifndef LDAP_SASL_QUIET #define LDAP_SASL_QUIET 2U @@ -106,5 +114,8 @@ const char *ldap_passwordpolicy_err2txt(LDAPPasswordPolicyError error); #ifndef LDAP_CONTROL_PASSWORDPOLICYRESPONSE #define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1" #endif /* LDAP_CONTROL_PASSWORDPOLICYRESPONSE */ +#ifndef LDAP_CONTROL_X_DEREF +#define LDAP_CONTROL_X_DEREF "1.3.6.1.4.1.4203.666.5.16" +#endif /* LDAP_CONTROL_X_DEREF */ #endif /* COMPAT__LDAP_COMPAT_H */ diff --git a/configure.ac b/configure.ac index cecb358..907446e 100644 --- a/configure.ac +++ b/configure.ac @@ -803,10 +803,10 @@ then AC_CHECK_FUNCS(ldap_get_values ldap_value_free) AC_CHECK_FUNCS(ldap_get_values_len ldap_count_values_len ldap_value_free_len) AC_CHECK_FUNCS(ldap_err2string ldap_abandon) - AC_CHECK_FUNCS(ldap_create_control ldap_control_find) + AC_CHECK_FUNCS(ldap_control_create ldap_create_control ldap_control_find) AC_CHECK_FUNCS(ldap_controls_free ldap_control_free) AC_CHECK_FUNCS(ldap_parse_passwordpolicy_control ldap_passwordpolicy_err2txt) - AC_CHECK_FUNCS(ldap_create_deref_control) + AC_CHECK_FUNCS(ldap_create_deref_control ldap_create_deref_control_value) # replace ldap_create_page_control() and ldap_parse_page_control() AC_CHECK_FUNCS(ldap_create_page_control ldap_parse_page_control,, [AC_LIBOBJ(pagectrl)]) @@ -861,6 +861,64 @@ then [Define to 1 if ldap_set_rebind_proc() returns void.]) fi + # check for broken implementations of ldap_create_deref_control() + if test "x$ac_cv_func_ldap_create_deref_control" = "xyes" + then + # this bug cannot be determined on compile time so we run a + # small test program + AC_CACHE_CHECK( + [ldap_create_deref_control() implementation], + nslcd_cv_ldap_create_deref_control_working, + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include <stdio.h> + #include <lber.h> + #include <ldap.h> + ]], [[ + int rc; + LDAP *ld; + LDAPControl *ctrls[2] = {NULL, NULL}; + struct LDAPDerefSpec ds[2]; + char *attrs[2] = {"uid", NULL}; + ld = ldap_init("localhost", LDAP_PORT); + if (ld == NULL) + { + fprintf(stderr, "ldap_init() failed\n"); + return 2; + } + ds[0].derefAttr = "member"; + ds[0].attributes = attrs; + ds[1].derefAttr = NULL; + rc = ldap_create_deref_control(ld, ds, 0, &ctrls[0]); + if (rc != LDAP_SUCCESS) + { + fprintf(stderr, "ldap_create_deref_control() failed: %s\n", + ldap_err2string(rc)); + return 2; + } + if (ldap_control_find(LDAP_CONTROL_X_DEREF, ctrls, NULL) != NULL) + return 0; + if (ldap_control_find(LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL) != NULL) + { + fprintf(stderr, "ldap_create_deref_control() created LDAP_CONTROL_PAGEDRESULTS control\n"); + return 3; + } + fprintf(stderr, "ldap_create_deref_control() created unknown control\n"); + return 2; + ]])], + [nslcd_cv_ldap_create_deref_control_working=ok], + [if test "$?" -eq 3; then nslcd_cv_ldap_create_deref_control_working=broken + else nslcd_cv_ldap_create_deref_control_working=unknown; fi], + [nslcd_cv_ldap_create_deref_control_working=cross])]) + if test "x$nslcd_cv_ldap_create_deref_control_working" != "xok" + then + AC_MSG_NOTICE([using replacement ldap_create_deref_control()]) + AC_LIBOBJ(derefctrl) + AC_DEFINE(REPLACE_LDAP_CREATE_DEREF_CONTROL, 1, + [Define to 1 if ldap_create_deref_control() is broken.]) + fi + fi + # save nslcd LIBS and CFLAGS and restore originals nslcd_CFLAGS="$CFLAGS" nslcd_LIBS="$LIBS" |