From: Luke Howard Date: Sun, 30 Aug 2009 15:34:32 +0000 (+0000) Subject: add KDCIssued helpers X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2cc5a58dcc595d12559c9f66ea662a0b3998e8ff;p=thirdparty%2Fkrb5.git add KDCIssued helpers git-svn-id: svn://anonsvn.mit.edu/krb5/users/lhoward/authdata@22660 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 02e04e46a0..a1337055a6 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1006,6 +1006,11 @@ typedef struct _krb5_fast_response { krb5_int32 nonce; } krb5_fast_response; +typedef struct _krb5_ad_kdcissued { + krb5_checksum ad_checksum; + krb5_principal i_principal; + krb5_authdata **elements; +} krb5_ad_kdcissued; typedef krb5_error_code (*krb5_preauth_obtain_proc) (krb5_context, @@ -1312,6 +1317,8 @@ void KRB5_CALLCONV krb5_free_fast_finished (krb5_context, krb5_fast_finished *); void KRB5_CALLCONV krb5_free_fast_response (krb5_context, krb5_fast_response *); +void KRB5_CALLCONV krb5_free_ad_kdcissued +(krb5_context, krb5_ad_kdcissued *); /* #include "krb5/wordsize.h" -- comes in through base-defs.h. */ #include "com_err.h" @@ -1732,6 +1739,9 @@ krb5_error_code encode_krb5_pa_fx_fast_reply krb5_error_code encode_krb5_fast_response (const krb5_fast_response *, krb5_data **); +krb5_error_code encode_krb5_ad_kdcissued +(const krb5_ad_kdcissued *, krb5_data **); + /************************************************************************* * End of prototypes for krb5_encode.c *************************************************************************/ @@ -1904,6 +1914,9 @@ krb5_error_code decode_krb5_pa_fx_fast_reply krb5_error_code decode_krb5_fast_response (const krb5_data *, krb5_fast_response **); +krb5_error_code decode_krb5_ad_kdcissued +(const krb5_data *, krb5_ad_kdcissued **); + struct _krb5_key_data; /* kdb.h */ struct ldap_seqof_key_data { diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index bf8c29c59e..7e9c63aaf2 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -2565,6 +2565,22 @@ krb5_encode_authdata_container(krb5_context context, krb5_authdata * const*authdata, krb5_authdata ***container); +/* + * AD-KDCIssued + */ +krb5_error_code KRB5_CALLCONV +krb5_make_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + krb5_const_principal issuer, + krb5_authdata *const *authdata, + krb5_authdata **ad_kdcissued); +krb5_error_code KRB5_CALLCONV +krb5_verify_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + const krb5_authdata *ad_kdcissued, + krb5_principal *issuer, + krb5_authdata ***authdata); + /* * Windows PAC */ diff --git a/src/lib/krb5/asn.1/asn1_k_decode.c b/src/lib/krb5/asn.1/asn1_k_decode.c index 1917d89743..30b48e842f 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.c +++ b/src/lib/krb5/asn.1/asn1_k_decode.c @@ -1678,7 +1678,28 @@ asn1_error_code asn1_decode_fast_finished_ptr decode_ptr( krb5_fast_finished *, asn1_decode_fast_finished); } - +asn1_error_code asn1_decode_ad_kdcissued +(asn1buf *buf, krb5_ad_kdcissued *val) +{ + setup(); + val->ad_checksum.contents = NULL; + val->i_principal = NULL; + val->elements = NULL; + {begin_structure(); + get_field(val->ad_checksum, 0, asn1_decode_checksum); + opt_field(val->i_principal, 1, asn1_decode_realm, 0); + opt_field(val->i_principal, 2, asn1_decode_principal_name, 0); + get_field(val->elements, 3, asn1_decode_authorization_data); + end_structure(); + } + return 0; +error_out: + krb5_free_checksum_contents(NULL, &val->ad_checksum); + krb5_free_principal(NULL, val->i_principal); + krb5_free_authdata(NULL, val->elements); + 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 7444443ba5..0532ad4677 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.h +++ b/src/lib/krb5/asn.1/asn1_k_decode.h @@ -278,4 +278,10 @@ asn1_error_code asn1_decode_fast_finished asn1_error_code asn1_decode_fast_finished_ptr (asn1buf *buf, krb5_fast_finished **val); +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); + #endif diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index ed01b7560d..f53ac7cd7d 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -1258,6 +1258,23 @@ DEFSEQTYPE(fast_rep, krb5_enc_data, fast_rep_fields, 0); DEFFIELDTYPE(pa_fx_fast_reply, krb5_enc_data, FIELDOF_ENCODEAS(krb5_enc_data, fast_rep, 0)); +static const struct field_info ad_kdcissued_fields[] = { + FIELDOF_NORM(krb5_ad_kdcissued, checksum, ad_checksum, 0), + FIELDOF_OPT(krb5_ad_kdcissued, realm_of_principal, i_principal, 1, 1), + FIELDOF_OPT(krb5_ad_kdcissued, principal, i_principal, 2, 1), + FIELDOF_NORM(krb5_ad_kdcissued, auth_data_ptr, elements, 3), +}; + +static unsigned int ad_kdcissued_optional(const void *p) +{ + unsigned int optional = 0; + const krb5_ad_kdcissued *val = p; + if (val->i_principal) + optional |= (1u << 1); + return optional; +} + +DEFSEQTYPE(ad_kdc_issued, krb5_ad_kdcissued, ad_kdcissued_fields, ad_kdcissued_optional); @@ -1332,7 +1349,7 @@ MAKE_FULL_ENCODER( encode_krb5_fast_req, fast_req); 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); diff --git a/src/lib/krb5/asn.1/krb5_decode.c b/src/lib/krb5/asn.1/krb5_decode.c index 7a08ec8884..e5df1428c3 100644 --- a/src/lib/krb5/asn.1/krb5_decode.c +++ b/src/lib/krb5/asn.1/krb5_decode.c @@ -1168,6 +1168,17 @@ krb5_error_code decode_krb5_pa_fx_fast_reply cleanup(free); } +krb5_error_code decode_krb5_ad_kdcissued +(const krb5_data *code, krb5_ad_kdcissued **repptr) +{ + setup_buf_only(krb5_ad_kdcissued *); + alloc_field(rep); + + retval = asn1_decode_ad_kdcissued(&buf, rep); + if (retval) clean_return(retval); + + cleanup(free); +} #ifndef DISABLE_PKINIT krb5_error_code diff --git a/src/lib/krb5/krb/copy_auth.c b/src/lib/krb5/krb/copy_auth.c index dc989acf4d..9f19289a1a 100644 --- a/src/lib/krb5/krb/copy_auth.c +++ b/src/lib/krb5/krb/copy_auth.c @@ -276,3 +276,123 @@ krb5_error_code krb5int_find_authdata else krb5_free_authdata(context, fctx.out); return retval; } + +krb5_error_code KRB5_CALLCONV +krb5_make_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + krb5_const_principal issuer, + krb5_authdata *const *authdata, + krb5_authdata **ad_kdcissued) +{ + krb5_error_code code; + krb5_ad_kdcissued ad_kdci; + krb5_data *data; + krb5_cksumtype cksumtype; + + *ad_kdcissued = NULL; + + ad_kdci.ad_checksum.contents = NULL; + ad_kdci.i_principal = (krb5_principal)issuer; + ad_kdci.elements = ad_kdcissued; + + code = krb5int_c_mandatory_cksumtype(context, key->enctype, + &cksumtype); + if (code != 0) + return code; + + code = encode_krb5_authdata(ad_kdcissued, &data); + if (code != 0) + return code; + + code = krb5_c_make_checksum(context, cksumtype, + key, KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM, + data, &ad_kdci.ad_checksum); + if (code != 0) { + krb5_free_data(context, data); + return code; + } + + krb5_free_data(context, data); + + code = encode_krb5_ad_kdcissued(&ad_kdci, &data); + if (code != 0) + return code; + + krb5_free_checksum_contents(context, &ad_kdci.ad_checksum); + + *ad_kdcissued = calloc(1, sizeof(krb5_authdata)); + if (*ad_kdcissued == NULL) { + krb5_free_data(context, data); + return ENOMEM; + } + + (*ad_kdcissued)->magic = KV5M_AUTHDATA; + (*ad_kdcissued)->ad_type = KRB5_AUTHDATA_KDC_ISSUED; + (*ad_kdcissued)->length = data->length; + (*ad_kdcissued)->contents = (krb5_octet *)data->data; + + free(data); + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_verify_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + const krb5_authdata *ad_kdcissued, + krb5_principal *issuer, + krb5_authdata ***authdata) +{ + krb5_error_code code; + krb5_ad_kdcissued *ad_kdci; + krb5_data data, *data2; + krb5_boolean valid = FALSE; + + if (issuer != NULL) + *issuer = NULL; + if (authdata != NULL) + *authdata = NULL; + + data.length = ad_kdcissued->length; + data.data = (char *)ad_kdcissued->contents; + + code = decode_krb5_ad_kdcissued(&data, &ad_kdci); + if (code != 0) + return code; + + code = encode_krb5_authdata(ad_kdci->elements, &data2); + if (code != 0) { + krb5_free_ad_kdcissued(context, ad_kdci); + return code; + } + + code = krb5_c_verify_checksum(context, key, + KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM, + data2, &ad_kdci->ad_checksum, &valid); + if (code != 0) { + krb5_free_ad_kdcissued(context, ad_kdci); + krb5_free_data(context, data2); + } + + krb5_free_data(context, data2); + + if (valid == FALSE) { + krb5_free_ad_kdcissued(context, ad_kdci); + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + + if (issuer != NULL) { + *issuer = ad_kdci->i_principal; + ad_kdci->i_principal = NULL; + } + + if (authdata != NULL) { + *authdata = ad_kdci->elements; + ad_kdci->elements = NULL; + } + + krb5_free_ad_kdcissued(context, ad_kdci); + + return 0; +} + diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index 6188534528..6f51223b39 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -873,3 +873,15 @@ krb5int_free_data_list(krb5_context context, krb5_data *data) free(data); } +void KRB5_CALLCONV +krb5_free_ad_kdcissued(krb5_context context, krb5_ad_kdcissued *val) +{ + if (val == NULL) + return; + + krb5_free_checksum_contents(context, &val->ad_checksum); + krb5_free_principal(context, val->i_principal); + krb5_free_authdata(context, val->elements); + free(val); +} + diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 51e9739d81..86e97dc8dc 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -371,6 +371,7 @@ krb5_kuserok krb5_libdefault_boolean krb5_locate_kdc krb5_lock_file +krb5_make_authdata_kdc_issued krb5_make_full_ipaddr krb5_make_fulladdr krb5_max_dgram_size @@ -527,6 +528,7 @@ krb5_unparse_name_flags_ext krb5_us_timeofday krb5_use_natural_time krb5_validate_times +krb5_verify_authdata_kdc_issued krb5_verify_init_creds krb5_verify_init_creds_opt_init krb5_verify_init_creds_opt_set_ap_req_nofail