From af0d8ef677f3c6955ccce3723812fa5a784c448e Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Mon, 31 Dec 2018 16:13:20 +1100 Subject: [PATCH] gssapi: support for client keytab in gss_acquire_cred (#383) For compatibility with MIT Kerberos, support automatic acquisition of initiator credentials if a client keytab is available. The default path on non-Windows is /var/heimdal/user/%{euid}/client.keytab, but can be overriden with the KRB5_CLIENT_KTNAME environment variable or the default_client_keytab_name configuration option. If a client keytab does not exist, or exists but does not contain the principal for which initiator credentials are being acquired, the system keytab is tried. --- include/config.h.w32 | 3 +++ lib/gssapi/krb5/acquire_cred.c | 33 ++++++++++++++++++++++++++++++--- lib/krb5/keytab.c | 16 ++++++++++++++++ lib/krb5/krb5_locl.h | 3 +++ lib/krb5/libkrb5-exports.def.in | 1 + lib/krb5/verify_krb5_conf.c | 1 + lib/krb5/version-script.map | 1 + 7 files changed, 55 insertions(+), 3 deletions(-) diff --git a/include/config.h.w32 b/include/config.h.w32 index 90eaeb91c..0baf07e9a 100644 --- a/include/config.h.w32 +++ b/include/config.h.w32 @@ -1450,6 +1450,9 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg } #define LIBDIR "%{LIBDIR}" +/* For compatibility with MIT, {USERCONFIG} would be better */ +#define CLIENT_KEYTAB_DEFAULT "FILE:%{WINDOWS}\\krb5clientkt" + #endif /* RC_INVOKED */ diff --git a/lib/gssapi/krb5/acquire_cred.c b/lib/gssapi/krb5/acquire_cred.c index 9c880b334..4c5ec35a3 100644 --- a/lib/gssapi/krb5/acquire_cred.c +++ b/lib/gssapi/krb5/acquire_cred.c @@ -58,7 +58,7 @@ __gsskrb5_ccache_lifetime(OM_uint32 *minor_status, static krb5_error_code -get_keytab(krb5_context context, krb5_keytab *keytab) +get_system_keytab(krb5_context context, krb5_keytab *keytab) { krb5_error_code kret; @@ -80,6 +80,33 @@ get_keytab(krb5_context context, krb5_keytab *keytab) return (kret); } +static krb5_error_code +get_client_keytab(krb5_context context, + krb5_const_principal principal, + krb5_keytab *keytab) +{ + krb5_error_code ret; + char *name = NULL; + + ret = _krb5_kt_client_default_name(context, &name); + if (ret == 0) + ret = krb5_kt_resolve(context, name, keytab); + if (ret == 0 && principal) { + krb5_keytab_entry entry; + + ret = krb5_kt_get_entry(context, *keytab, principal, + 0, 0, &entry); + if (ret == 0) + krb5_kt_free_entry(context, &entry); + } + krb5_xfree(name); + + if (ret) + ret = get_system_keytab(context, keytab); + + return ret; +} + /* * This function produces a cred with a MEMORY ccache containing a TGT * acquired with a password. @@ -292,7 +319,7 @@ try_keytab: if (kret) goto end; } - kret = get_keytab(context, &keytab); + kret = get_client_keytab(context, handle->principal, &keytab); if (kret) goto end; @@ -380,7 +407,7 @@ acquire_acceptor_cred(OM_uint32 * minor_status, ret = GSS_S_FAILURE; - kret = get_keytab(context, &handle->keytab); + kret = get_system_keytab(context, &handle->keytab); if (kret) goto end; diff --git a/lib/krb5/keytab.c b/lib/krb5/keytab.c index 075857d32..8273abc17 100644 --- a/lib/krb5/keytab.c +++ b/lib/krb5/keytab.c @@ -949,3 +949,19 @@ krb5_kt_have_content(krb5_context context, } return KRB5_KT_NOTFOUND; } + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_kt_client_default_name(krb5_context context, char **name) +{ + const char *tmp; + + tmp = secure_getenv("KRB5_CLIENT_KTNAME"); + if (tmp == NULL) + tmp = krb5_config_get_string(context, NULL, + "libdefaults", + "default_client_keytab_name", NULL); + if (tmp == NULL) + tmp = CLIENT_KEYTAB_DEFAULT; + + return _krb5_expand_path_tokens(context, tmp, 1, name); +} diff --git a/lib/krb5/krb5_locl.h b/lib/krb5/krb5_locl.h index 0ba68450d..17d21edef 100644 --- a/lib/krb5/krb5_locl.h +++ b/lib/krb5/krb5_locl.h @@ -171,6 +171,9 @@ struct _krb5_krb_auth_data; #define KEYTAB_DEFAULT "FILE:" SYSCONFDIR "/krb5.keytab" #define KEYTAB_DEFAULT_MODIFY "FILE:" SYSCONFDIR "/krb5.keytab" +#ifndef CLIENT_KEYTAB_DEFAULT +#define CLIENT_KEYTAB_DEFAULT "FILE:" LOCALSTATEDIR "/user/%{euid}/client.keytab"; +#endif #define MODULI_FILE SYSCONFDIR "/krb5.moduli" diff --git a/lib/krb5/libkrb5-exports.def.in b/lib/krb5/libkrb5-exports.def.in index aae574744..46de64a1f 100644 --- a/lib/krb5/libkrb5-exports.def.in +++ b/lib/krb5/libkrb5-exports.def.in @@ -753,6 +753,7 @@ EXPORTS _krb5_crc_update _krb5_get_krbtgt _krb5_build_authenticator + _krb5_kt_client_default_name ; Shared with libkdc _krb5_AES_SHA1_string_to_default_iterator diff --git a/lib/krb5/verify_krb5_conf.c b/lib/krb5/verify_krb5_conf.c index 12bd33701..b481e127e 100644 --- a/lib/krb5/verify_krb5_conf.c +++ b/lib/krb5/verify_krb5_conf.c @@ -404,6 +404,7 @@ struct entry libdefaults_entries[] = { { "date_format", krb5_config_string, NULL, 0 }, { "default_as_etypes", krb5_config_string, NULL, 0 }, { "default_ccache_name", krb5_config_string, NULL, 0 }, + { "default_client_keytab_name", krb5_config_string, NULL, 0 }, { "default_cc_name", krb5_config_string, NULL, 0 }, { "default_cc_type", krb5_config_string, NULL, 0 }, { "default_etypes", krb5_config_string, NULL, 0 }, diff --git a/lib/krb5/version-script.map b/lib/krb5/version-script.map index 82a107e49..bdaa4284d 100644 --- a/lib/krb5/version-script.map +++ b/lib/krb5/version-script.map @@ -745,6 +745,7 @@ HEIMDAL_KRB5_2.0 { _krb5_crc_update; _krb5_get_krbtgt; _krb5_build_authenticator; + _krb5_kt_client_default_name; # Shared with libkdc _krb5_AES_SHA1_string_to_default_iterator;