diff --git a/lib/krb5/get_cred.c b/lib/krb5/get_cred.c index b6fe2d611..42ebe111c 100644 --- a/lib/krb5/get_cred.c +++ b/lib/krb5/get_cred.c @@ -1239,21 +1239,31 @@ check_cc(krb5_context context, krb5_flags options, krb5_ccache ccache, { krb5_error_code ret; krb5_timestamp now; - krb5_times save_times = in_creds->times; - NAME_TYPE save_type = in_creds->server->name.name_type; + krb5_creds mcreds = *in_creds; krb5_timeofday(context, &now); if (!(options & KRB5_GC_EXPIRED_OK) && - in_creds->times.endtime < now) { - in_creds->times.renew_till = 0; - krb5_timeofday(context, &in_creds->times.endtime); + mcreds.times.endtime < now) { + mcreds.times.renew_till = 0; + krb5_timeofday(context, &mcreds.times.endtime); options |= KRB5_TC_MATCH_TIMES; } - if (save_type == KRB5_NT_SRV_HST_NEEDS_CANON) { + if (mcreds.server->name.name_type == KRB5_NT_SRV_HST_NEEDS_CANON) { /* Avoid name canonicalization in krb5_cc_retrieve_cred() */ - krb5_principal_set_type(context, in_creds->server, KRB5_NT_SRV_HST); + krb5_principal_set_type(context, mcreds.server, KRB5_NT_SRV_HST); + } + + if (options & KRB5_GC_ANONYMOUS) { + ret = krb5_make_principal(context, + &mcreds.client, + krb5_principal_get_realm(context, mcreds.client), + KRB5_WELLKNOWN_NAME, + KRB5_ANON_NAME, + NULL); + if (ret) + return ret; } ret = krb5_cc_retrieve_cred(context, ccache, @@ -1261,10 +1271,11 @@ check_cc(krb5_context context, krb5_flags options, krb5_ccache ccache, (KRB5_TC_DONT_MATCH_REALM | KRB5_TC_MATCH_KEYTYPE | KRB5_TC_MATCH_TIMES)), - in_creds, out_creds); + &mcreds, out_creds); + + if (options & KRB5_GC_ANONYMOUS) + krb5_free_principal(context, mcreds.client); - in_creds->server->name.name_type = save_type; - in_creds->times = save_times; return ret; } @@ -1635,6 +1646,8 @@ next_rule: flags.b.request_anonymous = 1; /* XXX ARGH confusion */ flags.b.constrained_delegation = 1; } + if (options & KRB5_GC_ANONYMOUS) + flags.b.request_anonymous = 1; tgts = NULL; ret = _krb5_get_cred_kdc_any(context, flags, ccache, diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h index 8697a1f45..17459c993 100644 --- a/lib/krb5/krb5.h +++ b/lib/krb5/krb5.h @@ -449,6 +449,7 @@ typedef union { #define KRB5_GC_NO_TRANSIT_CHECK (1U << 5) #define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6) #define KRB5_GC_CANONICALIZE (1U << 7) +#define KRB5_GC_ANONYMOUS (1U << 8) /* constants for compare_creds (and cc_retrieve_cred) */ #define KRB5_TC_DONT_MATCH_REALM (1U << 31) diff --git a/lib/krb5/ticket.c b/lib/krb5/ticket.c index 9a391e7fb..c9523bb56 100644 --- a/lib/krb5/ticket.c +++ b/lib/krb5/ticket.c @@ -527,26 +527,46 @@ noreferral: } +static krb5_boolean +is_anonymous_principal(krb5_context context, 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; +} + /* - * Verify referral data + * Verify returned client principal name in anonymous/referral case */ - static krb5_error_code -check_client_referral(krb5_context context, +check_client_mismatch(krb5_context context, krb5_kdc_rep *rep, krb5_const_principal requested, krb5_const_principal mapped, krb5_keyblock const * key) { - if (krb5_principal_compare(context, requested, mapped) == FALSE && - !rep->enc_part.flags.enc_pa_rep) - { - krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, - N_("Not same client principal returned " - "as requested", "")); - return KRB5KRB_AP_ERR_MODIFIED; + if (rep->enc_part.flags.anonymous) { + if (!is_anonymous_principal(context, mapped)) { + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + N_("Anonymous ticket does not contain anonymous " + "principal", "")); + return KRB5KRB_AP_ERR_MODIFIED; + } + } else { + if (krb5_principal_compare(context, requested, mapped) == FALSE && + !rep->enc_part.flags.enc_pa_rep) { + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + N_("Not same client principal returned " + "as requested", "")); + return KRB5KRB_AP_ERR_MODIFIED; + } } + return 0; } @@ -690,7 +710,7 @@ _krb5_extract_ticket(krb5_context context, /* check client referral and save principal */ /* anonymous here ? */ if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) { - ret = check_client_referral(context, rep, + ret = check_client_mismatch(context, rep, creds->client, tmp_principal, &creds->session);