diff options
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | Makefile.in | 15 | ||||
-rwxr-xr-x | configure | 843 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | ldap/servers/plugins/replication/repl5.h | 2 | ||||
-rw-r--r-- | ldap/servers/plugins/replication/repl5_agmt.c | 23 | ||||
-rw-r--r-- | ldap/servers/plugins/replication/repl5_connection.c | 312 | ||||
-rw-r--r-- | ldap/servers/slapd/proto-slap.h | 10 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi-plugin.h | 21 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi2nspr.c | 127 | ||||
-rw-r--r-- | ldap/servers/slapd/ssl.c | 5 | ||||
-rw-r--r-- | ldap/servers/slapd/util.c | 1034 | ||||
-rw-r--r-- | m4/kerberos.m4 | 199 |
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) #//////////////////////////////////////////////////////////////// # @@ -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) |