gssapi: support for client keytab in gss_acquire_cred (#383)
authorLuke Howard <lukeh@padl.com>
Mon, 31 Dec 2018 05:13:20 +0000 (16:13 +1100)
committerLuke Howard <lukeh@padl.com>
Mon, 31 Dec 2018 07:20:37 +0000 (18:20 +1100)
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
lib/gssapi/krb5/acquire_cred.c
lib/krb5/keytab.c
lib/krb5/krb5_locl.h
lib/krb5/libkrb5-exports.def.in
lib/krb5/verify_krb5_conf.c
lib/krb5/version-script.map

index 90eaeb91c42d8b1eb30e631c3d0160a9efa6bd40..0baf07e9a7f6813445dab6599acc0920e11f6247 100644 (file)
@@ -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 */
 
 
index 9c880b334fd6d684b8dc6cab1e410ea60011b822..4c5ec35a3e5c2e3b9f2cc7c860d1d84fbbcc1812 100644 (file)
@@ -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;
 
index 075857d32a25977a30ceef02f155f64b8df5035b..8273abc1708fd3c90cb2ee1f425410dbecf66983 100644 (file)
@@ -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);
+}
index 0ba68450db2bd5e14ca3f9fa68f1acbe25f24e03..17d21edef090c4d40d046219d345674dc7e0f51a 100644 (file)
@@ -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"
 
index aae574744a3bd5525d73489fb11f2efe9ecd5f1f..46de64a1f3f467ed5f5ee605a1e130e8e7d60709 100644 (file)
@@ -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
index 12bd33701e78b614d58f8068847b58dcaba14083..b481e127eb4a711632ed26cd7bea735dd0606704 100644 (file)
@@ -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 },
index 82a107e49df1c78e80c198ac0977b18c6c031743..bdaa4284decc708d8084f5855630c3a0d8cd533e 100644 (file)
@@ -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;