Skip to content

Commit

Permalink
Add token expansion for keytab names
Browse files Browse the repository at this point in the history
Make the default_keytab_name and default_client_keytab_name variables
subject to parameter expansion.

ticket: 7219 (new)
  • Loading branch information
greghudson committed Jul 24, 2012
1 parent 7d07dc6 commit fc3e8c6
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 61 deletions.
34 changes: 31 additions & 3 deletions doc/rst_source/krb_admins/conf_files/krb5_conf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
---------------------

Expand Down
4 changes: 2 additions & 2 deletions src/include/osconf.hin
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
100 changes: 44 additions & 56 deletions src/lib/krb5/os/ktdefname.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
16 changes: 16 additions & 0 deletions src/tests/t_keytab.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,20 @@
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')

0 comments on commit fc3e8c6

Please sign in to comment.