From d89b5cb966c41015fad524027107dd2d241b44e8 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Tue, 21 May 2019 15:18:16 +1000 Subject: [PATCH] kuser: allow kinit to renew anonymous PKINIT tickets Anonymous PKINIT tickets discard the realm information used to locate the issuing AS. Store the issuing realm in the credentials cache in order to locate a KDC which can renew them. --- kuser/kinit.c | 46 ++++++++++++++++++++++++++++++++++++++++-- tests/kdc/check-kdc.in | 3 ++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/kuser/kinit.c b/kuser/kinit.c index bcdbc565e..5a7d62f41 100644 --- a/kuser/kinit.c +++ b/kuser/kinit.c @@ -206,6 +206,9 @@ static struct getargs args[] = { { "help", 0, arg_flag, &help_flag, NULL, NULL } }; +static char * +get_default_realm(krb5_context context); + static void usage(int ret) { @@ -236,7 +239,7 @@ copy_configs(krb5_context context, krb5_principal start_ticket_server) { krb5_error_code ret; - const char *cfg_names[] = {"realm-config", "FriendlyName", NULL}; + const char *cfg_names[] = {"realm-config", "FriendlyName", "anon-pkinit-realm", NULL}; const char *cfg_names_w_pname[] = {"fast_avail", NULL}; krb5_data cfg_data; size_t i; @@ -276,6 +279,30 @@ copy_configs(krb5_context context, return 0; } +static krb5_error_code +get_anon_pkinit_tgs_name(krb5_context context, + krb5_ccache ccache, + krb5_principal *tgs_name) +{ + krb5_error_code ret; + krb5_data data; + char *realm; + + ret = krb5_cc_get_config(context, ccache, NULL, "anon-pkinit-realm", &data); + if (ret == 0) { + realm = malloc(data.length + 1); + memcpy(realm, data.data, data.length); + realm[data.length] = '\0'; + } else + realm = get_default_realm(context); + + ret = krb5_make_principal(context, tgs_name, realm, + KRB5_TGS_NAME, realm, NULL); + free(realm); + + return ret; +} + static krb5_error_code renew_validate(krb5_context context, int renew, @@ -296,7 +323,13 @@ renew_validate(krb5_context context, krb5_warn(context, ret, "krb5_cc_get_principal"); return ret; } - ret = get_server(context, in.client, server, &in.server); + + if (server == NULL && + krb5_principal_is_anonymous(context, in.client, + KRB5_ANON_MATCH_UNAUTHENTICATED)) + ret = get_anon_pkinit_tgs_name(context, cache, &in.server); + else + ret = get_server(context, in.client, server, &in.server); if (ret) { krb5_warn(context, ret, "get_server"); goto out; @@ -777,6 +810,15 @@ get_new_tickets(krb5_context context, krb5_cc_set_config(context, ccache, NULL, "realm-config", &data); } + if (anonymous_pkinit) { + krb5_data data; + + data.length = strlen(principal->realm); + data.data = principal->realm; + + krb5_cc_set_config(context, ccache, NULL, "anon-pkinit-realm", &data); + } + out: krb5_get_init_creds_opt_free(context, opt); if (ctx) diff --git a/tests/kdc/check-kdc.in b/tests/kdc/check-kdc.in index a341c6bd3..bef937d74 100644 --- a/tests/kdc/check-kdc.in +++ b/tests/kdc/check-kdc.in @@ -737,9 +737,10 @@ fi if test "$pkinit" = yes -a "$rsa" = yes ; then echo "try anonymous pkinit"; > messages.log - ${kinit} -n @${R} || \ + ${kinit} --renewable -n @${R} || \ { ec=1 ; eval "${testfailed}"; } ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; } + ${kinit} --renew || { ec=1 ; eval "${testfailed}"; } ${kdestroy} for type in "" "--pk-use-enckey"; do