diff options
author | Greg Hudson <ghudson@mit.edu> | 2012-06-15 11:14:39 -0400 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2012-07-02 00:59:45 -0400 |
commit | d1fe0728c830fe52bdcb5d53c517a9462391069d (patch) | |
tree | 9030eff3f99c4fb2f240380999b09be246b8fb41 | |
parent | 49ba7c90fce86581ff6faaa9ee48c80b0be9491e (diff) | |
download | krb5-d1fe0728c830fe52bdcb5d53c517a9462391069d.tar.gz krb5-d1fe0728c830fe52bdcb5d53c517a9462391069d.tar.xz krb5-d1fe0728c830fe52bdcb5d53c517a9462391069d.zip |
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)
-rw-r--r-- | doc/rst_source/conf.py | 1 | ||||
-rw-r--r-- | doc/rst_source/krb_admins/conf_files/krb5_conf.rst | 4 | ||||
-rw-r--r-- | doc/rst_source/krb_admins/env_variables.rst | 4 | ||||
-rw-r--r-- | doc/rst_source/krb_appldev/refs/api/index.rst | 1 | ||||
-rw-r--r-- | doc/rst_source/krb_basic/index.rst | 1 | ||||
-rw-r--r-- | doc/rst_source/krb_basic/keytab_def.rst | 61 | ||||
-rw-r--r-- | doc/rst_source/mitK5defaults.rst | 1 | ||||
-rw-r--r-- | src/include/k5-int.h | 4 | ||||
-rw-r--r-- | src/include/krb5/krb5.hin | 16 | ||||
-rw-r--r-- | src/include/osconf.hin | 2 | ||||
-rwxr-xr-x | src/kadmin/testing/scripts/env-setup.shin | 1 | ||||
-rwxr-xr-x | src/kadmin/testing/scripts/init_db | 1 | ||||
-rw-r--r-- | src/lib/krb5/keytab/ktdefault.c | 14 | ||||
-rw-r--r-- | src/lib/krb5/libkrb5.exports | 1 | ||||
-rw-r--r-- | src/lib/krb5/os/ktdefname.c | 33 | ||||
-rw-r--r-- | src/tests/dejagnu/config/default.exp | 16 | ||||
-rw-r--r-- | 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 31b4892e4b..655d3a9cb6 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 51ec79fc18..04d4d4d304 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 8963158acc..e85d54da0f 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 c61f2a00b1..9f9f399011 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 d402f21848..59e2783ea1 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 0000000000..3f1f0de10b --- /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 1d27bfcc02..eca502fb4d 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 b1e535e598..69d30b3b57 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 470835a2d3..51ebbb2e60 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 f53ef1b5cc..97aae48f0d 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 bee5b5482c..de1578b569 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 5cf7491099..12a118d765 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 7ee94edae0..2b1c298ce2 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 0af5150ccb..e5acff2d8a 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 afc344e4d9..a213750dba 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 8ab4b7902d..192ac6da9f 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 f60cb5d0b5..c5669bef29 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 |