From: Matt Rogers Date: Fri, 13 May 2016 00:14:01 +0000 (-0400) Subject: Add CAMMAC handling to the authdata framework X-Git-Tag: krb5-1.15-beta1~172 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f4f619e7905d762204695dd66450e586c183c9fd;p=thirdparty%2Fkrb5.git Add CAMMAC handling to the authdata framework Handle CAMMAC contained authdata similarly to KDC-issued authdata, where it is verified before passing to the import function. [ghudson@mit.edu: fix memory leak and reduce copying in extract_cammac()] ticket: 8425 --- diff --git a/src/include/krb5/authdata_plugin.h b/src/include/krb5/authdata_plugin.h index 3399eeaace..5bb95fa598 100644 --- a/src/include/krb5/authdata_plugin.h +++ b/src/include/krb5/authdata_plugin.h @@ -55,8 +55,9 @@ typedef krb5_error_code #define AD_USAGE_TGS_REQ 0x02 #define AD_USAGE_AP_REQ 0x04 #define AD_USAGE_KDC_ISSUED 0x08 -#define AD_USAGE_MASK 0x0F #define AD_INFORMATIONAL 0x10 +#define AD_CAMMAC_PROTECTED 0x20 +#define AD_USAGE_MASK 0x2F struct _krb5_authdata_context; diff --git a/src/lib/krb5/krb/authdata.c b/src/lib/krb5/krb/authdata.c index fb8beb3cfd..f2c66bdf66 100644 --- a/src/lib/krb5/krb/authdata.c +++ b/src/lib/krb5/krb/authdata.c @@ -536,6 +536,72 @@ k5_get_kdc_issued_authdata(krb5_context kcontext, return code; } +/* Decode and verify each CAMMAC and collect the resulting authdata, + * ignoring those that failed verification. */ +static krb5_error_code +extract_cammacs(krb5_context kcontext, krb5_authdata **cammacs, + const krb5_keyblock *key, krb5_authdata ***ad_out) +{ + krb5_error_code ret; + krb5_authdata **list = NULL, **elements = NULL, **new_list; + size_t i, n_elements, count = 0; + + *ad_out = NULL; + + for (i = 0; cammacs != NULL && cammacs[i] != NULL; i++) { + ret = k5_unwrap_cammac_svc(kcontext, cammacs[i], key, &elements); + if (ret && ret != KRB5KRB_AP_ERR_BAD_INTEGRITY) + goto cleanup; + ret = 0; + + /* Add the verified elements to list and free the container array. */ + for (n_elements = 0; elements[n_elements] != NULL; n_elements++); + new_list = realloc(list, (count + n_elements + 1) * sizeof(list)); + if (new_list == NULL) { + ret = ENOMEM; + goto cleanup; + } + list = new_list; + memcpy(list + count, elements, n_elements * sizeof(list)); + count += n_elements; + list[count] = NULL; + free(elements); + elements = NULL; + } + + *ad_out = list; + list = NULL; + +cleanup: + krb5_free_authdata(kcontext, list); + krb5_free_authdata(kcontext, elements); + return ret; +} + +/* Retrieve verified CAMMAC contained elements. */ +static krb5_error_code +get_cammac_authdata(krb5_context kcontext, const krb5_ap_req *ap_req, + const krb5_keyblock *key, krb5_authdata ***elems_out) +{ + krb5_error_code ret = 0; + krb5_authdata **ticket_authdata, **cammacs, **elements; + + *elems_out = NULL; + + ticket_authdata = ap_req->ticket->enc_part2->authorization_data; + ret = krb5_find_authdata(kcontext, ticket_authdata, NULL, + KRB5_AUTHDATA_CAMMAC, &cammacs); + if (ret || cammacs == NULL) + return ret; + + ret = extract_cammacs(kcontext, cammacs, key, &elements); + if (!ret) + *elems_out = elements; + + krb5_free_authdata(kcontext, cammacs); + return ret; +} + krb5_error_code krb5int_authdata_verify(krb5_context kcontext, krb5_authdata_context context, @@ -550,12 +616,17 @@ krb5int_authdata_verify(krb5_context kcontext, krb5_authdata **ticket_authdata; krb5_principal kdc_issuer = NULL; krb5_authdata **kdc_issued_authdata = NULL; + krb5_authdata **cammac_authdata = NULL; authen_authdata = (*auth_context)->authentp->authorization_data; ticket_authdata = ap_req->ticket->enc_part2->authorization_data; k5_get_kdc_issued_authdata(kcontext, ap_req, &kdc_issuer, &kdc_issued_authdata); + code = get_cammac_authdata(kcontext, ap_req, key, &cammac_authdata); + if (code) + goto cleanup; + for (i = 0; i < context->n_modules; i++) { struct _krb5_authdata_context_module *module = &context->modules[i]; krb5_authdata **authdata = NULL; @@ -577,6 +648,11 @@ krb5int_authdata_verify(krb5_context kcontext, kdc_issued_flag = TRUE; } + if (cammac_authdata != NULL && (module->flags & AD_CAMMAC_PROTECTED)) { + authdata = cammac_authdata; + kdc_issued_flag = TRUE; + } + if (authdata == NULL) { krb5_boolean ticket_usage = FALSE; krb5_boolean authen_usage = FALSE; @@ -628,6 +704,7 @@ krb5int_authdata_verify(krb5_context kcontext, break; } +cleanup: krb5_free_principal(kcontext, kdc_issuer); krb5_free_authdata(kcontext, kdc_issued_authdata);