diff options
author | Sam Hartman <hartmans@mit.edu> | 2009-03-26 05:37:06 +0000 |
---|---|---|
committer | Sam Hartman <hartmans@mit.edu> | 2009-03-26 05:37:06 +0000 |
commit | 10609fbcf5d3a056a74633224401904ad88818b7 (patch) | |
tree | d2a38809f25280b5e79dd3ff790e7d6f229227a1 | |
parent | fa2fcf03de2c39b0906bd33e31d445a5545755a3 (diff) | |
download | krb5-10609fbcf5d3a056a74633224401904ad88818b7.zip krb5-10609fbcf5d3a056a74633224401904ad88818b7.tar.gz krb5-10609fbcf5d3a056a74633224401904ad88818b7.tar.bz2 |
Implement client AS armor
* fast_armor_ap_request: generate ap_request armor
* krb5int_fast_as_armor: parse GIC options and request armor
* krb5_get_init_creds: call
* krb5_get_init_creds_opt_set_fast_ccache_name: API to indicate where armor credentials are found
* krb5_free_fast_armored_req: implement
git-svn-id: svn://anonsvn.mit.edu/krb5/branches/fast@22134 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r-- | src/include/k5-int.h | 5 | ||||
-rw-r--r-- | src/include/krb5/krb5.hin | 9 | ||||
-rw-r--r-- | src/lib/krb5/krb/fast.c | 120 | ||||
-rw-r--r-- | src/lib/krb5/krb/fast.h | 4 | ||||
-rw-r--r-- | src/lib/krb5/krb/get_in_tkt.c | 3 | ||||
-rw-r--r-- | src/lib/krb5/krb/gic_opt.c | 20 | ||||
-rw-r--r-- | src/lib/krb5/krb/kfree.c | 14 | ||||
-rw-r--r-- | src/lib/krb5/libkrb5.exports | 1 |
8 files changed, 170 insertions, 6 deletions
diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 957f39c..b7e793b 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -963,6 +963,10 @@ typedef struct _krb5_pa_for_user { krb5_data auth_package; } krb5_pa_for_user; +enum { + KRB5_FAST_ARMOR_AP_REQUEST = 0x1 +}; + typedef struct _krb5_fast_armor { krb5_int32 armor_type; krb5_data armor_value; @@ -1130,6 +1134,7 @@ void krb5_free_etype_info typedef struct _krb5_gic_opt_private { int num_preauth_data; krb5_gic_opt_pa_data *preauth_data; + char * fast_ccache_name; } krb5_gic_opt_private; /* diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index c385387..4443d33 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -2410,6 +2410,15 @@ krb5_get_init_creds_opt_set_pa const char *attr, const char *value); +krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_fast_ccache_name +(krb5_context context, krb5_get_init_creds_opt *opt, + const char * fast_ccache_name); + /* This API sets a ccache name that will contain some TGT on + calls to get_init_creds functions. If set, this ccache will + be used for FAST (draft-ietf-krb-wg-preauth-framework) to + protect the AS-REQ from observation and active attack. If + the fast_ccache_name is set, then FAST may be required by the + client library. In this version FAST is required.*/ krb5_error_code KRB5_CALLCONV krb5_get_init_creds_password (krb5_context context, diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c index 41f3731..4d5f62e 100644 --- a/src/lib/krb5/krb/fast.c +++ b/src/lib/krb5/krb/fast.c @@ -49,8 +49,59 @@ * important questions there is the presence of a cookie. */ #include "fast.h" +#include "int-proto.h" +static krb5_error_code fast_armor_ap_request +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_ccache ccache, krb5_data *target_realm) +{ + krb5_error_code retval = 0; + krb5_creds creds, *out_creds = NULL; + krb5_auth_context authcontext = NULL; + krb5_data encoded_authenticator; + krb5_fast_armor *armor = NULL; + krb5_keyblock *subkey = NULL, *armor_key = NULL; + encoded_authenticator.data = NULL; + memset(&creds, 0, sizeof(creds)); + retval = krb5_tgtname(context, target_realm, target_realm, &creds.server); + if (retval ==0) + retval = krb5_cc_get_principal(context, ccache, &creds.client); + if (retval == 0) + retval = krb5_get_credentials(context, 0, ccache, &creds, &out_creds); + if (retval == 0) + retval = krb5_mk_req_extended(context, &authcontext, AP_OPTS_USE_SUBKEY, NULL /*data*/, + out_creds, &encoded_authenticator); + if (retval == 0) + retval = krb5_auth_con_getsendsubkey(context, authcontext, &subkey); + if (retval == 0) + retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor", + &out_creds->keyblock, "ticketarmor", &armor_key); + if (retval == 0) { + armor = calloc(1, sizeof(krb5_fast_armor)); + if (armor == NULL) + retval = ENOMEM; + } + if (retval == 0) { + armor->armor_type = KRB5_FAST_ARMOR_AP_REQUEST; + armor->armor_value = encoded_authenticator; + encoded_authenticator.data = NULL; + encoded_authenticator.length = 0; + state->armor = armor; + armor = NULL; + state->armor_key = armor_key; + armor_key = NULL; + } + krb5_free_keyblock(context, armor_key); + krb5_free_keyblock(context, subkey); + if (out_creds) + krb5_free_creds(context, out_creds); + krb5_free_cred_contents(context, &creds); + if (encoded_authenticator.data) + krb5_free_data_contents(context, &encoded_authenticator); + krb5_auth_con_free(context, authcontext); + return retval; +} krb5_error_code krb5int_fast_prep_req_body(krb5_context context, struct krb5int_fast_request_state *state, @@ -77,6 +128,34 @@ krb5int_fast_prep_req_body(krb5_context context, struct krb5int_fast_request_sta return retval; } +krb5_error_code krb5int_fast_as_armor +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_gic_opt_ext *opte, + krb5_kdc_req *request) +{ + krb5_error_code retval = 0; + krb5_ccache ccache = NULL; + krb5_clear_error_message(context); + if (opte->opt_private->fast_ccache_name) { + retval = krb5_cc_resolve(context, opte->opt_private->fast_ccache_name, + &ccache); + if (retval==0) + retval = fast_armor_ap_request(context, state, ccache, + krb5_princ_realm(context, request->server)); + if (retval != 0) { + const char * errmsg; + errmsg = krb5_get_error_message(context, retval); + if (errmsg) { + krb5_set_error_message(context, retval, "%s constructing AP-REQ armor", errmsg); + krb5_free_error_message(context, errmsg); + } + } + } + if (ccache) + krb5_cc_close(context, ccache); + return retval; +} + krb5_error_code krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state *state, @@ -88,28 +167,51 @@ krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state * krb5_pa_data *pa_array[3]; krb5_pa_data pa[2]; krb5_fast_req fast_req; + krb5_fast_armored_req *armored_req = NULL; krb5_data *encoded_fast_req = NULL; + krb5_data *encoded_armored_req = NULL; krb5_data *local_encoded_result = NULL; + krb5_cksumtype cksumtype; assert(state != NULL); - assert(state->fast_outer_request.padata == NULL); + assert(state->fast_outer_request.padata == NULL); memset(pa_array, 0, sizeof pa_array); if (state->armor_key == NULL) { return encoder(request, encoded_request); } fast_req.req_body = request; if (fast_req.req_body->padata == NULL) { - fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *)); - if (fast_req.req_body->padata == NULL) - retval = ENOMEM; + fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *)); + if (fast_req.req_body->padata == NULL) + retval = ENOMEM; } fast_req.fast_options = state->fast_options; if (retval == 0) retval = encode_krb5_fast_req(&fast_req, &encoded_fast_req); + if (retval == 0) { + armored_req = calloc(1, sizeof(krb5_fast_armored_req)); + if (armored_req == NULL) + retval = ENOMEM; + } + if (retval == 0) + armored_req->armor = state->armor; + if (retval == 0) + retval = krb5int_c_mandatory_cksumtype(context, state->armor_key->enctype, + &cksumtype); + if (retval ==0) + retval = krb5_c_make_checksum(context, cksumtype, state->armor_key, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, to_be_checksummed, + &armored_req->req_checksum); + if (retval == 0) + retval = krb5_encrypt_helper(context, state->armor_key, + KRB5_KEYUSAGE_FAST_ENC, encoded_fast_req, + &armored_req->enc_part); + if (retval == 0) + retval = encode_krb5_pa_fx_fast_request(armored_req, &encoded_armored_req); if (retval==0) { pa[0].pa_type = KRB5_PADATA_FX_FAST; - pa[0].contents = (unsigned char *) encoded_fast_req->data; - pa[0].length = encoded_fast_req->length; + pa[0].contents = (unsigned char *) encoded_armored_req->data; + pa[0].length = encoded_armored_req->length; pa_array[0] = &pa[0]; } if (state->cookie_contents.data) { @@ -125,6 +227,12 @@ krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state * *encoded_request = local_encoded_result; local_encoded_result = NULL; } + if (encoded_armored_req) + krb5_free_data(context, encoded_armored_req); + if (armored_req) { + armored_req->armor = NULL; /*owned by state*/ + krb5_free_fast_armored_req(context, armored_req); + } if (encoded_fast_req) krb5_free_data(context, encoded_fast_req); if (local_encoded_result) diff --git a/src/lib/krb5/krb/fast.h b/src/lib/krb5/krb/fast.h index 3225eab..acd12b3 100644 --- a/src/lib/krb5/krb/fast.h +++ b/src/lib/krb5/krb/fast.h @@ -62,6 +62,10 @@ krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state void krb5int_fast_free_state( krb5_context , struct krb5int_fast_request_state *state); +krb5_error_code krb5int_fast_as_armor +(krb5_context context, struct krb5int_fast_request_state *state, + krb5_gic_opt_ext *opte, + krb5_kdc_req *request); #endif diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 7bfca3f..eb23e54 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -1239,6 +1239,9 @@ krb5_get_init_creds(krb5_context context, /* XXX Yuck. Old version. */ request.nonce = (krb5_int32) time_now; } + ret = krb5int_fast_as_armor(context, fast_state, options, &request); + if (ret != 0) + goto cleanup; /* give the preauth plugins a chance to prep the request body */ krb5_preauth_prepare_request(context, options, &request); ret = krb5int_fast_prep_req_body(context, fast_state, diff --git a/src/lib/krb5/krb/gic_opt.c b/src/lib/krb5/krb/gic_opt.c index 348637c..72203f0 100644 --- a/src/lib/krb5/krb/gic_opt.c +++ b/src/lib/krb5/krb/gic_opt.c @@ -146,6 +146,8 @@ krb5int_gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte) /* Free up any private stuff */ if (opte->opt_private->preauth_data != NULL) free_gic_opt_ext_preauth_data(context, opte); + if (opte->opt_private->fast_ccache_name) + free(opte->opt_private->fast_ccache_name); free(opte->opt_private); opte->opt_private = NULL; return 0; @@ -465,3 +467,21 @@ krb5_get_init_creds_opt_free_pa(krb5_context context, } free(preauth_data); } +krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_fast_ccache_name +(krb5_context context, krb5_get_init_creds_opt *opt, const char *ccache_name) +{ + krb5_error_code retval = 0; + krb5_gic_opt_ext *opte; + + retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0, + "krb5_get_init_creds_opt_set_fast_ccache_name"); + if (retval) + return retval; + if (opte->opt_private->fast_ccache_name) { + free(opte->opt_private->fast_ccache_name); + } + opte->opt_private->fast_ccache_name = strdup(ccache_name); + if (opte->opt_private->fast_ccache_name == NULL) + retval = ENOMEM; + return retval; +} diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index 5813fc0..d3ad3f7 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -830,6 +830,7 @@ void krb5_free_fast_finished krb5_free_principal(context, val->client); krb5_free_checksum_contents(context, &val->checksum); krb5_free_checksum_contents(context, &val->ticket_checksum); + free(val); } void krb5_free_typed_data(krb5_context context, krb5_typed_data **in) @@ -844,3 +845,16 @@ void krb5_free_typed_data(krb5_context context, krb5_typed_data **in) } free(in); } + +void krb5_free_fast_armored_req(krb5_context context, + krb5_fast_armored_req *val) +{ + if (val == NULL) + return; + if (val->armor) + krb5_free_fast_armor(context, val->armor); + krb5_free_data_contents(context, &val->enc_part.ciphertext); + if (val->req_checksum.contents) + krb5_free_checksum_contents(context, &val->req_checksum); + free(val); +} diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 17b8fd3..45192f5 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -305,6 +305,7 @@ krb5_get_init_creds_opt_set_address_list krb5_get_init_creds_opt_set_canonicalize krb5_get_init_creds_opt_set_change_password_prompt krb5_get_init_creds_opt_set_etype_list +krb5_get_init_creds_opt_set_fast_ccache_name krb5_get_init_creds_opt_set_forwardable krb5_get_init_creds_opt_set_pa krb5_get_init_creds_opt_set_preauth_list |