From 014e318d6bdefd8ecfcb99ca9928921f6a49d721 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sat, 18 May 2019 13:55:36 +1000 Subject: [PATCH] krb5: check KDC supports anonymous if requested Verify the KDC recognized the request-anonymous flag by validating the returned client principal name. --- lib/krb5/get_cred.c | 2 ++ lib/krb5/get_in_tkt.c | 2 +- lib/krb5/init_creds_pw.c | 2 ++ lib/krb5/krb5_locl.h | 1 + lib/krb5/ticket.c | 40 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/krb5/get_cred.c b/lib/krb5/get_cred.c index 42ebe111c..05248b8e1 100644 --- a/lib/krb5/get_cred.c +++ b/lib/krb5/get_cred.c @@ -560,6 +560,8 @@ get_cred_kdc(krb5_context context, /* XXX should do better testing */ if (flags.b.constrained_delegation || impersonate_principal) eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; + if (flags.b.request_anonymous) + eflags |= EXTRACT_TICKET_MATCH_ANON; ret = _krb5_extract_ticket(context, &rep, diff --git a/lib/krb5/get_in_tkt.c b/lib/krb5/get_in_tkt.c index 4d68b2a33..d6a1a9345 100644 --- a/lib/krb5/get_in_tkt.c +++ b/lib/krb5/get_in_tkt.c @@ -489,7 +489,7 @@ krb5_get_in_cred(krb5_context context, { unsigned flags = EXTRACT_TICKET_TIMESYNC; if (opts.request_anonymous) - flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH | EXTRACT_TICKET_MATCH_ANON; ret = _krb5_extract_ticket(context, &rep, diff --git a/lib/krb5/init_creds_pw.c b/lib/krb5/init_creds_pw.c index 0948796c8..66608b98e 100644 --- a/lib/krb5/init_creds_pw.c +++ b/lib/krb5/init_creds_pw.c @@ -2257,6 +2257,8 @@ krb5_init_creds_step(krb5_context context, } if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK) eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; + if (ctx->flags.request_anonymous) + eflags |= EXTRACT_TICKET_MATCH_ANON; ret = process_pa_data_to_key(context, ctx, &ctx->cred, &ctx->as_req, &rep.kdc_rep, diff --git a/lib/krb5/krb5_locl.h b/lib/krb5/krb5_locl.h index 809a7e3b3..9e4d7164c 100644 --- a/lib/krb5/krb5_locl.h +++ b/lib/krb5/krb5_locl.h @@ -310,6 +310,7 @@ typedef struct krb5_context_data { #define EXTRACT_TICKET_MATCH_REALM 4 #define EXTRACT_TICKET_AS_REQ 8 #define EXTRACT_TICKET_TIMESYNC 16 +#define EXTRACT_TICKET_MATCH_ANON 32 /* * Configurable options diff --git a/lib/krb5/ticket.c b/lib/krb5/ticket.c index da9396ef0..bf8b6a083 100644 --- a/lib/krb5/ticket.c +++ b/lib/krb5/ticket.c @@ -526,6 +526,33 @@ noreferral: return 0; } +/* + * Verify KDC supported anonymous if requested + */ +static krb5_error_code +check_client_anonymous(krb5_context context, + krb5_kdc_rep *rep, + krb5_const_principal requested, + krb5_const_principal mapped, + krb5_boolean is_tgs_rep) +{ + int flags; + + if (!rep->enc_part.flags.anonymous) + return KRB5KDC_ERR_BADOPTION; + + if (is_tgs_rep) + flags = KRB5_ANON_MATCH_ANY; + else if (krb5_principal_is_anonymous(context, requested, KRB5_ANON_MATCH_ANY)) + flags = KRB5_ANON_MATCH_UNAUTHENTICATED; + else + flags = KRB5_ANON_MATCH_AUTHENTICATED; + + if (!krb5_principal_is_anonymous(context, mapped, flags)) + return KRB5KRB_AP_ERR_MODIFIED; + + return 0; +} /* * Verify returned client principal name in anonymous/referral case @@ -695,8 +722,19 @@ _krb5_extract_ticket(krb5_context context, if (ret) goto out; + /* check KDC supported anonymous if it was requested */ + if (flags & EXTRACT_TICKET_MATCH_ANON) { + ret = check_client_anonymous(context,rep, + creds->client, + tmp_principal, + request == NULL); /* is TGS */ + if (ret) { + krb5_free_principal(context, tmp_principal); + goto out; + } + } + /* check client referral and save principal */ - /* anonymous here ? */ if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) { ret = check_client_mismatch(context, rep, creds->client,