svn rev #25488: trunk/src/lib/krb5/krb/
hartmans@MIT.EDU
hartmans at MIT.EDU
Tue Nov 22 20:04:38 EST 2011
http://src.mit.edu/fisheye/changelog/krb5/?cs=25488
Commit By: hartmans
Log Message:
ticket: 7026
subject: FAST TGS
Implement RFC 6113 FAST TGS support.
Includes library support for a varient of explicit TGS armor that has not yet been proposed within the IETF.
Changed Files:
U trunk/src/lib/krb5/krb/decode_kdc.c
U trunk/src/lib/krb5/krb/fast.c
U trunk/src/lib/krb5/krb/fast.h
U trunk/src/lib/krb5/krb/gc_via_tkt.c
U trunk/src/lib/krb5/krb/get_creds.c
U trunk/src/lib/krb5/krb/int-proto.h
U trunk/src/lib/krb5/krb/send_tgs.c
Modified: trunk/src/lib/krb5/krb/decode_kdc.c
===================================================================
--- trunk/src/lib/krb5/krb/decode_kdc.c 2011-11-23 01:00:36 UTC (rev 25487)
+++ trunk/src/lib/krb5/krb/decode_kdc.c 2011-11-23 01:04:38 UTC (rev 25488)
@@ -26,6 +26,7 @@
#include "k5-int.h"
#include "int-proto.h"
+#include "fast.h"
/*
Takes a KDC_REP message and decrypts encrypted part using etype and
@@ -41,11 +42,15 @@
*/
krb5_error_code
-krb5int_decode_tgs_rep(krb5_context context, krb5_data *enc_rep, const krb5_keyblock *key,
+krb5int_decode_tgs_rep(krb5_context context,
+ struct krb5int_fast_request_state *fast_state,
+krb5_data *enc_rep, const krb5_keyblock *key,
krb5_keyusage usage, krb5_kdc_rep **dec_rep)
{
krb5_error_code retval;
krb5_kdc_rep *local_dec_rep;
+ krb5_keyblock *strengthen_key = NULL, tgs_key;
+ tgs_key.contents = NULL;
if (krb5_is_as_rep(enc_rep)) {
retval = decode_krb5_as_rep(enc_rep, &local_dec_rep);
@@ -58,10 +63,23 @@
if (retval)
return retval;
- if ((retval = krb5_kdc_rep_decrypt_proc(context, key, &usage,
+ retval = krb5int_fast_process_response(context, fast_state,
+ local_dec_rep, &strengthen_key);
+ if (retval == KRB5_ERR_FAST_REQUIRED)
+ retval = 0;
+ else if (retval)
+ goto cleanup;
+ retval = krb5int_fast_reply_key(context, strengthen_key, key, &tgs_key);
+ if (retval)
+ goto cleanup;
+
+ if ((retval = krb5_kdc_rep_decrypt_proc(context, &tgs_key, &usage,
local_dec_rep)))
krb5_free_kdc_rep(context, local_dec_rep);
else
*dec_rep = local_dec_rep;
- return(retval);
-}
+cleanup:
+ krb5_free_keyblock(context, strengthen_key);
+ krb5_free_keyblock_contents(context, &tgs_key);
+ return (retval);
+ }
Modified: trunk/src/lib/krb5/krb/fast.c
===================================================================
--- trunk/src/lib/krb5/krb/fast.c 2011-11-23 01:00:36 UTC (rev 25487)
+++ trunk/src/lib/krb5/krb/fast.c 2011-11-23 01:04:38 UTC (rev 25488)
@@ -106,6 +106,37 @@
return retval;
}
+krb5_error_code krb5int_fast_tgs_armor(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_keyblock *subkey,krb5_keyblock *session_key,
+ krb5_ccache ccache,
+ krb5_data *target_realm)
+{
+ krb5_principal target_principal = NULL;
+ krb5_keyblock *existing_armor = NULL;
+ krb5_error_code retval = 0;
+
+ if (ccache) {
+ retval = krb5int_tgtname(context, target_realm, target_realm,
+ &target_principal);
+ if (retval == 0)
+ retval = fast_armor_ap_request(context, state, ccache, target_principal);
+ if (retval == 0) {
+ existing_armor = state->armor_key;
+ state->armor_key = NULL;
+ retval = krb5_c_fx_cf2_simple(context, existing_armor,
+ "explicitarmor", subkey,
+ "tgsarmor", &state->armor_key);
+ }
+ } else retval = krb5_c_fx_cf2_simple(context,
+ subkey, "subkeyarmor",
+ session_key, "ticketarmor", &state->armor_key);
+ if (target_principal)
+ krb5_free_principal(context, target_principal);
+ krb5_free_keyblock(context, existing_armor);
+ return retval;
+}
+
+
krb5_error_code
krb5int_fast_prep_req_body(krb5_context context,
struct krb5int_fast_request_state *state,
@@ -200,13 +231,15 @@
krb5_data **encoded_request)
{
krb5_error_code retval = 0;
- krb5_pa_data *pa_array[2];
+ krb5_pa_data *pa_array[3];
krb5_pa_data pa[2];
krb5_fast_req fast_req;
- krb5_fast_armored_req *armored_req = NULL;
+ krb5_pa_data *tgs = NULL;
+ 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;
+ int i,j;
assert(state != NULL);
assert(state->fast_outer_request.padata == NULL);
@@ -224,6 +257,16 @@
retval = ENOMEM;
}
fast_req.fast_options = state->fast_options;
+ if (retval == 0
+ && (tgs = krb5int_find_pa_data(context,fast_req.req_body->padata,
+ KRB5_PADATA_AP_REQ))) {
+ krb5_pa_data **paptr = &fast_req.req_body->padata[0];
+ for (i=0,j=0;paptr[j]; j++)
+ if (paptr[j]->pa_type == KRB5_PADATA_AP_REQ)
+ paptr[j] = NULL;
+ else paptr[i++] = paptr[j];
+ paptr[i++] = NULL;
+ }
if (retval == 0)
retval = encode_krb5_fast_req(&fast_req, &encoded_fast_req);
if (retval == 0) {
@@ -249,7 +292,10 @@
pa[0].pa_type = KRB5_PADATA_FX_FAST;
pa[0].contents = (unsigned char *) encoded_armored_req->data;
pa[0].length = encoded_armored_req->length;
- pa_array[0] = &pa[0];
+ if (tgs) {
+ pa_array[0] = tgs;
+ pa_array[1] = &pa[0];
+ } else pa_array[0] = &pa[0];
}
state->fast_outer_request.padata = pa_array;
if(retval == 0)
Modified: trunk/src/lib/krb5/krb/fast.h
===================================================================
--- trunk/src/lib/krb5/krb/fast.h 2011-11-23 01:00:36 UTC (rev 25487)
+++ trunk/src/lib/krb5/krb/fast.h 2011-11-23 01:04:38 UTC (rev 25488)
@@ -102,5 +102,10 @@
krb5int_upgrade_to_fast_p(krb5_context context,
struct krb5int_fast_request_state *state,
krb5_pa_data **padata);
+krb5_error_code krb5int_fast_tgs_armor(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_keyblock *subkey,
+ krb5_keyblock *session_key,
+ krb5_ccache ccache,
+ krb5_data *target_realm);
#endif
Modified: trunk/src/lib/krb5/krb/gc_via_tkt.c
===================================================================
--- trunk/src/lib/krb5/krb/gc_via_tkt.c 2011-11-23 01:00:36 UTC (rev 25487)
+++ trunk/src/lib/krb5/krb/gc_via_tkt.c 2011-11-23 01:04:38 UTC (rev 25488)
@@ -31,7 +31,9 @@
#include "k5-int.h"
#include "int-proto.h"
+#include "fast.h"
+
static krb5_error_code
kdcrep2creds(krb5_context context, krb5_kdc_rep *pkdcrep, krb5_address *const *address,
krb5_data *psectkt, krb5_creds **ppcreds)
@@ -171,6 +173,7 @@
krb5_error_code
krb5int_make_tgs_request(krb5_context context,
+ struct krb5int_fast_request_state *fast_state,
krb5_creds *tkt,
krb5_flags kdcoptions,
krb5_address *const *address,
@@ -214,7 +217,7 @@
enctypes[1] = 0;
}
- retval = krb5int_make_tgs_request_ext(context, kdcoptions, &in_cred->times,
+ retval = krb5int_make_tgs_request_ext(context, fast_state, kdcoptions, &in_cred->times,
enctypes, in_cred->server, address,
in_cred->authdata, in_padata,
second_tkt ?
@@ -230,6 +233,7 @@
krb5_error_code
krb5int_process_tgs_reply(krb5_context context,
+ struct krb5int_fast_request_state *fast_state,
krb5_data *response_data,
krb5_creds *tkt,
krb5_flags kdcoptions,
@@ -257,6 +261,10 @@
retval = decode_krb5_error(response_data, &err_reply);
if (retval != 0)
goto cleanup;
+ retval = krb5int_fast_process_error(context, fast_state,
+ &err_reply, NULL, NULL);
+ if (retval)
+ goto cleanup;
retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
if (err_reply->text.length > 0) {
switch (err_reply->error) {
@@ -292,13 +300,14 @@
/* Unfortunately, Heimdal at least up through 1.2 encrypts using
the session key not the subsession key. So we try both. */
- retval = krb5int_decode_tgs_rep(context, response_data,
+ retval = krb5int_decode_tgs_rep(context, fast_state,
+ response_data,
subkey,
KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY,
&dec_rep);
if (retval) {
TRACE_TGS_REPLY_DECODE_SESSION(context, &tkt->keyblock);
- if ((krb5int_decode_tgs_rep(context, response_data,
+ if ((krb5int_decode_tgs_rep(context, fast_state, response_data,
&tkt->keyblock,
KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY, &dec_rep)) == 0)
retval = 0;
@@ -416,19 +425,24 @@
krb5_int32 nonce;
krb5_keyblock *subkey = NULL;
int tcp_only = 0, use_master = 0;
+ struct krb5int_fast_request_state *fast_state = NULL;
request_data.data = NULL;
request_data.length = 0;
response_data.data = NULL;
response_data.length = 0;
+ retval = krb5int_fast_make_state(context, &fast_state);
+ if (retval)
+ goto cleanup;
+
#ifdef DEBUG_REFERRALS
printf("krb5_get_cred_via_tkt starting; referral flag is %s\n", kdcoptions&KDC_OPT_CANONICALIZE?"on":"off");
krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt requested ticket", in_cred->server);
krb5int_dbgref_dump_principal("krb5_get_cred_via_tkt TGT in use", tkt->server);
#endif
- retval = krb5int_make_tgs_request(context, tkt, kdcoptions,
+ retval = krb5int_make_tgs_request(context, fast_state, tkt, kdcoptions,
address, in_padata, in_cred,
pacb_fct, pacb_data,
&request_data, ×tamp, &nonce,
@@ -448,6 +462,10 @@
retval = decode_krb5_error(&response_data, &err_reply);
if (retval != 0)
goto cleanup;
+ retval = krb5int_fast_process_error(context, fast_state,
+ &err_reply, NULL, NULL);
+ if (retval)
+ goto cleanup;
if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG) {
tcp_only = 1;
krb5_free_error(context, err_reply);
@@ -460,7 +478,7 @@
} else
goto cleanup;
- retval = krb5int_process_tgs_reply(context, &response_data,
+ retval = krb5int_process_tgs_reply(context, fast_state, &response_data,
tkt, kdcoptions, address,
in_padata, in_cred,
timestamp, nonce, subkey,
@@ -470,6 +488,7 @@
goto cleanup;
cleanup:
+ krb5int_fast_free_state(context, fast_state);
#ifdef DEBUG_REFERRALS
printf("krb5_get_cred_via_tkt ending; %s\n", retval?error_message(retval):"no error");
#endif
Modified: trunk/src/lib/krb5/krb/get_creds.c
===================================================================
--- trunk/src/lib/krb5/krb/get_creds.c 2011-11-23 01:00:36 UTC (rev 25487)
+++ trunk/src/lib/krb5/krb/get_creds.c 2011-11-23 01:04:38 UTC (rev 25488)
@@ -39,6 +39,7 @@
#include "k5-int.h"
#include "int-proto.h"
+#include "fast.h"
/*
* Set *mcreds and *fields to a matching credential and field set for
@@ -151,6 +152,7 @@
krb5_flags req_options; /* Caller-requested KRB5_GC_* options */
krb5_flags req_kdcopt; /* Caller-requested options as KDC options */
krb5_authdata **authdata; /* Caller-requested authdata */
+ struct krb5int_fast_request_state *fast_state;
/* The following fields are used in multiple steps. */
krb5_creds *cur_tgt; /* TGT to be used for next query */
@@ -266,7 +268,8 @@
if (!krb5_c_valid_enctype(ctx->cur_tgt->keyblock.enctype))
return KRB5_PROG_ETYPE_NOSUPP;
- code = krb5int_make_tgs_request(context, ctx->cur_tgt, ctx->kdcopt,
+ code = krb5int_make_tgs_request(context, ctx->fast_state,
+ ctx->cur_tgt, ctx->kdcopt,
ctx->cur_tgt->addresses, NULL,
ctx->tgs_in_creds, NULL, NULL, &request,
&ctx->timestamp, &ctx->nonce,
@@ -354,7 +357,8 @@
krb5_free_creds(context, ctx->reply_creds);
ctx->reply_creds = NULL;
- code = krb5int_process_tgs_reply(context, reply, ctx->cur_tgt, ctx->kdcopt,
+ code = krb5int_process_tgs_reply(context, ctx->fast_state,
+ reply, ctx->cur_tgt, ctx->kdcopt,
ctx->cur_tgt->addresses, NULL,
ctx->tgs_in_creds, ctx->timestamp,
ctx->nonce, ctx->subkey, NULL, NULL,
@@ -1043,6 +1047,9 @@
ctx = k5alloc(sizeof(*ctx), &code);
if (ctx == NULL)
goto cleanup;
+ code = krb5int_fast_make_state(context, &ctx->fast_state);
+ if (code)
+ goto cleanup;
ctx->req_options = options;
ctx->req_kdcopt = 0;
@@ -1110,6 +1117,7 @@
{
if (ctx == NULL)
return;
+ krb5int_fast_free_state(context, ctx->fast_state);
krb5_free_creds(context, ctx->in_creds);
krb5_cc_close(context, ctx->ccache);
krb5_free_principal(context, ctx->req_server);
Modified: trunk/src/lib/krb5/krb/int-proto.h
===================================================================
--- trunk/src/lib/krb5/krb/int-proto.h 2011-11-23 01:00:36 UTC (rev 25487)
+++ trunk/src/lib/krb5/krb/int-proto.h 2011-11-23 01:04:38 UTC (rev 25488)
@@ -27,6 +27,8 @@
#ifndef KRB5_INT_FUNC_PROTO__
#define KRB5_INT_FUNC_PROTO__
+struct krb5int_fast_request_state;
+
krb5_error_code
krb5int_tgtname(krb5_context context, const krb5_data *, const krb5_data *,
krb5_principal *);
@@ -89,6 +91,7 @@
krb5_error_code
krb5int_make_tgs_request_ext(krb5_context context,
+ struct krb5int_fast_request_state *,
krb5_flags kdcoptions,
const krb5_ticket_times *timestruct,
const krb5_enctype *ktypes,
@@ -110,6 +113,7 @@
krb5_error_code
krb5int_make_tgs_request(krb5_context context,
+ struct krb5int_fast_request_state *,
krb5_creds *tkt,
krb5_flags kdcoptions,
krb5_address *const *address,
@@ -127,6 +131,7 @@
krb5_error_code
krb5int_process_tgs_reply(krb5_context context,
+ struct krb5int_fast_request_state *,
krb5_data *response_data,
krb5_creds *tkt,
krb5_flags kdcoptions,
@@ -145,7 +150,9 @@
* in with the subkey needed to decrypt the TGS
* response. Otherwise it will be set to null.
*/
-krb5_error_code krb5int_decode_tgs_rep(krb5_context, krb5_data *,
+krb5_error_code krb5int_decode_tgs_rep(krb5_context,
+ struct krb5int_fast_request_state *,
+ krb5_data *,
const krb5_keyblock *, krb5_keyusage,
krb5_kdc_rep ** );
Modified: trunk/src/lib/krb5/krb/send_tgs.c
===================================================================
--- trunk/src/lib/krb5/krb/send_tgs.c 2011-11-23 01:00:36 UTC (rev 25487)
+++ trunk/src/lib/krb5/krb/send_tgs.c 2011-11-23 01:04:38 UTC (rev 25488)
@@ -26,6 +26,7 @@
#include "k5-int.h"
#include "int-proto.h"
+#include "fast.h"
/*
Constructs a TGS request
@@ -147,6 +148,7 @@
krb5_error_code
krb5int_make_tgs_request_ext(krb5_context context,
+ struct krb5int_fast_request_state *fast_state,
krb5_flags kdcoptions,
const krb5_ticket_times *timestruct,
const krb5_enctype *ktypes,
@@ -208,7 +210,11 @@
return retval;
TRACE_SEND_TGS_SUBKEY(context, local_subkey);
- if (authorization_data) {
+ retval = krb5int_fast_tgs_armor(context, fast_state, local_subkey,
+ &in_cred->keyblock, NULL, NULL);
+ if (retval)
+ goto cleanup;
+ if (authorization_data) {
/* need to encrypt it in the request */
if ((retval = encode_krb5_authdata(authorization_data, &scratch)))
@@ -249,7 +255,7 @@
tgsreq.second_ticket = 0;
/* encode the body; then checksum it */
- if ((retval = encode_krb5_kdc_req_body(&tgsreq, &scratch)))
+ if ((retval = krb5int_fast_prep_req_body(context, fast_state, &tgsreq, &scratch)))
goto cleanup;
/*
@@ -320,7 +326,9 @@
goto cleanup;
}
/* the TGS_REQ is assembled in tgsreq, so encode it */
- if ((retval = encode_krb5_tgs_req(&tgsreq, &scratch)))
+ if ((retval = krb5int_fast_prep_req(context, fast_state, &tgsreq,
+ &scratch2, encode_krb5_tgs_req,
+ &scratch)))
goto cleanup;
*request_data = *scratch;
More information about the cvs-krb5
mailing list