diff --git a/lib/krb5/auth_context.c b/lib/krb5/auth_context.c index 9c6c0c40f..4473a4421 100644 --- a/lib/krb5/auth_context.c +++ b/lib/krb5/auth_context.c @@ -409,24 +409,79 @@ krb5_auth_con_getkeytype (krb5_context context, return 0; } +krb5_error_code +_krb5_add_1auth_data(krb5_context context, + krb5int32 ad_type, krb5_data *ad_data, int critical, + krb5_authdata **dst) +{ + AuthorizationDataElement e; + + e.ad_type = ad_type; + e.ad_data = *ad_data; + + if (!critical) { + AuthorizationData ad; + krb5_error_code ret; + krb5_data ir; + size_t len; + + /* Build an AD-IF-RELEVANT with the new element inside it */ + ad.len = 0; + ad.val = NULL; + ret = add_AuthorizationData(&ad, &e); + + /* Encode the AD-IF-RELEVANT */ + if (ret == 0) + ASN1_MALLOC_ENCODE(AuthorizationData, ir.data, ir.length, &ad, + &len, ret); + if (ret == 0 && ir.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + /* Re-enter to add the encoded AD-IF-RELEVANT */ + ret = _krb5_add_1auth_data(context, KRB5_AUTHDATA_IF_RELEVANT, &ir, 1, + dst); + + free_AuthorizationData(&ad); + krb5_data_free(&ir); + return ret; + } + + if (*dst == NULL) { + ALLOC(*dst, 1); + if (*dst == NULL) + return krb5_enomem(context); + } + return add_AuthorizationData(*dst, &e); +} + KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_auth_con_add_AuthorizationData(krb5_context context, krb5_auth_context auth_context, int type, krb5_data *data) { - AuthorizationDataElement el; - if (auth_context->auth_data == NULL) { auth_context->auth_data = calloc(1, sizeof(*auth_context->auth_data)); if (auth_context->auth_data == NULL) return krb5_enomem(context); } - el.ad_type = type; - el.ad_data.data = data->data; - el.ad_data.length = data->length; + return _krb5_add_1auth_data(context, type, data, 1, + &auth_context->auth_data); +} - return add_AuthorizationData(auth_context->auth_data, &el); +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_auth_con_add_AuthorizationDataIfRelevant(krb5_context context, + krb5_auth_context auth_context, + krb5int32 type, + krb5_data *data) +{ + if (auth_context->auth_data == NULL) { + auth_context->auth_data = calloc(1, sizeof(*auth_context->auth_data)); + if (auth_context->auth_data == NULL) + return krb5_enomem(context); + } + return _krb5_add_1auth_data(context, type, data, 0, + &auth_context->auth_data); } diff --git a/lib/krb5/build_auth.c b/lib/krb5/build_auth.c index cbc67744a..c0294835e 100644 --- a/lib/krb5/build_auth.c +++ b/lib/krb5/build_auth.c @@ -33,16 +33,30 @@ #include "krb5_locl.h" +static krb5_error_code +add_auth_data(krb5_context context, + AuthorizationData *src, + AuthorizationData **dst) +{ + krb5_error_code ret = 0; + size_t i; + + if (*dst == NULL && + (*dst = calloc(1, sizeof(**dst))) == NULL) + return krb5_enomem(context); + for (i = 0; ret == 0 && i < src->len; i++) + ret = add_AuthorizationData(*dst, &src->val[i]); + return ret; +} + 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; + krb5_data e; size_t len = 0; - size_t buf_size; ret = _krb5_init_etype(context, KRB5_PDU_NONE, &etypes.len, &etypes.val, @@ -50,52 +64,20 @@ make_etypelist(krb5_context context, if (ret) return ret; - ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret); + ASN1_MALLOC_ENCODE(EtypeList, e.data, e.length, &etypes, &len, ret); if (ret) { free_EtypeList(&etypes); return ret; } - if(buf_size != len) + if(e.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); free_EtypeList(&etypes); - ALLOC_SEQ(&ad, 1); - if (ad.val == NULL) { - free(buf); - return krb5_enomem(context); - } - - 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) { - free(buf); - return krb5_enomem(context); - } - - ALLOC_SEQ(*auth_data, 1); - if ((*auth_data)->val == NULL) { - free(*auth_data); - free(buf); - return krb5_enomem(context); - } - - (*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; + ret = _krb5_add_1auth_data(context, + KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION, &e, 0, + auth_data); + krb5_data_free(&e); + return ret; } KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL @@ -166,6 +148,13 @@ _krb5_build_authenticator (krb5_context context, } } + /* Copy other authz data from auth_context */ + if (auth_context->auth_data) { + ret = add_auth_data(context, auth_context->auth_data, &auth.authorization_data); + if (ret) + goto fail; + } + /* XXX - Copy more to auth_context? */ auth_context->authenticator->ctime = auth.ctime;