krb5 commit: Add krb5_kt_client_default API

Greg Hudson ghudson at MIT.EDU
Mon Jul 2 02:24:55 EDT 2012


https://github.com/krb5/krb5/commit/d1fe0728c830fe52bdcb5d53c517a9462391069d
commit d1fe0728c830fe52bdcb5d53c517a9462391069d
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri Jun 15 11:14:39 2012 -0400

    Add krb5_kt_client_default API
    
    The default client keytab is intended to be used to automatically
    acquire initial credentials for client applications.  The current
    hardcoded default is a placeholder, and will likely change before
    1.11.
    
    Add test framework settings to ensure that a system default client
    keytab doesn't interfere with tests, and to allow tests to be written
    to deliberately use the default client keytab.
    
    Add documentation about keytabs to the concepts section of the RST
    docs, and describe the default client keytab there.
    
    ticket: 7188 (new)

 doc/rst_source/conf.py                             |    1 +
 doc/rst_source/krb_admins/conf_files/krb5_conf.rst |    4 +
 doc/rst_source/krb_admins/env_variables.rst        |    4 +
 doc/rst_source/krb_appldev/refs/api/index.rst      |    1 +
 doc/rst_source/krb_basic/index.rst                 |    1 +
 doc/rst_source/krb_basic/keytab_def.rst            |   61 ++++++++++++++++++++
 doc/rst_source/mitK5defaults.rst                   |    1 +
 src/include/k5-int.h                               |    4 +
 src/include/krb5/krb5.hin                          |   16 +++++
 src/include/osconf.hin                             |    2 +
 src/kadmin/testing/scripts/env-setup.shin          |    1 +
 src/kadmin/testing/scripts/init_db                 |    1 +
 src/lib/krb5/keytab/ktdefault.c                    |   14 +++++
 src/lib/krb5/libkrb5.exports                       |    1 +
 src/lib/krb5/os/ktdefname.c                        |   33 +++++++++++
 src/tests/dejagnu/config/default.exp               |   16 +++++-
 src/util/k5test.py                                 |    5 ++
 17 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/doc/rst_source/conf.py b/doc/rst_source/conf.py
index 31b4892..655d3a9 100644
--- a/doc/rst_source/conf.py
+++ b/doc/rst_source/conf.py
@@ -233,6 +233,7 @@ rst_epilog += '.. |libdir| replace:: %s\n' % libdir
 rst_epilog += '.. |kdcdir| replace:: %s\\ ``/krb5kdc``\n' % localstatedir
 rst_epilog += '.. |sysconfdir| replace:: %s\n' % sysconfdir
 rst_epilog += '''
+.. |clkeytab| replace:: ``/etc/krb5.client-keytab``
 .. |keytab| replace:: ``/etc/krb5.keytab``
 .. |krb5conf| replace:: ``/etc/krb5.conf``
 .. |defkeysalts| replace:: ``aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal arcfour-hmac-md5:normal``
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 51ec79f..04d4d4d 100644
--- a/doc/rst_source/krb_admins/conf_files/krb5_conf.rst
+++ b/doc/rst_source/krb_admins/conf_files/krb5_conf.rst
@@ -132,6 +132,10 @@ The libdefaults section may contain any of the following relations:
     library will tolerate before assuming that a Kerberos message is
     invalid.  The default value is 300 seconds, or five minutes.
 
+**default_client_keytab_name**
+    This relation specifies the name of the default keytab for
+    obtaining client credentials.  The default is |clkeytab|.
+
 **default_keytab_name**
     This relation specifies the default keytab name to be used by
     application servers such as telnetd and rlogind.  The default is
diff --git a/doc/rst_source/krb_admins/env_variables.rst b/doc/rst_source/krb_admins/env_variables.rst
index 8963158..e85d54d 100644
--- a/doc/rst_source/krb_admins/env_variables.rst
+++ b/doc/rst_source/krb_admins/env_variables.rst
@@ -15,6 +15,10 @@ The following environment variables can be used during runtime:
     Default keytab file name.  (See :ref:`mitK5defaults` for the
     default name.)
 
+**KRB5_CLIENT_KTNAME**
+    Default client keytab file name.  (See :ref:`mitK5defaults` for
+    the default name.)
+
 **KRB5CCNAME**
     Default name for the credentials cache file, in the form *type*\:\
     *residual*.  The type of the default cache may determine the
diff --git a/doc/rst_source/krb_appldev/refs/api/index.rst b/doc/rst_source/krb_appldev/refs/api/index.rst
index c61f2a0..9f9f399 100644
--- a/doc/rst_source/krb_appldev/refs/api/index.rst
+++ b/doc/rst_source/krb_appldev/refs/api/index.rst
@@ -64,6 +64,7 @@ Frequently used public interfaces
    krb5_is_config_principal.rst
    krb5_is_thread_safe.rst
    krb5_kt_close.rst
+   krb5_kt_client_default.rst
    krb5_kt_default.rst
    krb5_kt_default_name.rst
    krb5_kt_get_name.rst
diff --git a/doc/rst_source/krb_basic/index.rst b/doc/rst_source/krb_basic/index.rst
index d402f21..59e2783 100644
--- a/doc/rst_source/krb_basic/index.rst
+++ b/doc/rst_source/krb_basic/index.rst
@@ -7,4 +7,5 @@ Basic Kerberos V5 concepts
 .. toctree::
    :maxdepth: 1
 
+   keytab_def.rst
    stash_file_def.rst
diff --git a/doc/rst_source/krb_basic/keytab_def.rst b/doc/rst_source/krb_basic/keytab_def.rst
new file mode 100644
index 0000000..3f1f0de
--- /dev/null
+++ b/doc/rst_source/krb_basic/keytab_def.rst
@@ -0,0 +1,61 @@
+.. _keytab_definition:
+
+keytab
+======
+
+A keytab (short for "key table") stores long-term keys for one or more
+principals.  Keytabs are normally represented by files in a standard
+format, although in rare cases they can be represented in other ways.
+Keytabs are used most often to allow server applications to accept
+authentications from clients, but can also be used to obtain initial
+credentials for client applications.
+
+Keytabs are named using the format *type*\ ``:``\ *value*.  Usually
+*type* is ``FILE`` and *value* is the absolute pathname of the file.
+Other possible values for *type* are ``SRVTAB``, which indicates a
+file in the deprecated Kerberos 4 srvtab format, and ``MEMORY``, which
+indicates a temporary keytab stored in the memory of the current
+process.
+
+A keytab contains one or more entries, where each entry consists of a
+timestamp (indicating when the entry was written to the keytab), a
+principal name, a key version number, an encryption type, and the
+encryption key itself.
+
+A keytab can be displayed using the :ref:`klist(1)` command with the
+``-k`` option.  Keytabs can be created or appended to by extracting
+keys from the KDC database using the :ref:`kadmin(1)` :ref:`ktadd`
+command.  Keytabs can be manipulated using the :ref:`ktutil(1)` and
+:ref:`k5srvutil(1)` commands.
+
+
+Default keytab
+--------------
+
+The default keytab is used by server applications if the application
+does not request a specific keytab.  The name of the default keytab is
+determined by the following, in decreasing order of preference:
+
+#. The **KRB5_KTNAME** environment variable.
+
+#. The **default_keytab_name** profile variable in :ref:`libdefaults`.
+
+#. The hardcoded default, ``FILE:``\ |keytab|.
+
+
+Default client keytab
+---------------------
+
+The default client keytab is used, if it is present and readable, to
+automatically obtain initial credentials for GSSAPI client
+applications.  The principal name of the first entry in the client
+keytab is used by default when obtaining initial credentials.  The
+name of the default client keytab is determined by the following, in
+decreasing order of preference:
+
+#. The **KRB5_CLIENT_KTNAME** environment variable.
+
+#. The **default_client_keytab_name** profile variable in
+   :ref:`libdefaults`.
+
+#. The hardcoded default, ``FILE:``\ |clkeytab|.
diff --git a/doc/rst_source/mitK5defaults.rst b/doc/rst_source/mitK5defaults.rst
index 1d27bfc..eca502f 100644
--- a/doc/rst_source/mitK5defaults.rst
+++ b/doc/rst_source/mitK5defaults.rst
@@ -10,6 +10,7 @@ General defaults
 Description                 Default                        Environment
 ==========================  =============================  ====================
 Keytab file                 ``FILE:``\ |keytab|            **KRB5_KTNAME**
+Client keytab file          ``FILE:``\ |clkeytab|          **KRB5_CLIENT_KTNAME**
 Kerberos config file        |krb5conf|\ ``:``\             **KRB5_CONFIG**
                             |sysconfdir|\ ``/krb5.conf``
 KDC config file             |kdcdir|\ ``/kdc.conf``        **KRB5_KDC_PROFILE**
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index b1e535e..69d30b3 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -199,6 +199,7 @@ typedef INT64_TYPE krb5_int64;
 #define KRB5_CONF_DB_MODULE_DIR                  "db_module_dir"
 #define KRB5_CONF_DEFAULT                        "default"
 #define KRB5_CONF_DEFAULT_REALM                  "default_realm"
+#define KRB5_CONF_DEFAULT_CLIENT_KEYTAB_NAME     "default_client_keytab_name"
 #define KRB5_CONF_DEFAULT_DOMAIN                 "default_domain"
 #define KRB5_CONF_DEFAULT_TKT_ENCTYPES           "default_tkt_enctypes"
 #define KRB5_CONF_DEFAULT_TGS_ENCTYPES           "default_tgs_enctypes"
@@ -2353,6 +2354,9 @@ krb5_error_code KRB5_CALLCONV krb5_kt_register(krb5_context,
 krb5_error_code k5_kt_get_principal(krb5_context context, krb5_keytab keytab,
                                     krb5_principal *princ_out);
 
+krb5_error_code k5_kt_client_default_name(krb5_context context,
+                                          char **name_out);
+
 krb5_error_code krb5_principal2salt_norealm(krb5_context, krb5_const_principal,
                                             krb5_data *);
 
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 470835a..51ebbb2 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -4209,6 +4209,22 @@ krb5_error_code KRB5_CALLCONV
 krb5_kt_default(krb5_context context, krb5_keytab *id);
 
 /**
+ * Resolve the default client key table.
+ *
+ * @param [in]     context      Library context
+ * @param [out]    keytab_out   Key table handle
+ *
+ * Fill @a keytab_out with a handle to the default client key table.
+ *
+ * @retval
+ * 0  Success
+ * @return
+ * Kerberos error codes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_kt_client_default(krb5_context context, krb5_keytab *keytab_out);
+
+/**
  * Free the contents of a key table entry.
  *
  * @param [in] context          Library context
diff --git a/src/include/osconf.hin b/src/include/osconf.hin
index f53ef1b..97aae48 100644
--- a/src/include/osconf.hin
+++ b/src/include/osconf.hin
@@ -43,6 +43,7 @@
 #if defined(_WIN32)
 #define DEFAULT_PROFILE_FILENAME "krb5.ini"
 #define DEFAULT_KEYTAB_NAME     "FILE:%s\\krb5kt"
+#define DEFAULT_CLIENT_KEYTAB_NAME "FILE:%s\\krb5clientkt"
 #else /* !_WINDOWS */
 #if TARGET_OS_MAC
 #define DEFAULT_SECURE_PROFILE_PATH "/Library/Preferences/edu.mit.Kerberos:/etc/krb5.conf:@SYSCONFDIR/krb5.conf"
@@ -55,6 +56,7 @@
 #define DEFAULT_PROFILE_PATH        DEFAULT_SECURE_PROFILE_PATH
 #endif
 #define DEFAULT_KEYTAB_NAME     "FILE:/etc/krb5.keytab"
+#define DEFAULT_CLIENT_KEYTAB_NAME "FILE:/etc/krb5.client-keytab"
 #endif /* _WINDOWS  */
 
 #define DEFAULT_PLUGIN_BASE_DIR "@LIBDIR/krb5/plugins"
diff --git a/src/kadmin/testing/scripts/env-setup.shin b/src/kadmin/testing/scripts/env-setup.shin
index bee5b54..de1578b 100755
--- a/src/kadmin/testing/scripts/env-setup.shin
+++ b/src/kadmin/testing/scripts/env-setup.shin
@@ -78,6 +78,7 @@ SRVTCL=$TESTDIR/util/kadm5_srv_tcl; export SRVTCL
 KRB5_CONFIG=$K5ROOT/krb5.conf; export KRB5_CONFIG
 KRB5_KDC_PROFILE=$K5ROOT/kdc.conf; export KRB5_KDC_PROFILE
 KRB5_KTNAME=$K5ROOT/ovsec_adm.srvtab; export KRB5_KTNAME
+KRB5_CLIENT_KTNAME=$K5ROOT/client_keytab; export KRB5_CLIENT_KTNAME
 KRB5CCNAME=$K5ROOT/krb5cc_unit-test; export KRB5CCNAME
 
 # Make sure we don't get confused by translated messages.
diff --git a/src/kadmin/testing/scripts/init_db b/src/kadmin/testing/scripts/init_db
index 5cf7491..12a118d 100755
--- a/src/kadmin/testing/scripts/init_db
+++ b/src/kadmin/testing/scripts/init_db
@@ -223,6 +223,7 @@ cat > $K5ROOT/setup.csh <<EOF
 setenv KRB5_CONFIG $KRB5_CONFIG
 setenv KRB5_KDC_PROFILE $KRB5_KDC_PROFILE
 setenv KRB5_KTNAME $KRB5_KTNAME
+setenv KRB5_CLIENT_KTNAME $KRB5_CLIENT_KTNAME
 $KRB5_RUN_ENV_CSH
 EOF
 
diff --git a/src/lib/krb5/keytab/ktdefault.c b/src/lib/krb5/keytab/ktdefault.c
index 7ee94ed..2b1c298 100644
--- a/src/lib/krb5/keytab/ktdefault.c
+++ b/src/lib/krb5/keytab/ktdefault.c
@@ -44,4 +44,18 @@ krb5_kt_default(krb5_context context, krb5_keytab *id)
     return krb5_kt_resolve(context, defname, id);
 }
 
+krb5_error_code KRB5_CALLCONV
+krb5_kt_client_default(krb5_context context, krb5_keytab *keytab_out)
+{
+    krb5_error_code ret;
+    char *name;
+
+    ret = k5_kt_client_default_name(context, &name);
+    if (ret)
+        return ret;
+    ret = krb5_kt_resolve(context, name, keytab_out);
+    free(name);
+    return ret;
+}
+
 #endif /* LEAN_CLIENT */
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 0af5150..e5acff2 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -395,6 +395,7 @@ krb5_is_referral_realm
 krb5_is_thread_safe
 krb5_kdc_rep_decrypt_proc
 krb5_kt_add_entry
+krb5_kt_client_default
 krb5_kt_close
 krb5_kt_default
 krb5_kt_default_name
diff --git a/src/lib/krb5/os/ktdefname.c b/src/lib/krb5/os/ktdefname.c
index afc344e..a213750 100644
--- a/src/lib/krb5/os/ktdefname.c
+++ b/src/lib/krb5/os/ktdefname.c
@@ -74,3 +74,36 @@ krb5_kt_default_name(krb5_context context, char *name, int name_size)
     }
     return 0;
 }
+
+krb5_error_code
+k5_kt_client_default_name(krb5_context context, char **name_out)
+{
+    char *str, *name;
+
+    *name_out = NULL;
+    if (!context->profile_secure &&
+        (str = getenv("KRB5_CLIENT_KTNAME")) != NULL) {
+        name = strdup(str);
+    } 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);
+        profile_release_string(str);
+    } 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
+    }
+    if (name == NULL)
+        return ENOMEM;
+    *name_out = name;
+    return 0;
+}
diff --git a/src/tests/dejagnu/config/default.exp b/src/tests/dejagnu/config/default.exp
index 8ab4b79..192ac6d 100644
--- a/src/tests/dejagnu/config/default.exp
+++ b/src/tests/dejagnu/config/default.exp
@@ -631,7 +631,7 @@ proc envstack_pop { } {
 # Initialize the envstack
 #
 set envvars_tosave {
-    KRB5_CONFIG KRB5CCNAME KRBTKFILE KRB5RCACHEDIR KRB5_KDC_PROFILE
+    KRB5_CONFIG KRB5CCNAME KRB5_CLIENT_KTNAME KRB5RCACHEDIR KRB5_KDC_PROFILE
 }
 set krb5_init_vars [list ]
 # XXX -- fix me later!
@@ -997,6 +997,12 @@ if [info exists env(KRB5CCNAME)] {
     catch "unset orig_krb5ccname"
 }
 
+if [info exists env(KRB5_CLIENT_KTNAME)] {
+    set orig_krb5clientktname $env(KRB5_CLIENT_KTNAME)
+} else {
+    catch "unset orig_krb5clientktname"
+}
+
 if [ info exists env(KRB5RCACHEDIR)] {
     set orig_krb5rcachedir $env(KRB5RCACHEDIR)
 } else {
@@ -1024,6 +1030,10 @@ proc setup_kerberos_env { {type client} } {
     set env(KRB5CCNAME) $tmppwd/tkt
     verbose "KRB5CCNAME=$env(KRB5CCNAME)"
 
+    # Direct the Kerberos programs at a local client keytab.
+    set env(KRB5_CLIENT_KTNAME) $tmppwd/client_keytab
+    verbose "KRB5_CLIENT_KTNAME=$env(KRB5_CLIENT_KTNAME)"
+
     # Direct the Kerberos server at a cache file stored in the
     # temporary directory.
     set env(KRB5RCACHEDIR) $tmppwd
@@ -1049,6 +1059,7 @@ proc setup_kerberos_env { {type client} } {
 	set envfile [open $tmppwd/$type-env.sh w]
 	puts $envfile "KRB5_CONFIG=$env(KRB5_CONFIG)"
 	puts $envfile "KRB5CCNAME=$env(KRB5CCNAME)"
+	puts $envfile "KRB5_CLIENT_KTNAME=$env(KRB5_CLIENT_KTNAME)"
 	puts $envfile "KRB5RCACHEDIR=$env(KRB5RCACHEDIR)"
 	if [info exists env(KRB5_KDC_PROFILE)] {
 	    puts $envfile "KRB5_KDC_PROFILE=$env(KRB5_KDC_PROFILE)"
@@ -1056,7 +1067,7 @@ proc setup_kerberos_env { {type client} } {
 	    puts $envfile "unset KRB5_KDC_PROFILE"
 	}
 	puts $envfile "export KRB5_CONFIG KRB5CCNAME KRB5RCACHEDIR"
-	puts $envfile "export KRB5_KDC_PROFILE"
+	puts $envfile "export KRB5_KDC_PROFILE KRB5_CLIENT_KTNAME"
 	foreach i $krb5_init_vars {
 		regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
 		puts $envfile "$evar=$env($evar)"
@@ -1068,6 +1079,7 @@ proc setup_kerberos_env { {type client} } {
 	set envfile [open $tmppwd/$type-env.csh w]
 	puts $envfile "setenv KRB5_CONFIG $env(KRB5_CONFIG)"
 	puts $envfile "setenv KRB5CCNAME $env(KRB5CCNAME)"
+	puts $envfile "setenv KRB5_CLIENT_KTNAME $env(KRB5_CLIENT_KTNAME)"
 	puts $envfile "setenv KRB5RCACHEDIR $env(KRB5RCACHEDIR)"
 	if [info exists env(KRB5_KDC_PROFILE)] {
 	    puts $envfile "setenv KRB5_KDC_PROFILE $env(KRB5_KDC_PROFILE)"
diff --git a/src/util/k5test.py b/src/util/k5test.py
index f60cb5d..c5669be 100644
--- a/src/util/k5test.py
+++ b/src/util/k5test.py
@@ -309,6 +309,9 @@ Scripts may use the following realm methods and attributes:
 * realm.keytab: A keytab file in realm.testdir.  Initially contains a
   host keytab unless disabled by the realm construction options.
 
+* realm.client_keytab: A keytab file in realm.testdir.  Initially
+  nonexistent.
+
 * realm.ccache: A ccache file in realm.testdir.  Initially contains
   credentials for user unless disabled by the realm construction
   options.
@@ -705,6 +708,7 @@ class K5Realm(object):
         self.nfs_princ = 'nfs/%s@%s' % (hostname, self.realm)
         self.krbtgt_princ = 'krbtgt/%s@%s' % (self.realm, self.realm)
         self.keytab = os.path.join(self.testdir, 'keytab')
+        self.client_keytab = os.path.join(self.testdir, 'client_keytab')
         self.ccache = os.path.join(self.testdir, 'ccache')
         self.kadmin_ccache = os.path.join(self.testdir, 'kadmin_ccache')
         self._krb5_conf = _cfg_merge(_default_krb5_conf, krb5_conf)
@@ -835,6 +839,7 @@ class K5Realm(object):
             env['KRB5_KDC_PROFILE'] = filename
         env['KRB5CCNAME'] = self.ccache
         env['KRB5_KTNAME'] = self.keytab
+        env['KRB5_CLIENT_KTNAME'] = self.client_keytab
         env['KRB5RCACHEDIR'] = self.testdir
         return env
 


More information about the cvs-krb5 mailing list