diff --git a/lib/krb5/build_auth.c b/lib/krb5/build_auth.c index 1e0a302e2..c8a45e2c1 100644 --- a/lib/krb5/build_auth.c +++ b/lib/krb5/build_auth.c @@ -35,6 +35,70 @@ RCSID("$Id$"); +static krb5_error_code +make_etypelist(krb5_context context, + krb5_authdata **auth_data) +{ + EtypeList etypes; + krb5_error_code ret; + krb5_authdata ad; + u_char *buf; + size_t len; + size_t buf_size; + + ret = krb5_init_etype(context, &etypes.len, &etypes.val, NULL); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret); + if (ret) { + free_EtypeList(&etypes); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_EtypeList(&etypes); + + ALLOC_SEQ(&ad, 1); + if (ad.val == NULL) { + free(buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION; + ad.val[0].ad_data.length = len; + ad.val[0].ad_data.data = buf; + + ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret); + if (ret) { + free_AuthorizationData(&ad); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_AuthorizationData(&ad); + + ALLOC(*auth_data, 1); + if (*auth_data == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ALLOC_SEQ(*auth_data, 1); + if ((*auth_data)->val == NULL) { + free(buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + (*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT; + (*auth_data)->val[0].ad_data.length = len; + (*auth_data)->val[0].ad_data.data = buf; + + return 0; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_build_authenticator (krb5_context context, krb5_auth_context auth_context, @@ -85,6 +149,16 @@ krb5_build_authenticator (krb5_context context, auth->authorization_data = NULL; auth->cksum = cksum; + if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) { + /* + * This is not GSS-API specific, we only enable it for + * GSS for now + */ + ret = make_etypelist(context, &auth->authorization_data); + if (ret) + goto fail; + } + /* XXX - Copy more to auth_context? */ if (auth_context) { diff --git a/lib/krb5/rd_req.c b/lib/krb5/rd_req.c index ce9f9a30b..7ab609299 100644 --- a/lib/krb5/rd_req.c +++ b/lib/krb5/rd_req.c @@ -155,6 +155,57 @@ check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) return ret; } +static krb5_error_code +find_etypelist(krb5_context context, + krb5_auth_context auth_context, + EtypeList *etypes) +{ + krb5_error_code ret; + krb5_authdata *ad; + krb5_authdata adIfRelevant; + unsigned i; + + adIfRelevant.len = 0; + + etypes->len = 0; + etypes->val = NULL; + + ad = auth_context->authenticator->authorization_data; + if (ad == NULL) + return 0; + + for (i = 0; i < ad->len; i++) { + if (ad->val[i].ad_type == KRB5_AUTHDATA_IF_RELEVANT) { + ret = decode_AD_IF_RELEVANT(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &adIfRelevant, + NULL); + if (ret) + return ret; + + if (adIfRelevant.len == 1 && + adIfRelevant.val[0].ad_type == + KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION) { + break; + } + free_AD_IF_RELEVANT(&adIfRelevant); + adIfRelevant.len = 0; + } + } + + if (adIfRelevant.len == 0) + return 0; + + ret = decode_EtypeList(adIfRelevant.val[0].ad_data.data, + adIfRelevant.val[0].ad_data.length, + etypes, + NULL); + + free_AD_IF_RELEVANT(&adIfRelevant); + + return ret; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_decrypt_ticket(krb5_context context, Ticket *ticket, @@ -279,6 +330,7 @@ krb5_verify_ap_req2(krb5_context context, krb5_ticket *t; krb5_auth_context ac; krb5_error_code ret; + EtypeList etypes; if (auth_context && *auth_context) { ac = *auth_context; @@ -374,8 +426,27 @@ krb5_verify_ap_req2(krb5_context context, goto out; } + ret = find_etypelist(context, ac, &etypes); + if (ret) + goto out; + + ac->keytype = ETYPE_NULL; + + if (etypes.val) { + int i; + + for (i = 0; i < etypes.len; i++) { + if (!krb5_enctype_is_disabled(context, etypes.val[i])) { + ac->keytype = etypes.val[i]; + break; + } + } + } + if (ap_req_options) { *ap_req_options = 0; + if (ac->keytype != ETYPE_NULL) + *ap_req_options |= AP_OPTS_USE_SUBKEY; if (ap_req->ap_options.use_session_key) *ap_req_options |= AP_OPTS_USE_SESSION_KEY; if (ap_req->ap_options.mutual_required) @@ -391,6 +462,7 @@ krb5_verify_ap_req2(krb5_context context, *auth_context = ac; } else krb5_auth_con_free (context, ac); + free_EtypeList(&etypes); return 0; out: if (t)