summaryrefslogtreecommitdiff
path: root/third_party/heimdal/lib/krb5/ticket.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib/krb5/ticket.c')
-rw-r--r--third_party/heimdal/lib/krb5/ticket.c91
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,