Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2013-12-28 10:51:06 +0100
committerArthur de Jong <arthur@arthurdejong.org>2014-01-05 22:08:40 +0100
commit15ee2fce08794ec82d2a08b9c01339c0db0a4725 (patch)
tree2df67515ff3ad323dce50983b87bba681dc1d744
parent547e4792c580b67ec14595e23a08836825424171 (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.am1
-rw-r--r--compat/derefctrl.c50
-rw-r--r--compat/ldap_compat.h13
-rw-r--r--configure.ac62
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"