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"