kuser: support authenticated anonymous AS-REQs in kinit

Allow kinit to request anonymous tickets with authenticated clients, not just
anonymous PKINIT.
This commit is contained in:
Luke Howard
2019-05-03 14:45:58 +10:00
committed by Jeffrey Altman
parent 63557427e0
commit 3051db0d5d
3 changed files with 58 additions and 16 deletions

View File

@@ -82,7 +82,7 @@
.Op Fl Fl password-file= Ns Ar filename
.Op Fl Fl fcache-version= Ns Ar version-number
.Op Fl A | Fl Fl no-addresses
.Op Fl Fl anonymous
.Op Fl n | Fl Fl anonymous
.Op Fl Fl enterprise
.Op Fl Fl version
.Op Fl Fl help
@@ -165,10 +165,12 @@ in
.Xr krb5.conf 5 .
.It Fl A , Fl Fl no-addresses
Request a ticket with no addresses.
.It Fl Fl anonymous
Request an anonymous ticket (which means that the ticket will be
issued to an anonymous principal, typically
.Dq anonymous@REALM ) .
.It Fl n , Fl Fl anonymous
Request an anonymous ticket. If the principal is specified as @REALM, then
anonymous PKINIT will be used to acquire an unauthenticated anonymous ticket
and both the client name and realm in the returned ticket will be anonymized.
Otherwise, authentication proceeds as normal and the anonymous ticket will have
only the client name anonymized.
.It Fl Fl enterprise
Parse principal as a enterprise (KRB5-NT-ENTERPRISE) name. Enterprise
names are email like principals that are stored in the name part of

View File

@@ -155,7 +155,7 @@ static struct getargs args[] = {
{ "extra-addresses",'a', arg_strings, &extra_addresses,
NP_("include these extra addresses", ""), "addresses" },
{ "anonymous", 0, arg_flag, &anonymous_flag,
{ "anonymous", 'n', arg_flag, &anonymous_flag,
NP_("request an anonymous ticket", ""), NULL },
{ "request-pac", 0, arg_flag, &pac_flag,
@@ -425,12 +425,25 @@ store_ntlmkey(krb5_context context, krb5_ccache id,
}
#endif
static krb5_boolean
is_anonymous_princ_p(krb5_const_principal principal)
{
if ((principal->name.name_type != KRB5_NT_WELLKNOWN &&
principal->name.name_type != KRB5_NT_UNKNOWN) ||
principal->name.name_string.len != 2 ||
strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 ||
strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0)
return 0;
return 1;
}
static krb5_error_code
get_new_tickets(krb5_context context,
krb5_principal principal,
krb5_ccache ccache,
krb5_deltat ticket_life,
int interactive)
int interactive,
int anonymous_pkinit)
{
krb5_error_code ret;
krb5_creds cred;
@@ -529,7 +542,7 @@ get_new_tickets(krb5_context context,
krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
if (pk_user_id || ent_user_id || anonymous_flag) {
if (pk_user_id || ent_user_id || anonymous_pkinit) {
ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
principal,
pk_user_id,
@@ -537,7 +550,7 @@ get_new_tickets(krb5_context context,
NULL,
NULL,
pk_use_enckey ? 2 : 0 |
anonymous_flag ? 4 : 0,
anonymous_pkinit ? 4 : 0,
prompter,
NULL,
passwd);
@@ -629,7 +642,7 @@ get_new_tickets(krb5_context context,
krb5_warn(context, ret, "krb5_init_creds_set_keytab");
goto out;
}
} else if (pk_user_id || ent_user_id || anonymous_flag) {
} else if (pk_user_id || ent_user_id || is_anonymous_princ_p(principal)) {
} else if (!interactive && passwd[0] == '\0') {
static int already_warned = 0;
@@ -924,7 +937,7 @@ renew_func(void *ptr)
server_str, ctx->ticket_life);
} else {
ret = get_new_tickets(ctx->context, ctx->principal, ctx->ccache,
ctx->ticket_life, 0);
ctx->ticket_life, 0, 0);
}
expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
server_str, &renew_expire);
@@ -1224,6 +1237,7 @@ main(int argc, char **argv)
struct sigaction sa;
#endif
krb5_boolean unique_ccache = FALSE;
int anonymous_pkinit = FALSE;
setprogname(argv[0]);
@@ -1273,15 +1287,16 @@ main(int argc, char **argv)
pk_user_id = NULL;
} else if (anonymous_flag) {
} else if (anonymous_flag && argc && argv[0][0] == '@') {
/* If principal argument as @REALM, try anonymous PKINIT */
ret = krb5_make_principal(context, &principal, argv[0],
ret = krb5_make_principal(context, &principal, &argv[0][1],
KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME,
NULL);
if (ret)
krb5_err(context, 1, ret, "krb5_make_principal");
krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN);
anonymous_pkinit = TRUE;
} else if (use_keytab || keytab_str) {
get_princ_kt(context, &principal, argv[0]);
} else {
@@ -1388,7 +1403,8 @@ main(int argc, char **argv)
exit(ret != 0);
}
ret = get_new_tickets(context, principal, ccache, ticket_life, 1);
ret = get_new_tickets(context, principal, ccache, ticket_life,
1, anonymous_pkinit);
if (ret) {
if (unique_ccache)
krb5_cc_destroy(context, ccache);

View File

@@ -487,6 +487,30 @@ for a in $enctypes; do
done
${kdestroy}
echo "Getting client authenticated anonymous initial tickets"; > messages.log
${kinit} -n --password-file=${objdir}/foopassword foo@$R || \
{ ec=1 ; eval "${testfailed}"; }
for a in $enctypes; do
echo "Getting tickets ($a)"; > messages.log
${kgetcred} -e $a ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
{ ec=1 ; eval "${testfailed}"; }
${kdestroy} --credential=${server}@${R}
done
${kdestroy}
echo "Getting client anonymous service tickets"; > messages.log
${kinit} --password-file=${objdir}/foopassword foo@$R || \
{ ec=1 ; eval "${testfailed}"; }
for a in $enctypes; do
echo "Getting tickets ($a)"; > messages.log
${kgetcred} -n -e $a ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
${test_ap_req} ${server}@${R} ${keytab} ${cache} || \
{ ec=1 ; eval "${testfailed}"; }
${kdestroy} --credential=${server}@${R}
done
${kdestroy}
echo "Getting client initial tickets for cross realm case"; > messages.log
${kinit} --password-file=${objdir}/foopassword foo@$R || { ec=1 ; eval "${testfailed}"; }
for a in $enctypes; do
@@ -713,7 +737,7 @@ fi
if test "$pkinit" = yes -a "$rsa" = yes ; then
echo "try anonymous pkinit"; > messages.log
${kinit} --anonymous ${R} || \
${kinit} -n @${R} || \
{ ec=1 ; eval "${testfailed}"; }
${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; }
${kdestroy}