diff options
author | Greg Hudson <ghudson@mit.edu> | 2009-11-14 04:46:30 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2009-11-14 04:46:30 +0000 |
commit | 0524889196c42d81dcc4c74277522b46f987cabb (patch) | |
tree | 9f906eb1a4a32346ae94837c4fe199410e2dd10f /src/lib | |
parent | 26044e2a3c3104b9c3f32a6ae58145e7e6394672 (diff) | |
download | krb5-0524889196c42d81dcc4c74277522b46f987cabb.zip krb5-0524889196c42d81dcc4c74277522b46f987cabb.tar.gz krb5-0524889196c42d81dcc4c74277522b46f987cabb.tar.bz2 |
Constrained delegation without PAC support
Merge Luke's users/lhoward/s4u2proxy branch to trunk. Implements a
Heimdal-compatible mechanism for allowing constrained delegation
without back-end support for PACs. Back-end support exists in LDAP
only (via a new krbAllowedToDelegateTo attribute), not DB2.
ticket: 6580
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23160 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_decode.c | 84 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_decode.h | 6 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_encode.c | 55 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/krb5_decode.c | 36 | ||||
-rw-r--r-- | src/lib/krb5/krb/copy_auth.c | 61 | ||||
-rw-r--r-- | src/lib/krb5/krb/kfree.c | 17 | ||||
-rw-r--r-- | src/lib/krb5/libkrb5.exports | 5 |
7 files changed, 243 insertions, 21 deletions
diff --git a/src/lib/krb5/asn.1/asn1_k_decode.c b/src/lib/krb5/asn.1/asn1_k_decode.c index 7653990..dd1a2ae 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.c +++ b/src/lib/krb5/asn.1/asn1_k_decode.c @@ -1007,6 +1007,45 @@ error_out: return retval; } +static asn1_error_code asn1_peek_authdata_elt(asn1buf *buf, krb5_authdatatype *val) +{ + setup(); + *val = 0; + { begin_structure(); + get_field(*val, 0, asn1_decode_authdatatype); + end_structure(); + } + return 0; +error_out: + return retval; +} + +asn1_error_code asn1_peek_authorization_data +(asn1buf *buf, unsigned int *num, krb5_authdatatype **val) +{ + int size = 0; + krb5_authdatatype *array = NULL, *new_array; + + asn1_error_code retval; + { sequence_of(buf); + while (asn1buf_remains(&seqbuf,seqofindef) > 0) { + size++; + new_array = realloc(array,size*sizeof(krb5_authdatatype)); + if (new_array == NULL) clean_return(ENOMEM); + array = new_array; + retval = asn1_peek_authdata_elt(&seqbuf,&array[size-1]); + if (retval) clean_return(retval); + } + end_sequence_of(buf); + } + *num = size; + *val = array; + return 0; +error_out: + free(array); + return retval; +} + asn1_error_code asn1_decode_authdata_elt_ptr(asn1buf *buf, krb5_authdata **valptr) { @@ -1812,6 +1851,51 @@ error_out: return retval; } +static asn1_error_code asn1_decode_princ_plus_realm +(asn1buf *buf, krb5_principal *valptr) +{ + setup(); + alloc_principal((*valptr)); + { begin_structure(); + get_field((*valptr), 0, asn1_decode_principal_name); + get_field((*valptr), 1, asn1_decode_realm); + end_structure(); + } + return 0; +error_out: + krb5_free_principal(NULL, *valptr); + *valptr = NULL; + return retval; +} + +static asn1_error_code asn1_decode_sequence_of_princ_plus_realm +(asn1buf *buf, krb5_principal **val) +{ + decode_array_body(krb5_principal_data,asn1_decode_princ_plus_realm,krb5_free_principal); +} + +asn1_error_code asn1_decode_ad_signedpath +(asn1buf *buf, krb5_ad_signedpath *val) +{ + setup(); + val->enctype = ENCTYPE_NULL; + val->checksum.contents = NULL; + val->delegated = NULL; + { + begin_structure(); + get_field(val->enctype, 0, asn1_decode_enctype); + get_field(val->checksum, 1, asn1_decode_checksum); + opt_field(val->delegated, 2, asn1_decode_sequence_of_princ_plus_realm, + NULL); + opt_field(val->method_data, 3, asn1_decode_sequence_of_pa_data, NULL); + end_structure(); + } + return 0; +error_out: + krb5_free_checksum_contents(NULL, &val->checksum); + return retval; +} + #ifndef DISABLE_PKINIT /* PKINIT */ diff --git a/src/lib/krb5/asn.1/asn1_k_decode.h b/src/lib/krb5/asn.1/asn1_k_decode.h index 8041535..1b0aa75 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.h +++ b/src/lib/krb5/asn.1/asn1_k_decode.h @@ -134,6 +134,9 @@ asn1_error_code asn1_decode_last_req_entry_ptr(asn1buf *buf, asn1_error_code asn1_decode_authdata_elt(asn1buf *buf, krb5_authdata *val); asn1_error_code asn1_decode_authdata_elt_ptr(asn1buf *buf, krb5_authdata **valptr); +asn1_error_code asn1_peek_authorization_data(asn1buf *buf, + unsigned int *num, + krb5_authdatatype **val); asn1_error_code asn1_decode_krb_cred_info(asn1buf *buf, krb5_cred_info *val); asn1_error_code asn1_decode_krb_cred_info_ptr(asn1buf *buf, krb5_cred_info **valptr); @@ -265,4 +268,7 @@ asn1_error_code asn1_decode_ad_kdcissued(asn1buf *buf, krb5_ad_kdcissued *val); asn1_error_code asn1_decode_ad_kdcissued_ptr(asn1buf *buf, krb5_ad_kdcissued **val); +asn1_error_code asn1_decode_ad_signedpath(asn1buf *buf, + krb5_ad_signedpath *val); + #endif diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index d0371f5..22ebae3 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -97,7 +97,6 @@ DEFFIELDTYPE(realm_of_principal_data, krb5_principal_data, FIELDOF_NORM(krb5_principal_data, gstring_data, realm, -1)); DEFPTRTYPE(realm_of_principal, realm_of_principal_data); - static const struct field_info princname_fields[] = { FIELDOF_NORM(krb5_principal_data, int32, type, 0), FIELDOF_SEQOF_INT32(krb5_principal_data, gstring_data_ptr, data, length, 1), @@ -1331,7 +1330,59 @@ ad_kdcissued_optional(const void *p) DEFSEQTYPE(ad_kdc_issued, krb5_ad_kdcissued, ad_kdcissued_fields, ad_kdcissued_optional); +static const struct field_info princ_plus_realm_fields[] = { + FIELDOF_ENCODEAS(krb5_principal_data, principal_data, 0), + FIELDOF_ENCODEAS(krb5_principal_data, realm_of_principal_data, 1), +}; + +DEFSEQTYPE(princ_plus_realm_data, krb5_principal_data, princ_plus_realm_fields, 0); +DEFPTRTYPE(princ_plus_realm, princ_plus_realm_data); + +DEFNULLTERMSEQOFTYPE(seq_of_princ_plus_realm, princ_plus_realm); +DEFPTRTYPE(ptr_seq_of_princ_plus_realm, seq_of_princ_plus_realm); + +static const struct field_info ad_signedpath_data_fields[] = { + FIELDOF_NORM(krb5_ad_signedpath_data, princ_plus_realm, client, 0), + FIELDOF_NORM(krb5_ad_signedpath_data, kerberos_time, authtime, 1), + FIELDOF_OPT(krb5_ad_signedpath_data, ptr_seq_of_princ_plus_realm, delegated, 2, 2), + FIELDOF_OPT(krb5_ad_signedpath_data, ptr_seqof_pa_data, method_data, 3, 3), + FIELDOF_OPT(krb5_ad_signedpath_data, auth_data_ptr, authorization_data, 4, 4), +}; + +static unsigned int ad_signedpath_data_optional(const void *p) +{ + unsigned int optional = 0; + const krb5_ad_signedpath_data *val = p; + if (val->delegated && val->delegated[0]) + optional |= (1u << 2); + if (val->method_data && val->method_data[0]) + optional |= (1u << 3); + if (val->authorization_data && val->authorization_data[0]) + optional |= (1u << 4); + return optional; +} + +DEFSEQTYPE(ad_signedpath_data, krb5_ad_signedpath_data, ad_signedpath_data_fields, ad_signedpath_data_optional); + +static const struct field_info ad_signedpath_fields[] = { + FIELDOF_NORM(krb5_ad_signedpath, int32, enctype, 0), + FIELDOF_NORM(krb5_ad_signedpath, checksum, checksum, 1), + FIELDOF_OPT(krb5_ad_signedpath, ptr_seq_of_princ_plus_realm, delegated, 2, 2), + FIELDOF_OPT(krb5_ad_signedpath, ptr_seqof_pa_data, method_data, 3, 3), +}; + +static unsigned int ad_signedpath_optional(const void *p) +{ + unsigned int optional = 0; + const krb5_ad_signedpath *val = p; + if (val->delegated && val->delegated[0]) + optional |= (1u << 2); + if (val->method_data && val->method_data[0]) + optional |= (1u << 3); + return optional; +} +DEFSEQTYPE(ad_signedpath, krb5_ad_signedpath, ad_signedpath_fields, ad_signedpath_optional); /* Exported complete encoders -- these produce a krb5_data with the encoding in the correct byte order. */ @@ -1407,6 +1458,8 @@ MAKE_FULL_ENCODER( encode_krb5_pa_fx_fast_reply, pa_fx_fast_reply); MAKE_FULL_ENCODER(encode_krb5_fast_response, fast_response); MAKE_FULL_ENCODER(encode_krb5_ad_kdcissued, ad_kdc_issued); +MAKE_FULL_ENCODER(encode_krb5_ad_signedpath_data, ad_signedpath_data); +MAKE_FULL_ENCODER(encode_krb5_ad_signedpath, ad_signedpath); diff --git a/src/lib/krb5/asn.1/krb5_decode.c b/src/lib/krb5/asn.1/krb5_decode.c index fa835fe..0daa32e 100644 --- a/src/lib/krb5/asn.1/krb5_decode.c +++ b/src/lib/krb5/asn.1/krb5_decode.c @@ -1192,6 +1192,42 @@ krb5_error_code decode_krb5_ad_kdcissued cleanup(free); } +krb5_error_code decode_krb5_ad_signedpath +(const krb5_data *code, krb5_ad_signedpath **repptr) +{ + setup_buf_only(krb5_ad_signedpath *); + alloc_field(rep); + + retval = asn1_decode_ad_signedpath(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} + +krb5_error_code +krb5int_get_authdata_containee_types(krb5_context context, + const krb5_authdata *authdata, + unsigned int *num, + krb5_authdatatype **repptr) +{ + krb5_data data, *code = &data; + + data.data = (char *)authdata->contents; + data.length = authdata->length; + + *num = 0; + + { + setup_buf_only(krb5_authdatatype *); + + retval = asn1_peek_authorization_data(&buf, num, &rep); + if (retval) clean_return(retval); + + cleanup_none(); + } + assert(0); /* NOTREACHED */ +} + #ifndef DISABLE_PKINIT krb5_error_code decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **repptr) diff --git a/src/lib/krb5/krb/copy_auth.c b/src/lib/krb5/krb/copy_auth.c index 0262fe5..d4c2700 100644 --- a/src/lib/krb5/krb/copy_auth.c +++ b/src/lib/krb5/krb/copy_auth.c @@ -223,34 +223,47 @@ grow_find_authdata(krb5_context context, struct find_authdata_context *fctx, static krb5_error_code find_authdata_1(krb5_context context, krb5_authdata *const *in_authdat, - krb5_authdatatype ad_type, struct find_authdata_context *fctx) + krb5_authdatatype ad_type, struct find_authdata_context *fctx, + int from_ap_req) { int i = 0; - krb5_error_code retval=0; + krb5_error_code retval = 0; for (i = 0; in_authdat[i]; i++) { krb5_authdata *ad = in_authdat[i]; - if (ad->ad_type == ad_type && retval ==0) - retval = grow_find_authdata(context, fctx, ad); - else switch (ad->ad_type) { - krb5_authdata **decoded_container; - case KRB5_AUTHDATA_IF_RELEVANT: - if (retval == 0) - retval = krb5_decode_authdata_container( context, ad->ad_type, ad, &decoded_container); - if (retval == 0) { - retval = find_authdata_1(context, - decoded_container, ad_type, fctx); - krb5_free_authdata(context, decoded_container); - } - break; - default: - break; + krb5_authdata **decoded_container; + + switch (ad->ad_type) { + case KRB5_AUTHDATA_IF_RELEVANT: + if (retval == 0) + retval = krb5_decode_authdata_container(context, + ad->ad_type, + ad, + &decoded_container); + if (retval == 0) { + retval = find_authdata_1(context, + decoded_container, + ad_type, + fctx, + from_ap_req); + krb5_free_authdata(context, decoded_container); } + break; + case KRB5_AUTHDATA_SIGNTICKET: + case KRB5_AUTHDATA_KDC_ISSUED: + case KRB5_AUTHDATA_WIN2K_PAC: + if (from_ap_req) + continue; + default: + if (ad->ad_type == ad_type && retval == 0) + retval = grow_find_authdata(context, fctx, ad); + break; + } } + return retval; } - krb5_error_code krb5int_find_authdata(krb5_context context, krb5_authdata *const *ticket_authdata, @@ -266,9 +279,9 @@ krb5int_find_authdata(krb5_context context, if (fctx.out == NULL) return ENOMEM; if (ticket_authdata) - retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx); + retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx, 0); if ((retval==0) && ap_req_authdata) - retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx); + retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx, 1); if ((retval== 0) && fctx.length) *results = fctx.out; else krb5_free_authdata(context, fctx.out); @@ -300,6 +313,9 @@ krb5_make_authdata_kdc_issued(krb5_context context, if (code != 0) return code; + if (!krb5_c_is_keyed_cksum(cksumtype)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + code = encode_krb5_authdata(ad_kdci.elements, &data); if (code != 0) return code; @@ -361,6 +377,11 @@ krb5_verify_authdata_kdc_issued(krb5_context context, if (code != 0) return code; + if (!krb5_c_is_keyed_cksum(ad_kdci->ad_checksum.checksum_type)) { + krb5_free_ad_kdcissued(context, ad_kdci); + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + code = encode_krb5_authdata(ad_kdci->elements, &data2); if (code != 0) { krb5_free_ad_kdcissued(context, ad_kdci); diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index c372e70..02906a1 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -909,3 +909,20 @@ krb5_free_ad_kdcissued(krb5_context context, krb5_ad_kdcissued *val) krb5_free_authdata(context, val->elements); free(val); } + +void KRB5_CALLCONV +krb5_free_ad_signedpath(krb5_context context, krb5_ad_signedpath *val) +{ + int i; + + if (val == NULL) + return; + + krb5_free_checksum_contents(context, &val->checksum); + if (val->delegated != NULL) { + for (i = 0; val->delegated[i] != NULL; i++) + krb5_free_principal(context, val->delegated[i]); + free(val->delegated); + } + krb5_free_pa_data(context, val->method_data); +} diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 2735c9f..8ef3a9d 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -1,5 +1,6 @@ _krb5_conf_boolean decode_krb5_ad_kdcissued +decode_krb5_ad_signedpath decode_krb5_alt_method decode_krb5_ap_rep decode_krb5_ap_rep_enc_part @@ -42,6 +43,8 @@ decode_krb5_tgs_req decode_krb5_ticket decode_krb5_typed_data encode_krb5_ad_kdcissued +encode_krb5_ad_signedpath_data +encode_krb5_ad_signedpath encode_krb5_alt_method encode_krb5_ap_rep encode_krb5_ap_rep_enc_part @@ -220,6 +223,7 @@ krb5_externalize_opaque krb5_fcc_ops krb5_find_serializer krb5_free_ad_kdcissued +krb5_free_ad_signedpath krb5_free_address krb5_free_addresses krb5_free_alt_method @@ -554,6 +558,7 @@ krb5int_find_pa_data krb5int_foreach_localaddr krb5int_free_addrlist krb5int_free_data_list +krb5int_get_authdata_containee_types krb5int_get_domain_realm_mapping krb5int_init_context_kdc krb5int_initialize_library |