--- Begin Message ---
Package: libnss-ldap
Version: 261-2
Severity: wishlist
Hello,
Trying to setup a kerberos/LDAP environment I'm unable to use SASL with
libnss-ldap.
After searching the web I found a patch to add a krb5_keytabname to
libnss-ldap.conf:
http://ml.osdir.com/ldap.padl.nss/2006-07/msg00036.html
I attach the patch.
Regards.
-- System Information:
Debian Release: lenny/sid
APT prefers testing
APT policy: (500, 'testing')
Architecture: amd64 (x86_64)
Kernel: Linux 2.6.26.2+kvm-guest.2 (SMP w/1 CPU core)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Versions of packages libnss-ldap depends on:
ii debconf [debconf-2.0] 1.5.22 Debian configuration management sy
ii libc6 2.7-13 GNU C Library: Shared libraries
ii libcomerr2 1.41.0-3 common error description library
ii libkrb53 1.6.dfsg.4~beta1-3 MIT Kerberos runtime libraries
ii libldap-2.4-2 2.4.10-3 OpenLDAP libraries
ii libsasl2-2 2.1.22.dfsg1-21 Cyrus SASL - authentication abstra
Versions of packages libnss-ldap recommends:
pn libpam-ldap <none> (no description available)
pn nscd <none> (no description available)
libnss-ldap suggests no packages.
-- debconf information excluded
diff -r -u -N nss_ldap-250/acconfig.h nss_ldap-250-n/acconfig.h
--- nss_ldap-250/acconfig.h 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/acconfig.h 2006-10-08 20:11:48.000000000 +0100
@@ -28,6 +28,9 @@
/* define to enable configurable Kerberos credentials cache (gssapi method) */
#undef CONFIGURE_KRB5_CCNAME_GSSAPI
+/* define to enable configurable Kerberos V keytab file name */
+#undef CONFIGURE_KRB5_KEYTAB
+
/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_KRB5_H
diff -r -u -N nss_ldap-250/config.h.in nss_ldap-250-n/config.h.in
--- nss_ldap-250/config.h.in 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/config.h.in 2006-10-08 20:12:35.000000000 +0100
@@ -32,6 +32,9 @@
/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_KRB5_H
+/* define to enable configurable Kerberos V keytab file name */
+#undef CONFIGURE_KRB5_KEYTAB
+
/* define to enable struct ether_addr definition */
#undef HAVE_STRUCT_ETHER_ADDR
@@ -99,6 +102,9 @@
/* Define to 1 if you have the <irs.h> header file. */
#undef HAVE_IRS_H
+/* Define to 1 if you have the <krb5.h> header file. */
+#undef HAVE_KRB5_H
+
/* Define to 1 if you have the <lber.h> header file. */
#undef HAVE_LBER_H
diff -r -u -N nss_ldap-250/configure.in nss_ldap-250-n/configure.in
--- nss_ldap-250/configure.in 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/configure.in 2006-10-08 20:11:48.000000000 +0100
@@ -40,6 +40,7 @@
dnl
AC_ARG_ENABLE(configurable-krb5-ccname-env, [ --enable-configurable-krb5-ccname-env enable configurable Kerberos V credentials cache name (putenv method)], [AC_DEFINE(CONFIGURE_KRB5_CCNAME) AC_DEFINE(CONFIGURE_KRB5_CCNAME_ENV)])
AC_ARG_ENABLE(configurable-krb5-ccname-gssapi, [ --enable-configurable-krb5-ccname-gssapi enable configurable Kerberos V credentials cache name (gssapi method)], [AC_DEFINE(CONFIGURE_KRB5_CCNAME) AC_DEFINE(CONFIGURE_KRB5_CCNAME_GSSAPI)])
+AC_ARG_ENABLE(configurable-krb5-keytab, [ --enable-configurable-krb5-keytab enable configurable Kerberos V keytab file name], [AC_DEFINE(CONFIGURE_KRB5_KEYTAB)])
AC_ARG_WITH(ldap-lib, [ --with-ldap-lib=type select ldap library [auto|netscape5|netscape4|netscape3|umich|openldap]])
AC_ARG_WITH(ldap-dir, [ --with-ldap-dir=DIR base directory of LDAP SDK])
@@ -181,6 +182,7 @@
AC_CHECK_HEADERS(gssldap.h)
AC_CHECK_HEADERS(gsssasl.h)
AC_CHECK_HEADERS(gssapi/gssapi_krb5.h gssapi.h)
+AC_CHECK_HEADERS(krb5.h)
AC_CHECK_LIB(resolv, main)
AC_CHECK_LIB(nsl, main)
@@ -255,9 +257,9 @@
dnl Following checks probably not strictly necessary.
dnl AC_CHECK_LIB(crypto, main,[LIBS="-lcrypto $LIBS"],,$LIBS)
dnl AC_CHECK_LIB(ssl, main,[LIBS="-lssl $LIBS"],,$LIBS)
-dnl AC_CHECK_LIB(com_err, main,[LIBS="-lcom_err $LIBS"],,$LIBS)
+AC_CHECK_LIB(com_err, main,[LIBS="-lcom_err $LIBS"],,$LIBS)
dnl AC_CHECK_LIB(k5crypto, main,[LIBS="-lk5crypto $LIBS"],,$LIBS)
-dnl AC_CHECK_LIB(krb5, main,[LIBS="-lkrb5 $LIBS"],,$LIBS)
+AC_CHECK_LIB(krb5, main,[LIBS="-lkrb5 $LIBS"],,$LIBS)
dnl AC_CHECK_LIB(krb4, main,[LIBS="-lkrb4 $LIBS"],,$LIBS)
dnl AC_CHECK_LIB(sasl, sasl_client_init,[LIBS="-lsasl $LIBS"],,$LIBS)
diff -r -u -N nss_ldap-250/ldap-init-krb5-cache.c nss_ldap-250-n/ldap-init-krb5-cache.c
--- nss_ldap-250/ldap-init-krb5-cache.c 1970-01-01 01:00:00.000000000 +0100
+++ nss_ldap-250-n/ldap-init-krb5-cache.c 2006-10-08 20:11:48.000000000 +0100
@@ -0,0 +1,317 @@
+#include "config.h"
+#ifdef HAVE_LBER_H
+#include <lber.h>
+#endif
+#ifdef HAVE_LDAP_H
+#include <ldap.h>
+#endif
+#include "ldap-nss.h"
+#ifdef CONFIGURE_KRB5_KEYTAB
+#include <krb5.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <time.h>
+#ifndef HEIMDAL
+#include <profile.h>
+#endif
+#ifdef HEIMDAL
+#define error_message(code) krb5_get_err_text(context,code)
+#endif
+
+int do_init_krb5_cache(ldap_config_t *config)
+{
+#define KT_PATH_MAX 256
+#define MAX_RENEW_TIME "365d"
+
+ int retval;
+
+ static krb5_context context = NULL;
+ static krb5_keytab keytab = 0;
+ static krb5_creds *creds=NULL;
+#ifdef HEIMDAL
+ static krb5_creds creds2;
+#endif
+ static krb5_principal principal = NULL;
+ static krb5_ccache cc = NULL;
+ static krb5_deltat skew=0;
+
+ krb5_get_init_creds_opt options;
+ krb5_error_code code = 0;
+ krb5_deltat rlife;
+ krb5_cc_cursor cursor;
+ char *principal_name;
+#ifndef HEIMDAL
+ typedef struct _profile_t *profile_t;
+ profile_t profile;
+#else
+ krb5_kdc_flags flags;
+ krb5_realm *client_realm;
+#endif
+
+
+
+ debug ("==> do_init_krb5_cache %s %s %s",
+ config->ldc_krb5_keytabname?config->ldc_krb5_keytabname:"NULL", config->ldc_krb5_ccname?config->ldc_krb5_ccname:"NULL", config->ldc_saslid?config->ldc_saslid:"NULL");
+
+
+restart:
+ if (creds &&
+ (creds->times.endtime - time(0) > skew) &&
+ (creds->times.renew_till - time(0) > 2*skew))
+ {
+ if (creds->times.endtime - time(0) < 2*skew)
+ {
+ debug ("==> do_init_krb5_cache renew ticket");
+#ifndef HEIMDAL
+ /* renew ticket */
+ code = krb5_get_renewed_creds(context, creds, principal, cc, NULL);
+#else
+ /* renew ticket */
+ flags.i = 0;
+ flags.b.renewable = flags.b.renew = 1;
+
+ code = krb5_cc_get_principal(context, cc, &creds2.client);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while getting principal from credential cache", error_message(code), (int)code);
+ return(1) ;
+ }
+ client_realm = krb5_princ_realm (context, creds2.client);
+ code = krb5_make_principal(context, &creds2.server, *client_realm,
+ KRB5_TGS_NAME, *client_realm, NULL);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while gettig krbtgt principal", error_message(code), (int)code);
+ return(1) ;
+ }
+ code = krb5_get_kdc_cred(context, cc, flags, NULL, NULL, &creds2, &creds);
+#endif
+ if (code)
+ {
+ if ( code == KRB5KRB_AP_ERR_TKT_EXPIRED )
+ {
+ creds=NULL;
+ /* this can happen because of clock skew */
+ goto restart;
+ }
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while renewing credentials", error_message(code), (int)code);
+ return(1) ;
+ }
+ }
+ else
+ {
+ debug ("==> do_init_krb5_cache use stored ticket");
+ }
+ }
+ else
+ {
+ /* reinit */
+ debug ("==> do_init_krb5_cache reinit ticket");
+ if (!context)
+ {
+ code = krb5_init_context(&context);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while initialising Kerberos library", error_message(code), (int)code);
+ return(1) ;
+ }
+ }
+
+#ifndef HEIMDAL
+ code = krb5_get_profile (context, &profile);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while getting profile", error_message(code), (int)code);
+ return(1) ;
+ }
+ code = profile_get_integer(profile, "libdefaults", "clockskew", 0, 5 * 60, &skew);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while getting clockskew", error_message(code), (int)code);
+ return(1) ;
+ }
+#else
+ skew=context->max_skew;
+#endif
+ creds = malloc(sizeof(*creds));
+ memset(creds, 0, sizeof(*creds));
+ /* check existing cache first */
+ if ( !config->ldc_krb5_ccname )
+ {
+ config->ldc_krb5_ccname = (char *)krb5_cc_default_name(context);
+ debug ("==> do_init_krb5_cache try default credential cache %s",config->ldc_krb5_ccname?config->ldc_krb5_ccname:"NULL");
+ }
+ code = krb5_cc_resolve(context, config->ldc_krb5_ccname, &cc);
+ if (!code)
+ {
+ code = krb5_cc_get_principal(context, cc, &principal );
+ if (!code)
+ {
+ debug ("==> do_init_krb5_cache found existing cache");
+ code = krb5_unparse_name(context, principal, &principal_name);
+ if (!code)
+ {
+ debug ("==> do_init_krb5_cache cache principal %s",principal_name?principal_name:"NULL");
+ code = krb5_cc_start_seq_get(context, cc, &cursor );
+ if (!code)
+ {
+ code = krb5_cc_next_cred(context, cc, &cursor, creds );
+ if (!code)
+ {
+ if ((creds->times.endtime - time(0) > skew) &&
+ (creds->times.renew_till - time(0) > 2*skew))
+ goto restart;
+ }
+ }
+ }
+ debug ("==> do_init_krb5_cache cache credentials not usable");
+ }
+ }
+
+ /* use keytab to fill cache */
+ if (!config->ldc_krb5_keytabname)
+ {
+ char buf[KT_PATH_MAX];
+
+ debug ("==> do_init_krb5_cache get default keytab");
+ krb5_kt_default_name(context, buf, KT_PATH_MAX);
+ config->ldc_krb5_keytabname = strdup(buf);
+ code = krb5_kt_default(context, &keytab);
+ }
+ else
+ {
+ code = krb5_kt_resolve(context, config->ldc_krb5_keytabname, &keytab);
+ }
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while resolving keytab filename %s", error_message(code), (int)code, config->ldc_krb5_keytabname);
+ return(1);
+ }
+
+ if (!config->ldc_saslid)
+ {
+ char hostname[HOST_NAME_MAX];
+
+ debug ("==> do_init_krb5_cache get default principal name");
+ errno = 0;
+ retval = gethostname(hostname,HOST_NAME_MAX);
+ if (retval)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s while resolving hostname", strerror(errno));
+ return(1);
+ }
+ hostname[HOST_NAME_MAX]='\0';
+ config->ldc_saslid=malloc(sizeof(hostname)+ 6);
+ strcpy(config->ldc_saslid,"host/");
+ strcat(config->ldc_saslid,hostname);
+ debug ("==> do_init_krb5_cache set principal name %s",config->ldc_saslid);
+ }
+
+ if (!principal)
+ {
+ code = krb5_parse_name(context, config->ldc_saslid, &principal);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while parsing principal name %s", error_message(code), (int)code, config->ldc_saslid);
+ return (1);
+ }
+ }
+
+ krb5_get_init_creds_opt_init(&options);
+ code = krb5_string_to_deltat(MAX_RENEW_TIME, &rlife);
+ if (code != 0 || rlife == 0)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while setting renew lifetime value to %s", error_message(code), (int)code, MAX_RENEW_TIME);
+ return (1);
+ }
+ krb5_get_init_creds_opt_set_renew_life(&options, rlife);
+
+ debug ("==> do_init_krb5_cache get credentials from keytab");
+ code = krb5_get_init_creds_keytab(context, creds, principal, keytab, 0, NULL, &options);
+ if (code && code != EEXIST )
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while initialising credentials from keytab", error_message(code), (int)code);
+ debug ("==> do_init_krb5_cache get credentials from keytab failed");
+ config->ldc_krb5_ccname = (char *)krb5_cc_default_name(context);
+ debug ("==> do_init_krb5_cache try default credential cache %s",config->ldc_krb5_ccname?config->ldc_krb5_ccname:"NULL");
+ code = krb5_cc_resolve(context, config->ldc_krb5_ccname, &cc);
+ if (!code)
+ {
+ code = krb5_cc_get_principal(context, cc, &principal );
+ if (!code)
+ {
+ debug ("==> do_init_krb5_cache found existing cache");
+ code = krb5_unparse_name(context, principal, &principal_name);
+ if (!code)
+ {
+ debug ("==> do_init_krb5_cache cache principal %s",principal_name?principal_name:"NULL");
+ code = krb5_cc_start_seq_get(context, cc, &cursor );
+ if (!code)
+ {
+ code = krb5_cc_next_cred(context, cc, &cursor, creds );
+ if (!code)
+ {
+ if ((creds->times.endtime - time(0) > skew) &&
+ (creds->times.renew_till - time(0) > 2*skew))
+ goto restart;
+ }
+ }
+ }
+ debug ("==> do_init_krb5_cache cache credentials not usable");
+ }
+ else
+ {
+ debug ("==> do_init_krb5_cache cache credentials not usable");
+ }
+ }
+ else
+ {
+ debug ("==> do_init_krb5_cache cache credentials not usable");
+ }
+ return (1);
+ }
+
+ code = krb5_cc_resolve(context, config->ldc_krb5_ccname, &cc);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while resolving credential cache", error_message(code), (int)code);
+ return(1) ;
+ }
+ code = krb5_cc_initialize(context, cc, principal);
+ if (code && code != EEXIST )
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while initializing credential cache", error_message(code), (int)code);
+ debug ("==> do_init_krb5_cache initializing credential cache failed");
+ config->ldc_krb5_ccname = (char *)krb5_cc_default_name(context);
+ debug ("==> do_init_krb5_cache try default credential cache %s",config->ldc_krb5_ccname?config->ldc_krb5_ccname:"NULL");
+ code = krb5_cc_resolve(context, config->ldc_krb5_ccname, &cc);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while resolving credential cache", error_message(code), (int)code);
+ return(1) ;
+ }
+ code = krb5_cc_initialize(context, cc, principal);
+ if (code && code != EEXIST )
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while initializing credential cache", error_message(code), (int)code);
+ return(1) ;
+ }
+ }
+ debug ("==> do_init_krb5_cache store credentials in cache file");
+ code = krb5_cc_store_cred(context, cc, creds);
+ if (code)
+ {
+ syslog (LOG_ERR, "nss_ldap: %s(%d) while storing credentials", error_message(code), (int)code);
+ return(1) ;
+ }
+
+ if (!creds->times.starttime)
+ creds->times.starttime = creds->times.authtime;
+ }
+ return(0);
+}
+#endif /* CONFIGURE_KRB5_KEYTAB */
diff -r -u -N nss_ldap-250/ldap-nss.c nss_ldap-250-n/ldap-nss.c
--- nss_ldap-250/ldap-nss.c 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/ldap-nss.c 2006-10-08 20:11:48.000000000 +0100
@@ -1019,6 +1019,9 @@
p = strchr (p, ':');
}
+# ifdef CONFIGURE_KRB5_KEYTAB
+ do_init_krb5_cache(__config);
+# endif /* CONFIGURE_KRB5_KEYTAB */
#ifdef HAVE_LDAP_INITIALIZE
if (p == NULL &&
((ldaps && defport != LDAPS_PORT) || (!ldaps && defport != LDAP_PORT)))
@@ -1053,7 +1056,6 @@
defport = atoi (p + 1);
uri = uribuf;
}
-
# ifdef HAVE_LDAP_INIT
*ld = ldap_init (uri, defport);
# else
diff -r -u -N nss_ldap-250/ldap-nss.h nss_ldap-250-n/ldap-nss.h
--- nss_ldap-250/ldap-nss.h 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/ldap-nss.h 2006-10-08 20:11:48.000000000 +0100
@@ -364,6 +364,10 @@
/* krb5 ccache name */
char *ldc_krb5_ccname;
#endif /* CONFIGURE_KRB5_CCNAME */
+#ifdef CONFIGURE_KRB5_KEYTAB
+ /* krb5 keytat name */
+ char *ldc_krb5_keytabname;
+#endif /* CONFIGURE_KRB5_KEYTAB */
/*
* attribute/objectclass maps relative to this config
*/
@@ -900,4 +904,7 @@
int _nss_ldap_test_initgroups_ignoreuser (const char *user);
int _nss_ldap_get_ld_errno (char **m, char **s);
+#ifdef CONFIGURE_KRB5_KEYTAB
+int do_init_krb5_cache(ldap_config_t *config);
+#endif /* CONFIGURE_KRB5_KEYTAB */
#endif /* _LDAP_NSS_LDAP_LDAP_NSS_H */
diff -r -u -N nss_ldap-250/Makefile.am nss_ldap-250-n/Makefile.am
--- nss_ldap-250/Makefile.am 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/Makefile.am 2006-10-08 20:11:48.000000000 +0100
@@ -22,7 +22,7 @@
ldap-hosts.c ldap-network.c ldap-proto.c ldap-spwd.c \
ldap-alias.c ldap-service.c ldap-schema.c ldap-ethers.c \
ldap-bp.c ldap-automount.c util.c ltf.c snprintf.c resolve.c \
- dnsconfig.c irs-nss.c pagectrl.c ldap-sldap.c
+ dnsconfig.c irs-nss.c pagectrl.c ldap-sldap.c ldap-init-krb5-cache.c
nss_ldap_so_LDFLAGS = @nss_ldap_so_LDFLAGS@
@@ -31,7 +31,7 @@
NSS_LDAP_SOURCES = ldap-nss.c ldap-grp.c ldap-pwd.c ldap-netgrp.c ldap-schema.c \
util.c ltf.c snprintf.c resolve.c dnsconfig.c \
- irs-nss.c pagectrl.c aix_authmeth.c
+ irs-nss.c pagectrl.c aix_authmeth.c ldap-init-krb5-cache.c
NSS_LDAP_LDFLAGS = @NSS_LDAP_LDFLAGS@
DEFS = @DEFS@
diff -r -u -N nss_ldap-250/util.c nss_ldap-250-n/util.c
--- nss_ldap-250/util.c 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/util.c 2006-10-08 20:11:48.000000000 +0100
@@ -648,6 +648,9 @@
#ifdef CONFIGURE_KRB5_CCNAME
result->ldc_krb5_ccname = NULL;
#endif /* CONFIGURE_KRB5_CCNAME */
+#ifdef CONFIGURE_KRB5_KEYTAB
+ result->ldc_krb5_keytabname = NULL;
+#endif /* CONFIGURE_KRB5_KEYTAB */
result->ldc_flags = 0;
#ifdef RFC2307BIS
result->ldc_flags |= NSS_LDAP_FLAGS_RFC2307BIS;
@@ -1036,6 +1039,12 @@
t = &result->ldc_krb5_ccname;
}
#endif /* CONFIGURE_KRB5_CCNAME */
+#ifdef CONFIGURE_KRB5_KEYTAB
+ else if (!strcasecmp (k, NSS_LDAP_KEY_KRB5_KEYTAB))
+ {
+ t = &result->ldc_krb5_keytabname;
+ }
+#endif /* CONFIGURE_KRB5_KEYTAB */
else if (!strcasecmp (k, "tls_checkpeer"))
{
if (!strcasecmp (v, "on") || !strcasecmp (v, "yes")
diff -r -u -N nss_ldap-250/util.h nss_ldap-250-n/util.h
--- nss_ldap-250/util.h 2006-04-27 02:19:00.000000000 +0100
+++ nss_ldap-250-n/util.h 2006-10-08 20:11:48.000000000 +0100
@@ -78,6 +78,9 @@
#ifdef CONFIGURE_KRB5_CCNAME
#define NSS_LDAP_KEY_KRB5_CCNAME "krb5_ccname"
#endif /* CONFIGURE_KRB5_CCNAME */
+#ifdef CONFIGURE_KRB5_KEYTAB
+#define NSS_LDAP_KEY_KRB5_KEYTAB "krb5_keytabname"
+#endif /* CONFIGURE_KRB5_KEYTAB */
#define NSS_LDAP_KEY_LOGDIR "logdir"
#define NSS_LDAP_KEY_DEBUG "debug"
#define NSS_LDAP_KEY_PAGESIZE "pagesize"
--- End Message ---