summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am5
-rw-r--r--Makefile.in15
-rwxr-xr-xconfigure843
-rw-r--r--configure.ac3
-rw-r--r--ldap/servers/plugins/replication/repl5.h2
-rw-r--r--ldap/servers/plugins/replication/repl5_agmt.c23
-rw-r--r--ldap/servers/plugins/replication/repl5_connection.c312
-rw-r--r--ldap/servers/slapd/proto-slap.h10
-rw-r--r--ldap/servers/slapd/slapi-plugin.h21
-rw-r--r--ldap/servers/slapd/slapi2nspr.c127
-rw-r--r--ldap/servers/slapd/ssl.c5
-rw-r--r--ldap/servers/slapd/util.c1034
-rw-r--r--m4/kerberos.m4199
13 files changed, 2247 insertions, 352 deletions
diff --git a/Makefile.am b/Makefile.am
index 57e54313..9bea4bfa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,6 +47,7 @@ SVRCORE_LINK = @svrcore_lib@ -lsvrcore
ICU_LINK = @icu_lib@ -licui18n -licuuc -licudata
NETSNMP_LINK = @netsnmp_lib@ @netsnmp_link@
PAM_LINK = -lpam
+KERBEROS_LINK = $(kerberos_lib)
LIBSOCKET=@LIBSOCKET@
LIBNSL=@LIBNSL@
@@ -534,12 +535,12 @@ libslapd_la_SOURCES = ldap/servers/slapd/add.c \
ldap/servers/slapd/vattr.c \
$(libavl_a_SOURCES)
+libslapd_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @sasl_inc@ @db_inc@ @svrcore_inc@ @kerberos_inc@
if SOLARIS
libslapd_la_SOURCES += ldap/servers/slapd/slapi_counter_sunos_sparcv9.S
endif
-libslapd_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @db_inc@ @svrcore_inc@
-libslapd_la_LIBADD = $(LDAPSDK_LINK) $(SASL_LINK) $(SVRCORE_LINK) $(NSS_LINK) $(NSPR_LINK)
+libslapd_la_LIBADD = $(LDAPSDK_LINK) $(SASL_LINK) $(SVRCORE_LINK) $(NSS_LINK) $(NSPR_LINK) $(KERBEROS_LINK)
#////////////////////////////////////////////////////////////////
diff --git a/Makefile.in b/Makefile.in
index 56832256..a85060a9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -59,7 +59,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/fhs.m4 $(top_srcdir)/m4/nspr.m4 \
$(top_srcdir)/m4/nss.m4 $(top_srcdir)/m4/mozldap.m4 \
$(top_srcdir)/m4/db.m4 $(top_srcdir)/m4/sasl.m4 \
$(top_srcdir)/m4/svrcore.m4 $(top_srcdir)/m4/icu.m4 \
- $(top_srcdir)/m4/netsnmp.m4 $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/netsnmp.m4 $(top_srcdir)/m4/kerberos.m4 \
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@@ -434,9 +435,10 @@ libschemareload_plugin_la_LIBADD =
am_libschemareload_plugin_la_OBJECTS = ldap/servers/plugins/schema_reload/libschemareload_plugin_la-schema_reload.lo
libschemareload_plugin_la_OBJECTS = \
$(am_libschemareload_plugin_la_OBJECTS)
+am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
libslapd_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am__libslapd_la_SOURCES_DIST = ldap/servers/slapd/add.c \
ldap/servers/slapd/agtmmap.c ldap/servers/slapd/apibroker.c \
ldap/servers/slapd/attr.c ldap/servers/slapd/attrlist.c \
@@ -905,6 +907,7 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KRB5_CONFIG_BIN = @KRB5_CONFIG_BIN@
LDFLAGS = @LDFLAGS@
LIBCRUN = @LIBCRUN@
LIBCSTD = @LIBCSTD@
@@ -1007,6 +1010,9 @@ initconfigdir = $(sysconfdir)@initconfigdir@
initdir = $(sysconfdir)@initdir@
install_sh = @install_sh@
instconfigdir = @instconfigdir@
+kerberos_inc = @kerberos_inc@
+kerberos_lib = @kerberos_lib@
+kerberos_libdir = @kerberos_libdir@
ldapsdk_bindir = @ldapsdk_bindir@
ldapsdk_inc = @ldapsdk_inc@
ldapsdk_lib = @ldapsdk_lib@
@@ -1098,6 +1104,7 @@ SVRCORE_LINK = @svrcore_lib@ -lsvrcore
ICU_LINK = @icu_lib@ -licui18n -licuuc -licudata
NETSNMP_LINK = @netsnmp_lib@ @netsnmp_link@
PAM_LINK = -lpam
+KERBEROS_LINK = $(kerberos_lib)
#------------------------
# Generated Sources
@@ -1488,8 +1495,8 @@ libslapd_la_SOURCES = ldap/servers/slapd/add.c \
ldap/servers/slapd/uuid.c ldap/servers/slapd/value.c \
ldap/servers/slapd/valueset.c ldap/servers/slapd/vattr.c \
$(libavl_a_SOURCES) $(am__append_1)
-libslapd_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @db_inc@ @svrcore_inc@
-libslapd_la_LIBADD = $(LDAPSDK_LINK) $(SASL_LINK) $(SVRCORE_LINK) $(NSS_LINK) $(NSPR_LINK)
+libslapd_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) @sasl_inc@ @db_inc@ @svrcore_inc@ @kerberos_inc@
+libslapd_la_LIBADD = $(LDAPSDK_LINK) $(SASL_LINK) $(SVRCORE_LINK) $(NSS_LINK) $(NSPR_LINK) $(KERBEROS_LINK)
#////////////////////////////////////////////////////////////////
#
diff --git a/configure b/configure
index 9b8bd2fe..8c3377ad 100755
--- a/configure
+++ b/configure
@@ -465,7 +465,7 @@ ac_includes_default="\
#endif"
ac_default_prefix=/opt/$PACKAGE_NAME
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT build build_cpu build_vendor build_os host host_cpu host_vendor host_os CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CC CFLAGS ac_ct_CC CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CCAS CCASFLAGS SED EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBOBJS debug_defs BUNDLE_TRUE BUNDLE_FALSE enable_pam_passthru_TRUE enable_pam_passthru_FALSE enable_dna_TRUE enable_dna_FALSE enable_ldapi_TRUE enable_ldapi_FALSE enable_autobind_TRUE enable_autobind_FALSE enable_auto_dn_suffix_TRUE enable_auto_dn_suffix_FALSE enable_bitwise_TRUE enable_bitwise_FALSE with_fhs_opt configdir sampledatadir propertydir schemadir serverdir serverplugindir scripttemplatedir perldir infdir mibdir defaultuser defaultgroup instconfigdir WINNT_TRUE WINNT_FALSE LIBSOCKET LIBNSL LIBDL LIBCSTD LIBCRUN initdir perlexec initconfigdir HPUX_TRUE HPUX_FALSE SOLARIS_TRUE SOLARIS_FALSE PKG_CONFIG ICU_CONFIG NETSNMP_CONFIG PACKAGE_BASE_VERSION nspr_inc nspr_lib nspr_libdir nss_inc nss_lib nss_libdir ldapsdk_inc ldapsdk_lib ldapsdk_libdir ldapsdk_bindir db_inc db_incdir db_lib db_libdir db_bindir db_libver sasl_inc sasl_lib sasl_libdir sasl_path svrcore_inc svrcore_lib icu_lib icu_inc icu_bin netsnmp_inc netsnmp_lib netsnmp_libdir netsnmp_link brand capbrand vendor LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT build build_cpu build_vendor build_os host host_cpu host_vendor host_os CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CC CFLAGS ac_ct_CC CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CCAS CCASFLAGS SED EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL LIBOBJS debug_defs BUNDLE_TRUE BUNDLE_FALSE enable_pam_passthru_TRUE enable_pam_passthru_FALSE enable_dna_TRUE enable_dna_FALSE enable_ldapi_TRUE enable_ldapi_FALSE enable_autobind_TRUE enable_autobind_FALSE enable_auto_dn_suffix_TRUE enable_auto_dn_suffix_FALSE enable_bitwise_TRUE enable_bitwise_FALSE with_fhs_opt configdir sampledatadir propertydir schemadir serverdir serverplugindir scripttemplatedir perldir infdir mibdir defaultuser defaultgroup instconfigdir WINNT_TRUE WINNT_FALSE LIBSOCKET LIBNSL LIBDL LIBCSTD LIBCRUN initdir perlexec initconfigdir HPUX_TRUE HPUX_FALSE SOLARIS_TRUE SOLARIS_FALSE PKG_CONFIG ICU_CONFIG NETSNMP_CONFIG KRB5_CONFIG_BIN kerberos_inc kerberos_lib kerberos_libdir PACKAGE_BASE_VERSION nspr_inc nspr_lib nspr_libdir nss_inc nss_lib nss_libdir ldapsdk_inc ldapsdk_lib ldapsdk_libdir ldapsdk_bindir db_inc db_incdir db_lib db_libdir db_bindir db_libver sasl_inc sasl_lib sasl_libdir sasl_path svrcore_inc svrcore_lib icu_lib icu_inc icu_bin netsnmp_inc netsnmp_lib netsnmp_libdir netsnmp_link brand capbrand vendor LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@@ -1099,6 +1099,25 @@ Optional Packages:
--with-netsnmp=PATH Net-SNMP directory
--with-netsnmp-inc=PATH Net-SNMP include directory
--with-netsnmp-lib=PATH Net-SNMP library directory
+ --with-kerberos=PATH Use the kerberos API in the server directly - allows
+ the server to authenticate directly with a keytab -
+ otherwise, SASL/GSSAPI auth depends on underlying
+ SASL libraries and external kinit with a keytab - if
+ PATH is not specified, look for kerberos in the
+ system locations. This will attempt to use
+ krb5-config from the PATH to find the libs and
+ include dirs - you can specify KRB5_CONFIG_BIN to
+ specify a different filename or absolute path. If
+ krb5-config does not work, this will attempt to look
+ in various system directories
+ --with-kerberos-inc=PATH
+ Allows you to explicitly set the directory
+ containing the kerberos include files - implies use
+ of kerberos
+ --with-kerberos-lib=PATH
+ Allows you to explicitly set the directory
+ containing the kerberos libraries - implies use of
+ kerberos
Some influential environment variables:
CXX C++ compiler command
@@ -4333,7 +4352,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 4336 "configure"' > conftest.$ac_ext
+ echo '#line 4355 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -5468,7 +5487,7 @@ fi
# Provide some information about the compiler.
-echo "$as_me:5471:" \
+echo "$as_me:5490:" \
"checking for Fortran 77 compiler version" >&5
ac_compiler=`set X $ac_compile; echo $2`
{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -6531,11 +6550,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6534: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6553: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6538: \$? = $ac_status" >&5
+ echo "$as_me:6557: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -6799,11 +6818,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6802: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6821: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6806: \$? = $ac_status" >&5
+ echo "$as_me:6825: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -6903,11 +6922,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6906: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6925: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:6910: \$? = $ac_status" >&5
+ echo "$as_me:6929: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -8372,7 +8391,7 @@ linux*)
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 8375 "configure"' > conftest.$ac_ext
+ echo '#line 8394 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -9269,7 +9288,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 9272 "configure"
+#line 9291 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9369,7 +9388,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 9372 "configure"
+#line 9391 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11712,11 +11731,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:11715: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:11734: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:11719: \$? = $ac_status" >&5
+ echo "$as_me:11738: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -11816,11 +11835,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:11819: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:11838: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:11823: \$? = $ac_status" >&5
+ echo "$as_me:11842: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -12352,7 +12371,7 @@ linux*)
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 12355 "configure"' > conftest.$ac_ext
+ echo '#line 12374 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -13410,11 +13429,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13413: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13432: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:13417: \$? = $ac_status" >&5
+ echo "$as_me:13436: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -13514,11 +13533,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13517: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13536: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:13521: \$? = $ac_status" >&5
+ echo "$as_me:13540: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -14963,7 +14982,7 @@ linux*)
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 14966 "configure"' > conftest.$ac_ext
+ echo '#line 14985 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -15741,11 +15760,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:15744: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:15763: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:15748: \$? = $ac_status" >&5
+ echo "$as_me:15767: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -16009,11 +16028,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16012: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16031: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:16016: \$? = $ac_status" >&5
+ echo "$as_me:16035: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -16113,11 +16132,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:16116: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16135: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:16120: \$? = $ac_status" >&5
+ echo "$as_me:16139: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -17582,7 +17601,7 @@ linux*)
libsuff=
case "$host_cpu" in
x86_64*|s390x*|powerpc64*)
- echo '#line 17585 "configure"' > conftest.$ac_ext
+ echo '#line 17604 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -23325,10 +23344,14 @@ echo "$as_me: error: Please specify a full path with --with-instconfigdir" >&2;}
{ (exit 1); exit 1; }; }
fi
instconfigdir="$withval"
+ echo "$as_me:$LINENO: result: $withval" >&5
+echo "${ECHO_T}$withval" >&6
else
instconfigdir='$(sysconfdir)/$(PACKAGE_NAME)'
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
fi;
@@ -25542,6 +25565,764 @@ echo "$as_me: error: Net-SNMP not found, specify with --with-netsnmp." >&2;}
{ (exit 1); exit 1; }; }
fi
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2008 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# END COPYRIGHT BLOCK
+# -*- tab-width: 4; -*-
+# Configure paths for Kerberos
+
+{ echo "$as_me:$LINENO: checking for kerberos..." >&5
+echo "$as_me: checking for kerberos..." >&6;}
+
+if test -z "$with_kerberos" ; then
+ with_kerberos=yes # if not set on cmdline, set default
+fi
+
+echo "$as_me:$LINENO: checking for --with-kerberos" >&5
+echo $ECHO_N "checking for --with-kerberos... $ECHO_C" >&6
+
+# Check whether --with-kerberos or --without-kerberos was given.
+if test "${with_kerberos+set}" = set; then
+ withval="$with_kerberos"
+
+ if test "x$withval" = "xyes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ elif test "x$withval" = "xno"; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ with_kerberos=
+ elif test -d "$withval" -a -d "$withval/lib" -a -d "$withval/include" ; then
+ echo "$as_me:$LINENO: result: using $withval" >&5
+echo "${ECHO_T}using $withval" >&6
+ kerberos_incdir="$withval/include"
+ kerberos_libdir="$withval/lib"
+ else
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ { { echo "$as_me:$LINENO: error: kerberos not found in $withval" >&5
+echo "$as_me: error: kerberos not found in $withval" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+else
+
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ with_kerberos=
+
+
+fi;
+
+echo "$as_me:$LINENO: checking for --with-kerberos-inc" >&5
+echo $ECHO_N "checking for --with-kerberos-inc... $ECHO_C" >&6
+
+# Check whether --with-kerberos-inc or --without-kerberos-inc was given.
+if test "${with_kerberos_inc+set}" = set; then
+ withval="$with_kerberos_inc"
+
+ if test -f "$withval"/krb5.h; then
+ echo "$as_me:$LINENO: result: using $withval" >&5
+echo "${ECHO_T}using $withval" >&6
+ kerberos_incdir="$withval"
+ with_kerberos=yes # implies use of kerberos
+ else
+ echo
+ { { echo "$as_me:$LINENO: error: $withval/krb5.h not found" >&5
+echo "$as_me: error: $withval/krb5.h not found" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+fi;
+
+echo "$as_me:$LINENO: checking for --with-kerberos-lib" >&5
+echo $ECHO_N "checking for --with-kerberos-lib... $ECHO_C" >&6
+
+# Check whether --with-kerberos-lib or --without-kerberos-lib was given.
+if test "${with_kerberos_lib+set}" = set; then
+ withval="$with_kerberos_lib"
+
+ if test -d "$withval"; then
+ echo "$as_me:$LINENO: result: using $withval" >&5
+echo "${ECHO_T}using $withval" >&6
+ kerberos_libdir="$withval"
+ with_kerberos=yes # implies use of kerberos
+ else
+ echo
+ { { echo "$as_me:$LINENO: error: $withval not found" >&5
+echo "$as_me: error: $withval not found" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+fi;
+
+if test -n "$with_kerberos" ; then
+ if test -z "$kerberos_incdir" -o -z "$kerberos_libdir" ; then
+ if test -z "$KRB5_CONFIG_BIN" ; then
+ # Extract the first word of "krb5-config", so it can be a program name with args.
+set dummy krb5-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_KRB5_CONFIG_BIN+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $KRB5_CONFIG_BIN in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_KRB5_CONFIG_BIN="$KRB5_CONFIG_BIN" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_KRB5_CONFIG_BIN="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+KRB5_CONFIG_BIN=$ac_cv_path_KRB5_CONFIG_BIN
+
+if test -n "$KRB5_CONFIG_BIN"; then
+ echo "$as_me:$LINENO: result: $KRB5_CONFIG_BIN" >&5
+echo "${ECHO_T}$KRB5_CONFIG_BIN" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ fi
+ if test -n "$KRB5_CONFIG_BIN" ; then
+ echo "$as_me:$LINENO: checking for kerberos with $KRB5_CONFIG_BIN" >&5
+echo $ECHO_N "checking for kerberos with $KRB5_CONFIG_BIN... $ECHO_C" >&6
+ if test -z "$kerberos_libdir" ; then
+ kerberos_lib=`$KRB5_CONFIG_BIN --libs krb5`
+ fi
+ if test -z "$kerberos_incdir" ; then
+ kerberos_inc=`$KRB5_CONFIG_BIN --cflags krb5`
+ fi
+ if test -n "$kerberos_lib" ; then
+ echo "$as_me:$LINENO: result: using kerberos found with $KRB5_CONFIG_BIN" >&5
+echo "${ECHO_T}using kerberos found with $KRB5_CONFIG_BIN" >&6
+ have_krb5=yes
+ fi
+ fi
+ fi
+fi
+
+if test -n "$with_kerberos" -a -z "$kerberos_lib" ; then
+ # save these in order to set them to use the check macros below
+ # like AC_CHECK_HEADERS, AC_CHECK_LIB, and AC_CHECK_FUNCS
+ save_CPPFLAGS="$CPPFLAGS"
+ if test -n "$kerberos_incdir" ; then
+ CPPFLAGS="-I$kerberos_incdir $CPPFLAGS"
+ fi
+ save_LDFLAGS="$LDFLAGS"
+ if test -n "$kerberos_libdir" ; then
+ LDFLAGS="-L$kerberos_libdir $LDFLAGS"
+ fi
+ krb5_impl=mit
+
+
+for ac_header in heim_err.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to http://bugzilla.redhat.com/ ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ if test $ac_cv_header_heim_err_h = yes ; then
+ krb5_impl=heimdal
+ fi
+
+ if test "x$krb5_impl" = "xmit"; then
+ echo "$as_me:$LINENO: checking for main in -lk5crypto" >&5
+echo $ECHO_N "checking for main in -lk5crypto... $ECHO_C" >&6
+if test "${ac_cv_lib_k5crypto_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lk5crypto $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_k5crypto_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_k5crypto_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_k5crypto_main" >&5
+echo "${ECHO_T}$ac_cv_lib_k5crypto_main" >&6
+if test $ac_cv_lib_k5crypto_main = yes; then
+ krb5crypto=k5crypto
+else
+ krb5crypto=crypto
+fi
+
+
+ echo "$as_me:$LINENO: checking for main in -lkrb5" >&5
+echo $ECHO_N "checking for main in -lkrb5... $ECHO_C" >&6
+if test "${ac_cv_lib_krb5_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkrb5 -l$krb5crypto -lcom_err $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_krb5_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_krb5_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_krb5_main" >&5
+echo "${ECHO_T}$ac_cv_lib_krb5_main" >&6
+if test $ac_cv_lib_krb5_main = yes; then
+ have_krb5=yes
+ kerberos_lib="-lkrb5 -l$krb5crypto -lcom_err"
+else
+ have_krb5=no
+fi
+
+
+ elif test "x$krb5_impl" = "xheimdal"; then
+ echo "$as_me:$LINENO: checking for main in -ldes" >&5
+echo $ECHO_N "checking for main in -ldes... $ECHO_C" >&6
+if test "${ac_cv_lib_des_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldes $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_des_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_des_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_des_main" >&5
+echo "${ECHO_T}$ac_cv_lib_des_main" >&6
+if test $ac_cv_lib_des_main = yes; then
+ krb5crypto=des
+else
+ krb5crypto=crypto
+fi
+
+
+ echo "$as_me:$LINENO: checking for main in -lkrb5" >&5
+echo $ECHO_N "checking for main in -lkrb5... $ECHO_C" >&6
+if test "${ac_cv_lib_krb5_main+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkrb5 -l$krb5crypto -lasn1 -lroken -lcom_err $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+main ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_krb5_main=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_krb5_main=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_krb5_main" >&5
+echo "${ECHO_T}$ac_cv_lib_krb5_main" >&6
+if test $ac_cv_lib_krb5_main = yes; then
+ have_krb5=yes
+ kerberos_lib="-lkrb5 -l$krb5crypto -lasn1 -lroken -lcom_err"
+else
+ have_krb5=no
+fi
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_HEIMDAL_KERBEROS 1
+_ACEOF
+
+
+ else
+ have_krb5=no
+ { echo "$as_me:$LINENO: WARNING: Unrecognized Kerberos5 Implementation" >&5
+echo "$as_me: WARNING: Unrecognized Kerberos5 Implementation" >&2;}
+ fi
+
+ # reset to original values
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ if test -n "$kerberos_incdir" ; then
+ kerberos_inc="-I$kerberos_incdir"
+ fi
+ if test -n "$kerberos_libdir" ; then
+ kerberos_lib="-L$kerberos_libdir $kerberos_lib"
+ fi
+fi
+
+
+if test -n "$with_kerberos" ; then
+ if test "x$have_krb5" = "xyes" ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_KRB5 1
+_ACEOF
+
+ else
+ { { echo "$as_me:$LINENO: error: Required Kerberos 5 support not available" >&5
+echo "$as_me: error: Required Kerberos 5 support not available" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ save_LIBS="$LIBS"
+ LIBS="$kerberos_lib"
+ save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$kerberos_inc $CPPFLAGS"
+
+for ac_func in krb5_cc_new_unique
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+ LIBS="$save_LIBS"
+ CPPFLAGS="$save_CPPFLAGS"
+fi
+
+
+
+
+
PACKAGE_BASE_VERSION=`echo $PACKAGE_VERSION | awk -F\. '{print $1"."$2}'`
@@ -26463,6 +27244,10 @@ s,@SOLARIS_FALSE@,$SOLARIS_FALSE,;t t
s,@PKG_CONFIG@,$PKG_CONFIG,;t t
s,@ICU_CONFIG@,$ICU_CONFIG,;t t
s,@NETSNMP_CONFIG@,$NETSNMP_CONFIG,;t t
+s,@KRB5_CONFIG_BIN@,$KRB5_CONFIG_BIN,;t t
+s,@kerberos_inc@,$kerberos_inc,;t t
+s,@kerberos_lib@,$kerberos_lib,;t t
+s,@kerberos_libdir@,$kerberos_libdir,;t t
s,@PACKAGE_BASE_VERSION@,$PACKAGE_BASE_VERSION,;t t
s,@nspr_inc@,$nspr_inc,;t t
s,@nspr_lib@,$nspr_lib,;t t
diff --git a/configure.ac b/configure.ac
index fc8d7246..35ce2334 100644
--- a/configure.ac
+++ b/configure.ac
@@ -271,10 +271,12 @@ AC_ARG_WITH(instconfigdir,
AC_ERROR([Please specify a full path with --with-instconfigdir])
fi
instconfigdir="$withval"
+ AC_MSG_RESULT($withval)
],
[
dnl this value is expanded out in Makefile.am
instconfigdir='$(sysconfdir)/$(PACKAGE_NAME)'
+ AC_MSG_RESULT(no)
])
AC_SUBST(instconfigdir)
@@ -422,6 +424,7 @@ m4_include(m4/sasl.m4)
m4_include(m4/svrcore.m4)
m4_include(m4/icu.m4)
m4_include(m4/netsnmp.m4)
+m4_include(m4/kerberos.m4)
PACKAGE_BASE_VERSION=`echo $PACKAGE_VERSION | awk -F\. '{print $1"."$2}'`
AC_SUBST(PACKAGE_BASE_VERSION)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 86834e8b..47526793 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -256,6 +256,8 @@ typedef struct repl5agmt Repl_Agmt;
#define TRANSPORT_FLAG_TLS 2
#define BINDMETHOD_SIMPLE_AUTH 1
#define BINDMETHOD_SSL_CLIENTAUTH 2
+#define BINDMETHOD_SASL_GSSAPI 3
+#define BINDMETHOD_SASL_DIGEST_MD5 4
Repl_Agmt *agmt_new_from_entry(Slapi_Entry *e);
Repl_Agmt *agmt_new_from_pblock(Slapi_PBlock *pb);
void agmt_delete(void **ra);
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index a6314498..ceb3e43f 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -87,7 +87,6 @@
#include "slapi-plugin.h"
#define DEFAULT_TIMEOUT 600 /* (seconds) default outbound LDAP connection */
-#define TRANSPORT_FLAG_SSL 1
#define STATUS_LEN 1024
struct changecounter {
@@ -1223,6 +1222,14 @@ agmt_set_bind_method_no_lock(Repl_Agmt *ra, const Slapi_Entry *e)
{
ra->bindmethod = BINDMETHOD_SSL_CLIENTAUTH;
}
+ else if (strcasecmp(tmpstr, "SASL/GSSAPI") == 0)
+ {
+ ra->bindmethod = BINDMETHOD_SASL_GSSAPI;
+ }
+ else if (strcasecmp(tmpstr, "SASL/DIGEST-MD5") == 0)
+ {
+ ra->bindmethod = BINDMETHOD_SASL_DIGEST_MD5;
+ }
else
{
ra->bindmethod = BINDMETHOD_SIMPLE_AUTH;
@@ -1261,14 +1268,16 @@ agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry *e)
int rc = 0;
tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5TransportInfo);
- if (NULL != tmpstr && strcasecmp(tmpstr, "SSL") == 0)
- {
- ra->transport_flags |= TRANSPORT_FLAG_SSL;
- } else {
- ra->transport_flags &= ~TRANSPORT_FLAG_SSL;
+ if (!tmpstr || !strcasecmp(tmpstr, "LDAP")) {
+ ra->transport_flags = 0;
+ } else if (strcasecmp(tmpstr, "SSL") == 0) {
+ ra->transport_flags = TRANSPORT_FLAG_SSL;
+ } else if (strcasecmp(tmpstr, "TLS") == 0) {
+ ra->transport_flags = TRANSPORT_FLAG_TLS;
}
+ /* else do nothing - invalid value is a no-op */
- slapi_ch_free((void **)&tmpstr);
+ slapi_ch_free_string(&tmpstr);
return (rc);
}
diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c
index a8aecafe..d36a58d2 100644
--- a/ldap/servers/plugins/replication/repl5_connection.c
+++ b/ldap/servers/plugins/replication/repl5_connection.c
@@ -93,7 +93,6 @@ static LDAPControl manageDSAITControl = {LDAP_CONTROL_MANAGEDSAIT, {0, ""}, '\0'
static int attribute_string_value_present(LDAP *ld, LDAPMessage *entry,
const char *type, const char *value);
static int bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password);
-static int do_simple_bind (Repl_Connection *conn, LDAP *ld, char * binddn, char *password);
static int s_debug_timeout = 0;
static int s_debug_level = 0;
@@ -445,6 +444,80 @@ conn_read_result(Repl_Connection *conn, int *message_id)
return conn_read_result_ex(conn,NULL,NULL,NULL,message_id,1);
}
+/* Because the SDK isn't really thread-safe (it can deadlock between
+ * a thread sending an operation and a thread trying to retrieve a response
+ * on the same connection), we need to _first_ verify that the connection
+ * is writable. If it isn't, we can deadlock if we proceed any further...
+ */
+/* Since we're poking around with ldap c sdk internals, we have to
+ be careful since the PR layer stores different session and socket
+ info than the NSS SSL layer than the SASL layer - and they all
+ use different poll functions too
+*/
+static ConnResult
+see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout)
+{
+ LDAP_X_PollFD pollstr;
+ int nfds = 1;
+ struct ldap_x_ext_io_fns iofns;
+ int rc = LDAP_SUCCESS;
+ LDAP_X_EXTIOF_POLL_CALLBACK *ldap_poll;
+ struct lextiof_session_private *private;
+
+ /* get the poll function to use */
+ memset(&iofns, 0, sizeof(iofns));
+ iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
+ if (ldap_get_option(conn->ld, LDAP_X_OPT_EXTIO_FN_PTRS, &iofns) < 0) {
+ rc = ldap_get_lderrno(conn->ld, NULL, NULL);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: Failed call to ldap_get_option to get extiofns in "
+ "see_if_write_available: LDAP error %d (%s)\n",
+ agmt_get_long_name(conn->agmt),
+ rc, ldap_err2string(rc));
+ conn->last_ldap_error = rc;
+ return CONN_OPERATION_FAILED;
+ }
+ ldap_poll = iofns.lextiof_poll;
+
+ /* set up the poll structure */
+ if (ldap_get_option(conn->ld, LDAP_OPT_DESC, &pollstr.lpoll_fd) < 0) {
+ rc = ldap_get_lderrno(conn->ld, NULL, NULL);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: Failed call to ldap_get_option for poll_fd in "
+ "see_if_write_available: LDAP error %d (%s)\n",
+ agmt_get_long_name(conn->agmt),
+ rc, ldap_err2string(rc));
+ conn->last_ldap_error = rc;
+ return CONN_OPERATION_FAILED;
+ }
+
+ if (ldap_get_option(conn->ld, LDAP_X_OPT_SOCKETARG,
+ &pollstr.lpoll_socketarg) < 0) {
+ rc = ldap_get_lderrno(conn->ld, NULL, NULL);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: Failed call to ldap_get_option for socketarg in "
+ "see_if_write_available: LDAP error %d (%s)\n",
+ agmt_get_long_name(conn->agmt),
+ rc, ldap_err2string(rc));
+ conn->last_ldap_error = rc;
+ return CONN_OPERATION_FAILED;
+ }
+
+ pollstr.lpoll_events = LDAP_X_POLLOUT;
+ pollstr.lpoll_revents = 0;
+ private = iofns.lextiof_session_arg;
+
+ if (0 == (*ldap_poll)(&pollstr, nfds, timeout, private)) {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "%s: poll timed out - poll interval [%d]\n",
+ agmt_get_long_name(conn->agmt),
+ timeout);
+ return CONN_TIMEOUT;
+ }
+
+ return CONN_OPERATION_SUCCESS;
+}
+
/*
* Common code to send an LDAPv3 operation and collect the result.
* Return values:
@@ -483,54 +556,11 @@ perform_operation(Repl_Connection *conn, int optype, const char *dn,
Slapi_Eq_Context eqctx = repl5_start_debug_timeout(&setlevel);
- /* Because the SDK isn't really thread-safe (it can deadlock between
- * a thread sending an operation and a thread trying to retrieve a response
- * on the same connection), we need to _first_ verify that the connection
- * is writable. If it isn't, we can deadlock if we proceed any further...
- */
- {
- struct PRPollDesc pr_pd;
- PRIntervalTime timeout = PR_SecondsToInterval(conn->timeout.tv_sec);
- PRFileDesc *prfd = NULL;
- struct lextiof_socket_private *socketargp = NULL;
- PRLDAPSocketInfo soi;
-
- if ( (rc = ldap_get_option(conn->ld, LDAP_X_OPT_SOCKETARG, &socketargp)) != LDAP_SUCCESS)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Failed call to ldap_get_option in perform_operation: LDAP error %d (%s)\n",
- agmt_get_long_name(conn->agmt),
- op_string ? op_string : "NULL", rc, ldap_err2string(rc));
- conn->last_ldap_error = rc;
- return CONN_OPERATION_FAILED;
- }
- memset( &soi, 0, sizeof(soi));
- soi.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
- if (LDAP_SUCCESS != (rc = prldap_get_socket_info(0, socketargp, &soi)))
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Failed call to prldap_get_socket_info in perform_operation: LDAP error %d (%s)\n",
- agmt_get_long_name(conn->agmt),
- op_string ? op_string : "NULL", rc, ldap_err2string(rc));
- conn->last_ldap_error = rc;
- return CONN_OPERATION_FAILED;
- }
- prfd = soi.soinfo_prfd;
- /* Before we connect, the prfd can be null */
- if (prfd)
- {
- pr_pd.fd = prfd;
- pr_pd.in_flags = PR_POLL_WRITE;
- pr_pd.out_flags = 0;
- rc = PR_Poll(&pr_pd, 1, timeout);
- /* Did we time out ? */
- if (rc == 0)
- {
- return CONN_TIMEOUT;
- }
- }
+ return_value = see_if_write_available(
+ conn, PR_SecondsToInterval(conn->timeout.tv_sec));
+ if (return_value != CONN_OPERATION_SUCCESS) {
+ return return_value;
}
-
conn->last_operation = optype;
switch (optype)
{
@@ -919,16 +949,8 @@ conn_connect(Repl_Connection *conn)
/* ugaston: if SSL has been selected in the replication agreement, SSL client
* initialisation should be done before ever trying to open any connection at all.
*/
- if (conn->transport_flags == TRANSPORT_FLAG_TLS)
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Replication secured by StartTLS not currently supported\n",
- agmt_get_long_name(conn->agmt));
-
- return_value = CONN_OPERATION_FAILED;
- conn->last_ldap_error = LDAP_STRONG_AUTH_NOT_SUPPORTED;
- conn->state = STATE_DISCONNECTED;
- } else if(conn->transport_flags == TRANSPORT_FLAG_SSL)
+ if ((conn->transport_flags == TRANSPORT_FLAG_TLS) ||
+ (conn->transport_flags == TRANSPORT_FLAG_SSL))
{
/** Make sure the SSL Library has been initialized before anything else **/
@@ -942,9 +964,12 @@ conn_connect(Repl_Connection *conn)
ber_bvfree(creds);
creds = NULL;
return CONN_SSL_NOT_ENABLED;
- } else
+ } else if (conn->transport_flags == TRANSPORT_FLAG_SSL)
{
secure = 1;
+ } else
+ {
+ secure = 2; /* 2 means starttls security */
}
}
@@ -953,11 +978,12 @@ conn_connect(Repl_Connection *conn)
/* Now we initialize the LDAP Structure and set options */
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "%s: Trying %s slapi_ldap_init\n",
+ "%s: Trying %s%s slapi_ldap_init_ext\n",
agmt_get_long_name(conn->agmt),
- secure ? "secure" : "non-secure");
+ secure ? "secure" : "non-secure",
+ (secure == 2) ? " startTLS" : "");
/* shared = 1 because we will read results from a second thread */
- conn->ld = slapi_ldap_init(conn->hostname, conn->port, secure, 1);
+ conn->ld = slapi_ldap_init_ext(NULL, conn->hostname, conn->port, secure, 1, NULL);
if (NULL == conn->ld)
{
return_value = CONN_OPERATION_FAILED;
@@ -1501,8 +1527,28 @@ void conn_set_agmt_changed(Repl_Connection *conn)
PR_Unlock(conn->lock);
}
+static const char *
+bind_method_to_mech(int bindmethod)
+{
+ switch (bindmethod) {
+ case BINDMETHOD_SSL_CLIENTAUTH:
+ return LDAP_SASL_EXTERNAL;
+ break;
+ case BINDMETHOD_SASL_GSSAPI:
+ return "GSSAPI";
+ break;
+ case BINDMETHOD_SASL_DIGEST_MD5:
+ return "DIGEST-MD5";
+ break;
+ default: /* anything else */
+ return LDAP_SASL_SIMPLE;
+ }
+
+ return LDAP_SASL_SIMPLE;
+}
+
/*
- * Check the result of an ldap_simple_bind operation to see we it
+ * Check the result of an ldap BIND operation to see we it
* contains the expiration controls
* return: -1 error, not bound
* 0, OK bind has succeeded
@@ -1512,91 +1558,24 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
{
LDAPControl **ctrls = NULL;
- LDAPMessage *res = NULL;
- char *errmsg = NULL;
LDAP *ld = conn->ld;
- int msgid;
- int *msgidAdr = &msgid;
int rc;
+ const char *mech = bind_method_to_mech(conn->bindmethod);
- char * optype; /* ldap_simple_bind or slapd_SSL_client_bind */
-
- if ( conn->transport_flags == TRANSPORT_FLAG_SSL )
- {
- char *auth;
- optype = "ldap_sasl_bind";
-
- if ( conn->bindmethod == BINDMETHOD_SSL_CLIENTAUTH )
- {
- rc = slapd_sasl_ext_client_bind(conn->ld, &msgidAdr);
- auth = "SSL client authentication";
-
- if ( rc == LDAP_SUCCESS )
- {
- if (conn->last_ldap_error != rc)
- {
- conn->last_ldap_error = rc;
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Replication bind with %s resumed\n",
- agmt_get_long_name(conn->agmt), auth);
- }
- }
- else
- {
- /* Do not report the same error over and over again */
- if (conn->last_ldap_error != rc)
- {
- conn->last_ldap_error = rc;
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Replication bind with %s failed: LDAP error %d (%s)\n",
- agmt_get_long_name(conn->agmt), auth, rc,
- ldap_err2string(rc));
- }
+ rc = slapi_ldap_bind(conn->ld, binddn, password, mech, NULL,
+ &ctrls, NULL);
- return (CONN_OPERATION_FAILED);
- }
- }
- else
- {
- if( ( msgid = do_simple_bind( conn, ld, binddn, password ) ) == -1 )
- {
- return (CONN_OPERATION_FAILED);
- }
- }
- }
- else
+ if ( rc == LDAP_SUCCESS )
{
- optype = "ldap_simple_bind";
- if( ( msgid = do_simple_bind( conn, ld, binddn, password ) ) == -1 )
+ if (conn->last_ldap_error != rc)
{
- return (CONN_OPERATION_FAILED);
+ conn->last_ldap_error = rc;
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: Replication bind with %s auth resumed\n",
+ agmt_get_long_name(conn->agmt),
+ mech ? mech : "SIMPLE");
}
- }
-
- /* Wait for the result */
- if ( ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 )
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Received error from consumer for %s operation\n",
- agmt_get_long_name(conn->agmt), optype);
- return (CONN_OPERATION_FAILED);
- }
- /* Don't check ldap_result against 0 because, no timeout is specified */
-
- /* Free res as we won't use it any longer */
- if ( ldap_parse_result( ld, res, &rc, NULL, NULL, NULL, &ctrls, 1 /* Free res */)
- != LDAP_SUCCESS )
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Received error from consumer for %s operation\n",
- agmt_get_long_name(conn->agmt), optype);
-
- return (CONN_OPERATION_FAILED);
- }
-
- if ( rc == LDAP_SUCCESS )
- {
if ( ctrls )
{
int i;
@@ -1631,50 +1610,23 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
}
else
{
- /* errmsg is a pointer directly into the ld structure - do not free */
- rc = ldap_get_lderrno( ld, NULL, &errmsg );
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Replication bind to %s on consumer failed: %d (%s)\n",
- agmt_get_long_name(conn->agmt), binddn, rc, errmsg);
-
- conn->last_ldap_error = rc; /* specific error */
- return (CONN_OPERATION_FAILED);
- }
-}
-
-static int
-do_simple_bind (Repl_Connection *conn, LDAP *ld, char * binddn, char *password)
-{
- int msgid;
-
- if( ( msgid = ldap_simple_bind( ld, binddn, password ) ) == -1 )
- {
- char *ldaperrtext = NULL;
- int ldaperr;
- int prerr = PR_GetError();
-
- ldaperr = ldap_get_lderrno( ld, NULL, &ldaperrtext );
+ ldap_controls_free( ctrls );
/* Do not report the same error over and over again */
- if (conn->last_ldap_error != ldaperr)
+ if (conn->last_ldap_error != rc)
{
- conn->last_ldap_error = ldaperr;
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Simple bind failed, "
- SLAPI_COMPONENT_NAME_LDAPSDK " error %d (%s), "
- SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
- agmt_get_long_name(conn->agmt),
- ldaperr, ldaperrtext ? ldaperrtext : ldap_err2string(ldaperr),
- prerr, slapd_pr_strerror(prerr));
+ char *errmsg = NULL;
+ conn->last_ldap_error = rc;
+ /* errmsg is a pointer directly into the ld structure - do not free */
+ rc = ldap_get_lderrno( ld, NULL, &errmsg );
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: Replication bind with %s auth failed: LDAP error %d (%s) (%s)\n",
+ agmt_get_long_name(conn->agmt),
+ mech ? mech : "SIMPLE", rc,
+ ldap_err2string(rc), errmsg);
}
+
+ return (CONN_OPERATION_FAILED);
}
- else if (conn->last_ldap_error != LDAP_SUCCESS)
- {
- conn->last_ldap_error = LDAP_SUCCESS;
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "%s: Simple bind resumed\n",
- agmt_get_long_name(conn->agmt));
- }
- return msgid;
}
void
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 0bfa98ba..61a5fe85 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -904,6 +904,7 @@ int slapd_ssl_init2(PRFileDesc **fd, int startTLS);
int slapd_security_library_is_initialized();
int slapd_ssl_listener_is_initialized();
int sasl_io_cleanup(Connection *c);
+int slapd_SSL_client_auth (LDAP* ld);
/*
* security_wrappers.c
@@ -1279,6 +1280,15 @@ int ids_sasl_init(void);
char **ids_sasl_listmech(Slapi_PBlock *pb);
void ids_sasl_check_bind(Slapi_PBlock *pb);
void ids_sasl_server_new(Connection *conn);
+int slapd_ldap_sasl_interactive_bind(
+ LDAP *ld, /* ldap connection */
+ const char *bindid, /* usually a bind DN for simple bind */
+ const char *creds, /* usually a password for simple bind */
+ const char *mech, /* name of mechanism */
+ LDAPControl **serverctrls, /* additional controls to send */
+ LDAPControl ***returnedctrls, /* returned controls */
+ int *msgidp /* pass in non-NULL for async handling */
+);
/*
* sasl_io.c
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 43e783db..12de2ff4 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -1084,6 +1084,27 @@ int slapi_notify_condvar( Slapi_CondVar *cvar, int notify_all );
*/
LDAP *slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared );
void slapi_ldap_unbind( LDAP *ld );
+LDAP *
+slapi_ldap_init_ext(
+ const char *ldapurl, /* full ldap url */
+ const char *hostname, /* can also use this to override
+ host in url */
+ int port, /* can also use this to override port in url */
+ int secure, /* 0 for ldap, 1 for ldaps, 2 for starttls -
+ override proto in url */
+ int shared, /* if true, LDAP* will be shared among multiple threads */
+ const char *filename /* for ldapi */
+);
+int
+slapi_ldap_bind(
+ LDAP *ld, /* ldap connection */
+ const char *bindid, /* usually a bind DN for simple bind */
+ const char *creds, /* usually a password for simple bind */
+ const char *mech, /* name of mechanism */
+ LDAPControl **serverctrls, /* additional controls to send */
+ LDAPControl ***returnedctrls, /* returned controls */
+ int *msgidp /* pass in non-NULL for async handling */
+);
/*
diff --git a/ldap/servers/slapd/slapi2nspr.c b/ldap/servers/slapd/slapi2nspr.c
index ebe2e451..18eebfb0 100644
--- a/ldap/servers/slapd/slapi2nspr.c
+++ b/ldap/servers/slapd/slapi2nspr.c
@@ -46,9 +46,6 @@
*/
#include "slap.h"
-#include "snmp_collator.h"
-#include <ldap_ssl.h>
-#include <ldappr.h>
#include <nspr.h>
/*
@@ -213,127 +210,3 @@ slapi_notify_condvar( Slapi_CondVar *cvar, int notify_all )
return( prrc == PR_SUCCESS ? 1 : 0 );
}
-
-#ifdef MEMPOOL_EXPERIMENTAL
-void _free_wrapper(void *ptr)
-{
- slapi_ch_free(&ptr);
-}
-#endif
-
-/*
- * Function: slapi_ldap_init()
- * Description: just like ldap_ssl_init() but also arranges for the LDAP
- * session handle returned to be safely shareable by multiple threads
- * if "shared" is non-zero.
- * Returns:
- * an LDAP session handle (NULL if some local error occurs).
- */
-LDAP *
-slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared )
-{
- LDAP *ld;
- int io_timeout_ms;
-
-
- if ( secure && slapd_SSL_client_init() != 0 ) {
- return( NULL );
- }
-
- /*
- * Leverage the libprldap layer to take care of all the NSPR integration.
- * Note that ldapssl_init() uses libprldap implicitly.
- */
-
-#ifdef MEMPOOL_EXPERIMENTAL
- {
- /*
- * slapi_ch_malloc functions need to be set to LDAP C SDK
- */
- struct ldap_memalloc_fns memalloc_fns;
- memalloc_fns.ldapmem_malloc = (LDAP_MALLOC_CALLBACK *)slapi_ch_malloc;
- memalloc_fns.ldapmem_calloc = (LDAP_CALLOC_CALLBACK *)slapi_ch_calloc;
- memalloc_fns.ldapmem_realloc = (LDAP_REALLOC_CALLBACK *)slapi_ch_realloc;
- memalloc_fns.ldapmem_free = (LDAP_FREE_CALLBACK *)_free_wrapper;
- }
- /*
- * MEMPOOL_EXPERIMENTAL:
- * These LDAP C SDK init function needs to be revisited.
- * In ldap_init called via ldapssl_init and prldap_init initializes
- * options and set default values including memalloc_fns, then it
- * initializes as sasl client by calling sasl_client_init. In
- * sasl_client_init, it creates mechlist using the malloc function
- * available at the moment which could mismatch the malloc/free functions
- * set later.
- */
-#endif
- if ( secure ) {
- ld = ldapssl_init( ldaphost, ldapport, secure );
- } else {
- ld = prldap_init( ldaphost, ldapport, shared );
- }
-
- /* Update snmp interaction table */
- if ( ld == NULL) {
- set_snmp_interaction_row( ldaphost, ldapport, -1);
- } else {
- set_snmp_interaction_row( ldaphost, ldapport, 0);
- }
-
- if ( ld != NULL ) {
- /*
- * Set the outbound LDAP I/O timeout based on the server config.
- */
- io_timeout_ms = config_get_outbound_ldap_io_timeout();
- if ( io_timeout_ms > 0 ) {
- if ( prldap_set_session_option( ld, NULL, PRLDAP_OPT_IO_MAX_TIMEOUT,
- io_timeout_ms ) != LDAP_SUCCESS ) {
- slapi_log_error( SLAPI_LOG_FATAL, "slapi_ldap_init",
- "failed: unable to set outbound I/O timeout to %dms\n",
- io_timeout_ms );
- slapi_ldap_unbind( ld );
- return( NULL );
- }
- }
-
- /*
- * Set SSL strength (server certificate validity checking).
- */
- if ( secure ) {
- int ssl_strength;
-
- if ( config_get_ssl_check_hostname()) {
- /* check hostname against name in certificate */
- ssl_strength = LDAPSSL_AUTH_CNCHECK;
- } else {
- /* verify certificate only */
- ssl_strength = LDAPSSL_AUTH_CERT;
- }
-
- if ( ldapssl_set_strength( ld, ssl_strength ) != 0 ) {
- int prerr = PR_GetError();
-
- slapi_log_error( SLAPI_LOG_FATAL, "slapi_ldap_init",
- "failed: unable to set SSL strength to %d ("
- SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
- ssl_strength, prerr, slapd_pr_strerror( prerr ));
-
- }
- }
- }
-
- return( ld );
-}
-
-
-/*
- * Function: slapi_ldap_unbind()
- * Purpose: release an LDAP session obtained from a call to slapi_ldap_init().
- */
-void
-slapi_ldap_unbind( LDAP *ld )
-{
- if ( ld != NULL ) {
- ldap_unbind( ld );
- }
-}
diff --git a/ldap/servers/slapd/ssl.c b/ldap/servers/slapd/ssl.c
index b33b0ce8..abb127f9 100644
--- a/ldap/servers/slapd/ssl.c
+++ b/ldap/servers/slapd/ssl.c
@@ -1034,8 +1034,7 @@ int slapd_ssl_init2(PRFileDesc **fd, int startTLS)
}
NSS_Init(certdbpath);
SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE);
- SSL_OptionSetDefault(SSL_ENABLE_SSLdirs
-3, PR_TRUE);
+ SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE);
s = NSS_SetDomesticPolicy();
We already do pr_init, we don't need pr_setconcurrency, we already do nss_init and the rest
@@ -1047,7 +1046,7 @@ slapd_SSL_client_init()
return 0;
}
-static int
+int
slapd_SSL_client_auth (LDAP* ld)
{
int rc = 0;
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index e51c6685..c6981449 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -54,6 +54,9 @@
#include "slap.h"
#include "prtime.h"
#include "prinrval.h"
+#include "snmp_collator.h"
+#include <ldap_ssl.h>
+#include <ldappr.h>
#define UTIL_ESCAPE_NONE 0
#define UTIL_ESCAPE_HEX 1
@@ -69,6 +72,11 @@
#define _CSEP '/'
#endif
+#ifdef HAVE_KRB5
+static void set_krb5_creds();
+#endif
+
+
static int special_np(unsigned char c)
{
if(c < 32 || c > 126) {
@@ -775,3 +783,1029 @@ slapd_comp_path(char *p0, char *p1)
slapi_ch_free_string(&norm_p1);
return rval;
}
+
+#ifdef MEMPOOL_EXPERIMENTAL
+void _free_wrapper(void *ptr)
+{
+ slapi_ch_free(&ptr);
+}
+#endif
+
+/*
+ * Function: slapi_ldap_unbind()
+ * Purpose: release an LDAP session obtained from a call to slapi_ldap_init().
+ */
+void
+slapi_ldap_unbind( LDAP *ld )
+{
+ if ( ld != NULL ) {
+ ldap_unbind( ld );
+ }
+}
+
+const char *
+slapi_urlparse_err2string( int err )
+{
+ const char *s="internal error";
+
+ switch( err ) {
+ case 0:
+ s = "no error";
+ break;
+ case LDAP_URL_ERR_NOTLDAP:
+ s = "missing ldap:// or ldaps:// or ldapi://";
+ break;
+ case LDAP_URL_ERR_NODN:
+ s = "missing suffix";
+ break;
+ case LDAP_URL_ERR_BADSCOPE:
+ s = "invalid search scope";
+ break;
+ case LDAP_URL_ERR_MEM:
+ s = "unable to allocate memory";
+ break;
+ case LDAP_URL_ERR_PARAM:
+ s = "bad parameter to an LDAP URL function";
+ break;
+ }
+
+ return( s );
+}
+
+/*
+ Perform LDAP init and return an LDAP* handle. If ldapurl is given,
+ that is used as the basis for the protocol, host, port, and whether
+ to use starttls (given on the end as ldap://..../?????starttlsOID
+ If hostname is given, LDAP or LDAPS is assumed, and this will override
+ the hostname from the ldapurl, if any. If port is > 0, this is the
+ port number to use. It will override the port in the ldapurl, if any.
+ If no port is given in port or ldapurl, the default will be used based
+ on the secure setting (389 for ldap, 636 for ldaps, 389 for starttls)
+ secure takes 1 of 3 values - 0 means regular ldap, 1 means ldaps, 2
+ means regular ldap with starttls.
+ filename is the ldapi file name - if this is given, and no other options
+ are given, ldapi is assumed.
+ */
+LDAP *
+slapi_ldap_init_ext(
+ const char *ldapurl, /* full ldap url */
+ const char *hostname, /* can also use this to override
+ host in url */
+ int port, /* can also use this to override port in url */
+ int secure, /* 0 for ldap, 1 for ldaps, 2 for starttls -
+ override proto in url */
+ int shared, /* if true, LDAP* will be shared among multiple threads */
+ const char *filename /* for ldapi */
+)
+{
+ LDAPURLDesc *ludp = NULL;
+ LDAP *ld = NULL;
+ int rc = 0;
+
+ /* if ldapurl is given, parse it */
+ if (ldapurl && ((rc = ldap_url_parse_no_defaults(ldapurl, &ludp, 0)) ||
+ !ludp)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "Could not parse given LDAP URL [%s] : error [%s]\n",
+ ldapurl ? ldapurl : "NULL",
+ slapi_urlparse_err2string(rc));
+ goto done;
+ }
+
+ /* use url host if no host given */
+ if (!hostname && ludp && ludp->lud_host) {
+ hostname = ludp->lud_host;
+ }
+
+ /* use url port if no port given */
+ if (!port && ludp && ludp->lud_port) {
+ port = ludp->lud_port;
+ }
+
+ /* use secure setting from url if none given */
+ if (!secure && ludp) {
+ if (ludp->lud_options & LDAP_URL_OPT_SECURE) {
+ secure = 1;
+ } else if (0/* starttls option - not supported yet in LDAP URLs */) {
+ secure = 2;
+ }
+ }
+
+ /* ldap_url_parse doesn't yet handle ldapi */
+ /*
+ if (!filename && ludp && ludp->lud_file) {
+ filename = ludp->lud_file;
+ }
+ */
+
+#ifdef MEMPOOL_EXPERIMENTAL
+ {
+ /*
+ * slapi_ch_malloc functions need to be set to LDAP C SDK
+ */
+ struct ldap_memalloc_fns memalloc_fns;
+ memalloc_fns.ldapmem_malloc = (LDAP_MALLOC_CALLBACK *)slapi_ch_malloc;
+ memalloc_fns.ldapmem_calloc = (LDAP_CALLOC_CALLBACK *)slapi_ch_calloc;
+ memalloc_fns.ldapmem_realloc = (LDAP_REALLOC_CALLBACK *)slapi_ch_realloc;
+ memalloc_fns.ldapmem_free = (LDAP_FREE_CALLBACK *)_free_wrapper;
+ }
+ /*
+ * MEMPOOL_EXPERIMENTAL:
+ * These LDAP C SDK init function needs to be revisited.
+ * In ldap_init called via ldapssl_init and prldap_init initializes
+ * options and set default values including memalloc_fns, then it
+ * initializes as sasl client by calling sasl_client_init. In
+ * sasl_client_init, it creates mechlist using the malloc function
+ * available at the moment which could mismatch the malloc/free functions
+ * set later.
+ */
+#endif
+ if (filename) {
+ /* ldapi in mozldap client is not yet supported */
+ } else if (secure == 1) {
+ ld = ldapssl_init(hostname, port, secure);
+ } else { /* regular ldap and/or starttls */
+ /*
+ * Leverage the libprldap layer to take care of all the NSPR
+ * integration.
+ * Note that ldapssl_init() uses libprldap implicitly.
+ */
+ ld = prldap_init(hostname, port, shared);
+ }
+
+ /* Update snmp interaction table */
+ if (hostname) {
+ if (ld == NULL) {
+ set_snmp_interaction_row((char *)hostname, port, -1);
+ } else {
+ set_snmp_interaction_row((char *)hostname, port, 0);
+ }
+ }
+
+ if ((ld != NULL) && !filename) {
+ /*
+ * Set the outbound LDAP I/O timeout based on the server config.
+ */
+ int io_timeout_ms = config_get_outbound_ldap_io_timeout();
+ if (io_timeout_ms > 0) {
+ if (prldap_set_session_option(ld, NULL, PRLDAP_OPT_IO_MAX_TIMEOUT,
+ io_timeout_ms) != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "failed: unable to set outbound I/O "
+ "timeout to %dms\n",
+ io_timeout_ms);
+ slapi_ldap_unbind(ld);
+ ld = NULL;
+ goto done;
+ }
+ }
+
+ /*
+ * Set SSL strength (server certificate validity checking).
+ */
+ if (secure > 0) {
+ int ssl_strength = 0;
+
+ if (config_get_ssl_check_hostname()) {
+ /* check hostname against name in certificate */
+ ssl_strength = LDAPSSL_AUTH_CNCHECK;
+ } else {
+ /* verify certificate only */
+ ssl_strength = LDAPSSL_AUTH_CERT;
+ }
+
+ if (ldapssl_set_strength(ld, ssl_strength) != 0) {
+ int prerr = PR_GetError();
+
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_init_ext",
+ "failed: unable to set SSL strength to %d ("
+ SLAPI_COMPONENT_NAME_NSPR " error %d - %s)",
+ ssl_strength, prerr,
+ slapd_pr_strerror(prerr));
+
+ }
+ if (secure == 1) {
+ /* tell bind code we are using SSL */
+ ldap_set_option(ld, LDAP_OPT_SSL, LDAP_OPT_ON);
+ }
+ }
+ }
+
+ if (ld && (secure == 2)) {
+ /* We don't have a way to stash context data with the LDAP*, so we
+ stash the information in the client controls (currently unused).
+ We don't want to open the connection in ldap_init, since that's
+ not the semantic - the connection is not usually opened until
+ the first operation is sent, which is usually the bind - or
+ in this case, the start_tls - so we stash the start_tls so
+ we can do it in slapi_ldap_bind - note that this will get
+ cleaned up when the LDAP* is disposed of
+ */
+ LDAPControl start_tls_dummy_ctrl;
+ LDAPControl **clientctrls = NULL;
+
+ /* returns copy of controls */
+ ldap_get_option(ld, LDAP_OPT_CLIENT_CONTROLS, &clientctrls);
+
+ start_tls_dummy_ctrl.ldctl_oid = slapi_ch_strdup(START_TLS_OID);
+ start_tls_dummy_ctrl.ldctl_value.bv_val = NULL;
+ start_tls_dummy_ctrl.ldctl_value.bv_len = 0;
+ start_tls_dummy_ctrl.ldctl_iscritical = 0;
+ slapi_add_control_ext(&clientctrls, &start_tls_dummy_ctrl, 1);
+ /* set option frees old list and copies the new list */
+ ldap_set_option(ld, LDAP_OPT_CLIENT_CONTROLS, clientctrls);
+ ldap_controls_free(clientctrls); /* free the copy */
+ }
+
+done:
+ ldap_free_urldesc(ludp);
+
+ return( ld );
+}
+
+/*
+ * Function: slapi_ldap_init()
+ * Description: just like ldap_ssl_init() but also arranges for the LDAP
+ * session handle returned to be safely shareable by multiple threads
+ * if "shared" is non-zero.
+ * Returns:
+ * an LDAP session handle (NULL if some local error occurs).
+ */
+LDAP *
+slapi_ldap_init( char *ldaphost, int ldapport, int secure, int shared )
+{
+ return slapi_ldap_init_ext(NULL, ldaphost, ldapport, secure, shared, NULL);
+}
+
+/*
+ * Does the correct bind operation simple/sasl/cert depending
+ * on the arguments passed in. If the user specified to use
+ * starttls in init, this will do the starttls first. If using
+ * ssl or client cert auth, this will initialize the client side
+ * of that.
+ */
+int
+slapi_ldap_bind(
+ LDAP *ld, /* ldap connection */
+ const char *bindid, /* usually a bind DN for simple bind */
+ const char *creds, /* usually a password for simple bind */
+ const char *mech, /* name of mechanism */
+ LDAPControl **serverctrls, /* additional controls to send */
+ LDAPControl ***returnedctrls, /* returned controls */
+ int *msgidp /* pass in non-NULL for async handling */
+)
+{
+ int rc = LDAP_SUCCESS;
+ LDAPControl **clientctrls = NULL;
+ int secure = 0;
+ struct berval bvcreds = {0, NULL};
+ LDAPMessage *result = NULL;
+ struct berval *servercredp = NULL;
+
+ /* do starttls if requested
+ NOTE - starttls is an extop, not a control, but we don't have
+ a place we can stash this information in the LDAP*, other
+ than the currently unused clientctrls */
+ ldap_get_option(ld, LDAP_OPT_CLIENT_CONTROLS, &clientctrls);
+ if (clientctrls && clientctrls[0] &&
+ slapi_control_present(clientctrls, START_TLS_OID, NULL, NULL)) {
+ secure = 2;
+ } else {
+ ldap_get_option(ld, LDAP_OPT_SSL, &secure);
+ }
+
+ if ((secure > 0) && mech && !strcmp(mech, LDAP_SASL_EXTERNAL)) {
+ /* SSL connections will use the server's security context
+ and cert for client auth */
+ rc = slapd_SSL_client_auth(ld);
+
+ if (rc != 0) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Error: could not configure the server for cert "
+ "auth - error %d - make sure the server is "
+ "correctly configured for SSL/TLS\n", rc);
+ goto done;
+ }
+ bvcreds.bv_val = NULL; /* ignore username and passed in creds */
+ bvcreds.bv_len = 0; /* for external auth */
+ bindid = NULL;
+ } else { /* other type of auth */
+ bvcreds.bv_val = (char *)creds;
+ bvcreds.bv_len = creds ? strlen(creds) : 0;
+ }
+
+ if (secure == 2) { /* send start tls */
+ rc = ldap_start_tls_s(ld, NULL /* serverctrls?? */, NULL);
+ if (LDAP_SUCCESS != rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Error: could not send startTLS request: "
+ "error %d (%s)\n",
+ rc, ldap_err2string(rc));
+ goto done;
+ }
+ }
+
+ /* The connection has been set up - now do the actual bind, depending on
+ the mechanism and arguments */
+ if (!mech || (mech == LDAP_SASL_SIMPLE) ||
+ !strcmp(mech, LDAP_SASL_EXTERNAL)) {
+ int mymsgid = 0;
+
+ if ((rc = ldap_sasl_bind(ld, bindid, mech, &bvcreds, serverctrls,
+ NULL /* clientctrls */, &mymsgid))) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Error: could not send bind request for id "
+ "[%s] mech [%s]: error %d (%s)\n",
+ bindid ? bindid : "(anon)",
+ mech ? mech : "SIMPLE",
+ rc, ldap_err2string(rc));
+ goto done;
+ }
+
+ if (msgidp) { /* let caller process result */
+ *msgidp = mymsgid;
+ } else { /* process results */
+ if (ldap_result(ld, mymsgid, LDAP_MSG_ALL,
+ (struct timeval *)0, &result) == -1) {
+ rc = ldap_get_lderrno(ld, NULL, NULL);
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Error reading bind response for id "
+ "[%s] mech [%s]: error %d (%s)\n",
+ bindid ? bindid : "(anon)",
+ mech ? mech : "SIMPLE",
+ rc, ldap_err2string(rc));
+ goto done;
+ }
+
+ /* Get the controls sent by the server if requested */
+ if (returnedctrls) {
+ if ((rc = ldap_parse_result(ld, result, &rc, NULL, NULL,
+ NULL, returnedctrls,
+ 0)) != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Error: could not bind id "
+ "[%s] mech [%s]: error %d (%s)\n",
+ bindid ? bindid : "(anon)",
+ mech ? mech : "SIMPLE",
+ rc, ldap_err2string(rc));
+ goto done;
+ }
+ }
+
+ /* parse the bind result and get the ldap error code */
+ if ((rc = ldap_parse_sasl_bind_result(ld, result, &servercredp,
+ 0)) ||
+ (rc = ldap_result2error(ld, result, 0))) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Error: could not read bind results for id "
+ "[%s] mech [%s]: error %d (%s)\n",
+ bindid ? bindid : "(anon)",
+ mech ? mech : "SIMPLE",
+ rc, ldap_err2string(rc));
+ goto done;
+ }
+ }
+ } else {
+ rc = slapd_ldap_sasl_interactive_bind(ld, bindid, creds, mech,
+ serverctrls, returnedctrls,
+ msgidp);
+ if (LDAP_SUCCESS != rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapi_ldap_bind",
+ "Error: could not perform interactive bind for id "
+ "[%s] mech [%s]: error %d (%s)\n",
+ bindid ? bindid : "(anon)",
+ mech ? mech : "SIMPLE",
+ rc, ldap_err2string(rc));
+ }
+ }
+
+done:
+ slapi_ch_bvfree(&servercredp);
+ ldap_msgfree(result);
+
+ return rc;
+}
+
+/* the following implements the client side of sasl bind, for LDAP server
+ -> LDAP server SASL */
+#include <sasl.h>
+
+typedef struct {
+ char *mech;
+ char *authid;
+ char *username;
+ char *passwd;
+ char *realm;
+} ldapSaslInteractVals;
+
+static void *
+ldap_sasl_set_interact_vals(LDAP *ld, const char *mech, const char *authid,
+ const char *username, const char *passwd,
+ const char *realm)
+{
+ ldapSaslInteractVals *vals = NULL;
+
+ vals = (ldapSaslInteractVals *)
+ slapi_ch_calloc(1, sizeof(ldapSaslInteractVals));
+
+ if (!vals) {
+ return NULL;
+ }
+
+ if (mech) {
+ vals->mech = slapi_ch_strdup(mech);
+ } else {
+ ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &vals->mech);
+ }
+
+ if (authid) { /* use explicit passed in value */
+ vals->authid = slapi_ch_strdup(authid);
+ } else { /* use option value if any */
+ ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &vals->authid);
+ if (!vals->authid) {
+/* get server user id? */
+ vals->authid = slapi_ch_strdup("");
+ }
+ }
+
+#ifdef HAVE_KRB5
+ if (mech && !strcmp(mech, "GSSAPI")) {
+ username = NULL; /* get from krb creds */
+ }
+#endif
+
+ if (username) { /* use explicit passed in value */
+ vals->username = slapi_ch_strdup(username);
+ } else { /* use option value if any */
+ ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &vals->username);
+ if (!vals->username) { /* use default sasl value */
+ vals->username = slapi_ch_strdup("");
+ }
+ }
+
+ if (passwd) {
+ vals->passwd = slapi_ch_strdup(passwd);
+ } else {
+ vals->passwd = slapi_ch_strdup("");
+ }
+
+ if (realm) {
+ vals->realm = slapi_ch_strdup(realm);
+ } else {
+ ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &vals->realm);
+ if (!vals->realm) { /* use default sasl value */
+ vals->realm = slapi_ch_strdup("");
+ }
+ }
+
+#ifdef HAVE_KRB5
+ if (mech && !strcmp(mech, "GSSAPI")) {
+ set_krb5_creds();
+ }
+#endif /* HAVE_KRB5 */
+
+ return vals;
+}
+
+static void
+ldap_sasl_free_interact_vals(void *defaults)
+{
+ ldapSaslInteractVals *vals = defaults;
+
+ if (vals) {
+ slapi_ch_free_string(&vals->mech);
+ slapi_ch_free_string(&vals->authid);
+ slapi_ch_free_string(&vals->username);
+ slapi_ch_free_string(&vals->passwd);
+ slapi_ch_free_string(&vals->realm);
+ slapi_ch_free(&defaults);
+ }
+}
+
+static int
+ldap_sasl_get_val(ldapSaslInteractVals *vals, sasl_interact_t *interact, unsigned flags)
+{
+ const char *defvalue = interact->defresult;
+ int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing */
+
+ if (vals != NULL) {
+ switch(interact->id) {
+ case SASL_CB_AUTHNAME:
+ defvalue = vals->authid;
+ slapi_log_error(authtracelevel, "ldap_sasl_get_val",
+ "Using value [%s] for SASL_CB_AUTHNAME\n",
+ defvalue ? defvalue : "(null)");
+ break;
+ case SASL_CB_USER:
+ defvalue = vals->username;
+ slapi_log_error(authtracelevel, "ldap_sasl_get_val",
+ "Using value [%s] for SASL_CB_USER\n",
+ defvalue ? defvalue : "(null)");
+ break;
+ case SASL_CB_PASS:
+ defvalue = vals->passwd;
+ slapi_log_error(authtracelevel, "ldap_sasl_get_val",
+ "Using value [%s] for SASL_CB_PASS\n",
+ defvalue ? defvalue : "(null)");
+ break;
+ case SASL_CB_GETREALM:
+ defvalue = vals->realm;
+ slapi_log_error(authtracelevel, "ldap_sasl_get_val",
+ "Using value [%s] for SASL_CB_GETREALM\n",
+ defvalue ? defvalue : "(null)");
+ break;
+ }
+ }
+
+ if (defvalue != NULL) {
+ interact->result = defvalue;
+ if ((char *)interact->result == NULL)
+ return (LDAP_NO_MEMORY);
+ interact->len = strlen((char *)(interact->result));
+ }
+ return (LDAP_SUCCESS);
+}
+
+static int
+ldap_sasl_interact_cb(LDAP *ld, unsigned flags, void *defaults, void *prompts)
+{
+ sasl_interact_t *interact = NULL;
+ ldapSaslInteractVals *sasldefaults = defaults;
+ int rc;
+
+ if (prompts == NULL) {
+ return (LDAP_PARAM_ERROR);
+ }
+
+ for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++) {
+ /* Obtain the default value */
+ if ((rc = ldap_sasl_get_val(sasldefaults, interact, flags)) != LDAP_SUCCESS) {
+ return (rc);
+ }
+ }
+
+ return (LDAP_SUCCESS);
+}
+
+int
+slapd_ldap_sasl_interactive_bind(
+ LDAP *ld, /* ldap connection */
+ const char *bindid, /* usually a bind DN for simple bind */
+ const char *creds, /* usually a password for simple bind */
+ const char *mech, /* name of mechanism */
+ LDAPControl **serverctrls, /* additional controls to send */
+ LDAPControl ***returnedctrls, /* returned controls */
+ int *msgidp /* pass in non-NULL for async handling */
+)
+{
+ int rc = LDAP_SUCCESS;
+ void *defaults = ldap_sasl_set_interact_vals(ld, mech, NULL, bindid,
+ creds, NULL);
+ /* have to first set the defaults used by the callback function */
+ /* call the bind function */
+ rc = ldap_sasl_interactive_bind_ext_s(ld, bindid, mech, serverctrls,
+ NULL, LDAP_SASL_QUIET,
+ ldap_sasl_interact_cb, defaults,
+ returnedctrls);
+ ldap_sasl_free_interact_vals(defaults);
+ if (LDAP_SUCCESS != rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, "slapd_ldap_sasl_interactive_bind",
+ "Error: could not perform interactive bind for id "
+ "[%s] mech [%s]: error %d (%s)\n",
+ bindid ? bindid : "(anon)",
+ mech ? mech : "SIMPLE",
+ rc, ldap_err2string(rc));
+ }
+
+ return rc;
+}
+
+#ifdef HAVE_KRB5
+#include <krb5.h>
+
+/* for some reason this is not in the public API?
+ but it is documented e.g. man kinit */
+#ifndef KRB5_ENV_CCNAME
+#define KRB5_ENV_CCNAME "KRB5CCNAME"
+#endif
+
+static void
+show_one_credential(int authtracelevel,
+ krb5_context ctx, krb5_creds *cred)
+{
+ char *logname = "show_one_credential";
+ krb5_error_code rc;
+ char *name = NULL, *sname = NULL;
+ char startts[BUFSIZ], endts[BUFSIZ], renewts[BUFSIZ];
+
+ if ((rc = krb5_unparse_name(ctx, cred->client, &name))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not get client name from credential: %d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+ if ((rc = krb5_unparse_name(ctx, cred->server, &sname))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not get server name from credential: %d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+ if (!cred->times.starttime) {
+ cred->times.starttime = cred->times.authtime;
+ }
+ krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.starttime,
+ startts, sizeof(startts), NULL);
+ krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.endtime,
+ endts, sizeof(endts), NULL);
+ krb5_timestamp_to_sfstring((krb5_timestamp)cred->times.renew_till,
+ renewts, sizeof(renewts), NULL);
+
+ slapi_log_error(authtracelevel, logname,
+ "\tKerberos credential: client [%s] server [%s] "
+ "start time [%s] end time [%s] renew time [%s] "
+ "flags [0x%x]\n", name, sname, startts, endts,
+ renewts, (uint32_t)cred->ticket_flags);
+
+cleanup:
+ krb5_free_unparsed_name(ctx, name);
+ krb5_free_unparsed_name(ctx, sname);
+
+ return;
+}
+
+/*
+ * Call this after storing the credentials in the cache
+ */
+static void
+show_cached_credentials(int authtracelevel,
+ krb5_context ctx, krb5_ccache cc,
+ krb5_principal princ)
+{
+ char *logname = "show_cached_credentials";
+ krb5_error_code rc = 0;
+ krb5_creds creds;
+ krb5_cc_cursor cur;
+ char *princ_name = NULL;
+
+ if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not get principal name from principal: %d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+
+ slapi_log_error(authtracelevel, logname,
+ "Ticket cache: %s:%s\nDefault principal: %s\n\n",
+ krb5_cc_get_type(ctx, cc),
+ krb5_cc_get_name(ctx, cc), princ_name);
+
+ if ((rc = krb5_cc_start_seq_get(ctx, cc, &cur))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not get cursor to iterate cached credentials: "
+ "%d (%s)\n", rc, error_message(rc));
+ goto cleanup;
+ }
+
+ while (!(rc = krb5_cc_next_cred(ctx, cc, &cur, &creds))) {
+ show_one_credential(authtracelevel, ctx, &creds);
+ krb5_free_cred_contents(ctx, &creds);
+ }
+ if (rc == KRB5_CC_END) {
+ if ((rc = krb5_cc_end_seq_get(ctx, cc, &cur))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not close cached credentials cursor: "
+ "%d (%s)\n", rc, error_message(rc));
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ krb5_free_unparsed_name(ctx, princ_name);
+
+ return;
+}
+
+/*
+ * This implementation assumes that we want to use the
+ * keytab from the default keytab env. var KRB5_KTNAME
+ * as. This code is very similar to kinit -k -t. We
+ * get a krb context, get the default keytab, get
+ * the credentials from the keytab, authenticate with
+ * those credentials, create a ccache, store the
+ * credentials in the ccache, and set the ccache
+ * env var to point to those credentials.
+ */
+static void
+set_krb5_creds()
+{
+ char *logname = "set_krb5_creds";
+ const char *cc_type = "MEMORY"; /* keep cred cache in memory */
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal princ = NULL;
+ char *princ_name = NULL;
+ krb5_error_code rc = 0;
+ krb5_error_code looprc = 0;
+ krb5_creds creds;
+ krb5_keytab kt = NULL;
+ krb5_keytab_entry ktent;
+ krb5_kt_cursor ktcur = NULL;
+ char *cc_name = NULL;
+ char ktname[MAX_KEYTAB_NAME_LEN];
+ static char cc_env_name[1024+32]; /* size from ccdefname.c */
+ int new_ccache = 0;
+ int authtracelevel = SLAPI_LOG_SHELL; /* special auth tracing
+ not sure what shell was
+ used for, does not
+ appear to be used
+ currently */
+
+ /* probably have to put a mutex around this whole thing, to avoid
+ problems with reentrancy, since we are setting a "global"
+ variable via an environment variable */
+
+ /* wipe this out so we can safely free it later if we
+ short circuit */
+ memset(&creds, 0, sizeof(creds));
+
+ /* initialize the kerberos context */
+ if ((rc = krb5_init_context(&ctx))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not init Kerberos context: %d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* see if there is already a ccache, and see if there are
+ creds in the ccache */
+ /* grab the default ccache - note: this does not open the cache */
+ if ((rc = krb5_cc_default(ctx, &cc))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not get default Kerberos ccache: %d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* use this cache - construct the full cache name */
+ cc_name = slapi_ch_smprintf("%s:%s", krb5_cc_get_type(ctx, cc),
+ krb5_cc_get_name(ctx, cc));
+
+ /* grab the principal from the ccache - will fail if there
+ is no ccache */
+ if ((rc = krb5_cc_get_principal(ctx, cc, &princ))) {
+ if (KRB5_FCC_NOFILE == rc) { /* no cache - ok */
+ slapi_log_error(authtracelevel, logname,
+ "The default credentials cache [%s] not found: "
+ "will create a new one.\n", cc_name);
+ /* close the cache - we will create a new one below */
+ krb5_cc_close(ctx, cc);
+ cc = NULL;
+ slapi_ch_free_string(&cc_name);
+ /* fall through to the keytab auth code below */
+ } else { /* fatal */
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not open default Kerberos ccache [%s]: "
+ "%d (%s)\n", cc_name, rc, error_message(rc));
+ goto cleanup;
+ }
+ } else { /* have a valid ccache && found principal */
+ if ((rc = krb5_unparse_name(ctx, princ, &princ_name))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Unable to get name of principal from ccache [%s]: "
+ "%d (%s)\n", cc_name, rc, error_message(rc));
+ goto cleanup;
+ }
+ slapi_log_error(authtracelevel, logname,
+ "Using principal [%s] from ccache [%s]\n",
+ princ_name, cc_name);
+ }
+
+ /* if this is not our type of ccache, there is nothing more we can
+ do - just punt and let sasl/gssapi take it's course - this
+ usually means there has been an external kinit e.g. in the
+ start up script, and it is the responsibility of the script to
+ renew those credentials or face lots of sasl/gssapi failures
+ This means, however, that the caller MUST MAKE SURE THERE IS NO
+ DEFAULT CCACHE FILE or the server will attempt to use it (and
+ likely fail) - THERE MUST BE NO DEFAULT CCACHE FILE IF YOU WANT
+ THE SERVER TO AUTHENTICATE WITH THE KEYTAB
+ NOTE: cc types are case sensitive and always upper case */
+ if (cc && strcmp(cc_type, krb5_cc_get_type(ctx, cc))) {
+ static int errmsgcounter = 0;
+ int loglevel = SLAPI_LOG_FATAL;
+ if (errmsgcounter) {
+ loglevel = authtracelevel;
+ }
+ /* make sure we log this message once, in case the user has
+ done something unintended, we want to make sure they know
+ about it. However, if the user knows what he/she is doing,
+ by using an external ccache file, they probably don't want
+ to be notified with an error every time. */
+ slapi_log_error(loglevel, logname,
+ "The server will use the external SASL/GSSAPI "
+ "credentials cache [%s:%s]. If you want the "
+ "server to automatically authenticate with its "
+ "keytab, you must remove this cache. If you "
+ "did not intend to use this cache, you will likely "
+ "see many SASL/GSSAPI authentication failures.\n",
+ krb5_cc_get_type(ctx, cc), krb5_cc_get_name(ctx, cc));
+ errmsgcounter++;
+ goto cleanup;
+ }
+
+ /* find our default keytab */
+ if ((rc = krb5_kt_default(ctx, &kt))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Unable to get default keytab: %d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* get name of keytab for debugging purposes */
+ if ((rc = krb5_kt_get_name(ctx, kt, ktname, sizeof(ktname)))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Unable to get name of default keytab: %d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+
+ slapi_log_error(authtracelevel, logname,
+ "Using keytab named [%s]\n", ktname);
+
+ /* if there was no cache, or no principal in the cache, we look
+ in the keytab */
+ if (!princ) {
+ /* just use the first principal in the keytab
+ "first principals, clarice"
+ */
+ if ((rc = krb5_kt_start_seq_get(ctx, kt, &ktcur))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Unable to open keytab [%s] cursor: %d (%s)\n",
+ ktname, rc, error_message(rc));
+ goto cleanup;
+ }
+
+ memset(&ktent, 0, sizeof(ktent));
+ while ((looprc = krb5_kt_next_entry(ctx, kt, &ktent, &ktcur)) == 0) {
+ if ((looprc = krb5_unparse_name(ctx, ktent.principal,
+ &princ_name))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Unable to get name from keytab [%s] "
+ "principal: %d (%s)\n", ktname, looprc,
+ error_message(looprc));
+ break;
+ }
+ /* found one - make a copy to free later */
+ if ((looprc = krb5_copy_principal(ctx, ktent.principal,
+ &princ))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Unable to copy keytab [%s] principal [%s]: "
+ "%d (%s)\n", ktname, princ_name, looprc,
+ error_message(looprc));
+ break;
+ }
+ slapi_log_error(authtracelevel, logname,
+ "Using keytab principal [%s]\n", princ_name);
+ break;
+ }
+
+ krb5_free_keytab_entry_contents(ctx, &ktent);
+ memset(&ktent, 0, sizeof(ktent));
+ if ((rc = krb5_kt_end_seq_get(ctx, kt, &ktcur))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Unable to close keytab [%s] cursor: %d (%s)\n",
+ ktname, rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* if we had an error in the loop above, just bail out
+ after closing the keytab cursor and keytab */
+ if (looprc) {
+ rc = looprc;
+ goto cleanup;
+ }
+ }
+
+ /* now do the actual kerberos authentication using
+ the keytab, and get the creds */
+ rc = krb5_get_init_creds_keytab(ctx, &creds, princ, kt,
+ 0, NULL, NULL);
+ if (rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not get initial credentials for principal [%s] "
+ "in keytab [%s]: %d (%s)\n",
+ princ_name, ktname, rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* completely done with the keytab now, close it */
+ krb5_kt_close(ctx, kt);
+ kt = NULL; /* no double free */
+
+ /* we now have the creds and the principal to which the
+ creds belong - use or allocate a new memory based
+ cache to hold the creds */
+ if (!cc_name) {
+#if HAVE_KRB5_CC_NEW_UNIQUE
+ /* krb5_cc_new_unique is a new convenience function which
+ generates a new unique name and returns a memory
+ cache with that name */
+ if ((rc = krb5_cc_new_unique(ctx, cc_type, NULL, &cc))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not create new unique memory ccache: "
+ "%d (%s)\n",
+ rc, error_message(rc));
+ goto cleanup;
+ }
+ cc_name = slapi_ch_smprintf("%s:%s", cc_type,
+ krb5_cc_get_name(ctx, cc));
+#else
+ /* store the cache in memory - krb5_init_context uses malloc
+ to create the ctx, so the address should be unique enough
+ for our purposes */
+ if (!(cc_name = slapi_ch_smprintf("%s:%p", cc_type, ctx))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could create Kerberos memory ccache: "
+ "out of memory\n");
+ rc = 1;
+ goto cleanup;
+ }
+#endif
+ slapi_log_error(authtracelevel, logname,
+ "Generated new memory ccache [%s]\n", cc_name);
+ new_ccache = 1; /* need to set this in env. */
+ } else {
+ slapi_log_error(authtracelevel, logname,
+ "Using existing ccache [%s]\n", cc_name);
+ }
+
+ /* krb5_cc_resolve is basically like an init -
+ this creates the cache structure, and creates a slot
+ for the cache in the static linked list in memory, if
+ there is not already a slot -
+ see cc_memory.c for details
+ cc could already have been created by new_unique above
+ */
+ if (!cc && (rc = krb5_cc_resolve(ctx, cc_name, &cc))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not create ccache [%s]: %d (%s)\n",
+ cc_name, rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* wipe out previous contents of cache for this principal, if any */
+ if ((rc = krb5_cc_initialize(ctx, cc, princ))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not initialize ccache [%s] for the new "
+ "credentials for principal [%s]: %d (%s)\n",
+ cc_name, princ_name, rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* store the credentials in the cache */
+ if ((rc = krb5_cc_store_cred(ctx, cc, &creds))) {
+ slapi_log_error(SLAPI_LOG_FATAL, logname,
+ "Could not store the credentials in the "
+ "ccache [%s] for principal [%s]: %d (%s)\n",
+ cc_name, princ_name, rc, error_message(rc));
+ goto cleanup;
+ }
+
+ /* now, do a "klist" to show the credential information, and log it */
+ show_cached_credentials(authtracelevel, ctx, cc, princ);
+
+ /* set the CC env var to the value of the cc cache name */
+ /* since we can't pass krb5 context up and out of here
+ and down through the ldap sasl layer, we set this
+ env var so that calls to krb5_cc_default_name will
+ use this */
+ if (new_ccache) {
+ PR_snprintf(cc_env_name, sizeof(cc_env_name),
+ "%s=%s", KRB5_ENV_CCNAME, cc_name);
+ PR_SetEnv(cc_env_name);
+ slapi_log_error(authtracelevel, logname,
+ "Set new env for ccache: [%s]\n",
+ cc_env_name);
+ }
+
+cleanup:
+ krb5_free_unparsed_name(ctx, princ_name);
+ if (kt) { /* NULL not allowed */
+ krb5_kt_close(ctx, kt);
+ }
+ if (creds.client == princ) {
+ creds.client = NULL;
+ }
+ krb5_free_cred_contents(ctx, &creds);
+ slapi_ch_free_string(&cc_name);
+ krb5_free_principal(ctx, princ);
+ if (cc) {
+ krb5_cc_close(ctx, cc);
+ }
+ if (ctx) { /* cannot pass NULL to free context */
+ krb5_free_context(ctx);
+ }
+ return;
+}
+
+#endif /* HAVE_KRB5 */
diff --git a/m4/kerberos.m4 b/m4/kerberos.m4
new file mode 100644
index 00000000..26234149
--- /dev/null
+++ b/m4/kerberos.m4
@@ -0,0 +1,199 @@
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2008 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# END COPYRIGHT BLOCK
+# -*- tab-width: 4; -*-
+# Configure paths for Kerberos
+
+dnl ========================================================
+dnl = Kerberos is used directly for server to server SASL/GSSAPI
+dnl = authentication (replication, chaining, etc.)
+dnl = This allows us to authenticate using a keytab without
+dnl = having to call kinit outside the process
+dnl ========================================================
+AC_CHECKING(for kerberos)
+
+if test -z "$with_kerberos" ; then
+ with_kerberos=yes # if not set on cmdline, set default
+fi
+
+AC_MSG_CHECKING(for --with-kerberos)
+AC_ARG_WITH(kerberos,
+ AS_HELP_STRING([--with-kerberos[=PATH]], [Use the kerberos API in the server directly - allows the server to authenticate directly with a keytab - otherwise, SASL/GSSAPI auth depends on underlying SASL libraries and external kinit with a keytab - if PATH is not specified, look for kerberos in the system locations. This will attempt to use krb5-config from the PATH to find the libs and include dirs - you can specify KRB5_CONFIG_BIN to specify a different filename or absolute path. If krb5-config does not work, this will attempt to look in various system directories]),
+ [
+ if test "x$withval" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ elif test "x$withval" = "xno"; then
+ AC_MSG_RESULT(no)
+ with_kerberos=
+ elif test -d "$withval" -a -d "$withval/lib" -a -d "$withval/include" ; then
+ AC_MSG_RESULT([using $withval])
+ kerberos_incdir="$withval/include"
+ kerberos_libdir="$withval/lib"
+ else
+ AC_MSG_RESULT(yes)
+ AC_MSG_ERROR([kerberos not found in $withval])
+ fi
+ ],
+ [
+ AC_MSG_RESULT(no)
+ with_kerberos=
+ ]
+)
+
+AC_MSG_CHECKING(for --with-kerberos-inc)
+AC_ARG_WITH(kerberos-inc,
+ AS_HELP_STRING([--with-kerberos-inc=PATH], [Allows you to explicitly set the directory containing the kerberos include files - implies use of kerberos]),
+ [
+ if test -f "$withval"/krb5.h; then
+ AC_MSG_RESULT([using $withval])
+ kerberos_incdir="$withval"
+ with_kerberos=yes # implies use of kerberos
+ else
+ echo
+ AC_MSG_ERROR([$withval/krb5.h not found])
+ fi
+ ],
+ AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(for --with-kerberos-lib)
+AC_ARG_WITH(kerberos-lib,
+ AS_HELP_STRING([--with-kerberos-lib=PATH], [Allows you to explicitly set the directory containing the kerberos libraries - implies use of kerberos]),
+ [
+ if test -d "$withval"; then
+ AC_MSG_RESULT([using $withval])
+ kerberos_libdir="$withval"
+ with_kerberos=yes # implies use of kerberos
+ else
+ echo
+ AC_MSG_ERROR([$withval not found])
+ fi
+ ],
+ AC_MSG_RESULT(no)
+)
+
+if test -n "$with_kerberos" ; then
+ if test -z "$kerberos_incdir" -o -z "$kerberos_libdir" ; then
+ dnl look for these using the krb5-config script
+ dnl user can define KRB5_CONFIG_BIN to the full path
+ dnl and filename of the script if it cannot or will not
+ dnl be found in PATH
+ if test -z "$KRB5_CONFIG_BIN" ; then
+ AC_PATH_PROG(KRB5_CONFIG_BIN, krb5-config)
+ fi
+ if test -n "$KRB5_CONFIG_BIN" ; then
+ AC_MSG_CHECKING(for kerberos with $KRB5_CONFIG_BIN)
+ if test -z "$kerberos_libdir" ; then
+ kerberos_lib=`$KRB5_CONFIG_BIN --libs krb5`
+ fi
+ if test -z "$kerberos_incdir" ; then
+ kerberos_inc=`$KRB5_CONFIG_BIN --cflags krb5`
+ fi
+ dnl if using system includes, inc will be empty - ok
+ if test -n "$kerberos_lib" ; then
+ AC_MSG_RESULT([using kerberos found with $KRB5_CONFIG_BIN])
+ have_krb5=yes
+ fi
+ fi
+ fi
+fi
+
+if test -n "$with_kerberos" -a -z "$kerberos_lib" ; then
+ # save these in order to set them to use the check macros below
+ # like AC_CHECK_HEADERS, AC_CHECK_LIB, and AC_CHECK_FUNCS
+ save_CPPFLAGS="$CPPFLAGS"
+ if test -n "$kerberos_incdir" ; then
+ CPPFLAGS="-I$kerberos_incdir $CPPFLAGS"
+ fi
+ save_LDFLAGS="$LDFLAGS"
+ if test -n "$kerberos_libdir" ; then
+ LDFLAGS="-L$kerberos_libdir $LDFLAGS"
+ fi
+ krb5_impl=mit
+
+ dnl check for Heimdal Kerberos
+ AC_CHECK_HEADERS(heim_err.h)
+ if test $ac_cv_header_heim_err_h = yes ; then
+ krb5_impl=heimdal
+ fi
+
+ if test "x$krb5_impl" = "xmit"; then
+ AC_CHECK_LIB(k5crypto, main,
+ [krb5crypto=k5crypto],
+ [krb5crypto=crypto])
+
+ AC_CHECK_LIB(krb5, main,
+ [have_krb5=yes
+ kerberos_lib="-lkrb5 -l$krb5crypto -lcom_err"],
+ [have_krb5=no],
+ [-l$krb5crypto -lcom_err])
+
+ elif test "x$krb5_impl" = "xheimdal"; then
+ AC_CHECK_LIB(des, main,
+ [krb5crypto=des],
+ [krb5crypto=crypto])
+
+ AC_CHECK_LIB(krb5, main,
+ [have_krb5=yes
+ kerberos_lib="-lkrb5 -l$krb5crypto -lasn1 -lroken -lcom_err"],
+ [have_krb5=no],
+ [-l$krb5crypto -lasn1 -lroken -lcom_err])
+
+ AC_DEFINE(HAVE_HEIMDAL_KERBEROS, 1,
+ [define if you have HEIMDAL Kerberos])
+
+ else
+ have_krb5=no
+ AC_MSG_WARN([Unrecognized Kerberos5 Implementation])
+ fi
+
+ # reset to original values
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ if test -n "$kerberos_incdir" ; then
+ kerberos_inc="-I$kerberos_incdir"
+ fi
+ if test -n "$kerberos_libdir" ; then
+ kerberos_lib="-L$kerberos_libdir $kerberos_lib"
+ fi
+fi
+
+dnl at this point kerberos_lib and kerberos_inc should be set
+
+if test -n "$with_kerberos" ; then
+ if test "x$have_krb5" = "xyes" ; then
+ AC_DEFINE(HAVE_KRB5, 1,
+ [define if you have Kerberos V])
+ else
+ AC_MSG_ERROR([Required Kerberos 5 support not available])
+ fi
+
+ dnl look for the wonderfully time saving function krb5_cc_new_unique
+ save_LIBS="$LIBS"
+ LIBS="$kerberos_lib"
+ save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$kerberos_inc $CPPFLAGS"
+ AC_CHECK_FUNCS([krb5_cc_new_unique])
+ LIBS="$save_LIBS"
+ CPPFLAGS="$save_CPPFLAGS"
+fi
+
+AC_SUBST(kerberos_inc)
+AC_SUBST(kerberos_lib)
+AC_SUBST(kerberos_libdir)