Skip to content

Commit

Permalink
Better handle failures to resolve client keytab
Browse files Browse the repository at this point in the history
In krb5_gss_acquire_cred(), treat failure to resolve the client keytab
similarly to a client keytab which resolves but does not exist or has
no entries.  The client keytab could fail to resolve if its name
contains %{username} and the current process is acting on behalf of
the NSS system.

[ghudson@mit.edu: rewrote commit message; changed tracing call to use
a macro; cleared error message when ignoring krb5_kt_client_default()
error; added test case]

ticket: 8462 (new)
  • Loading branch information
Will Fiveash authored and greghudson committed Jul 22, 2016
1 parent de92d6c commit bd2c2a0
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/include/k5-trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ void krb5int_trace(krb5_context context, const char *fmt, ...);
#define TRACE_GIC_PWD_MASTER(c) \
TRACE(c, "Retrying AS request with master KDC")

#define TRACE_GSS_CLIENT_KEYTAB_FAIL(c, ret) \
TRACE(c, "Unable to resolve default client keytab: {kerr}", ret)

#define TRACE_ENCTYPE_LIST_UNKNOWN(c, profvar, name) \
TRACE(c, "Unrecognized enctype name in {str}: {str}", profvar, name)

Expand Down
23 changes: 20 additions & 3 deletions src/lib/gssapi/krb5/acquire_cred.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ can_get_initial_creds(krb5_context context, krb5_gss_cred_id_rec *cred)
if (cred->password != NULL)
return TRUE;

if (cred->client_keytab == NULL)
return FALSE;

/* If we don't know the client principal yet, check for any keytab keys. */
if (cred->name == NULL)
return !krb5_kt_have_content(context, cred->client_keytab);
Expand Down Expand Up @@ -522,6 +525,10 @@ get_name_from_client_keytab(krb5_context context, krb5_gss_cred_id_rec *cred)
krb5_principal princ;

assert(cred->name == NULL);

if (cred->client_keytab == NULL)
return KRB5_KT_NOTFOUND;

code = k5_kt_get_principal(context, cred->client_keytab, &princ);
if (code)
return code;
Expand Down Expand Up @@ -601,9 +608,11 @@ get_initial_cred(krb5_context context, krb5_gss_cred_id_rec *cred)
code = krb5_get_init_creds_password(context, &creds, cred->name->princ,
cred->password, NULL, NULL, 0,
NULL, opt);
} else {
} else if (cred->client_keytab != NULL) {
code = krb5_get_init_creds_keytab(context, &creds, cred->name->princ,
cred->client_keytab, 0, NULL, opt);
} else {
code = KRB5_KT_NOTFOUND;
}
if (code)
goto cleanup;
Expand Down Expand Up @@ -680,10 +689,18 @@ acquire_init_cred(krb5_context context,
goto error;
}

if (client_keytab != NULL)
if (client_keytab != NULL) {
code = krb5_kt_dup(context, client_keytab, &cred->client_keytab);
else
} else {
code = krb5_kt_client_default(context, &cred->client_keytab);
if (code) {
/* Treat resolution failure similarly to a client keytab which
* resolves but doesn't exist or has no content. */
TRACE_GSS_CLIENT_KEYTAB_FAIL(context, code);
krb5_clear_error_message(context);
code = 0;
}
}
if (code)
goto error;

Expand Down
4 changes: 3 additions & 1 deletion src/lib/gssapi/krb5/iakerb.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,11 @@ iakerb_init_creds_ctx(iakerb_ctx_id_t ctx,
if (cred->password != NULL) {
code = krb5_init_creds_set_password(ctx->k5c, ctx->icc,
cred->password);
} else {
} else if (cred->client_keytab != NULL) {
code = krb5_init_creds_set_keytab(ctx->k5c, ctx->icc,
cred->client_keytab);
} else {
code = KRB5_KT_NOTFOUND;
}
if (code != 0)
goto cleanup;
Expand Down
10 changes: 10 additions & 0 deletions src/tests/gssapi/t_client_keytab.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,14 @@
fail('Expected error not seen')
realm.run([kdestroy, '-A'])

# Test 16: default client keytab cannot be resolved, but valid
# credentials exist in ccache.
conf = {'libdefaults': {'default_client_keytab_name': '%{'}}
bad_cktname = realm.special_env('bad_cktname', False, krb5_conf=conf)
del bad_cktname['KRB5_CLIENT_KTNAME']
realm.kinit(realm.user_princ, password('user'))
out = realm.run(['./t_ccselect', phost], env=bad_cktname)
if realm.user_princ not in out:
fail('Expected principal not seen for bad client keytab name')

success('Client keytab tests')

1 comment on commit bd2c2a0

@wfiveash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing up my pull request.

Please sign in to comment.