krb5: support for anonymous TGS requests

Add support to krb5_get_creds() for requesting anonymous service tickets using
a TGT, using the flag KRB5_GC_ANONYMOUS.
This commit is contained in:
Luke Howard
2019-05-03 16:04:10 +10:00
committed by Jeffrey Altman
parent af63541515
commit 55ee6c1282
3 changed files with 55 additions and 21 deletions

View File

@@ -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,

View File

@@ -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)

View File

@@ -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);