diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index b1193b3f8..635f6472a 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -97,7 +97,7 @@ find_etype(hdb_entry *princ, krb5_enctype *etypes, unsigned len, for(i = 0; ret != 0 && i < len ; i++) { Key *key = NULL; - if (krb5_enctype_is_disabled(context, etypes[i])) + if (krb5_enctype_valid(context, etypes[i]) != 0) continue; while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) { @@ -348,7 +348,7 @@ get_pa_etype_info(METHOD_DATA *md, hdb_entry *client, goto skip1; for(i = 0; i < client->keys.len; i++) { if(client->keys.val[i].key.keytype == etypes[j]) { - if (krb5_enctype_is_disabled(context, etypes[j])) + if (krb5_enctype_valid(context, etypes[j]) != 0) continue; if((ret = make_etype_info_entry(&pa.val[n++], &client->keys.val[i])) != 0) { @@ -364,7 +364,7 @@ get_pa_etype_info(METHOD_DATA *md, hdb_entry *client, if(client->keys.val[i].key.keytype == etypes[j]) goto skip2; } - if (krb5_enctype_is_disabled(context, client->keys.val[i].key.keytype)) + if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0) continue; if((ret = make_etype_info_entry(&pa.val[n++], &client->keys.val[i])) != 0) { @@ -500,7 +500,7 @@ get_pa_etype_info2(METHOD_DATA *md, hdb_entry *client, goto skip1; for(i = 0; i < client->keys.len; i++) { if(client->keys.val[i].key.keytype == etypes[j]) { - if (krb5_enctype_is_disabled(context, etypes[j])) + if (krb5_enctype_valid(context, etypes[j]) != 0) continue; if((ret = make_etype_info2_entry(&pa.val[n++], &client->keys.val[i])) != 0) { @@ -516,7 +516,7 @@ get_pa_etype_info2(METHOD_DATA *md, hdb_entry *client, if(client->keys.val[i].key.keytype == etypes[j]) goto skip2; } - if (krb5_enctype_is_disabled(context, client->keys.val[i].key.keytype)) + if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0) continue; if((ret = make_etype_info2_entry(&pa.val[n++], &client->keys.val[i])) != 0) { @@ -1408,6 +1408,7 @@ tgs_make_reply(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *adtkt, AuthorizationData *auth_data, + krb5_data *referral, hdb_entry *server, hdb_entry *client, krb5_principal client_principal, @@ -1455,6 +1456,7 @@ tgs_make_reply(KDC_REQ_BODY *b, rep.pvno = 5; rep.msg_type = krb_tgs_rep; + rep.padata = NULL; et.authtime = tgt->authtime; fix_time(&b->till); @@ -1564,8 +1566,7 @@ tgs_make_reply(KDC_REQ_BODY *b, ek.key = et.key; /* MIT must have at least one last_req */ - ek.last_req.len = 1; - ek.last_req.val = calloc(1, sizeof(*ek.last_req.val)); + ALLOC_SEQ(&ek.last_req, 1); ek.nonce = b->nonce; ek.flags = et.flags; ek.authtime = et.authtime; @@ -1575,6 +1576,45 @@ tgs_make_reply(KDC_REQ_BODY *b, ek.srealm = rep.ticket.realm; ek.sname = rep.ticket.sname; + if (referral) { + krb5_crypto crypto; + EncryptedData enc; + size_t len; + + ALLOC(rep.padata); + ALLOC_SEQ(rep.padata, 1); + rep.padata->val[0].padata_type = KRB5_PADATA_SERVER_REFERRAL; + + ret = krb5_crypto_init(context, &et.key, 0, &crypto); + if (ret) { + kdc_log(0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + goto out; + } + ret = krb5_encrypt_EncryptedData(context, + crypto, + KRB5_KU_PA_SERVER_REFERRAL, + referral->data, + referral->length, + 0, + &enc); + krb5_crypto_destroy(context, crypto); + if (ret) { + kdc_log(0, "referral krb5_encrypt_EncryptedData: %s", + krb5_get_err_text(context, ret)); + goto out; + } + ASN1_MALLOC_ENCODE(EncryptedData, rep.padata->val[0].padata_value.data, + rep.padata->val[0].padata_value.length, &enc, + &len, ret); + free_EncryptedData(&enc); + if (ret) { + kdc_log(0, "failed encoding EncryptedData for referral: %s", + krb5_get_err_text(context, ret)); + goto out; + } + } + /* It is somewhat unclear where the etype in the following encryption should come from. What we have is a session key in the passed tgt, and a list of preferred etypes @@ -1739,6 +1779,9 @@ tgs_rep2(KDC_REQ_BODY *b, krb5_principal sp = NULL; AuthorizationData *auth_data = NULL; + krb5_boolean did_referral = FALSE; + krb5_data *referral = NULL; + *csec = NULL; *cusec = NULL; @@ -2024,6 +2067,7 @@ tgs_rep2(KDC_REQ_BODY *b, if (ret) goto out; krb5_free_host_realm(context, realms); + did_referral = TRUE; goto server_lookup; } krb5_free_host_realm(context, realms); @@ -2082,10 +2126,43 @@ tgs_rep2(KDC_REQ_BODY *b, goto out; } + if (did_referral) { + KrbServerReferralData r; + size_t len; + + r.referred_realm = &sp->realm; + r.true_principal_name = NULL; + + ALLOC(referral); + if (referral == NULL) { + kdc_log(0, "malloc: out of memory"); + e_text = "malloc: out of memory"; + ret = ENOMEM; + goto out; + } + ASN1_MALLOC_ENCODE(KrbServerReferralData, referral->data, + referral->length, &r, &len, ret); + if (ret) { + kdc_log(0, "failed to encode referral: %s", + krb5_get_err_text(context, ret)); + e_text = "failed to encode referral"; + goto out; + } + if (len != referral->length) { + krb5_free_data(context, referral); + kdc_log(0, "Internal error in ASN.1 encoder"); + referral = NULL; + e_text = "KDC internal error"; + ret = KRB5KRB_ERR_GENERIC; + goto out2; + } + } + ret = tgs_make_reply(b, tgt, b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL, auth_data, + referral, server, client, cp, @@ -2102,6 +2179,8 @@ tgs_rep2(KDC_REQ_BODY *b, free_ent(server); if(client) free_ent(client); + if (referral) + krb5_free_data(context, referral); } out2: if(ret) { diff --git a/lib/krb5/context.c b/lib/krb5/context.c index 00a4afca1..4a57e5c85 100644 --- a/lib/krb5/context.c +++ b/lib/krb5/context.c @@ -68,7 +68,7 @@ set_etypes (krb5_context context, krb5_enctype e; if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0) continue; - if (krb5_enctype_is_disabled(context, e)) + if (krb5_enctype_valid(context, e) != 0) continue; etypes[k++] = e; } @@ -436,7 +436,7 @@ default_etypes(krb5_context context, krb5_enctype **etype) int i, n = 0; for (i = 0; i < sizeof(p)/sizeof(p[0]); i++) { - if (krb5_enctype_is_disabled(context, p[i])) + if (krb5_enctype_valid(context, p[i]) != 0) continue; ep = realloc(e, (n + 2) * sizeof(*e)); if (ep == NULL) { diff --git a/lib/krb5/rd_req.c b/lib/krb5/rd_req.c index 7ab609299..1747d6b89 100644 --- a/lib/krb5/rd_req.c +++ b/lib/krb5/rd_req.c @@ -436,7 +436,7 @@ krb5_verify_ap_req2(krb5_context context, int i; for (i = 0; i < etypes.len; i++) { - if (!krb5_enctype_is_disabled(context, etypes.val[i])) { + if (krb5_enctype_valid(context, etypes.val[i]) == 0) { ac->keytype = etypes.val[i]; break; }