From: Chris Provenzano Date: Thu, 23 Feb 1995 13:35:36 +0000 (+0000) Subject: All to change krb5_get_credentials() .. X-Git-Tag: krb5-1.0-beta5~675 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=568e193e9ea9a739906a7948cc4086982b7fd377;p=krb5.git All to change krb5_get_credentials() .. * send_tgs.c (krb5_send_tgs()) Added check for a valid krb5_creds * arg. * mk_req_ext.c (krb5_mk_req_extended()) Require caller to pass in a valid krb5_creds * arg, and removed kdc_options krb5_flags and krb5_ccache from arg list. * send_tgs.c (krb5_send_tgs()) * sendauth.c (krb5_sendauth()) Fix calls to krb5_mk_req_extended() * gc_frm_kdc.c (krb5_get_cred_from_kdc()) Changed krb5_creds * in/out arg to be an in only arg and added krb5_creds ** out arg. * gc_via_tgt.c (krb5_get_cred_via_tgt()) Changed krb5_creds * in/out arg to be an in only arg and added krb5_creds ** out arg. * gc_2tgt.c (krb5_get_cred_via_2tgt()) Changed krb5_creds * in/out arg to be an in only arg and added krb5_creds ** out arg. * int-proto.h Updated prototypes for krb5_get_cred_via_tgt() and krb5_get_cred_via_2tgt(). * get_creds.c (krb5_get_credentials()) Changed krb5_creds * in/out arg to be an in only arg and added krb5_creds ** out arg. * sendauth.c (krb5_sendauth()) Routines that also require krb5_creds * in/out arg to be appropriately changed because krb5_get_credentials() changed. * gc_frm_kdc.c (krb5_get_cred_from_kdc()) * get_fcreds.c (krb5_get_for_creds()) * mk_req.c (krb5_mk_req()) Other routines that needed adjusting because krb5_get_credentials() changed but didn't need an API change. * int-proto.h Don't prototype krb5_get_cred_via_tgt() twice. Use the second to prototype krb5_get_cred_via_2tgt(). git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@4993 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog index 3f5518254..8223b84a9 100644 --- a/src/lib/krb5/krb/ChangeLog +++ b/src/lib/krb5/krb/ChangeLog @@ -3,6 +3,43 @@ Tue Feb 21 23:38:34 1995 Theodore Y. Ts'o (tytso@dcl) * mk_cred.c (krb5_mk_cred): Fix argument type to krb5_free_cred_enc_part(). +Thu Feb 16 00:22:03 1995 Chris Provenzano (proven@mit.edu) + + * send_tgs.c (krb5_send_tgs()) Added check for a valid krb5_creds * arg. + + * mk_req_ext.c (krb5_mk_req_extended()) Require caller to pass in a + valid krb5_creds * arg, and removed kdc_options krb5_flags + and krb5_ccache from arg list. + * send_tgs.c (krb5_send_tgs()) + * sendauth.c (krb5_sendauth()) + Fix calls to krb5_mk_req_extended() + + * gc_frm_kdc.c (krb5_get_cred_from_kdc()) Changed krb5_creds * in/out + arg to be an in only arg and added krb5_creds ** out arg. + + * gc_via_tgt.c (krb5_get_cred_via_tgt()) Changed krb5_creds * in/out + arg to be an in only arg and added krb5_creds ** out arg. + + * gc_2tgt.c (krb5_get_cred_via_2tgt()) Changed krb5_creds * in/out + arg to be an in only arg and added krb5_creds ** out arg. + + * int-proto.h Updated prototypes for krb5_get_cred_via_tgt() and + krb5_get_cred_via_2tgt(). + + * get_creds.c (krb5_get_credentials()) Changed krb5_creds * in/out + arg to be an in only arg and added krb5_creds ** out arg. + * sendauth.c (krb5_sendauth()) + Routines that also require krb5_creds * in/out arg to be + appropriately changed because krb5_get_credentials() changed. + * gc_frm_kdc.c (krb5_get_cred_from_kdc()) + * get_fcreds.c (krb5_get_for_creds()) + * mk_req.c (krb5_mk_req()) + Other routines that needed adjusting because + krb5_get_credentials() changed but didn't need an API change. + + * int-proto.h Don't prototype krb5_get_cred_via_tgt() twice. Use the + second to prototype krb5_get_cred_via_2tgt(). + Mon Feb 13 20:25:20 1995 Theodore Y. Ts'o (tytso@dcl) * get_in_tkt.c (krb5_get_in_tkt): Fix memory leak --- the default diff --git a/src/lib/krb5/krb/gc_2tgt.c b/src/lib/krb5/krb/gc_2tgt.c index 8cf6be0e9..7503ee76f 100644 --- a/src/lib/krb5/krb/gc_2tgt.c +++ b/src/lib/krb5/krb/gc_2tgt.c @@ -32,12 +32,13 @@ #include "int-proto.h" krb5_error_code -krb5_get_cred_via_2tgt (context, tgt, kdcoptions, sumtype, cred) +krb5_get_cred_via_2tgt (context, tgt, kdcoptions, sumtype, in_cred, out_cred) krb5_context context; krb5_creds *tgt; const krb5_flags kdcoptions; const krb5_cksumtype sumtype; - register krb5_creds * cred; + krb5_creds * in_cred; + krb5_creds ** out_cred; { krb5_error_code retval; #if 0 @@ -49,20 +50,20 @@ krb5_get_cred_via_2tgt (context, tgt, kdcoptions, sumtype, cred) krb5_response tgsrep; krb5_enctype etype; - /* tgt->client must be equal to cred->client */ + /* tgt->client must be equal to in_cred->client */ /* tgt->server must be equal to krbtgt/realmof(cred->client) */ - if (!krb5_principal_compare(context, tgt->client, cred->client)) + if (!krb5_principal_compare(context, tgt->client, in_cred->client)) return KRB5_PRINC_NOMATCH; if (!tgt->ticket.length) return(KRB5_NO_TKT_SUPPLIED); - if (!cred->second_ticket.length) + if (!in_cred->second_ticket.length) return(KRB5_NO_2ND_TKT); #if 0 /* What does this do? */ - if (retval = krb5_tgtname(context, krb5_princ_realm(cred->server), - krb5_princ_realm(context, cred->client), &tempprinc)) + if (retval = krb5_tgtname(context, krb5_princ_realm(in_cred->server), + krb5_princ_realm(context, in_cred->client), &tempprinc)) return(retval); if (!krb5_principal_compare(context, tempprinc, tgt->server)) { @@ -75,14 +76,11 @@ krb5_get_cred_via_2tgt (context, tgt, kdcoptions, sumtype, cred) if (!(kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY)) return KRB5_INVALID_FLAGS; - if (retval = krb5_send_tgs(context, kdcoptions, &cred->times, NULL, - sumtype, - cred->server, - tgt->addresses, - cred->authdata, + if (retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, NULL, + sumtype, in_cred->server, tgt->addresses, + in_cred->authdata, 0, /* no padata */ - &cred->second_ticket, - tgt, &tgsrep)) + &in_cred->second_ticket, tgt, &tgsrep)) return retval; if (tgsrep.message_type != KRB5_TGS_REP) @@ -120,58 +118,71 @@ krb5_get_cred_via_2tgt (context, tgt, kdcoptions, sumtype, cred) retval = KRB5_KDCREP_MODIFIED; goto errout; } - /* put pieces into cred-> */ - if (cred->keyblock.contents) { - memset(&cred->keyblock.contents, 0, cred->keyblock.length); - krb5_xfree(cred->keyblock.contents); + + /* + * get a cred structure + * The caller is responsible for cleaning up + */ + if (((*out_cred) = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) { + retval = ENOMEM; + goto errout; + } + + /* Copy the client straig from in_cred */ + if (retval = krb5_copy_principal(context, in_cred->client, + &(*out_cred)->client)) { + goto errout; } - cred->keyblock.magic = KV5M_KEYBLOCK; - cred->keyblock.etype = dec_rep->ticket->enc_part.etype; - if (retval = krb5_copy_keyblock_contents(context, dec_rep->enc_part2->session, - &cred->keyblock)) + + /* put pieces into out_cred-> */ + (*out_cred)->keyblock.magic = KV5M_KEYBLOCK; + (*out_cred)->keyblock.etype = dec_rep->ticket->enc_part.etype; + if (retval = krb5_copy_keyblock_contents(context, + dec_rep->enc_part2->session, + &(*out_cred)->keyblock)) goto errout; /* Should verify that the ticket is what we asked for. */ - cred->times = dec_rep->enc_part2->times; - cred->ticket_flags = dec_rep->enc_part2->flags; - cred->is_skey = TRUE; - if (cred->addresses) - krb5_free_addresses(context, cred->addresses); + (*out_cred)->times = dec_rep->enc_part2->times; + (*out_cred)->ticket_flags = dec_rep->enc_part2->flags; + (*out_cred)->is_skey = TRUE; if (dec_rep->enc_part2->caddrs) retval = krb5_copy_addresses(context, dec_rep->enc_part2->caddrs, - &cred->addresses); + &(*out_cred)->addresses); else /* no addresses in the list means we got what we had */ - retval = krb5_copy_addresses(context, tgt->addresses, &cred->addresses); + retval = krb5_copy_addresses(context, tgt->addresses, &(*out_cred)->addresses); if (retval) goto errout; - if (cred->server) - krb5_free_principal(context, cred->server); if (retval = krb5_copy_principal(context, dec_rep->enc_part2->server, - &cred->server)) + &(*out_cred)->server)) goto errout; if (retval = encode_krb5_ticket(dec_rep->ticket, &scratch)) goto errout; - cred->ticket = *scratch; + (*out_cred)->ticket = *scratch; krb5_xfree(scratch); errout: if (retval) { - if (cred->keyblock.contents) { - memset((char *)cred->keyblock.contents, 0, cred->keyblock.length); - krb5_xfree(cred->keyblock.contents); - cred->keyblock.contents = 0; - } - if (cred->addresses) { - krb5_free_addresses(context, cred->addresses); - cred->addresses = 0; - } - if (cred->server) { - krb5_free_principal(context, cred->server); - cred->server = 0; + if (*out_cred) { + if ((*out_cred)->keyblock.contents) { + memset((*out_cred)->keyblock.contents, 0, + (*out_cred)->keyblock.length); + krb5_xfree((*out_cred)->keyblock.contents); + (*out_cred)->keyblock.contents = 0; + } + if ((*out_cred)->addresses) { + krb5_free_addresses(context, (*out_cred)->addresses); + (*out_cred)->addresses = 0; + } + if ((*out_cred)->server) { + krb5_free_principal(context, (*out_cred)->server); + (*out_cred)->server = 0; + } + krb5_free_creds(context, *out_cred); } } memset((char *)dec_rep->enc_part2->session->contents, 0, diff --git a/src/lib/krb5/krb/gc_frm_kdc.c b/src/lib/krb5/krb/gc_frm_kdc.c index 5b3a90970..865d07395 100644 --- a/src/lib/krb5/krb/gc_frm_kdc.c +++ b/src/lib/krb5/krb/gc_frm_kdc.c @@ -65,16 +65,17 @@ extern krb5_cksumtype krb5_kdc_req_sumtype; #define TGT_ETYPE \ krb5_keytype_array[tgt.keyblock.keytype]->system->proto_enctype; -krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) +krb5_error_code krb5_get_cred_from_kdc(context, ccache, in_cred, out_cred, tgts) krb5_context context; krb5_ccache ccache; - krb5_creds *cred; + krb5_creds *in_cred; + krb5_creds **out_cred; krb5_creds ***tgts; { krb5_creds **ret_tgts = NULL; int ntgts = 0; - krb5_creds tgt, tgtq; + krb5_creds tgt, tgtq, *tgtr = NULL; krb5_enctype etype; krb5_error_code retval; krb5_principal int_server = NULL; /* Intermediate server for request */ @@ -107,12 +108,12 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) * (the ticket may be issued by some other intermediate * realm's KDC; so we use KRB5_TC_MATCH_SRV_NAMEONLY) */ - if (retval = krb5_copy_principal(context, cred->client, &tgtq.client)) + if (retval = krb5_copy_principal(context, in_cred->client, &tgtq.client)) goto cleanup; /* get target tgt from cache */ - if (retval = krb5_tgtname(context, krb5_princ_realm(context, cred->server), - krb5_princ_realm(context, cred->client), + if (retval = krb5_tgtname(context, krb5_princ_realm(context, in_cred->server), + krb5_princ_realm(context, in_cred->client), &int_server)) { goto cleanup; } @@ -145,15 +146,15 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) krb5_free_principal(context, int_server); int_server = NULL; if (retval = krb5_tgtname(context, - krb5_princ_realm(context, cred->client), - krb5_princ_realm(context, cred->client), + krb5_princ_realm(context, in_cred->client), + krb5_princ_realm(context, in_cred->client), &int_server)) { goto cleanup; } krb5_free_cred_contents(context, &tgtq); memset((char *)&tgtq, 0, sizeof(tgtq)); - if(retval = krb5_copy_principal(context, cred->client, &tgtq.client)) + if(retval = krb5_copy_principal(context, in_cred->client, &tgtq.client)) goto cleanup; if(retval = krb5_copy_principal(context, int_server, &tgtq.server)) goto cleanup; @@ -168,8 +169,8 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) /* get a list of realms to consult */ if (retval = krb5_walk_realm_tree(context, - krb5_princ_realm(context, cred->client), - krb5_princ_realm(context, cred->server), + krb5_princ_realm(context,in_cred->client), + krb5_princ_realm(context,in_cred->server), &tgs_list, KRB5_REALM_BRANCH_CHAR)) { goto cleanup; @@ -213,7 +214,7 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) krb5_free_principal(context, int_server); int_server = NULL; if (retval = krb5_tgtname(context, - krb5_princ_realm(context, cred->server), + krb5_princ_realm(context, in_cred->server), krb5_princ_realm(context, *top_server), &int_server)) { goto cleanup; @@ -252,7 +253,7 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) if(retval = krb5_get_cred_via_tgt(context, &tgt, FLAGS2OPTS(tgtq.ticket_flags), krb5_kdc_req_sumtype, - &tgtq)) { + &tgtq, &tgtr)) { /* * couldn't get one so now loop backwards through the realms @@ -283,8 +284,7 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) if(retval = krb5_cc_retrieve_cred(context, ccache, KRB5_TC_MATCH_SRV_NAMEONLY, - &tgtq, - &tgt)) { + &tgtq, &tgt)) { if (retval != KRB5_CC_NOTFOUND) { goto cleanup; } @@ -299,9 +299,9 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) krb5_free_cred_contents(context, &tgtq); memset(&tgtq, 0, sizeof(tgtq)); tgtq.times = tgt.times; - if (retval = krb5_copy_principal(context, tgt.client, &tgtq.client)) + if (retval = krb5_copy_principal(context,tgt.client,&tgtq.client)) goto cleanup; - if(retval = krb5_copy_principal(context, int_server, &tgtq.server)) + if(retval = krb5_copy_principal(context,int_server,&tgtq.server)) goto cleanup; tgtq.is_skey = FALSE; tgtq.ticket_flags = tgt.ticket_flags; @@ -309,14 +309,16 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) if (retval = krb5_get_cred_via_tgt(context, &tgt, FLAGS2OPTS(tgtq.ticket_flags), krb5_kdc_req_sumtype, - &tgtq)) { + &tgtq, &tgtr)) { continue; } /* save tgt in return array */ - if (retval = krb5_copy_creds(context, &tgtq, &ret_tgts[ntgts])) { + if (retval = krb5_copy_creds(context, tgtr, &ret_tgts[ntgts])) { goto cleanup; } + krb5_free_creds(context, tgtr); + tgtr = NULL; tgt = *ret_tgts[ntgts++]; } @@ -342,7 +344,7 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) for (next_server = top_server; *next_server; next_server++) { krb5_data *realm_1 = krb5_princ_component(context, next_server[0], 1); - krb5_data *realm_2 = krb5_princ_component(context, tgtq.server, 1); + krb5_data *realm_2 = krb5_princ_component(context, tgtr->server, 1); if (realm_1->length == realm_2->length && !memcmp(realm_1->data, realm_2->data, realm_1->length)) { break; @@ -354,9 +356,11 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) goto cleanup; } - if (retval = krb5_copy_creds(context, &tgtq, &ret_tgts[ntgts])) { + if (retval = krb5_copy_creds(context, tgtr, &ret_tgts[ntgts])) { goto cleanup; } + krb5_free_creds(context, tgtr); + tgtr = NULL; tgt = *ret_tgts[ntgts++]; @@ -375,25 +379,22 @@ krb5_error_code krb5_get_cred_from_kdc(context, ccache, cred, tgts) } etype = TGT_ETYPE; - if (cred->second_ticket.length) { + if (in_cred->second_ticket.length) { retval = krb5_get_cred_via_2tgt(context, &tgt, KDC_OPT_ENC_TKT_IN_SKEY | FLAGS2OPTS(tgt.ticket_flags), - etype, - krb5_kdc_req_sumtype, - cred); - } - else { + krb5_kdc_req_sumtype, in_cred, out_cred); + } else { retval = krb5_get_cred_via_tgt(context, &tgt, - FLAGS2OPTS(tgt.ticket_flags), - krb5_kdc_req_sumtype, - cred); + FLAGS2OPTS(tgt.ticket_flags), + krb5_kdc_req_sumtype, in_cred, out_cred); } /* cleanup and return */ cleanup: + if (tgtr) krb5_free_creds(context, tgtr); if(tgs_list) krb5_free_realm_tree(context, tgs_list); krb5_free_cred_contents(context, &tgtq); if (int_server) krb5_free_principal(context, int_server); diff --git a/src/lib/krb5/krb/gc_via_tgt.c b/src/lib/krb5/krb/gc_via_tgt.c index 1e9b8da53..620a50db2 100644 --- a/src/lib/krb5/krb/gc_via_tgt.c +++ b/src/lib/krb5/krb/gc_via_tgt.c @@ -34,24 +34,23 @@ #include "int-proto.h" krb5_error_code -krb5_get_cred_via_tgt (context, tgt, kdcoptions, sumtype, cred) +krb5_get_cred_via_tgt (context, tgt, kdcoptions, sumtype, in_cred, out_cred) krb5_context context; krb5_creds * tgt; const krb5_flags kdcoptions; const krb5_cksumtype sumtype; - krb5_creds * cred; + krb5_creds * in_cred; + krb5_creds ** out_cred; { krb5_error_code retval; krb5_principal tempprinc; krb5_data *scratch; - krb5_enctype etype; krb5_kdc_rep *dec_rep; krb5_error *err_reply; krb5_response tgsrep; - /* tgt->client must be equal to cred->client */ - - if (!krb5_principal_compare(context, tgt->client, cred->client)) + /* tgt->client must be equal to in_cred->client */ + if (!krb5_principal_compare(context, tgt->client, in_cred->client)) return KRB5_PRINC_NOMATCH; if (!tgt->ticket.length) @@ -61,43 +60,36 @@ krb5_get_cred_via_tgt (context, tgt, kdcoptions, sumtype, cred) /* tgt->server must be equal to */ /* krbtgt/realmof(cred->server)@realmof(tgt->server) */ - if(retval = krb5_tgtname(context, - krb5_princ_realm(context, cred->server), + if (retval = krb5_tgtname(context, + krb5_princ_realm(context, in_cred->server), krb5_princ_realm(context, tgt->server), &tempprinc)) return(retval); + if (!krb5_principal_compare(context, tempprinc, tgt->server)) { - krb5_free_principal(context, tempprinc); - return KRB5_PRINC_NOMATCH; + retval = KRB5_PRINC_NOMATCH; + goto error_5; } - krb5_free_principal(context, tempprinc); - - if (retval = krb5_send_tgs(context, kdcoptions, &cred->times, NULL, - sumtype, - cred->server, - tgt->addresses, - cred->authdata, + if (retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, NULL, + sumtype, in_cred->server, tgt->addresses, + in_cred->authdata, 0, /* no padata */ 0, /* no second ticket */ tgt, &tgsrep)) - return retval; - -#undef cleanup -#define cleanup() free(tgsrep.response.data) + goto error_5; switch (tgsrep.message_type) { case KRB5_TGS_REP: break; case KRB5_ERROR: default: - if (!krb5_is_krb_error(&tgsrep.response)) { - retval = KRB5KRB_AP_ERR_MSG_TYPE; - } else + if (krb5_is_krb_error(&tgsrep.response)) retval = decode_krb5_error(&tgsrep.response, &err_reply); - if (retval) { - cleanup(); - return retval; /* neither proper reply nor error! */ - } + else + retval = KRB5KRB_AP_ERR_MSG_TYPE; + + if (retval) /* neither proper reply nor error! */ + goto error_4; #if 0 /* XXX need access to the actual assembled request... @@ -111,56 +103,47 @@ krb5_get_cred_via_tgt (context, tgt, kdcoptions, sumtype, cred) retval = err_reply->error + ERROR_TABLE_BASE_krb5; krb5_free_error(context, err_reply); - cleanup(); - return retval; + goto error_4; } - etype = tgt->keyblock.etype; - retval = krb5_decode_kdc_rep(context, &tgsrep.response, - &tgt->keyblock, - etype, /* enctype */ - &dec_rep); - cleanup(); - if (retval) - return retval; -#undef cleanup -#define cleanup() {\ - memset((char *)dec_rep->enc_part2->session->contents, 0,\ - dec_rep->enc_part2->session->length);\ - krb5_free_kdc_rep(context, dec_rep); } + if (retval = krb5_decode_kdc_rep(context, &tgsrep.response, &tgt->keyblock, + tgt->keyblock.etype, &dec_rep)) + goto error_4; if (dec_rep->msg_type != KRB5_TGS_REP) { retval = KRB5KRB_AP_ERR_MSG_TYPE; - cleanup(); - return retval; + goto error_3; } /* now it's decrypted and ready for prime time */ - if (!krb5_principal_compare(context, dec_rep->client, tgt->client)) { - cleanup(); - return KRB5_KDCREP_MODIFIED; + retval = KRB5_KDCREP_MODIFIED; + goto error_3; } - /* put pieces into cred-> */ - if (cred->keyblock.contents) { - memset(&cred->keyblock.contents, 0, cred->keyblock.length); - krb5_xfree(cred->keyblock.contents); + + /* get a cred structure */ + /* The caller is responsible for cleaning up */ + if (((*out_cred) = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) { + retval = ENOMEM; + goto error_2; } - if (retval = krb5_copy_keyblock_contents(context, dec_rep->enc_part2->session, - &cred->keyblock)) { - cleanup(); - return retval; + memset((*out_cred), 0, sizeof(krb5_creds)); + + /* Copy the client straigt from in_cred */ + if (retval = krb5_copy_principal(context, in_cred->client, + &(*out_cred)->client)) { + goto error_2; } - cred->keyblock.etype = dec_rep->ticket->enc_part.etype; - memset((char *)dec_rep->enc_part2->session->contents, 0, - dec_rep->enc_part2->session->length); -#undef cleanup -#define cleanup() {\ - memset((char *)cred->keyblock.contents, 0, cred->keyblock.length);\ - krb5_free_kdc_rep(context, dec_rep); } + /* put pieces into out_cred-> */ + if (retval = krb5_copy_keyblock_contents(context, + dec_rep->enc_part2->session, + &(*out_cred)->keyblock)) { + goto error_2; + } - cred->times = dec_rep->enc_part2->times; + (*out_cred)->keyblock.etype = dec_rep->ticket->enc_part.etype; + (*out_cred)->times = dec_rep->enc_part2->times; #if 0 /* XXX probably need access to the request */ @@ -185,56 +168,57 @@ krb5_get_cred_via_tgt (context, tgt, kdcoptions, sumtype, cred) ) retval = KRB5_KDCREP_MODIFIED; - if ((request.from == 0) && - !in_clock_skew(dec_rep->enc_part2->times.starttime)) + if (!request.from && !in_clock_skew(dec_rep->enc_part2->times.starttime)) { retval = KRB5_KDCREP_SKEW; - - if (retval) { - cleanup(); - return retval; + goto error_1; } #endif - cred->ticket_flags = dec_rep->enc_part2->flags; - cred->is_skey = FALSE; - if (cred->addresses) { - krb5_free_addresses(context, cred->addresses); - } + (*out_cred)->ticket_flags = dec_rep->enc_part2->flags; + (*out_cred)->is_skey = FALSE; if (dec_rep->enc_part2->caddrs) { if (retval = krb5_copy_addresses(context, dec_rep->enc_part2->caddrs, - &cred->addresses)) { - cleanup(); - return retval; + &(*out_cred)->addresses)) { + goto error_1; } } else { /* no addresses in the list means we got what we had */ if (retval = krb5_copy_addresses(context, tgt->addresses, - &cred->addresses)) { - cleanup(); - return retval; + &(*out_cred)->addresses)) { + goto error_1; } } - /* - * Free cred->server before overwriting it. - */ - if (cred->server) - krb5_free_principal(context, cred->server); if (retval = krb5_copy_principal(context, dec_rep->enc_part2->server, - &cred->server)) { - cleanup(); - return retval; + &(*out_cred)->server)) { + goto error_1; } if (retval = encode_krb5_ticket(dec_rep->ticket, &scratch)) { - cleanup(); - krb5_free_addresses(context, cred->addresses); - return retval; + krb5_free_addresses(context, (*out_cred)->addresses); + goto error_1; } - cred->ticket = *scratch; + (*out_cred)->ticket = *scratch; krb5_xfree(scratch); +error_1:; + if (retval) + memset((*out_cred)->keyblock.contents, 0, (*out_cred)->keyblock.length); + +error_2:; + if (retval) + krb5_free_creds(context, *out_cred); + +error_3:; + memset(dec_rep->enc_part2->session->contents, 0, + dec_rep->enc_part2->session->length); krb5_free_kdc_rep(context, dec_rep); + +error_4:; + free(tgsrep.response.data); + +error_5:; + krb5_free_principal(context, tempprinc); return retval; } diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c index 21f043e15..14f44b233 100644 --- a/src/lib/krb5/krb/get_creds.c +++ b/src/lib/krb5/krb/get_creds.c @@ -44,26 +44,28 @@ #include krb5_error_code -krb5_get_credentials(context, options, ccache, creds) +krb5_get_credentials(context, options, ccache, in_creds, out_creds) krb5_context context; const krb5_flags options; krb5_ccache ccache; - krb5_creds *creds; + krb5_creds *in_creds; + krb5_creds **out_creds; { krb5_error_code retval, rv2; krb5_creds **tgts; - krb5_creds mcreds, ncreds; + krb5_creds *ncreds; + krb5_creds mcreds; krb5_flags fields; - if (!creds || !creds->server || !creds->client) - return -EINVAL; + if (!in_creds || !in_creds->server || !in_creds->client) + return -EINVAL; - memset((char *)&mcreds, 0, sizeof(mcreds)); - mcreds.server = creds->server; - mcreds.client = creds->client; - mcreds.times.endtime = creds->times.endtime; - mcreds.keyblock = creds->keyblock; - mcreds.authdata = creds->authdata; + memset((char *)&mcreds, 0, sizeof(krb5_creds)); + mcreds.times.endtime = in_creds->times.endtime; + mcreds.keyblock = in_creds->keyblock; + mcreds.authdata = in_creds->authdata; + mcreds.server = in_creds->server; + mcreds.client = in_creds->client; fields = KRB5_TC_MATCH_TIMES /*XXX |KRB5_TC_MATCH_SKEY_TYPE */ | KRB5_TC_MATCH_AUTHDATA; @@ -73,20 +75,28 @@ krb5_get_credentials(context, options, ccache, creds) session key */ fields |= KRB5_TC_MATCH_2ND_TKT|KRB5_TC_MATCH_IS_SKEY; mcreds.is_skey = TRUE; - mcreds.second_ticket = creds->second_ticket; - if (!creds->second_ticket.length) + mcreds.second_ticket = in_creds->second_ticket; + if (!in_creds->second_ticket.length) return KRB5_NO_2ND_TKT; } - retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds, &ncreds); - if (retval == 0) { - krb5_free_cred_contents(context, creds); - *creds = ncreds; + if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) + return -ENOMEM; + + memset((char *)ncreds, 0, sizeof(krb5_creds)); + + /* The caller is now responsible for cleaning up in_creds */ + if (retval = krb5_cc_retrieve_cred(context,ccache,fields,&mcreds,ncreds)) { + krb5_xfree(ncreds); + ncreds = in_creds; + } else { + *out_creds = ncreds; } + if (retval != KRB5_CC_NOTFOUND || options & KRB5_GC_CACHED) return retval; - retval = krb5_get_cred_from_kdc(context, ccache, creds, &tgts); + retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts); if (tgts) { register int i = 0; while (tgts[i]) { @@ -99,6 +109,6 @@ krb5_get_credentials(context, options, ccache, creds) krb5_free_tgt_creds(context, tgts); } if (!retval) - retval = krb5_cc_store_cred(context, ccache, creds); + retval = krb5_cc_store_cred(context, ccache, *out_creds); return retval; } diff --git a/src/lib/krb5/krb/get_fcreds.c b/src/lib/krb5/krb/get_fcreds.c index a7cfda724..b5fea089d 100644 --- a/src/lib/krb5/krb/get_fcreds.c +++ b/src/lib/krb5/krb/get_fcreds.c @@ -143,10 +143,8 @@ krb5_get_for_creds(context, sumtype, rhost, client, enc_key, goto errout; /* fetch tgt directly from cache */ - retval = krb5_cc_retrieve_cred (context, cc, - KRB5_TC_MATCH_SRV_NAMEONLY, - &creds, - &tgt); + retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_MATCH_SRV_NAMEONLY, + &creds, &tgt); krb5_cc_close(context, cc); if (retval) goto errout; @@ -168,10 +166,7 @@ krb5_get_for_creds(context, sumtype, rhost, client, enc_key, kdcoptions &= ~(KDC_OPT_FORWARDABLE); if (retval = krb5_send_tgs(context, kdcoptions, &creds.times, NULL, - sumtype, - tgt.server, - addrs, - creds.authdata, + sumtype, tgt.server, addrs, creds.authdata, 0, /* no padata */ 0, /* no second ticket */ &tgt, &tgsrep)) diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h index fcf739acb..0a08e39cd 100644 --- a/src/lib/krb5/krb/int-proto.h +++ b/src/lib/krb5/krb/int-proto.h @@ -38,13 +38,15 @@ krb5_error_code krb5_get_cred_via_tgt krb5_creds *, const krb5_flags, const krb5_cksumtype, - krb5_creds * )); -krb5_error_code krb5_get_cred_via_tgt + krb5_creds *, + krb5_creds **)); +krb5_error_code krb5_get_cred_via_2tgt PROTOTYPE((krb5_context context, krb5_creds *, const krb5_flags, const krb5_cksumtype, - krb5_creds * )); + krb5_creds *, + krb5_creds **)); #endif /* KRB5_INT_FUNC_PROTO__ */ diff --git a/src/lib/krb5/krb/mk_req.c b/src/lib/krb5/krb/mk_req.c index c99aa463b..178b2dd29 100644 --- a/src/lib/krb5/krb/mk_req.c +++ b/src/lib/krb5/krb/mk_req.c @@ -60,6 +60,7 @@ krb5_mk_req(context, server, ap_req_options, checksum, ccache, outbuf) krb5_data *outbuf; { krb5_error_code retval; + krb5_creds * credsp; krb5_creds creds; /* obtain ticket & session key */ @@ -76,21 +77,18 @@ krb5_mk_req(context, server, ap_req_options, checksum, ccache, outbuf) preference */ if (retval = krb5_get_credentials(context, krb5_kdc_default_options, - ccache, - &creds)) + ccache, &creds, &credsp)) goto errout; - retval = krb5_mk_req_extended(context, ap_req_options, - checksum, - krb5_kdc_default_options, + retval = krb5_mk_req_extended(context, ap_req_options, checksum, 0, /* no sequence number */ 0, /* no sub-key */ - ccache, - &creds, + credsp, 0, /* We don't need the authenticator */ outbuf); errout: krb5_free_cred_contents(context, &creds); + krb5_free_creds(context, credsp); return retval; } diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index b4d60177a..9b5c060ec 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -73,16 +73,14 @@ krb5_generate_authenticator PROTOTYPE((krb5_context, krb5_int32, krb5_authdata ** )); krb5_error_code -krb5_mk_req_extended(context, ap_req_options, checksum, kdc_options, - sequence, newkey, ccache, creds, authentp, outbuf) +krb5_mk_req_extended(context, ap_req_options, checksum, sequence, + newkey, in_creds, authentp, outbuf) krb5_context context; const krb5_flags ap_req_options; const krb5_checksum *checksum; - const krb5_flags kdc_options; krb5_int32 sequence; krb5_keyblock **newkey; - krb5_ccache ccache; - krb5_creds *creds; + krb5_creds *in_creds; krb5_authenticator *authentp; krb5_data *outbuf; { @@ -102,19 +100,17 @@ krb5_mk_req_extended(context, ap_req_options, checksum, kdc_options, scratch = 0; if ((ap_req_options & AP_OPTS_USE_SESSION_KEY) && - !creds->ticket.length) + !in_creds->ticket.length) return(KRB5_NO_TKT_SUPPLIED); - if (!creds->ticket.length) { - /* go get creds */ - if (retval = krb5_get_credentials(context, kdc_options, - ccache, - creds)) - return(retval); - } + if (!in_creds->ticket.length) + return(KRB5_NO_TKT_SUPPLIED); + +/* if (retval = krb5_get_credentials(context, kdc_options, + ccache, in_creds, out_creds)) */ /* we need a native ticket */ - if (retval = decode_krb5_ticket(&creds->ticket, &request.ticket)) + if (retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket)) return(retval); /* verify a valid etype is available */ @@ -127,13 +123,15 @@ krb5_mk_req_extended(context, ap_req_options, checksum, kdc_options, request.ap_options = ap_req_options; if (newkey) { - if (retval = krb5_generate_subkey(context, &creds->keyblock, newkey)) + if (retval = krb5_generate_subkey(context, &(in_creds)->keyblock, + newkey)) goto cleanup; } - if (retval = krb5_generate_authenticator(context, &authent, creds->client, checksum, - newkey ? *newkey : 0, - sequence, creds->authdata)) + if (retval = krb5_generate_authenticator(context, &authent, + (in_creds)->client, checksum, + newkey ? *newkey : 0, sequence, + (in_creds)->authdata)) goto cleanup; /* encode the authenticator */ @@ -175,7 +173,7 @@ krb5_mk_req_extended(context, ap_req_options, checksum, kdc_options, } /* do any necessary key pre-processing */ - if (retval = krb5_process_key(context, &eblock, &creds->keyblock)) + if (retval = krb5_process_key(context, &eblock, &(in_creds)->keyblock)) goto cleanup; cleanup_key++; diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c index 27fde8f00..a5e118d38 100644 --- a/src/lib/krb5/krb/send_tgs.c +++ b/src/lib/krb5/krb/send_tgs.c @@ -39,8 +39,8 @@ addrs, if non-NULL, is used for addresses " " " authorization_dat, if non-NULL, is used for authorization_dat " " " second_ticket, if required by options, is used for the 2nd ticket in the req. - usecred is used for the ticket & session key in the KRB_AP_REQ header " " " - (the KDC realm is extracted from usecred->server's realm) + in_cred is used for the ticket & session key in the KRB_AP_REQ header " " " + (the KDC realm is extracted from in_cred->server's realm) The response is placed into *rep. rep->response.data is set to point at allocated storage which should be @@ -50,7 +50,7 @@ */ krb5_error_code krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, - authorization_data, padata, second_ticket, usecred, rep) + authorization_data, padata, second_ticket, in_cred, rep) krb5_context context; const krb5_flags kdcoptions; const krb5_ticket_times * timestruct; @@ -61,7 +61,7 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, krb5_authdata * const * authorization_data; krb5_pa_data * const * padata; const krb5_data * second_ticket; - krb5_creds * usecred; + krb5_creds * in_cred; krb5_response * rep; { krb5_error_code retval; @@ -74,20 +74,14 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, krb5_pa_data **combined_padata; krb5_pa_data ap_req_padata; - memset((char *)&tgsreq, 0, sizeof(tgsreq)); + /* + * in_creds MUST be a valid credential NOT just a partially filled in + * place holder for us to get credentials for the caller. + */ + if (!in_cred->ticket.length) + return(KRB5_NO_TKT_SUPPLIED); - if (etypes) { - /* Check passed etypes and make sure they're valid. */ - for (tgsreq.netypes = 0; etypes[tgsreq.netypes]; tgsreq.netypes++) { - if (!valid_etype(etypes[tgsreq.netypes])) - return KRB5_PROG_ETYPE_NOSUPP; - } - tgsreq.etype = (krb5_enctype *)etypes; - } else { - /* Get the default etypes */ - krb5_get_default_in_tkt_etypes(context, &(tgsreq.etype)); - for(tgsreq.netypes = 0; tgsreq.etype[tgsreq.netypes]; tgsreq.netypes++); - } + memset((char *)&tgsreq, 0, sizeof(tgsreq)); tgsreq.kdc_options = kdcoptions; tgsreq.server = (krb5_principal) sname; @@ -104,20 +98,19 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, if (authorization_data) { /* need to encrypt it in the request */ - krb5_encrypt_block eblock; if (retval = encode_krb5_authdata(authorization_data, &scratch)) return(retval); - krb5_use_cstype(context, &eblock, usecred->keyblock.etype); - tgsreq.authorization_data.etype = usecred->keyblock.etype; + krb5_use_cstype(context, &eblock, in_cred->keyblock.etype); + tgsreq.authorization_data.etype = in_cred->keyblock.etype; tgsreq.authorization_data.kvno = 0; /* ticket session key has */ /* no version */ tgsreq.authorization_data.ciphertext.length = krb5_encrypt_size(scratch->length, eblock.crypto_entry); /* add padding area, and zero it */ if (!(scratch->data = realloc(scratch->data, - tgsreq.authorization_data.ciphertext.length))) { + tgsreq.authorization_data.ciphertext.length))) { /* may destroy scratch->data */ krb5_xfree(scratch); return ENOMEM; @@ -129,13 +122,13 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, krb5_free_data(context, scratch); return ENOMEM; } - if (retval = krb5_process_key(context, &eblock, &usecred->keyblock)) { + if (retval = krb5_process_key(context, &eblock, &in_cred->keyblock)) { krb5_free_data(context, scratch); return retval; } /* call the encryption routine */ if (retval = krb5_encrypt(context, (krb5_pointer) scratch->data, - (krb5_pointer) tgsreq.authorization_data.ciphertext.data, + (krb5_pointer) tgsreq.authorization_data.ciphertext.data, scratch->length, &eblock, 0)) { (void) krb5_finish_key(context, &eblock); krb5_xfree(tgsreq.authorization_data.ciphertext.data); @@ -148,62 +141,52 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, return retval; } } -#define cleanup_authdata() { if (tgsreq.authorization_data.ciphertext.data) {\ - (void) memset(tgsreq.authorization_data.ciphertext.data, 0,\ - tgsreq.authorization_data.ciphertext.length); \ - krb5_xfree(tgsreq.authorization_data.ciphertext.data);}} - + /* Get the encryption types list */ + if (etypes) { + /* Check passed etypes and make sure they're valid. */ + for (tgsreq.netypes = 0; etypes[tgsreq.netypes]; tgsreq.netypes++) { + if (!valid_etype(etypes[tgsreq.netypes])) + return KRB5_PROG_ETYPE_NOSUPP; + } + tgsreq.etype = (krb5_enctype *)etypes; + } else { + /* Get the default etypes */ + krb5_get_default_in_tkt_etypes(context, &(tgsreq.etype)); + for(tgsreq.netypes = 0; tgsreq.etype[tgsreq.netypes]; tgsreq.netypes++); + } if (second_ticket) { - if (retval = decode_krb5_ticket(second_ticket, &sec_ticket)) { - cleanup_authdata(); - return retval; - } + if (retval = decode_krb5_ticket(second_ticket, &sec_ticket)) + goto send_tgs_error_1; sec_ticket_arr[0] = sec_ticket; sec_ticket_arr[1] = 0; tgsreq.second_ticket = sec_ticket_arr; } else tgsreq.second_ticket = 0; - /* encode the body; then checksum it */ - - retval = encode_krb5_kdc_req_body(&tgsreq, &scratch); - if (retval) { - if (sec_ticket) - krb5_free_ticket(context, sec_ticket); - cleanup_authdata(); - return(retval); - } + if (retval = encode_krb5_kdc_req_body(&tgsreq, &scratch)) + goto send_tgs_error_2; if (!(ap_checksum.contents = (krb5_octet *) malloc(krb5_checksum_size(context, sumtype)))) { - if (sec_ticket) - krb5_free_ticket(context, sec_ticket); krb5_free_data(context, scratch); - cleanup_authdata(); - return ENOMEM; + retval = ENOMEM; + goto send_tgs_error_2; } - if (retval = krb5_calculate_checksum(context, sumtype, - scratch->data, + if (retval = krb5_calculate_checksum(context, sumtype, scratch->data, scratch->length, - (krb5_pointer) usecred->keyblock.contents, - usecred->keyblock.length, + (krb5_pointer) in_cred->keyblock.contents, + in_cred->keyblock.length, &ap_checksum)) { - if (sec_ticket) - krb5_free_ticket(context, sec_ticket); - krb5_xfree(ap_checksum.contents); krb5_free_data(context, scratch); - cleanup_authdata(); - return retval; + goto send_tgs_error_3; } /* done with body */ krb5_free_data(context, scratch); -#define cleanup() {krb5_xfree(ap_checksum.contents);\ - if (sec_ticket) krb5_free_ticket(context, sec_ticket);} /* attach ap_req to the tgsreq */ /* @@ -212,16 +195,12 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, if (retval = krb5_mk_req_extended (context, 0L /* no ap options */, &ap_checksum, - 0L, /* don't need kdc_options for this */ 0, /* no initial sequence */ 0, /* no new key */ - 0, /* no ccache--already have creds */ - usecred, + in_cred, 0, /* don't need authenticator */ &scratch2)) { - cleanup(); - cleanup_authdata(); - return retval; + goto send_tgs_error_3; } ap_req_padata.pa_type = KRB5_PADATA_AP_REQ; @@ -235,10 +214,9 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, for (counter = padata; *counter; counter++, i++); combined_padata = (krb5_pa_data **)malloc(i+2); if (!combined_padata) { - cleanup(); - cleanup_authdata(); krb5_xfree(ap_req_padata.contents); - return ENOMEM; + retval = ENOMEM; + goto send_tgs_error_3; } combined_padata[0] = &ap_req_padata; for (i = 1, counter = padata; *counter; counter++, i++) @@ -247,10 +225,9 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, } else { combined_padata = (krb5_pa_data **)malloc(2*sizeof(*combined_padata)); if (!combined_padata) { - cleanup(); - cleanup_authdata(); krb5_xfree(ap_req_padata.contents); - return ENOMEM; + retval = ENOMEM; + goto send_tgs_error_3; } combined_padata[0] = &ap_req_padata; combined_padata[1] = 0; @@ -259,35 +236,42 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, /* the TGS_REQ is assembled in tgsreq, so encode it */ if (retval = encode_krb5_tgs_req(&tgsreq, &scratch)) { - cleanup(); - cleanup_authdata(); - krb5_xfree(combined_padata); krb5_xfree(ap_req_padata.contents); - return(retval); + krb5_xfree(combined_padata); + goto send_tgs_error_3; } - if (sec_ticket) - krb5_free_ticket(context, sec_ticket); - cleanup_authdata(); - krb5_xfree(combined_padata); krb5_xfree(ap_req_padata.contents); -#undef cleanup_authdata -#undef cleanup -#define cleanup() {krb5_xfree(ap_checksum.contents);} + krb5_xfree(combined_padata); /* now send request & get response from KDC */ retval = krb5_sendto_kdc(context, scratch, krb5_princ_realm(context, sname), &rep->response); krb5_free_data(context, scratch); - cleanup(); - if (retval) { - return retval; + + if (retval == 0) { + if (krb5_is_tgs_rep(&rep->response)) + rep->message_type = KRB5_TGS_REP; + else /* assume it's an error */ + rep->message_type = KRB5_ERROR; } -#undef cleanup - if (krb5_is_tgs_rep(&rep->response)) - rep->message_type = KRB5_TGS_REP; - else /* assume it's an error */ - rep->message_type = KRB5_ERROR; - return 0; +send_tgs_error_3:; + krb5_xfree(ap_checksum.contents); + +send_tgs_error_2:; + if (sec_ticket) + krb5_free_ticket(context, sec_ticket); + +send_tgs_error_1:; + if (etypes == NULL) + krb5_xfree(tgsreq.etype); + if (tgsreq.authorization_data.ciphertext.data) { + memset(tgsreq.authorization_data.ciphertext.data, 0, + tgsreq.authorization_data.ciphertext.length); + krb5_xfree(tgsreq.authorization_data.ciphertext.data); + } + + + return retval; } diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c index ec320698e..f5a139424 100644 --- a/src/lib/krb5/krb/sendauth.c +++ b/src/lib/krb5/krb/sendauth.c @@ -47,13 +47,12 @@ static char *sendauth_version = "KRB5_SENDAUTH_V1.0"; krb5_error_code krb5_sendauth(context, /* IN */ - fd, appl_version, client, server, ap_req_options, - checksump, + fd, appl_version, client, server, ap_req_options, checksump, + in_creds, /* IN/OUT */ - credsp, ccache, + ccache, /* OUT */ - sequence, newkey, - error, rep_result) + sequence, newkey, error, rep_result, out_creds) krb5_context context; krb5_pointer fd; char *appl_version; @@ -63,14 +62,17 @@ krb5_sendauth(context, krb5_int32 *sequence; krb5_keyblock **newkey; krb5_checksum *checksump; - krb5_creds *credsp; + krb5_creds *in_creds; krb5_ccache ccache; krb5_error **error; krb5_ap_rep_enc_part **rep_result; + krb5_creds **out_creds; { krb5_flags kdc_options = krb5_kdc_default_options; krb5_octet result; krb5_creds creds; + krb5_creds * credsp = NULL; + krb5_creds * credspout = NULL; krb5_error_code retval = 0; krb5_authenticator authent; krb5_data inbuf, outbuf; @@ -118,17 +120,18 @@ krb5_sendauth(context, /* * See if we need to access the credentials cache */ - if (!credsp || !credsp->ticket.length) { + if (!in_creds || !in_creds->ticket.length) { if (ccache) use_ccache = ccache; else if (retval = krb5_cc_default(context, &use_ccache)) goto error_return; } - if (!credsp) { + if (!in_creds) { if (retval = krb5_copy_principal(context, server, &creds.server)) goto error_return; if (client) - retval = krb5_copy_principal(context, client, &creds.client); + retval = krb5_copy_principal(context, client, + &creds.client); else retval = krb5_cc_get_principal(context, use_ccache, &creds.client); @@ -141,30 +144,31 @@ krb5_sendauth(context, /* creds.keyblock.keytype = 0; -- as well as this. zero means no session keytype preference */ - credsp = &creds; + in_creds = &creds; } - if (!credsp->ticket.length) { - if (retval = krb5_get_credentials(context, kdc_options, - use_ccache, - credsp)) + if (!in_creds->ticket.length) { + if (retval = krb5_get_credentials(context, kdc_options, use_ccache, + in_creds, &credsp)) goto error_return; + credspout = credsp; + } else { + credsp = in_creds; } /* * Generate a random sequence number */ if (sequence && - (retval = krb5_generate_seq_number(context, &credsp->keyblock, sequence))) + (retval = krb5_generate_seq_number(context, &credsp->keyblock, + sequence))) goto error_return; /* * OK, get the authentication header! */ if (retval = krb5_mk_req_extended(context, ap_req_options, checksump, - kdc_options, sequence ? *sequence : 0, newkey, - use_ccache, credsp, &authent, - &outbuf)) + credsp, &authent, &outbuf)) goto error_return; /* @@ -227,13 +231,16 @@ krb5_sendauth(context, krb5_free_ap_rep_enc_part(context, repl); } retval = 0; /* Normal return */ + if (out_creds) { + *out_creds = credsp; + } error_return: + if (credspout) + krb5_free_creds(context, credspout); if (!ccache && use_ccache) krb5_cc_close(context, use_ccache); - krb5_free_cred_contents(context, &creds); krb5_free_authenticator_contents(context, &authent); return(retval); - }