diff options
Diffstat (limited to 'third_party/heimdal/lib/krb5/ticket.c')
-rw-r--r-- | third_party/heimdal/lib/krb5/ticket.c | 91 |
1 files changed, 67 insertions, 24 deletions
diff --git a/third_party/heimdal/lib/krb5/ticket.c b/third_party/heimdal/lib/krb5/ticket.c index 11e4e84963b..e2f2ab2085c 100644 --- a/third_party/heimdal/lib/krb5/ticket.c +++ b/third_party/heimdal/lib/krb5/ticket.c @@ -204,13 +204,38 @@ krb5_ticket_get_flags(krb5_context context, return TicketFlags2int(ticket->ticket.flags); } +/* + * Find an authz-data element in the given `ad'. If `failp', then validate any + * containing AD-KDC-ISSUED's keyed checksum with the `sessionkey' (if given). + * + * All AD-KDC-ISSUED will be validated (if requested) even when `type' is + * `KRB5_AUTHDATA_KDC_ISSUED'. + * + * Only the first matching element will be output (via `data'). + * + * Note that all AD-KDC-ISSUEDs found while traversing the authz-data will be + * validated, though only the first one will be returned. + * + * XXX We really need a better interface though. First, forget AD-AND-OR -- + * just remove it. Second, probably forget AD-KDC-ISSUED, but still, between + * that, the PAC, and the CAMMAC, we need an interface that can: + * + * a) take the derived keys instead of the service key or the session key, + * b) can indicate whether the element was marked critical, + * c) can indicate whether the element was authenticated to the KDC, + * d) can iterate over all the instances found (if more than one is found). + * + * Also, we need to know here if the authz-data is from a Ticket or from an + * Authenticator -- if the latter then we must refuse to find AD-KDC-ISSUED / + * PAC / CAMMAC or anything of the sort, ever. + */ static int find_type_in_ad(krb5_context context, int type, - krb5_data *data, + krb5_data *data, /* optional */ krb5_boolean *found, - krb5_boolean failp, - krb5_keyblock *sessionkey, + krb5_boolean failp, /* validate AD-KDC-ISSUED */ + krb5_keyblock *sessionkey, /* ticket session key */ const AuthorizationData *ad, int level) { @@ -233,14 +258,19 @@ find_type_in_ad(krb5_context context, */ for (i = 0; i < ad->len; i++) { if (!*found && ad->val[i].ad_type == type) { - ret = der_copy_octet_string(&ad->val[i].ad_data, data); - if (ret) { - krb5_set_error_message(context, ret, - N_("malloc: out of memory", "")); - goto out; - } + if (data) { + ret = der_copy_octet_string(&ad->val[i].ad_data, data); + if (ret) { + krb5_set_error_message(context, ret, + N_("malloc: out of memory", "")); + goto out; + } + } *found = TRUE; - continue; + if (type != KRB5_AUTHDATA_KDC_ISSUED || + !failp || !sessionkey || !sessionkey->keyvalue.length) + continue; + /* else go on to validate the AD-KDC-ISSUED's keyed checksum */ } switch (ad->val[i].ad_type) { case KRB5_AUTHDATA_IF_RELEVANT: { @@ -263,7 +293,6 @@ find_type_in_ad(krb5_context context, goto out; break; } -#if 0 /* XXX test */ case KRB5_AUTHDATA_KDC_ISSUED: { AD_KDCIssued child; @@ -278,7 +307,7 @@ find_type_in_ad(krb5_context context, ret); goto out; } - if (failp) { + if (failp && sessionkey && sessionkey->keyvalue.length) { krb5_boolean valid; krb5_data buf; size_t len; @@ -306,7 +335,12 @@ find_type_in_ad(krb5_context context, free_AD_KDCIssued(&child); goto out; } - } + } else if (failp) { + krb5_clear_error_message(context); + ret = ENOENT; + free_AD_KDCIssued(&child); + goto out; + } ret = find_type_in_ad(context, type, data, found, failp, sessionkey, &child.elements, level + 1); free_AD_KDCIssued(&child); @@ -314,7 +348,6 @@ find_type_in_ad(krb5_context context, goto out; break; } -#endif case KRB5_AUTHDATA_AND_OR: if (!failp) break; @@ -338,7 +371,8 @@ find_type_in_ad(krb5_context context, out: if (ret) { if (*found) { - krb5_data_free(data); + if (data) + krb5_data_free(data); *found = 0; } } @@ -355,7 +389,8 @@ _krb5_get_ad(krb5_context context, krb5_boolean found = FALSE; krb5_error_code ret; - krb5_data_zero(data); + if (data) + krb5_data_zero(data); if (ad == NULL) { krb5_set_error_message(context, ENOENT, @@ -399,7 +434,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context, krb5_error_code ret; krb5_boolean found = FALSE; - krb5_data_zero(data); + if (data) + krb5_data_zero(data); ad = ticket->ticket.authorization_data; if (ticket->ticket.authorization_data == NULL) { @@ -752,9 +788,9 @@ _krb5_extract_ticket(krb5_context context, /* compare client and save */ ret = _krb5_principalname2krb5_principal(context, - &tmp_principal, - rep->kdc_rep.cname, - rep->kdc_rep.crealm); + &tmp_principal, + rep->kdc_rep.cname, + rep->kdc_rep.crealm); if (ret) goto out; @@ -785,12 +821,19 @@ _krb5_extract_ticket(krb5_context context, creds->client = tmp_principal; /* check server referral and save principal */ - ret = _krb5_principalname2krb5_principal (context, - &tmp_principal, - rep->enc_part.sname, - rep->enc_part.srealm); + ret = _krb5_kdcrep2krb5_principal(context, &tmp_principal, &rep->enc_part); if (ret) goto out; + + tmp_principal->nameattrs->peer_realm = + calloc(1, sizeof(tmp_principal->nameattrs->peer_realm[0])); + if (tmp_principal->nameattrs->peer_realm == NULL) { + ret = krb5_enomem(context); + goto out; + } + ret = copy_Realm(&creds->client->realm, tmp_principal->nameattrs->peer_realm); + if (ret) goto out; + if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){ ret = check_server_referral(context, rep, |