]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add krb5_kt_client_default API
authorGreg Hudson <ghudson@mit.edu>
Fri, 15 Jun 2012 15:14:39 +0000 (11:14 -0400)
committerGreg Hudson <ghudson@mit.edu>
Mon, 2 Jul 2012 04:59:45 +0000 (00:59 -0400)
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)

17 files changed:
doc/rst_source/conf.py
doc/rst_source/krb_admins/conf_files/krb5_conf.rst
doc/rst_source/krb_admins/env_variables.rst
doc/rst_source/krb_appldev/refs/api/index.rst
doc/rst_source/krb_basic/index.rst
doc/rst_source/krb_basic/keytab_def.rst [new file with mode: 0644]
doc/rst_source/mitK5defaults.rst
src/include/k5-int.h
src/include/krb5/krb5.hin
src/include/osconf.hin
src/kadmin/testing/scripts/env-setup.shin
src/kadmin/testing/scripts/init_db
src/lib/krb5/keytab/ktdefault.c
src/lib/krb5/libkrb5.exports
src/lib/krb5/os/ktdefname.c
src/tests/dejagnu/config/default.exp
src/util/k5test.py

index 31b4892e4b2cd4cb4b6a52d1dc079f3d6fbf70ae..655d3a9cb654e11aea0a77ea6bb6501dcc77c0a5 100644 (file)
@@ -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``
index 51ec79fc18c50e12c7c79ece40f946f13fd24754..04d4d4d3040dae9198c818102484ef0e6676c687 100644 (file)
@@ -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
index 8963158acc63a1286dea099db5abf1ea5c5a4b5a..e85d54da0f103e78cd79e2f20fb9f81094269a40 100644 (file)
@@ -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
index c61f2a00b1af1bf0341ba9b451aafe4e974809c7..9f9f3990119f1563c9decef5978b7d27ee435b36 100644 (file)
@@ -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
index d402f2184821b6913341e092be8c2a746efdd447..59e2783ea1959d1a495f806ac647e3372f627517 100644 (file)
@@ -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 (file)
index 0000000..3f1f0de
--- /dev/null
@@ -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|.
index 1d27bfcc0214e6f62996d7ca36fa046cb7958bbe..eca502fb4d1879e772412e1ad149789a938a23ed 100644 (file)
@@ -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**
index b1e535e598d825638aa6461a839274467ba12dde..69d30b3b57f6de002a93bb773e627d3129a60aea 100644 (file)
@@ -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 *);
 
index 470835a2d3585e5e8d0b875d58d28878e603f653..51ebbb2e6060c5c4976756ae1772e3bc63e4cf32 100644 (file)
@@ -4208,6 +4208,22 @@ krb5_kt_default_name(krb5_context context, char *name, int name_size);
 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.
  *
index f53ef1b5cc0a7e6de11489aa622bb8e548b5bee6..97aae48f0d800a6b4846b89be0d8935814d4e927 100644 (file)
@@ -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"
index bee5b5482ca8c483e8dac37917840a9392a2966a..de1578b569e2f21ca2784ae391c6ba0cf1cc1eed 100755 (executable)
@@ -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.
index 5cf7491099335366913e1584c34f774e69692de4..12a118d76562a008f5890d300485a02fdd1ec961 100755 (executable)
@@ -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
 
index 7ee94edae01565760a3433d22f0d171b1c9ba2ba..2b1c298ce263a287ab903d705ae9789c1099b6ef 100644 (file)
@@ -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 */
index 0af5150ccbf8babce49b9b9439efe3539c75c642..e5acff2d8a7c092ba2ecd2659cba555b392f64cc 100644 (file)
@@ -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
index afc344e4d9d3df0f87b1f78303ab308941558e27..a213750dba26c3c89b71d88849fb402226722aac 100644 (file)
@@ -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;
+}
index 8ab4b7902d9896b987f460ca606010717c6edef9..192ac6da9f9647e115bc268abf8c41a24f489b6f 100644 (file)
@@ -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)"
index f60cb5d0b597c33564c0c8969b2e5bbf2a09b023..c5669bef2998bba990e9bdcdfd86ad86e9bb81bf 100644 (file)
@@ -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