+
+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 <eichin@cygnus.com>
* configure.in: take out ISODE_INCLUDE.
OBJS= addr_comp.$(OBJEXT) \
addr_order.$(OBJEXT) \
addr_srch.$(OBJEXT) \
+ auth_con.$(OBJEXT) \
bld_pr_ext.$(OBJEXT) \
bld_princ.$(OBJEXT) \
chk_trans.$(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 \
--- /dev/null
+
+#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;
+}
+
--- /dev/null
+
+#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
*/
#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,
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;
}
*/
#include "k5-int.h"
+#include "auth_con.h"
/*
Formats a KRB_AP_REQ message into outbuf.
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;
}
* 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
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);
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);
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;
}
*/
#include "k5-int.h"
+#include "auth_con.h"
/*
Formats a KRB_SAFE message into outbuf.
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;
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;
}
*/
#include "k5-int.h"
+#include "auth_con.h"
extern krb5_deltat krb5_clockskew;
#define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew)
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
*/
-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 +
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;
+
}
*/
#include "k5-int.h"
+#include "auth_con.h"
/*
* Parses a KRB_AP_REP message, returning its contents.
*/
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;
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))
}
/* 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;
}
*/
#include "k5-int.h"
+#include "auth_con.h"
extern krb5_deltat krb5_clockskew;
#define in_clock_skew(date) (labs((date)-currenttime) < 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;
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);
}
*/
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;
+
}
+
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)
{
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];
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;
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++)
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;
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);
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);
*/
#define NEED_SOCKETS
+
#include "k5-int.h"
#include "com_err.h"
+#include "auth_con.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
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;
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;
* 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)
* credentials cache.
*/
memset((char *)&creds, 0, sizeof(creds));
- memset((char *)&authent, 0, sizeof(authent));
/*
* See if we need to access the credentials cache
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
goto error_return;
}
}
- krb5_xfree(inbuf.data);
retval = KRB5_SENDAUTH_REJECTED;
+ krb5_xfree(inbuf.data);
goto error_return;
}
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
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);
}