* 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
#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
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)) {
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)
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,
#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 */
* (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;
}
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;
/* 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;
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;
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
if(retval = krb5_cc_retrieve_cred(context, ccache,
KRB5_TC_MATCH_SRV_NAMEONLY,
- &tgtq,
- &tgt)) {
+ &tgtq, &tgt)) {
if (retval != KRB5_CC_NOTFOUND) {
goto cleanup;
}
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;
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++];
}
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;
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++];
}
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);
#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)
/* 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...
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 */
)
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;
}
#include <krb5/ext-proto.h>
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;
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]) {
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;
}
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;
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))
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__ */
krb5_data *outbuf;
{
krb5_error_code retval;
+ krb5_creds * credsp;
krb5_creds creds;
/* obtain ticket & session key */
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;
}
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;
{
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 */
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 */
}
/* 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++;
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
*/
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;
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;
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;
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;
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);
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 */
/*
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;
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++)
} 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;
/* 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;
}
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;
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;
/*
* 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);
/* 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;
/*
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);
-
}