krb5 commit: Add token expansion for keytab names

Greg Hudson ghudson at MIT.EDU
Tue Jul 24 16:36:28 EDT 2012


https://github.com/krb5/krb5/commit/fc3e8c660d98b134767c574d899528dfd29d7a16
commit fc3e8c660d98b134767c574d899528dfd29d7a16
Author: Greg Hudson <ghudson at mit.edu>
Date:   Tue Jul 24 16:26:27 2012 -0400

    Add token expansion for keytab names
    
    Make the default_keytab_name and default_client_keytab_name variables
    subject to parameter expansion.
    
    ticket: 7219 (new)

 doc/rst_source/krb_admins/conf_files/krb5_conf.rst |   34 ++++++-
 src/include/osconf.hin                             |    4 +-
 src/lib/krb5/os/ktdefname.c                        |  100 +++++++++-----------
 src/tests/t_keytab.py                              |   16 +++
 4 files changed, 93 insertions(+), 61 deletions(-)

diff --git a/doc/rst_source/krb_admins/conf_files/krb5_conf.rst b/doc/rst_source/krb_admins/conf_files/krb5_conf.rst
index b595a6d..d9c3ffb 100644
--- a/doc/rst_source/krb_admins/conf_files/krb5_conf.rst
+++ b/doc/rst_source/krb_admins/conf_files/krb5_conf.rst
@@ -136,12 +136,13 @@ The libdefaults section may contain any of the following relations:
 
 **default_client_keytab_name**
     This relation specifies the name of the default keytab for
-    obtaining client credentials.  The default is |clkeytab|.
+    obtaining client credentials.  The default is |clkeytab|.  This
+    relation is subject to parameter expansion (see below).
 
 **default_keytab_name**
     This relation specifies the default keytab name to be used by
-    application servers such as telnetd and rlogind.  The default is
-    |keytab|.
+    application servers such as sshd.  The default is |keytab|.  This
+    relation is subject to parameter expansion (see below).
 
 **default_realm**
     Identifies the default Kerberos realm for the client.  Set its
@@ -968,6 +969,33 @@ PKINIT krb5.conf options
     The default is false.
 
 
+.. _parameter_expansion:
+
+Parameter expansion
+-------------------
+
+Several variables, such as **default_keytab_name**, allow parameters
+to be expanded.  Valid parameters are:
+
+    =================  ===================================================
+    %{TEMP}            Temporary directory
+    %{uid}             Unix real UID or Windows SID
+    %{euid}            Unix effective user ID or Windows SID
+    %{USERID}          Same as %{uid}
+    %{null}            Empty string
+    %{LIBDIR}          Installation library directory
+    %{BINDIR}          Installation binary directory
+    %{SBINDIR}         Installation admin binary directory
+    %{APPDATA}         (Windows) Roaming application data for current user
+    %{COMMON_APPDATA}  (Windows) Application data for all users
+    %{LOCAL_APPDATA}   (Windows) Local application data for current user
+    %{SYSTEM}          (Windows) Windows system folder
+    %{WINDOWS}         (Windows) Windows folder
+    %{USERCONFIG}      (Windows) Per-user MIT krb5 config file directory
+    %{COMMONCONFIG}    (Windows) Common MIT krb5 config file directory
+    ================   ===================================================
+
+
 Sample krb5.conf file
 ---------------------
 
diff --git a/src/include/osconf.hin b/src/include/osconf.hin
index 3f33cc3..803d73b 100644
--- a/src/include/osconf.hin
+++ b/src/include/osconf.hin
@@ -42,8 +42,8 @@
 
 #if defined(_WIN32)
 #define DEFAULT_PROFILE_FILENAME "krb5.ini"
-#define DEFAULT_KEYTAB_NAME     "FILE:%s\\krb5kt"
-#define DEFAULT_CLIENT_KEYTAB_NAME "FILE:%s\\krb5clientkt"
+#define DEFAULT_KEYTAB_NAME     "FILE:%{WINDOWS}\\krb5kt"
+#define DEFAULT_CLIENT_KEYTAB_NAME "FILE:%{WINDOWS}\\krb5clientkt"
 #else /* !_WINDOWS */
 #if TARGET_OS_MAC
 #define DEFAULT_SECURE_PROFILE_PATH "/Library/Preferences/edu.mit.Kerberos:/etc/krb5.conf:@SYSCONFDIR/krb5.conf"
diff --git a/src/lib/krb5/os/ktdefname.c b/src/lib/krb5/os/ktdefname.c
index a213750..93b28dd 100644
--- a/src/lib/krb5/os/ktdefname.c
+++ b/src/lib/krb5/os/ktdefname.c
@@ -27,83 +27,71 @@
 #define NEED_WINDOWS
 
 #include "k5-int.h"
+#include "os-proto.h"
 
 extern char *krb5_defkeyname;
 
 /* this is a an exceedinly gross thing. */
 char *krb5_overridekeyname = NULL;
 
-krb5_error_code KRB5_CALLCONV
-krb5_kt_default_name(krb5_context context, char *name, int name_size)
+static krb5_error_code
+kt_default_name(krb5_context context, char **name_out)
 {
-    char *cp = 0;
-    char *retval;
-    unsigned int namesize = (name_size < 0 ? 0 : name_size);
+    krb5_error_code ret;
+    char *str;
 
-    if (krb5_overridekeyname) {
-        if (strlcpy(name, krb5_overridekeyname, namesize) >= namesize)
-            return KRB5_CONFIG_NOTENUFSPACE;
-    } else if ((context->profile_secure == FALSE) &&
-               (cp = getenv("KRB5_KTNAME"))) {
-        if (strlcpy(name, cp, namesize) >= namesize)
-            return KRB5_CONFIG_NOTENUFSPACE;
-    } else if ((profile_get_string(context->profile,
-                                   KRB5_CONF_LIBDEFAULTS,
-                                   KRB5_CONF_DEFAULT_KEYTAB_NAME, NULL,
-                                   NULL, &retval) == 0) &&
-               retval) {
-        if (strlcpy(name, retval, namesize) >= namesize)
-            return KRB5_CONFIG_NOTENUFSPACE;
-        profile_release_string(retval);
+    if (krb5_overridekeyname != NULL) {
+        *name_out = strdup(krb5_overridekeyname);
+        return (*name_out == NULL) ? ENOMEM : 0;
+    } else if (context->profile_secure == FALSE &&
+               (str = getenv("KRB5_KTNAME")) != NULL) {
+        *name_out = strdup(str);
+        return (*name_out == NULL) ? ENOMEM : 0;
+    } else if (profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
+                                  KRB5_CONF_DEFAULT_KEYTAB_NAME, NULL, NULL,
+                                  &str) == 0 && str != NULL) {
+        ret = k5_expand_path_tokens(context, str, name_out);
+        profile_release_string(str);
+        return ret;
     } else {
-#if defined(_WIN32)
-        {
-            char    defname[160];
-            int     len;
-
-            len= GetWindowsDirectory( defname, sizeof(defname)-2 );
-            defname[len]= '\0';
-            if ( (len + strlen(krb5_defkeyname) + 1) > namesize )
-                return KRB5_CONFIG_NOTENUFSPACE;
-            snprintf(name, namesize, krb5_defkeyname, defname);
-        }
-#else
-        if (strlcpy(name, krb5_defkeyname, namesize) >= namesize)
-            return KRB5_CONFIG_NOTENUFSPACE;
-#endif
+        return k5_expand_path_tokens(context, krb5_defkeyname, name_out);
     }
-    return 0;
 }
 
 krb5_error_code
 k5_kt_client_default_name(krb5_context context, char **name_out)
 {
-    char *str, *name;
+    krb5_error_code ret;
+    char *str;
 
-    *name_out = NULL;
-    if (!context->profile_secure &&
+    if (context->profile_secure == FALSE &&
         (str = getenv("KRB5_CLIENT_KTNAME")) != NULL) {
-        name = strdup(str);
+        *name_out = strdup(str);
+        return (*name_out == NULL) ? ENOMEM : 0;
     } else if (profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
                                   KRB5_CONF_DEFAULT_CLIENT_KEYTAB_NAME, NULL,
                                   NULL, &str) == 0 && str != NULL) {
-        name = strdup(str);
+        ret = k5_expand_path_tokens(context, str, name_out);
         profile_release_string(str);
+        return ret;
     } else {
-#ifdef _WIN32
-        char windir[160];
-        unsigned int len;
-
-        len = GetWindowsDirectory(windir, sizeof(windir) - 2);
-        windir[len] = '\0';
-        if (asprintf(&name, DEFAULT_CLIENT_KEYTAB_NAME, windir) < 0)
-            return ENOMEM;
-#else
-        name = strdup(DEFAULT_CLIENT_KEYTAB_NAME);
-#endif
+        return k5_expand_path_tokens(context, DEFAULT_CLIENT_KEYTAB_NAME,
+                                     name_out);
     }
-    if (name == NULL)
-        return ENOMEM;
-    *name_out = name;
-    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_kt_default_name(krb5_context context, char *name, int name_size)
+{
+    krb5_error_code ret;
+    unsigned int namesize = (name_size < 0 ? 0 : name_size);
+    char *ktname;
+
+    ret = kt_default_name(context, &ktname);
+    if (ret)
+        return ret;
+    if (strlcpy(name, ktname, namesize) >= namesize)
+        ret = KRB5_CONFIG_NOTENUFSPACE;
+    free(ktname);
+    return ret;
 }
diff --git a/src/tests/t_keytab.py b/src/tests/t_keytab.py
index 8d73636..f8cea68 100644
--- a/src/tests/t_keytab.py
+++ b/src/tests/t_keytab.py
@@ -40,4 +40,20 @@ output = realm.run_kadminl('getprinc %s' % princ)
 if 'Key: vno 258,' not in output:
     fail('Expected vno not seen in kadmin.local output')
 
+# Test parameter expansion in profile variables
+realm.stop()
+conf = {'client': {'libdefaults': {
+            'default_keytab_name': 'testdir/%{null}abc%{uid}',
+            'default_client_keytab_name': 'testdir/%{null}xyz%{uid}'}}}
+realm = K5Realm(krb5_conf=conf, create_kdb=False)
+del realm.env_client['KRB5_KTNAME']
+del realm.env_client['KRB5_CLIENT_KTNAME']
+uidstr = str(os.getuid())
+out = realm.run_as_client([klist, '-k'], expected_code=1)
+if 'FILE:testdir/abc%s' % uidstr not in out:
+    fail('Wrong keytab in klist -k output')
+out = realm.run_as_client([klist, '-ki'], expected_code=1)
+if 'FILE:testdir/xyz%s' % uidstr not in out:
+    fail('Wrong keytab in klist -ki output')
+
 success('Keytab-related tests')


More information about the cvs-krb5 mailing list