From: Chris Provenzano Date: Fri, 10 Mar 1995 17:26:04 +0000 (+0000) Subject: * auth_con.h auth_con.c Added for krb5_auth_con definition and X-Git-Tag: krb5-1.0-beta5~573 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=b2f49b74f53d6deafc39fc0069de3e249a383b13;p=krb5.git * auth_con.h auth_con.c Added for krb5_auth_con definition and support routines. * mk_req.c (krb5_mk_req()) * mk_req_ext.c (krb5_mk_req_extended()) * rd_rep.c (krb5_rd_rep()) * sendauth.c (krb5_sendauth()) * mk_priv.c (krb5_mk_priv()) * mk_safe.c (krb5_mk_safe()) * rd_priv.c (krb5_rd_priv()) * rd_safe.c (krb5_rd_safe()) Added a krb5_auth_context argument and eliminated many of the other arguments because they are included in the krb5_auth_context structure. * send_tgs.c (krb5_send_tgs()) Eliminate call to krb5_mk_req_extended(), which does far more than krb5_send_tgs() needs. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5099 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog index 260765474..6d3e670c5 100644 --- a/src/lib/krb5/krb/ChangeLog +++ b/src/lib/krb5/krb/ChangeLog @@ -1,3 +1,24 @@ + +Fri Mar 10 10:58:59 1995 Chris Provenzano (proven@mit.edu) + + * auth_con.h auth_con.c Added for krb5_auth_con definition and + support routines. + + * mk_req.c (krb5_mk_req()) + * mk_req_ext.c (krb5_mk_req_extended()) + * rd_rep.c (krb5_rd_rep()) + * sendauth.c (krb5_sendauth()) + * mk_priv.c (krb5_mk_priv()) + * mk_safe.c (krb5_mk_safe()) + * rd_priv.c (krb5_rd_priv()) + * rd_safe.c (krb5_rd_safe()) + Added a krb5_auth_context argument and eliminated many of + the other arguments because they are included in the + krb5_auth_context structure. + + * send_tgs.c (krb5_send_tgs()) Eliminate call to krb5_mk_req_extended(), + which does far more than krb5_send_tgs() needs. + Tue Mar 7 19:57:34 1995 Mark Eichin * configure.in: take out ISODE_INCLUDE. diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index c9556785d..429d2b9cd 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -8,6 +8,7 @@ LDFLAGS = -g OBJS= addr_comp.$(OBJEXT) \ addr_order.$(OBJEXT) \ addr_srch.$(OBJEXT) \ + auth_con.$(OBJEXT) \ bld_pr_ext.$(OBJEXT) \ bld_princ.$(OBJEXT) \ chk_trans.$(OBJEXT) \ @@ -73,6 +74,7 @@ OBJS= addr_comp.$(OBJEXT) \ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/addr_order.c \ $(srcdir)/addr_srch.c \ + $(srcdir)/auth_con.c \ $(srcdir)/bld_pr_ext.c \ $(srcdir)/bld_princ.c \ $(srcdir)/chk_trans.c \ diff --git a/src/lib/krb5/krb/auth_con.c b/src/lib/krb5/krb/auth_con.c new file mode 100644 index 000000000..571e38c3f --- /dev/null +++ b/src/lib/krb5/krb/auth_con.c @@ -0,0 +1,132 @@ + +#include "k5-int.h" +#include "auth_con.h" + +krb5_error_code INTERFACE +krb5_auth_con_init(context, auth_context) + krb5_context context; + krb5_auth_context ** auth_context; +{ + if (*auth_context = (krb5_auth_context *)malloc(sizeof(krb5_auth_context))){ + memset(*auth_context, 0, sizeof(krb5_auth_context)); + + /* Default flags, do time not seq */ + (*auth_context)->auth_context_flags = + KRB5_AUTH_CONTEXT_DO_TIME | KRB5_AUTH_CONN_INITIALIZED; + + (*auth_context)->cksumtype = CKSUMTYPE_CRC32; + return 0; + } + return ENOMEM; +} + +krb5_error_code INTERFACE +krb5_auth_con_free(context, auth_context) + krb5_context context; + krb5_auth_context * auth_context; +{ + if (auth_context->authentp) + krb5_free_authenticator(context, auth_context->authentp); + if (auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + if (auth_context->local_subkey) + krb5_free_keyblock(context, auth_context->local_subkey); + if (auth_context->remote_subkey) + krb5_free_keyblock(context, auth_context->remote_subkey); + free(auth_context); + return 0; +} + +krb5_error_code INTERFACE +krb5_auth_con_setaddrs(context, auth_context, local_addr, remote_addr) + krb5_context context; + krb5_auth_context * auth_context; + krb5_address * local_addr; + krb5_address * remote_addr; +{ + auth_context->remote_addr = remote_addr; + auth_context->local_addr = local_addr; + return 0; +} + +/* XXX this call is a hack. Fixed when I do the servers. */ +krb5_error_code INTERFACE +krb5_auth_con_setkey(context, auth_context, keyblock) + krb5_context context; + krb5_auth_context * auth_context; + krb5_keyblock * keyblock; +{ + if (auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + return(krb5_copy_keyblock(context, keyblock, &(auth_context->keyblock))); +} + +krb5_error_code INTERFACE +krb5_auth_con_getlocalsubkey(context, auth_context, keyblock) + krb5_context context; + krb5_auth_context * auth_context; + krb5_keyblock ** keyblock; +{ + return(krb5_copy_keyblock(context, auth_context->local_subkey, keyblock)); +} + +krb5_error_code INTERFACE +krb5_auth_con_setcksumtype(context, auth_context, cksumtype) + krb5_context context; + krb5_auth_context * auth_context; + krb5_cksumtype cksumtype; +{ + auth_context->cksumtype = cksumtype; + return 0; +} + +krb5_error_code INTERFACE +krb5_auth_con_getlocalseqnumber(context, auth_context, seqnumber) + krb5_context context; + krb5_auth_context * auth_context; + krb5_int32 * seqnumber; +{ + *seqnumber = auth_context->local_seq_number; + return 0; +} + +krb5_error_code INTERFACE +krb5_auth_con_setivector(context, auth_context, ivector) + krb5_context context; + krb5_auth_context * auth_context; + krb5_pointer ivector; +{ + auth_context->i_vector = ivector; + return 0; +} + +krb5_error_code INTERFACE +krb5_auth_con_getivector(context, auth_context, ivector) + krb5_context context; + krb5_auth_context * auth_context; + krb5_pointer * ivector; +{ + *ivector = auth_context->i_vector; + return 0; +} + +krb5_error_code INTERFACE +krb5_auth_con_setflags(context, auth_context, flags) + krb5_context context; + krb5_auth_context * auth_context; + krb5_int32 flags; +{ + auth_context->auth_context_flags = flags; + return 0; +} + +krb5_error_code INTERFACE +krb5_auth_con_setrcache(context, auth_context, rcache) + krb5_context context; + krb5_auth_context * auth_context; + krb5_rcache rcache; +{ + auth_context->rcache = rcache; + return 0; +} + diff --git a/src/lib/krb5/krb/auth_con.h b/src/lib/krb5/krb/auth_con.h new file mode 100644 index 000000000..0cf2ed7a2 --- /dev/null +++ b/src/lib/krb5/krb/auth_con.h @@ -0,0 +1,27 @@ + +#ifndef KRB5_AUTH_CONTEXT +#define KRB5_AUTH_CONTEXT + +struct _krb5_auth_context { + krb5_address * remote_addr; + krb5_address * local_addr; + krb5_keyblock * keyblock; + krb5_keyblock * local_subkey; + krb5_keyblock * remote_subkey; + + krb5_int32 auth_context_flags; + krb5_int32 remote_seq_number; + krb5_int32 local_seq_number; + krb5_authenticator *authentp; /* mk_req, rd_rep */ + krb5_cksumtype cksumtype; /* mk_safe, ... */ + krb5_pointer i_vector; /* mk_priv only */ + krb5_rcache rcache; +}; + + +/* Internal auth_context_flags */ +#define KRB5_AUTH_CONN_INITIALIZED 0x00010000 +#define KRB5_AUTH_CONN_USED_W_MK_REQ 0x00020000 +#define KRB5_AUTH_CONN_USED_W_RD_REQ 0x00040000 + +#endif diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c index c09a467de..37cf62f91 100644 --- a/src/lib/krb5/krb/mk_priv.c +++ b/src/lib/krb5/krb/mk_priv.c @@ -25,121 +25,78 @@ */ #include "k5-int.h" - -/* - Formats a KRB_PRIV message into outbuf. - - userdata is formatted as the user data in the message. - etype specifies the encryption type; key specifies the key for the - encryption; sender_addr and recv_addr specify the full addresses (host - and port) of the sender and receiver. - - i_vector is used as an initialization vector for the encryption, and if - non-NULL its contents are replaced with the last block of the encrypted - data upon exit. - - The outbuf buffer storage is allocated, and should be freed by the - caller when finished. - - returns system errors -*/ -krb5_error_code INTERFACE -krb5_mk_priv(context, userdata, etype, key, sender_addr, recv_addr, - seq_number, priv_flags, rcache, i_vector, outbuf) - krb5_context context; - const krb5_data * userdata; - const krb5_enctype etype; - const krb5_keyblock * key; - const krb5_address * sender_addr; - const krb5_address * recv_addr; - krb5_int32 seq_number; - krb5_int32 priv_flags; - krb5_rcache rcache; - krb5_pointer i_vector; - krb5_data * outbuf; +#include "auth_con.h" + +static krb5_error_code +krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr, + remote_addr, i_vector, outbuf) + krb5_context context; + const krb5_data * userdata; + const krb5_keyblock * keyblock; + krb5_replay_data * replaydata; + krb5_address * local_addr; + krb5_address * remote_addr; + krb5_pointer i_vector; + krb5_data * outbuf; { - krb5_error_code retval; - krb5_encrypt_block eblock; - krb5_priv privmsg; - krb5_priv_enc_part privmsg_enc_part; - krb5_data *scratch; + krb5_error_code retval; + krb5_encrypt_block eblock; + krb5_priv privmsg; + krb5_priv_enc_part privmsg_enc_part; + krb5_data *scratch1, *scratch2; - if (!valid_etype(etype)) + if (!valid_etype(keyblock->etype)) return KRB5_PROG_ETYPE_NOSUPP; - privmsg.enc_part.etype = etype; + privmsg.enc_part.kvno = 0; /* XXX allow user-set? */ + privmsg.enc_part.etype = keyblock->etype; privmsg_enc_part.user_data = *userdata; - privmsg_enc_part.s_address = (krb5_address *)sender_addr; - if (recv_addr) - privmsg_enc_part.r_address = (krb5_address *)recv_addr; - else - privmsg_enc_part.r_address = 0; - - if (!(priv_flags & KRB5_PRIV_NOTIME)) { - if (!rcache) - /* gotta provide an rcache in this case... */ - return KRB5_RC_REQUIRED; - if (retval = krb5_us_timeofday(context, &privmsg_enc_part.timestamp, - &privmsg_enc_part.usec)) - return retval; - } else - privmsg_enc_part.timestamp = 0, privmsg_enc_part.usec = 0; - if (priv_flags & KRB5_PRIV_DOSEQUENCE) { - privmsg_enc_part.seq_number = seq_number; - } else - privmsg_enc_part.seq_number = 0; + privmsg_enc_part.s_address = local_addr; + privmsg_enc_part.r_address = remote_addr; - /* start by encoding to-be-encrypted part of the message */ + /* We should check too make sure one exists. */ + privmsg_enc_part.timestamp = replaydata->timestamp; + privmsg_enc_part.usec = replaydata->usec; + privmsg_enc_part.seq_number = replaydata->seq; - if (retval = encode_krb5_enc_priv_part(&privmsg_enc_part, &scratch)) + /* start by encoding to-be-encrypted part of the message */ + if (retval = encode_krb5_enc_priv_part(&privmsg_enc_part, &scratch1)) return retval; -#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); krb5_free_data(context, scratch); } - /* put together an eblock for this encryption */ - - krb5_use_cstype(context, &eblock, etype); - privmsg.enc_part.ciphertext.length = krb5_encrypt_size(scratch->length, + krb5_use_cstype(context, &eblock, keyblock->etype); + privmsg.enc_part.ciphertext.length = krb5_encrypt_size(scratch1->length, eblock.crypto_entry); /* add padding area, and zero it */ - if (!(scratch->data = realloc(scratch->data, + if (!(scratch1->data = realloc(scratch1->data, privmsg.enc_part.ciphertext.length))) { - /* may destroy scratch->data */ - krb5_xfree(scratch); + /* may destroy scratch1->data */ + krb5_xfree(scratch1); return ENOMEM; } - memset(scratch->data + scratch->length, 0, - privmsg.enc_part.ciphertext.length - scratch->length); + + memset(scratch1->data + scratch1->length, 0, + privmsg.enc_part.ciphertext.length - scratch1->length); if (!(privmsg.enc_part.ciphertext.data = malloc(privmsg.enc_part.ciphertext.length))) { retval = ENOMEM; goto clean_scratch; } -#define cleanup_encpart() {\ - (void) memset(privmsg.enc_part.ciphertext.data, 0, \ - privmsg.enc_part.ciphertext.length); \ - free(privmsg.enc_part.ciphertext.data); \ - privmsg.enc_part.ciphertext.length = 0; \ - privmsg.enc_part.ciphertext.data = 0;} - /* do any necessary key pre-processing */ - if (retval = krb5_process_key(context, &eblock, key)) { + if (retval = krb5_process_key(context, &eblock, keyblock)) goto clean_encpart; - } - -#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);} /* call the encryption routine */ - if (retval = krb5_encrypt(context, (krb5_pointer) scratch->data, + if (retval = krb5_encrypt(context, (krb5_pointer) scratch1->data, (krb5_pointer) privmsg.enc_part.ciphertext.data, - scratch->length, &eblock, + scratch1->length, &eblock, i_vector)) { - goto clean_prockey; + krb5_finish_key(context, &eblock); + goto clean_encpart; } - /* put last block into the i_vector */ if (i_vector) memcpy(i_vector, @@ -148,50 +105,106 @@ krb5_mk_priv(context, userdata, etype, key, sender_addr, recv_addr, eblock.crypto_entry->block_length), eblock.crypto_entry->block_length); - /* private message is now assembled-- do some cleanup */ - cleanup_scratch(); - - if (retval = krb5_finish_key(context, &eblock)) { - cleanup_encpart(); - return retval; + if (retval = encode_krb5_priv(&privmsg, &scratch2)) { + krb5_finish_key(context, &eblock); + goto clean_encpart; } + /* encode private message */ - if (retval = encode_krb5_priv(&privmsg, &scratch)) { - cleanup_encpart(); - return retval; + if (retval = krb5_finish_key(context, &eblock)) + goto clean_encpart; + + *outbuf = *scratch2; + krb5_xfree(scratch2); + retval = 0; + +clean_encpart: + memset(privmsg.enc_part.ciphertext.data, 0, + privmsg.enc_part.ciphertext.length); + free(privmsg.enc_part.ciphertext.data); + privmsg.enc_part.ciphertext.length = 0; + privmsg.enc_part.ciphertext.data = 0; + +clean_scratch: + memset(scratch1->data, 0, scratch1->length); + krb5_free_data(context, scratch1); + + return retval; +} + + +krb5_error_code INTERFACE +krb5_mk_priv(context, auth_context, userdata, outbuf, outdata) + krb5_context context; + krb5_auth_context * auth_context; + const krb5_data * userdata; + krb5_data * outbuf; + krb5_replay_data * outdata; +{ + krb5_replay_data replaydata; + krb5_error_code retval; + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && + (auth_context->rcache == NULL)) + return KRB5_RC_REQUIRED; + + if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + (outdata == NULL)) + /* Need a better error */ + return KRB5_RC_REQUIRED; + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) { + if (retval = krb5_us_timeofday(context, &replaydata.timestamp, + &replaydata.usec)) + return retval; + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) { + outdata->timestamp = replaydata.timestamp; + outdata->usec = replaydata.usec; + } } + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { + replaydata.seq = auth_context->local_seq_number; + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + auth_context->local_seq_number++; + } else { + outdata->seq = replaydata.seq; + } + } + + if (retval = krb5_mk_priv_basic(context, userdata, auth_context->keyblock, + &replaydata, auth_context->local_addr, auth_context->remote_addr, + auth_context->i_vector, outbuf)) + goto error; - cleanup_encpart(); - if (!(priv_flags & KRB5_PRIV_NOTIME)) { + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; - if (retval = krb5_gen_replay_name(context, sender_addr, "_priv", - &replay.client)) { - cleanup_scratch(); - return retval; + if (retval = krb5_gen_replay_name(context, auth_context->local_addr, + "_priv", &replay.client)) { + krb5_xfree(outbuf); + goto error; } replay.server = ""; /* XXX */ - replay.cusec = privmsg_enc_part.usec; - replay.ctime = privmsg_enc_part.timestamp; - if (retval = krb5_rc_store(context, rcache, &replay)) { + replay.cusec = replaydata.usec; + replay.ctime = replaydata.timestamp; + if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) { /* should we really error out here? XXX */ - cleanup_scratch(); - krb5_xfree(replay.client); - return retval; + krb5_xfree(outbuf); + goto error; } krb5_xfree(replay.client); } - *outbuf = *scratch; - krb5_xfree(scratch); + return 0; - clean_prockey: - cleanup_prockey(); - clean_encpart: - cleanup_encpart(); - clean_scratch: - cleanup_scratch(); +error: + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) + auth_context->local_seq_number--; return retval; } diff --git a/src/lib/krb5/krb/mk_req.c b/src/lib/krb5/krb/mk_req.c index 91a769e93..3d86741fc 100644 --- a/src/lib/krb5/krb/mk_req.c +++ b/src/lib/krb5/krb/mk_req.c @@ -25,6 +25,7 @@ */ #include "k5-int.h" +#include "auth_con.h" /* Formats a KRB_AP_REQ message into outbuf. @@ -48,44 +49,56 @@ extern krb5_flags krb5_kdc_default_options; krb5_error_code INTERFACE -krb5_mk_req(context, server, ap_req_options, checksum, ccache, outbuf) - krb5_context context; - krb5_const_principal server; - const krb5_flags ap_req_options; - const krb5_checksum *checksum; - krb5_ccache ccache; - krb5_data *outbuf; +krb5_mk_req(context, auth_context, ap_req_options, service, hostname, in_data, + ccache, outbuf) + krb5_context context; + krb5_auth_context ** auth_context; + const krb5_flags ap_req_options; + char * service; + char * hostname; + krb5_data * in_data; + krb5_ccache ccache; + krb5_data * outbuf; { - krb5_error_code retval; - krb5_creds * credsp; - krb5_creds creds; + krb5_error_code retval; + krb5_principal server; + krb5_creds * credsp; + krb5_creds creds; + char ** realm; - /* obtain ticket & session key */ + /* get realm */ + if (retval = krb5_get_host_realm(context, hostname, &realm)) + return retval; + /* build principal */ + if (retval = krb5_build_principal(context, &server, strlen(realm[0]), + realm[0], service, hostname, NULL)) + goto cleanup_realm; + + /* obtain ticket & session key */ memset((char *)&creds, 0, sizeof(creds)); if (retval = krb5_copy_principal(context, server, &creds.server)) - goto errout; + goto cleanup_princ; + if (retval = krb5_cc_get_principal(context, ccache, &creds.client)) - goto errout; - /* creds.times.endtime = 0; -- memset 0 takes care of this - zero means "as long as possible" */ - /* creds.keyblock.keytype = 0; -- as well as this. - zero means no session keytype - preference */ + goto cleanup_creds; if (retval = krb5_get_credentials(context, krb5_kdc_default_options, ccache, &creds, &credsp)) - goto errout; + goto cleanup_creds; - retval = krb5_mk_req_extended(context, ap_req_options, checksum, - 0, /* no sequence number */ - 0, /* no sub-key */ - credsp, - 0, /* We don't need the authenticator */ - outbuf); + retval = krb5_mk_req_extended(context, auth_context, ap_req_options, + in_data, credsp, outbuf); -errout: - krb5_free_cred_contents(context, &creds); krb5_free_creds(context, credsp); + +cleanup_creds: + krb5_free_cred_contents(context, &creds); + +cleanup_princ: + krb5_free_principal(context, server); + +cleanup_realm: + krb5_free_host_realm(context, realm); return retval; } diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index 38c287c19..d30382fb8 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -24,7 +24,9 @@ * krb5_mk_req_extended() */ + #include "k5-int.h" +#include "auth_con.h" /* Formats a KRB_AP_REQ message into outbuf, with more complete options than @@ -66,87 +68,123 @@ krb5_generate_authenticator PROTOTYPE((krb5_context, krb5_int32, krb5_authdata ** )); krb5_error_code INTERFACE -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; - krb5_int32 sequence; - krb5_keyblock **newkey; - krb5_creds *in_creds; - krb5_authenticator *authentp; - krb5_data *outbuf; +krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds, + outbuf) + krb5_context context; + krb5_auth_context **auth_context; + const krb5_flags ap_req_options; + krb5_data * in_data; + krb5_creds * in_creds; + krb5_data * outbuf; { - krb5_error_code retval; + krb5_error_code retval; + krb5_checksum checksum; + krb5_auth_context * new_auth_context; + krb5_ap_req request; - krb5_authenticator authent; - krb5_data *scratch; - krb5_enctype etype; + krb5_data *scratch = 0; krb5_encrypt_block eblock; krb5_data *toutbuf; - int cleanup_key = 0; - request.ticket = 0; request.authenticator.ciphertext.data = 0; - if (newkey) - *newkey = 0; - scratch = 0; + request.ap_options = ap_req_options; + request.ticket = 0; - if ((ap_req_options & AP_OPTS_USE_SESSION_KEY) && - !in_creds->ticket.length) - return(KRB5_NO_TKT_SUPPLIED); - 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(&(in_creds)->ticket, &request.ticket)) return(retval); /* verify a valid etype is available */ - etype = request.ticket->enc_part.etype; - - if (!valid_etype(etype)) { + if (!valid_etype(request.ticket->enc_part.etype)) { retval = KRB5_PROG_ETYPE_NOSUPP; goto cleanup; } - request.ap_options = ap_req_options; - if (newkey) { + /* generate auth_context if needed */ + if (*auth_context == NULL) { + if (retval = krb5_auth_con_init(context, &new_auth_context)) + goto cleanup; + *auth_context = new_auth_context; + } + + /* set auth context keyblock */ + if (retval = krb5_copy_keyblock(context, &in_creds->keyblock, + &((*auth_context)->keyblock))) + goto cleanup; + + /* generate seq number if needed */ + if ((((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) + || ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) + && ((*auth_context)->local_seq_number == 0)) + if (retval = krb5_generate_seq_number(context, &in_creds->keyblock, + &(*auth_context)->local_seq_number)) + goto cleanup; + + + /* generate subkey if needed */ + if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->local_subkey)) if (retval = krb5_generate_subkey(context, &(in_creds)->keyblock, - newkey)) + &(*auth_context)->local_subkey)) goto cleanup; + + + /* Generate checksum, XXX What should the seed be? */ + if ((checksum.contents = (krb5_octet *)malloc(krb5_checksum_size( + context, CKSUMTYPE_CRC32))) == NULL) { + retval = ENOMEM; + goto cleanup; + } + + if (in_data == NULL) { + if (retval = krb5_calculate_checksum(context, + (*auth_context)->cksumtype, + 0, 0, 0, 0, &checksum)) + goto cleanup_cksum; + } else + if ((*auth_context)->cksumtype == 0x8003) { + /* XXX Special hack for GSSAPI */ + checksum.checksum_type = 0x8003; + checksum.length = in_data->length; + checksum.contents = in_data->data; + } else + if (retval = krb5_calculate_checksum(context, + (*auth_context)->cksumtype, + in_data->data, in_data->length, + 0, 0, &checksum)) + goto cleanup_cksum; + + /* Generate authenticator */ + if (((*auth_context)->authentp = (krb5_authenticator *)malloc(sizeof( + krb5_authenticator))) == NULL) { + retval = ENOMEM; + goto cleanup_cksum; } - if (retval = krb5_generate_authenticator(context, &authent, - (in_creds)->client, checksum, - newkey ? *newkey : 0, sequence, + if (retval = krb5_generate_authenticator(context, (*auth_context)->authentp, + (in_creds)->client, &checksum, + (*auth_context)->local_subkey, + (*auth_context)->local_seq_number, (in_creds)->authdata)) - goto cleanup; + goto cleanup_cksum; /* encode the authenticator */ - retval = encode_krb5_authenticator(&authent, &scratch); - if (retval) - goto cleanup; + if (retval = encode_krb5_authenticator((*auth_context)->authentp, &scratch)) + goto cleanup_cksum; /* Null out these fields, to prevent pointer sharing problems; * they were supplied by the caller */ - authent.client = NULL; - authent.checksum = NULL; - authent.authorization_data = NULL; - if (authentp) - *authentp = authent; - else - krb5_free_authenticator_contents(context, &authent); + (*auth_context)->authentp->client = NULL; + (*auth_context)->authentp->checksum = NULL; + (*auth_context)->authentp->authorization_data = NULL; /* put together an eblock for this encryption */ - krb5_use_cstype(context, &eblock, etype); - request.authenticator.etype = etype; + krb5_use_cstype(context, &eblock, request.ticket->enc_part.etype); + request.authenticator.etype = request.ticket->enc_part.etype; request.authenticator.kvno = 0; request.authenticator.ciphertext.length = krb5_encrypt_size(scratch->length, eblock.crypto_entry); @@ -155,39 +193,40 @@ krb5_mk_req_extended(context, ap_req_options, checksum, sequence, request.authenticator.ciphertext.length))) { /* may destroy scratch->data */ retval = ENOMEM; - goto cleanup; + goto cleanup_cksum; } memset(scratch->data + scratch->length, 0, request.authenticator.ciphertext.length - scratch->length); if (!(request.authenticator.ciphertext.data = malloc(request.authenticator.ciphertext.length))) { retval = ENOMEM; - goto cleanup; + goto cleanup_cksum; } /* do any necessary key pre-processing */ if (retval = krb5_process_key(context, &eblock, &(in_creds)->keyblock)) goto cleanup; - cleanup_key++; - /* call the encryption routine */ if (retval = krb5_encrypt(context, (krb5_pointer) scratch->data, (krb5_pointer) request.authenticator.ciphertext.data, - scratch->length, &eblock, 0)) - goto cleanup; + scratch->length, &eblock, 0)) { + krb5_finish_key(context, &eblock); + goto cleanup_cksum; + } if (retval = krb5_finish_key(context, &eblock)) - goto cleanup; - cleanup_key = 0; + goto cleanup_cksum; - retval = encode_krb5_ap_req(&request, &toutbuf); - if (retval) - goto cleanup; + if (retval = encode_krb5_ap_req(&request, &toutbuf)) + goto cleanup_cksum; *outbuf = *toutbuf; krb5_xfree(toutbuf); +cleanup_cksum: + free(checksum.contents); + cleanup: if (request.ticket) krb5_free_ticket(context, request.ticket); @@ -196,16 +235,11 @@ cleanup: request.authenticator.ciphertext.length); free(request.authenticator.ciphertext.data); } - if (retval && newkey && *newkey) - krb5_free_keyblock(context, *newkey); if (scratch) { memset(scratch->data, 0, scratch->length); krb5_xfree(scratch->data); krb5_xfree(scratch); } - if (cleanup_key) - krb5_finish_key(context, &eblock); - return retval; } diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c index 2832dd882..905e8a1e4 100644 --- a/src/lib/krb5/krb/mk_safe.c +++ b/src/lib/krb5/krb/mk_safe.c @@ -25,6 +25,7 @@ */ #include "k5-int.h" +#include "auth_con.h" /* Formats a KRB_SAFE message into outbuf. @@ -41,25 +42,23 @@ returns system errors */ -krb5_error_code INTERFACE -krb5_mk_safe(context, userdata, sumtype, key, sender_addr, recv_addr, - seq_number, safe_flags, rcache, outbuf) - krb5_context context; - const krb5_data * userdata; - const krb5_cksumtype sumtype; - const krb5_keyblock * key; - const krb5_address * sender_addr; - const krb5_address * recv_addr; - krb5_int32 seq_number; - krb5_int32 safe_flags; - krb5_rcache rcache; - krb5_data * outbuf; +static krb5_error_code +krb5_mk_safe_basic(context, userdata, keyblock, replaydata, local_addr, + remote_addr, sumtype, outbuf) + krb5_context context; + const krb5_data * userdata; + const krb5_keyblock * keyblock; + krb5_replay_data * replaydata; + const krb5_address * local_addr; + const krb5_address * remote_addr; + const krb5_cksumtype sumtype; + krb5_data * outbuf; { krb5_error_code retval; krb5_safe safemsg; krb5_octet zero_octet = 0; krb5_checksum safe_checksum; - krb5_data *scratch; + krb5_data *scratch1, *scratch2; if (!valid_cksumtype(sumtype)) return KRB5_PROG_SUMTYPE_NOSUPP; @@ -67,86 +66,128 @@ krb5_mk_safe(context, userdata, sumtype, key, sender_addr, recv_addr, return KRB5KRB_AP_ERR_INAPP_CKSUM; safemsg.user_data = *userdata; - safemsg.s_address = (krb5_address *)sender_addr; - if (recv_addr) - safemsg.r_address = (krb5_address *)recv_addr; - else - safemsg.r_address = 0; - - if (!(safe_flags & KRB5_SAFE_NOTIME)) { - if (!rcache) - /* gotta provide an rcache in this case... */ - return KRB5_RC_REQUIRED; - if (retval = krb5_us_timeofday(context, &safemsg.timestamp, &safemsg.usec)) - return retval; - } else - safemsg.timestamp = 0, safemsg.usec = 0; - if (safe_flags & KRB5_SAFE_DOSEQUENCE) { - safemsg.seq_number = seq_number; - } else - safemsg.seq_number = 0; - - /* to do the checksum stuff, we need to encode the message with a - zero-length zero-type checksum, then checksum the encoding, then - re-encode with the - checksum. */ + safemsg.s_address = local_addr; + safemsg.r_address = remote_addr; + + /* We should check too make sure one exists. */ + safemsg.timestamp = replaydata->timestamp; + safemsg.usec = replaydata->usec; + safemsg.seq_number = replaydata->seq; + + /* + * To do the checksum stuff, we need to encode the message with a + * zero-length zero-type checksum, then checksum the encoding, then + * re-encode with the checksum. + */ - safe_checksum.checksum_type = 0; safe_checksum.length = 0; + safe_checksum.checksum_type = 0; safe_checksum.contents = &zero_octet; safemsg.checksum = &safe_checksum; - if (retval = encode_krb5_safe(&safemsg, &scratch)) + if (retval = encode_krb5_safe(&safemsg, &scratch1)) return retval; -#define clean_scratch() {(void) memset((char *)scratch->data, 0,\ - scratch->length); \ - krb5_free_data(context, scratch);} - if (!(safe_checksum.contents = (krb5_octet *) malloc(krb5_checksum_size(context, sumtype)))) { - clean_scratch(); - return ENOMEM; + retval = ENOMEM; + goto cleanup_scratch; } - if (retval = krb5_calculate_checksum(context, sumtype, scratch->data, - scratch->length, - (krb5_pointer) key->contents, - key->length, &safe_checksum)) { - krb5_xfree(safe_checksum.contents); - clean_scratch(); - return retval; + if (retval = krb5_calculate_checksum(context, sumtype, scratch1->data, + scratch1->length, + (krb5_pointer) keyblock->contents, + keyblock->length, &safe_checksum)) { + goto cleanup_checksum; } safemsg.checksum = &safe_checksum; - clean_scratch(); - if (retval = encode_krb5_safe(&safemsg, &scratch)) { - krb5_xfree(safe_checksum.contents); - return retval; + if (retval = encode_krb5_safe(&safemsg, &scratch2)) { + goto cleanup_checksum; } + *outbuf = *scratch2; + krb5_xfree(scratch2); + retval = 0; + +cleanup_checksum: krb5_xfree(safe_checksum.contents); - if (!(safe_flags & KRB5_SAFE_NOTIME)) { - krb5_donot_replay replay; - if (retval = krb5_gen_replay_name(context, sender_addr, "_safe", - &replay.client)) { - clean_scratch(); +cleanup_scratch: + memset((char *)scratch1->data, 0, scratch1->length); + krb5_free_data(context, scratch1); + return retval; +} + +krb5_error_code INTERFACE +krb5_mk_safe(context, auth_context, userdata, outbuf, outdata) + krb5_context context; + krb5_auth_context * auth_context; + const krb5_data * userdata; + krb5_data * outbuf; + krb5_replay_data * outdata; +{ + krb5_replay_data replaydata; + krb5_error_code retval; + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && + (auth_context->rcache == NULL)) + return KRB5_RC_REQUIRED; + + if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + (outdata == NULL)) + /* Need a better error */ + return KRB5_RC_REQUIRED; + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) { + if (retval = krb5_us_timeofday(context, &replaydata.timestamp, + &replaydata.usec)) return retval; + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) { + outdata->timestamp = replaydata.timestamp; + outdata->usec = replaydata.usec; + } + } + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { + replaydata.seq = auth_context->local_seq_number++; + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) { + outdata->seq = replaydata.seq; + } + } + + if (retval = krb5_mk_safe_basic(context, userdata, auth_context->keyblock, + &replaydata, auth_context->local_addr, auth_context->remote_addr, + auth_context->cksumtype, outbuf)) + goto error; + + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_donot_replay replay; + + if (retval = krb5_gen_replay_name(context, auth_context->local_addr, + "_safe", &replay.client)) { + krb5_xfree(outbuf); + goto error; } replay.server = ""; /* XXX */ - replay.cusec = safemsg.usec; - replay.ctime = safemsg.timestamp; - if (retval = krb5_rc_store(context, rcache, &replay)) { + replay.cusec = replaydata.usec; + replay.ctime = replaydata.timestamp; + if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) { /* should we really error out here? XXX */ - clean_scratch(); - krb5_xfree(replay.client); - return retval; + krb5_xfree(outbuf); + goto error; } krb5_xfree(replay.client); } - *outbuf = *scratch; - krb5_xfree(scratch); return 0; + +error: + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) + auth_context->local_seq_number--; + + return retval; } diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index f00440f9d..3aa6bd265 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -25,6 +25,7 @@ */ #include "k5-int.h" +#include "auth_con.h" extern krb5_deltat krb5_clockskew; #define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew) @@ -36,7 +37,7 @@ data in *outbuf. key specifies the key to be used for decryption of the message. -sender_addr and recv_addr specify the full +remote_addr and local_addr specify the full addresses (host and port) of the sender and receiver. outbuf points to allocated storage which the caller should @@ -50,75 +51,59 @@ Returns system errors, integrity errors. */ -krb5_error_code INTERFACE -krb5_rd_priv(context, inbuf, key, sender_addr, recv_addr, seq_number, - priv_flags, i_vector, rcache, outbuf) - krb5_context context; - const krb5_data * inbuf; - const krb5_keyblock * key; - const krb5_address * sender_addr; - const krb5_address * recv_addr; - krb5_int32 seq_number; - krb5_int32 priv_flags; - krb5_pointer i_vector; - krb5_rcache rcache; - krb5_data * outbuf; +static krb5_error_code +krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr, + i_vector, replaydata, outbuf) + krb5_context context; + const krb5_data * inbuf; + const krb5_keyblock * keyblock; + const krb5_address * local_addr; + const krb5_address * remote_addr; + krb5_pointer i_vector; + krb5_replay_data * replaydata; + krb5_data * outbuf; { - krb5_error_code retval; - krb5_encrypt_block eblock; - krb5_priv *privmsg; - krb5_priv_enc_part *privmsg_enc_part; - krb5_data scratch; - krb5_timestamp currenttime; + krb5_error_code retval; + krb5_priv * privmsg; + krb5_data scratch; + krb5_encrypt_block eblock; + krb5_priv_enc_part * privmsg_enc_part; if (!krb5_is_krb_priv(inbuf)) return KRB5KRB_AP_ERR_MSG_TYPE; + /* decode private message */ - if (retval = decode_krb5_priv(inbuf, &privmsg)) { + if (retval = decode_krb5_priv(inbuf, &privmsg)) return retval; - } -#define cleanup_privmsg() {(void)krb5_xfree(privmsg->enc_part.ciphertext.data); (void)krb5_xfree(privmsg);} if (!valid_etype(privmsg->enc_part.etype)) { - cleanup_privmsg(); - return KRB5_PROG_ETYPE_NOSUPP; + retval = KRB5_PROG_ETYPE_NOSUPP; + goto cleanup_privmsg; } /* put together an eblock for this decryption */ - krb5_use_cstype(context, &eblock, privmsg->enc_part.etype); scratch.length = privmsg->enc_part.ciphertext.length; if (!(scratch.data = malloc(scratch.length))) { - cleanup_privmsg(); - return ENOMEM; + retval = ENOMEM; + goto cleanup_privmsg; } -#define cleanup_scratch() {(void)memset(scratch.data, 0, scratch.length); (void)krb5_xfree(scratch.data);} - /* do any necessary key pre-processing */ - if (retval = krb5_process_key(context, &eblock, key)) { - cleanup_privmsg(); - cleanup_scratch(); - return retval; - } - -#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);} + if (retval = krb5_process_key(context, &eblock, keyblock)) + goto cleanup_scratch; /* call the decryption routine */ - if (retval = krb5_decrypt(context, (krb5_pointer) privmsg->enc_part.ciphertext.data, + if (retval = krb5_decrypt(context, + (krb5_pointer) privmsg->enc_part.ciphertext.data, (krb5_pointer) scratch.data, - scratch.length, &eblock, - i_vector)) { - cleanup_privmsg(); - cleanup_scratch(); - cleanup_prockey(); - return retval; + scratch.length, &eblock, i_vector)) { + krb5_finish_key(context, &eblock); + goto cleanup_scratch; } - /* if i_vector is set, fill it in with the last block of the encrypted - input */ - /* put last block into the i_vector */ + /* if i_vector is set, put last block into the i_vector */ if (i_vector) memcpy(i_vector, privmsg->enc_part.ciphertext.data + @@ -126,106 +111,140 @@ krb5_rd_priv(context, inbuf, key, sender_addr, recv_addr, seq_number, eblock.crypto_entry->block_length), eblock.crypto_entry->block_length); - /* private message is now decrypted -- do some cleanup */ - - cleanup_privmsg(); - - if (retval = krb5_finish_key(context, &eblock)) { - cleanup_scratch(); - return retval; - } + if (retval = krb5_finish_key(context, &eblock)) + goto cleanup_scratch; /* now decode the decrypted stuff */ - if (retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part)) { - cleanup_scratch(); - return retval; - } - cleanup_scratch(); + if (retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part)) + goto cleanup_scratch; -#define cleanup_data() {(void)memset(privmsg_enc_part->user_data.data,0,privmsg_enc_part->user_data.length); (void)krb5_xfree(privmsg_enc_part->user_data.data);} -#define cleanup_mesg() {(void)krb5_xfree(privmsg_enc_part);} - - if (!(priv_flags & KRB5_PRIV_NOTIME)) { - krb5_donot_replay replay; - - if (retval = krb5_timeofday(context, ¤ttime)) { - cleanup_data(); - cleanup_mesg(); - return retval; - } - if (!in_clock_skew(privmsg_enc_part->timestamp)) { - cleanup_data(); - cleanup_mesg(); - return KRB5KRB_AP_ERR_SKEW; - } - if (!rcache) { - /* gotta provide an rcache in this case... */ - cleanup_data(); - cleanup_mesg(); - return KRB5_RC_REQUIRED; - } - if (retval = krb5_gen_replay_name(context, sender_addr, "_priv", - &replay.client)) { - cleanup_data(); - cleanup_mesg(); - return retval; - } - replay.server = ""; /* XXX */ - replay.cusec = privmsg_enc_part->usec; - replay.ctime = privmsg_enc_part->timestamp; - if (retval = krb5_rc_store(context, rcache, &replay)) { - krb5_xfree(replay.client); - cleanup_data(); - cleanup_mesg(); - return retval; - } - krb5_xfree(replay.client); - } - - if (priv_flags & KRB5_PRIV_DOSEQUENCE) - if (privmsg_enc_part->seq_number != seq_number) { - cleanup_data(); - cleanup_mesg(); - return KRB5KRB_AP_ERR_BADORDER; - } - - if (!krb5_address_compare(context, sender_addr, privmsg_enc_part->s_address)) { - cleanup_data(); - cleanup_mesg(); - return KRB5KRB_AP_ERR_BADADDR; + if (!krb5_address_compare(context,remote_addr,privmsg_enc_part->s_address)){ + retval = KRB5KRB_AP_ERR_BADADDR; + goto cleanup_data; } if (privmsg_enc_part->r_address) { - if (recv_addr) { - if (!krb5_address_compare(context, recv_addr, + if (local_addr) { + if (!krb5_address_compare(context, local_addr, privmsg_enc_part->r_address)) { - cleanup_data(); - cleanup_mesg(); - return KRB5KRB_AP_ERR_BADADDR; + retval = KRB5KRB_AP_ERR_BADADDR; + goto cleanup_data; } } else { krb5_address **our_addrs; if (retval = krb5_os_localaddr(&our_addrs)) { - cleanup_data(); - cleanup_mesg(); - return retval; + goto cleanup_data; } if (!krb5_address_search(context, privmsg_enc_part->r_address, our_addrs)) { krb5_free_addresses(context, our_addrs); - cleanup_data(); - cleanup_mesg(); - return KRB5KRB_AP_ERR_BADADDR; + retval = KRB5KRB_AP_ERR_BADADDR; + goto cleanup_data; } krb5_free_addresses(context, our_addrs); } } - /* everything is ok - return data to the user */ + replaydata->timestamp = privmsg_enc_part->timestamp; + replaydata->usec = privmsg_enc_part->usec; + replaydata->seq = privmsg_enc_part->seq_number; + /* everything is ok - return data to the user */ *outbuf = privmsg_enc_part->user_data; - cleanup_mesg(); + retval = 0; + +cleanup_data:; + if (retval) { + memset(privmsg_enc_part->user_data.data, 0, + privmsg_enc_part->user_data.length); + krb5_xfree(privmsg_enc_part->user_data.data); + } + krb5_xfree(privmsg_enc_part); + +cleanup_scratch:; + memset(scratch.data, 0, scratch.length); + krb5_xfree(scratch.data); + +cleanup_privmsg:; + krb5_xfree(privmsg->enc_part.ciphertext.data); + krb5_xfree(privmsg); + + return retval; +} + +krb5_error_code INTERFACE +krb5_rd_priv(context, auth_context, inbuf, outbuf, outdata) + krb5_context context; + krb5_auth_context * auth_context; + const krb5_data * inbuf; + krb5_data * outbuf; + krb5_replay_data * outdata; +{ + krb5_error_code retval; + krb5_replay_data replaydata; + + if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + (outdata == NULL)) + /* Need a better error */ + return KRB5_RC_REQUIRED; + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && + (auth_context->rcache == NULL)) + return KRB5_RC_REQUIRED; + + if (retval = krb5_rd_priv_basic(context, inbuf, auth_context->keyblock, + auth_context->local_addr, auth_context->remote_addr, + auth_context->i_vector, &replaydata, outbuf)) + return retval; + + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_donot_replay replay; + krb5_timestamp currenttime; + + if (retval = krb5_timeofday(context, ¤ttime)) + goto error; + + if (!in_clock_skew(replaydata.timestamp)) { + retval = KRB5KRB_AP_ERR_SKEW; + goto error; + } + + if (retval = krb5_gen_replay_name(context, auth_context->remote_addr, + "_priv", &replay.client)) + goto error; + + replay.server = ""; /* XXX */ + replay.cusec = replaydata.usec; + replay.ctime = replaydata.timestamp; + if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) { + krb5_xfree(replay.client); + goto error; + } + krb5_xfree(replay.client); + } + + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if (auth_context->remote_seq_number != replaydata.seq) { + retval = KRB5KRB_AP_ERR_BADORDER; + goto error; + } + auth_context->remote_seq_number++; + } + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { + outdata->timestamp = replaydata.timestamp; + outdata->usec = replaydata.usec; + outdata->seq = replaydata.seq; + } + + /* everything is ok - return data to the user */ return 0; +error:; + krb5_xfree(outbuf->data); + return retval; + } diff --git a/src/lib/krb5/krb/rd_rep.c b/src/lib/krb5/krb/rd_rep.c index e933b1dfc..1dd981611 100644 --- a/src/lib/krb5/krb/rd_rep.c +++ b/src/lib/krb5/krb/rd_rep.c @@ -25,6 +25,7 @@ */ #include "k5-int.h" +#include "auth_con.h" /* * Parses a KRB_AP_REP message, returning its contents. @@ -38,10 +39,10 @@ */ krb5_error_code INTERFACE -krb5_rd_rep(context, inbuf, kblock, repl) - krb5_context context; - const krb5_data *inbuf; - const krb5_keyblock *kblock; +krb5_rd_rep(context, auth_context, inbuf, repl) + krb5_context context; + krb5_auth_context * auth_context; + const krb5_data * inbuf; krb5_ap_rep_enc_part **repl; { krb5_error_code retval; @@ -52,9 +53,6 @@ krb5_rd_rep(context, inbuf, kblock, repl) if (!krb5_is_ap_rep(inbuf)) return KRB5KRB_AP_ERR_MSG_TYPE; - if (!valid_keytype(kblock->keytype)) - return KRB5_PROG_KEYTYPE_NOSUPP; - /* decode it */ if (retval = decode_krb5_ap_rep(inbuf, &reply)) @@ -75,33 +73,46 @@ krb5_rd_rep(context, inbuf, kblock, repl) } /* do any necessary key pre-processing */ - if (retval = krb5_process_key(context, &eblock, kblock)) { - errout: - free(scratch.data); - krb5_free_ap_rep(context, reply); - return(retval); + if (retval = krb5_process_key(context, &eblock, auth_context->keyblock)) { + goto errout; } /* call the encryption routine */ - if (retval = krb5_decrypt(context, (krb5_pointer) reply->enc_part.ciphertext.data, + if (retval = krb5_decrypt(context, + (krb5_pointer) reply->enc_part.ciphertext.data, (krb5_pointer) scratch.data, scratch.length, &eblock, 0)) { (void) krb5_finish_key(context, &eblock); goto errout; } -#define clean_scratch() {memset(scratch.data, 0, scratch.length); \ -free(scratch.data);} + /* finished with the top-level encoding of the ap_rep */ - krb5_free_ap_rep(context, reply); - if (retval = krb5_finish_key(context, &eblock)) { + if (retval = krb5_finish_key(context, &eblock)) + goto clean_scratch; - clean_scratch(); - return retval; - } - /* now decode the decrypted stuff */ + /* now decode the decrypted stuff */ retval = decode_krb5_ap_rep_enc_part(&scratch, repl); - clean_scratch(); - if ((*repl)->subkey) + + /* Check reply fields */ + if (((*repl)->ctime != auth_context->authentp->ctime) || + ((*repl)->cusec != auth_context->authentp->cusec)) { + retval = KRB5_SENDAUTH_MUTUAL_FAILED; + goto clean_scratch; + } + + /* Set auth subkey */ + if ((*repl)->subkey) { (*repl)->subkey->etype = reply->enc_part.etype; + auth_context->remote_subkey = (*repl)->subkey; + } + + /* Get remote sequence number */ + auth_context->remote_seq_number = (*repl)->seq_number; + +clean_scratch: + memset(scratch.data, 0, scratch.length); +errout: + krb5_free_ap_rep(context, reply); + free(scratch.data); return retval; } diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c index 68c264bc8..f97ca201b 100644 --- a/src/lib/krb5/krb/rd_safe.c +++ b/src/lib/krb5/krb/rd_safe.c @@ -25,6 +25,7 @@ */ #include "k5-int.h" +#include "auth_con.h" extern krb5_deltat krb5_clockskew; #define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew) @@ -42,21 +43,19 @@ extern krb5_deltat krb5_clockskew; returns system errors, integrity errors */ -krb5_error_code INTERFACE -krb5_rd_safe(context, inbuf, key, sender_addr, recv_addr, seq_number, - safe_flags, rcache, outbuf) - krb5_context context; - const krb5_data *inbuf; - const krb5_keyblock *key; - const krb5_address *sender_addr; - const krb5_address *recv_addr; - krb5_int32 seq_number; - krb5_int32 safe_flags; - krb5_rcache rcache; - krb5_data *outbuf; +static krb5_error_code +krb5_rd_safe_basic(context, inbuf, keyblock, recv_addr, sender_addr, + replaydata, outbuf) + krb5_context context; + const krb5_data * inbuf; + const krb5_keyblock * keyblock; + const krb5_address * recv_addr; + const krb5_address * sender_addr; + krb5_replay_data * replaydata; + krb5_data * outbuf; { - krb5_error_code retval; - krb5_safe *message; + krb5_error_code retval; + krb5_safe * message; krb5_checksum our_cksum, *his_cksum; krb5_octet zero_octet = 0; krb5_data *scratch; @@ -68,79 +67,37 @@ krb5_rd_safe(context, inbuf, key, sender_addr, recv_addr, seq_number, if (retval = decode_krb5_safe(inbuf, &message)) return retval; -#define cleanup() krb5_free_safe(context, message) - if (!valid_cksumtype(message->checksum->checksum_type)) { - cleanup(); - return KRB5_PROG_SUMTYPE_NOSUPP; + retval = KRB5_PROG_SUMTYPE_NOSUPP; + goto cleanup; } if (!is_coll_proof_cksum(message->checksum->checksum_type) || !is_keyed_cksum(message->checksum->checksum_type)) { - cleanup(); - return KRB5KRB_AP_ERR_INAPP_CKSUM; - } - - if (!(safe_flags & KRB5_SAFE_NOTIME)) { - krb5_donot_replay replay; - - if (retval = krb5_timeofday(context, ¤ttime)) { - cleanup(); - return retval; - } - /* in_clock_skew #defined above */ - if (!in_clock_skew(message->timestamp)) { - cleanup(); - return KRB5KRB_AP_ERR_SKEW; - } - if (!rcache) { - /* gotta provide an rcache in this case... */ - cleanup(); - return KRB5_RC_REQUIRED; - } - if (retval = krb5_gen_replay_name(context, sender_addr, "_safe", - &replay.client)) { - cleanup(); - return retval; - } - replay.server = ""; /* XXX */ - replay.cusec = message->usec; - replay.ctime = message->timestamp; - if (retval = krb5_rc_store(context, rcache, &replay)) { - krb5_xfree(replay.client); - cleanup(); - return retval; - } - krb5_xfree(replay.client); + retval = KRB5KRB_AP_ERR_INAPP_CKSUM; + goto cleanup; } - if (safe_flags & KRB5_SAFE_DOSEQUENCE) - if (message->seq_number != seq_number) { - cleanup(); - return KRB5KRB_AP_ERR_BADORDER; - } - if (!krb5_address_compare(context, sender_addr, message->s_address)) { - cleanup(); - return KRB5KRB_AP_ERR_BADADDR; + retval = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; } if (message->r_address) { if (recv_addr) { if (!krb5_address_compare(context, recv_addr, message->r_address)) { - cleanup(); - return KRB5KRB_AP_ERR_BADADDR; + retval = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; } } else { krb5_address **our_addrs; - if (retval = krb5_os_localaddr( &our_addrs)) { - cleanup(); - return retval; - } + if (retval = krb5_os_localaddr( &our_addrs)) + goto cleanup; + if (!krb5_address_search(context, message->r_address, our_addrs)) { krb5_free_addresses(context, our_addrs); - cleanup(); - return KRB5KRB_AP_ERR_BADADDR; + retval = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; } krb5_free_addresses(context, our_addrs); } @@ -152,56 +109,131 @@ krb5_rd_safe(context, inbuf, key, sender_addr, recv_addr, seq_number, */ his_cksum = message->checksum; - our_cksum.checksum_type = 0; our_cksum.length = 0; + our_cksum.checksum_type = 0; our_cksum.contents = &zero_octet; message->checksum = &our_cksum; - if (retval = encode_krb5_safe(message, &scratch)) { - message->checksum = his_cksum; - cleanup(); - return retval; - } + if (retval = encode_krb5_safe(message, &scratch)) + goto cleanup; + message->checksum = his_cksum; if (!(our_cksum.contents = (krb5_octet *) malloc(krb5_checksum_size(context, his_cksum->checksum_type)))) { - cleanup(); - return ENOMEM; + retval = ENOMEM; + goto cleanup; } -#undef cleanup -#define cleanup() {krb5_free_safe(context, message); krb5_xfree(our_cksum.contents);} - retval = krb5_calculate_checksum(context, his_cksum->checksum_type, scratch->data, scratch->length, - (krb5_pointer) key->contents, - key->length, &our_cksum); + (krb5_pointer) keyblock->contents, + keyblock->length, &our_cksum); (void) memset((char *)scratch->data, 0, scratch->length); krb5_free_data(context, scratch); if (retval) { - cleanup(); - return retval; + goto cleanup_cksum; } if (our_cksum.length != his_cksum->length || memcmp((char *)our_cksum.contents, (char *)his_cksum->contents, our_cksum.length)) { - cleanup(); - return KRB5KRB_AP_ERR_MODIFIED; + retval = KRB5KRB_AP_ERR_MODIFIED; + goto cleanup_cksum; } + replaydata->timestamp = message->timestamp; + replaydata->usec = message->usec; + replaydata->seq = message->seq_number; + *outbuf = message->user_data; + message->user_data.data = NULL; - krb5_xfree(our_cksum.contents); - if (message->s_address) - krb5_free_address(context, message->s_address); - if (message->r_address) - krb5_free_address(context, message->r_address); krb5_free_checksum(context, his_cksum); - krb5_xfree(message); + return 0; +cleanup_cksum: + krb5_xfree(our_cksum.contents); + +cleanup: + krb5_free_safe(context, message); + return retval; +} + +krb5_error_code INTERFACE +krb5_rd_safe(context, auth_context, inbuf, outbuf, outdata) + krb5_context context; + krb5_auth_context * auth_context; + const krb5_data * inbuf; + krb5_data * outbuf; + krb5_replay_data * outdata; +{ + krb5_error_code retval; + krb5_replay_data replaydata; + + if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + (outdata == NULL)) + /* Need a better error */ + return KRB5_RC_REQUIRED; + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && + (auth_context->rcache == NULL)) + return KRB5_RC_REQUIRED; + + if (retval = krb5_rd_safe_basic(context, inbuf, auth_context->keyblock, + auth_context->local_addr, auth_context->remote_addr, + auth_context->cksumtype, &replaydata, outbuf)) + return retval; + + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_donot_replay replay; + krb5_timestamp currenttime; + + if (retval = krb5_timeofday(context, ¤ttime)) + goto error; + + if (!in_clock_skew(replaydata.timestamp)) { + retval = KRB5KRB_AP_ERR_SKEW; + goto error; + } + + if (retval = krb5_gen_replay_name(context, auth_context->remote_addr, + "_safe", &replay.client)) + goto error; + + replay.server = ""; /* XXX */ + replay.cusec = replaydata.usec; + replay.ctime = replaydata.timestamp; + if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) { + krb5_xfree(replay.client); + goto error; + } + krb5_xfree(replay.client); + } + + if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if (auth_context->remote_seq_number != replaydata.seq) { + retval = KRB5KRB_AP_ERR_BADORDER; + goto error; + } + } + + if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { + outdata->timestamp = replaydata.timestamp; + outdata->usec = replaydata.usec; + outdata->seq = replaydata.seq; + } + + /* everything is ok - return data to the user */ return 0; + +error:; + krb5_xfree(outbuf->data); + return retval; + } + diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c index 9eb08668e..f093c488e 100644 --- a/src/lib/krb5/krb/send_tgs.c +++ b/src/lib/krb5/krb/send_tgs.c @@ -45,6 +45,124 @@ returns system errors */ + +static krb5_error_code +krb5_send_tgs_basic(context, in_data, sumtype, in_cred, outbuf) + krb5_context context; + krb5_data * in_data; + const krb5_cksumtype sumtype; + krb5_creds * in_cred; + krb5_data * outbuf; +{ + krb5_error_code retval; + krb5_checksum checksum; + krb5_authenticator authent; + krb5_ap_req request; + krb5_encrypt_block eblock; + krb5_data * scratch; + krb5_data * toutbuf; + + /* Generate checksum */ + if ((checksum.contents = + (krb5_octet *)malloc(krb5_checksum_size(context, sumtype))) == NULL) + return(ENOMEM); + + if (retval = krb5_calculate_checksum(context, sumtype, + in_data->data, in_data->length, + (krb5_pointer) in_cred->keyblock.contents, + in_cred->keyblock.length, &checksum)) { + free(checksum.contents); + return(retval); + } + + /* gen authenticator */ + authent.subkey = 0; + authent.seq_number = 0; + authent.checksum = &checksum; + authent.client = in_cred->client; + authent.authorization_data = in_cred->authdata; + if (retval = krb5_us_timeofday(context, &authent.ctime, &authent.cusec)) { + free(checksum.contents); + return(retval); + } + + /* encode the authenticator */ + if (retval = encode_krb5_authenticator(&authent, &scratch)) { + free(checksum.contents); + return(retval); + } + + free(checksum.contents); + + request.authenticator.ciphertext.data = 0; + request.authenticator.kvno = 0; + request.ap_options = 0; + request.ticket = 0; + + if (retval = decode_krb5_ticket(&(in_cred)->ticket, &request.ticket)) + /* Cleanup scratch and scratch data */ + goto cleanup_data; + + /* put together an eblock for this encryption */ + krb5_use_cstype(context, &eblock, request.ticket->enc_part.etype); + request.authenticator.etype = request.ticket->enc_part.etype; + request.authenticator.ciphertext.length = + krb5_encrypt_size(scratch->length, eblock.crypto_entry); + + /* add padding area, and zero it */ + if (!(scratch->data = realloc(scratch->data, + request.authenticator.ciphertext.length))) { + /* may destroy scratch->data */ + krb5_free_ticket(context, request.ticket); + retval = ENOMEM; + goto cleanup_scratch; + } + memset(scratch->data + scratch->length, 0, + request.authenticator.ciphertext.length - scratch->length); + + if (!(request.authenticator.ciphertext.data = + malloc(request.authenticator.ciphertext.length))) { + retval = ENOMEM; + goto cleanup_ticket; + } + + /* do any necessary key pre-processing */ + if (retval = krb5_process_key(context, &eblock, &(in_cred)->keyblock)) + goto cleanup; + + /* call the encryption routine */ + if (retval=krb5_encrypt(context, (krb5_pointer) scratch->data, + (krb5_pointer)request.authenticator.ciphertext.data, + scratch->length, &eblock, 0)) { + krb5_finish_key(context, &eblock); + goto cleanup; + } + + if (retval = krb5_finish_key(context, &eblock)) + goto cleanup; + + retval = encode_krb5_ap_req(&request, &toutbuf); + *outbuf = *toutbuf; + krb5_xfree(toutbuf); + +cleanup: + memset(request.authenticator.ciphertext.data, 0, + request.authenticator.ciphertext.length); + free(request.authenticator.ciphertext.data); + +cleanup_ticket: + krb5_free_ticket(context, request.ticket); + +cleanup_data: + memset(scratch->data, 0, scratch->length); + free(scratch->data); + +cleanup_scratch: + free(scratch); + + return retval; +} + krb5_error_code INTERFACE krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, authorization_data, padata, second_ticket, in_cred, rep) @@ -63,7 +181,6 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, { krb5_error_code retval; krb5_kdc_req tgsreq; - krb5_checksum ap_checksum; krb5_data *scratch, scratch2; krb5_ticket *sec_ticket = 0; krb5_ticket *sec_ticket_arr[2]; @@ -167,39 +284,15 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, 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)))) { - krb5_free_data(context, scratch); - retval = ENOMEM; - goto send_tgs_error_2; - } - - if (retval = krb5_calculate_checksum(context, sumtype, scratch->data, - scratch->length, - (krb5_pointer) in_cred->keyblock.contents, - in_cred->keyblock.length, - &ap_checksum)) { - krb5_free_data(context, scratch); - goto send_tgs_error_3; - } - /* done with body */ - krb5_free_data(context, scratch); - - /* attach ap_req to the tgsreq */ - /* * Get an ap_req. */ - if (retval = krb5_mk_req_extended (context, - 0L /* no ap options */, - &ap_checksum, - 0, /* no initial sequence */ - 0, /* no new key */ - in_cred, - 0, /* don't need authenticator */ - &scratch2)) { - goto send_tgs_error_3; + if (retval = krb5_send_tgs_basic(context, scratch, sumtype, + in_cred, &scratch2)) { + krb5_free_data(context, scratch); + goto send_tgs_error_2; } + krb5_free_data(context, scratch); ap_req_padata.pa_type = KRB5_PADATA_AP_REQ; ap_req_padata.length = scratch2.length; @@ -214,7 +307,7 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, if (!combined_padata) { krb5_xfree(ap_req_padata.contents); retval = ENOMEM; - goto send_tgs_error_3; + goto send_tgs_error_2; } combined_padata[0] = &ap_req_padata; for (i = 1, counter = padata; *counter; counter++, i++) @@ -225,7 +318,7 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, if (!combined_padata) { krb5_xfree(ap_req_padata.contents); retval = ENOMEM; - goto send_tgs_error_3; + goto send_tgs_error_2; } combined_padata[0] = &ap_req_padata; combined_padata[1] = 0; @@ -236,7 +329,7 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, if (retval = encode_krb5_tgs_req(&tgsreq, &scratch)) { krb5_xfree(ap_req_padata.contents); krb5_xfree(combined_padata); - goto send_tgs_error_3; + goto send_tgs_error_2; } krb5_xfree(ap_req_padata.contents); krb5_xfree(combined_padata); @@ -254,9 +347,6 @@ krb5_send_tgs(context, kdcoptions, timestruct, etypes, sumtype, sname, addrs, rep->message_type = KRB5_ERROR; } -send_tgs_error_3:; - krb5_xfree(ap_checksum.contents); - send_tgs_error_2:; if (sec_ticket) krb5_free_ticket(context, sec_ticket); diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c index 4964cc7f3..e71a74970 100644 --- a/src/lib/krb5/krb/sendauth.c +++ b/src/lib/krb5/krb/sendauth.c @@ -25,8 +25,10 @@ */ #define NEED_SOCKETS + #include "k5-int.h" #include "com_err.h" +#include "auth_con.h" #include #include #include @@ -38,28 +40,27 @@ extern krb5_flags krb5_kdc_default_options; static char *sendauth_version = "KRB5_SENDAUTH_V1.0"; krb5_error_code INTERFACE -krb5_sendauth(context, +krb5_sendauth(context, auth_context, /* IN */ - fd, appl_version, client, server, ap_req_options, checksump, + fd, appl_version, client, server, ap_req_options, in_data, in_creds, /* IN/OUT */ ccache, /* OUT */ - sequence, newkey, error, rep_result, out_creds) - krb5_context context; - krb5_pointer fd; - char *appl_version; - krb5_principal client; - krb5_principal server; - krb5_flags ap_req_options; - krb5_int32 *sequence; - krb5_keyblock **newkey; - krb5_checksum *checksump; - krb5_creds *in_creds; - krb5_ccache ccache; - krb5_error **error; - krb5_ap_rep_enc_part **rep_result; - krb5_creds **out_creds; + error, rep_result, out_creds) + krb5_context context; + krb5_auth_context ** auth_context; + krb5_pointer fd; + char * appl_version; + krb5_principal client; + krb5_principal server; + krb5_flags ap_req_options; + krb5_data * in_data; + 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; @@ -67,7 +68,6 @@ krb5_sendauth(context, krb5_creds * credsp = NULL; krb5_creds * credspout = NULL; krb5_error_code retval = 0; - krb5_authenticator authent; krb5_data inbuf, outbuf; int len; krb5_ccache use_ccache = 0; @@ -90,14 +90,14 @@ krb5_sendauth(context, * Now, read back a byte: 0 means no error, 1 means bad sendauth * version, 2 means bad application version */ - if ((len = krb5_net_read(context, *((int *) fd), (char *)&result, 1)) != 1) - return((len < 0) ? errno : ECONNABORTED); - if (result == 1) - return(KRB5_SENDAUTH_BADAUTHVERS); - else if (result == 2) - return(KRB5_SENDAUTH_BADAPPLVERS); - else if (result != 0) - return(KRB5_SENDAUTH_BADRESPONSE); + if ((len = krb5_net_read(context, *((int *) fd), (char *)&result, 1)) != 1) + return((len < 0) ? errno : ECONNABORTED); + if (result == 1) + return(KRB5_SENDAUTH_BADAUTHVERS); + else if (result == 2) + return(KRB5_SENDAUTH_BADAPPLVERS); + else if (result != 0) + return(KRB5_SENDAUTH_BADRESPONSE); /* * We're finished with the initial negotiations; let's get and * send over the authentication header. (The AP_REQ message) @@ -108,7 +108,6 @@ krb5_sendauth(context, * credentials cache. */ memset((char *)&creds, 0, sizeof(creds)); - memset((char *)&authent, 0, sizeof(authent)); /* * See if we need to access the credentials cache @@ -148,21 +147,9 @@ krb5_sendauth(context, credsp = in_creds; } - /* - * Generate a random sequence number - */ - if (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, - sequence ? *sequence : 0, newkey, - credsp, &authent, &outbuf)) - goto error_return; + if (retval = krb5_mk_req_extended(context, auth_context, ap_req_options, + in_data, credsp, &outbuf)) + goto error_return; /* * First write the length of the AP_REQ message, then write @@ -189,8 +176,8 @@ krb5_sendauth(context, goto error_return; } } - krb5_xfree(inbuf.data); retval = KRB5_SENDAUTH_REJECTED; + krb5_xfree(inbuf.data); goto error_return; } @@ -204,16 +191,14 @@ krb5_sendauth(context, if (retval = krb5_read_message(context, fd, &inbuf)) goto error_return; - retval = krb5_rd_rep(context, &inbuf, &credsp->keyblock, &repl); - krb5_xfree(inbuf.data); - if (retval || ((repl->ctime != authent.ctime) || - (repl->cusec != authent.cusec))) - retval = KRB5_SENDAUTH_MUTUAL_FAILED; - if (retval) { + if (retval = krb5_rd_rep(context, *auth_context, &inbuf, &repl)) { if (repl) krb5_free_ap_rep_enc_part(context, repl); + krb5_xfree(inbuf.data); goto error_return; } + + krb5_xfree(inbuf.data); /* * If the user wants to look at the AP_REP message, * copy it for him @@ -227,13 +212,13 @@ krb5_sendauth(context, 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_authenticator_contents(context, &authent); - return(retval); + if (credspout) + krb5_free_creds(context, credspout); + if (!ccache && use_ccache) + krb5_cc_close(context, use_ccache); + return(retval); }