+
+Mon Mar 27 08:34:49 1995 Chris Provenzano (proven@mit.edu)
+
+ * Makefile.in: Removed rd_req_sim.c
+
+ * auth_con.c: Default cksumtype is now CKSUMTYPE_RSA_MD4_DES.
+
+ * auth_con.c: Added krb5_auth_con_setuseruserkey(),
+ krb5_auth_con_getkey(),
+ krb5_auth_con_getremotesubkey(),
+ krb5_auth_con_getauthenticator(),
+ krb5_auth_con_getremoteseqnumber(),
+ krb5_auth_con_initivector().
+
+ * auth_con.c: Fixed krb5_auth_con_getlocalsubkey() to check for
+ a valid local_subkey before calling krb5_copy_keyblock().
+
+ * auth_con.h: Fixed some comments.
+
+ * mk_req_ext.c (krb5_mk_req_extended()): Always pass in a seed
+ (the keyblock contents) to krb5_calculate_checksum()
+
+ * rd_rep.c (krb5_rd_rep()): Use appropriate key to decode reply.
+
+ * rd_safe.c (krb5_rd_safe()): Don't pass checksum to
+ krb5_rd_safe_basic(), it's unnecessary.
+
+ * compat_recv.c (krb5_compat_recvauth()):
+ * mk_rep.c (krb5_mk_rep()):
+ * rd_req.c (krb5_rd_req()):
+ * rd_req_dec.c (krb5_rd_req_decode()):
+ * recvauth.c (krb5_recvauth()):
+ Added a krb5_auth_context argument and eliminated many of
+ the other arguments because they are included in the
+ krb5_auth_context structure.
+
+
Tue Mar 21 19:22:51 1995 Keith Vetter (keithv@fusion.com)
* mk_safe.c: fixed signed/unsigned mismatch.
* rd_safe.c: removed unused local variable currentime.
* mk_req_e.c: fixed signed/unsigned mismatch.
+
Sat Mar 18 18:58:02 1995 John Gilmore (gnu at toad.com)
* bld_pr_ext.c, bld_princ.c: Replace STDARG_PROTOTYPES with
rd_priv.$(OBJEXT) \
rd_rep.$(OBJEXT) \
rd_req.$(OBJEXT) \
- rd_req_sim.$(OBJEXT) \
rd_req_dec.$(OBJEXT) \
rd_safe.$(OBJEXT) \
recvauth.$(OBJEXT) \
$(srcdir)/rd_priv.c \
$(srcdir)/rd_rep.c \
$(srcdir)/rd_req.c \
- $(srcdir)/rd_req_sim.c \
$(srcdir)/rd_req_dec.c \
$(srcdir)/rd_safe.c \
$(srcdir)/recvauth.c \
(*auth_context)->auth_context_flags =
KRB5_AUTH_CONTEXT_DO_TIME | KRB5_AUTH_CONN_INITIALIZED;
- (*auth_context)->cksumtype = CKSUMTYPE_CRC32;
+ (*auth_context)->cksumtype = CKSUMTYPE_RSA_MD4_DES;
+ /* (*auth_context)->cksumtype = CKSUMTYPE_CRC32; */
return 0;
}
return ENOMEM;
return(krb5_copy_keyblock(context, keyblock, &(auth_context->keyblock)));
}
+/*
+ * This function overloads the keyblock field. It is only useful prior to
+ * a krb5_rd_req_decode() call for user to user authentication where the
+ * server has the key and needs to use it to decrypt the incoming request.
+ * Once decrypted this key is no longer necessary and is then overwritten
+ * with the session key sent by the client.
+ */
+krb5_error_code INTERFACE
+krb5_auth_con_setuseruserkey(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_getkey(context, auth_context, keyblock)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_keyblock ** keyblock;
+{
+ if (auth_context->keyblock)
+ return krb5_copy_keyblock(context, auth_context->keyblock, keyblock);
+ *keyblock = NULL;
+ return 0;
+}
+
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));
+ if (auth_context->local_subkey)
+ return krb5_copy_keyblock(context,auth_context->local_subkey,keyblock);
+ *keyblock = NULL;
+ return 0;
+}
+
+krb5_error_code INTERFACE
+krb5_auth_con_getremotesubkey(context, auth_context, keyblock)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_keyblock ** keyblock;
+{
+ if (auth_context->remote_subkey)
+ return krb5_copy_keyblock(context,auth_context->remote_subkey,keyblock);
+ *keyblock = NULL;
+ return 0;
}
krb5_error_code INTERFACE
return 0;
}
+krb5_error_code INTERFACE
+krb5_auth_con_getauthenticator(context, auth_context, authenticator)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_authenticator ** authenticator;
+{
+ return (krb5_copy_authenticator(context, auth_context->authentp,
+ authenticator));
+}
+
+krb5_error_code INTERFACE
+krb5_auth_con_getremoteseqnumber(context, auth_context, seqnumber)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_int32 * seqnumber;
+{
+ *seqnumber = auth_context->remote_seq_number;
+ return 0;
+}
+
+krb5_error_code INTERFACE
+krb5_auth_con_initivector(context, auth_context)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+{
+ if (auth_context->keyblock) {
+ int size = krb5_keytype_array[auth_context->keyblock->keytype]->
+ system->block_length;
+
+ if (auth_context->i_vector = (krb5_pointer)malloc(size)) {
+ memset(auth_context->i_vector, 0, size);
+ return 0;
+ }
+ return ENOMEM;
+ }
+ return EINVAL; /* XXX need an error for no keyblock */
+}
+
krb5_error_code INTERFACE
krb5_auth_con_setivector(context, auth_context, ivector)
krb5_context context;
krb5_int32 auth_context_flags;
krb5_int32 remote_seq_number;
krb5_int32 local_seq_number;
- krb5_authenticator *authentp; /* mk_req, rd_rep */
+ krb5_authenticator *authentp; /* mk_req, rd_req, mk_rep, ...*/
krb5_cksumtype cksumtype; /* mk_safe, ... */
- krb5_pointer i_vector; /* mk_priv only */
+ krb5_pointer i_vector; /* mk_priv, rd_priv only */
krb5_rcache rcache;
};
#define KRB5_RECVAUTH_V5 5
krb5_error_code
-krb5_compat_recvauth(context,
- /* IN */
- fdp, appl_version, server, sender_addr, fetch_from,
- keyproc, keyprocarg, rc_type, flags,
+krb5_compat_recvauth(context, auth_context,
+ /* IN */
+ fdp, appl_version, server, rc_type, flags, keytab,
v4_options, v4_service, v4_instance, v4_faddr, v4_laddr,
v4_filename,
/* OUT */
- auth_sys, seq_number, client, ticket, authent,
- v4_kdata, v4_schedule, v4_version)
+ ticket,
+ auth_sys, v4_kdata, v4_schedule, v4_version)
krb5_context context;
+ krb5_auth_context **auth_context;
krb5_pointer fdp;
char *appl_version;
krb5_principal server;
- krb5_address *sender_addr;
- krb5_pointer fetch_from;
- krb5_int32 *seq_number;
char *rc_type;
krb5_int32 flags;
- krb5_rdreq_key_proc keyproc;
- krb5_pointer keyprocarg;
- krb5_principal *client;
- krb5_ticket **ticket;
- krb5_authenticator **authent;
- krb5_int32 *auth_sys;
+ krb5_keytab keytab;
+ krb5_ticket ** ticket;
+ krb5_int32 *auth_sys;
+
/*
* Version 4 arguments
*/
*auth_sys = KRB5_RECVAUTH_V5;
- retval = krb5_recvauth(context, fdp, appl_version, server, sender_addr,
- fetch_from,
- keyproc, keyprocarg, rc_type,
- flags | KRB5_RECVAUTH_SKIP_VERSION,
- seq_number, client, ticket, authent);
+ retval = krb5_recvauth(context, auth_context, fdp, appl_version, server,
+ rc_type, flags | KRB5_RECVAUTH_SKIP_VERSION,
+ keytab, ticket);
return retval;
}
*/
#include "k5-int.h"
+#include "auth_con.h"
/*
Formats a KRB_AP_REP message into outbuf.
- The reply in repl is encrypted under the key in kblock, and the resulting
- message encoded and left in outbuf.
-
The outbuf buffer storage is allocated, and should be freed by the
caller when finished.
*/
krb5_error_code INTERFACE
-krb5_mk_rep(context, repl, kblock, outbuf)
- krb5_context context;
- const krb5_ap_rep_enc_part *repl;
- const krb5_keyblock *kblock;
- krb5_data *outbuf;
+krb5_mk_rep(context, auth_context, outbuf)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_data * outbuf;
{
- krb5_error_code retval;
- krb5_data *scratch;
- krb5_ap_rep reply;
- krb5_enctype etype;
- krb5_encrypt_block eblock;
- krb5_data *toutbuf;
+ krb5_error_code retval;
+ krb5_keyblock * keyblock;
+ krb5_keytype keytype;
+ krb5_enctype etype;
+ krb5_ap_rep_enc_part repl;
+ krb5_encrypt_block eblock;
+ krb5_ap_rep reply;
+ krb5_data * scratch;
+ krb5_data * toutbuf;
+
+ if (auth_context->remote_subkey)
+ keyblock = auth_context->remote_subkey;
+ else
+ keyblock = auth_context->keyblock;
/* verify a valid etype is available */
- if (!valid_keytype(kblock->keytype))
+ if (!valid_keytype(keytype = keyblock->keytype))
return KRB5_PROG_KEYTYPE_NOSUPP;
- etype = krb5_keytype_array[kblock->keytype]->system->proto_enctype;
+ etype = krb5_keytype_array[keytype]->system->proto_enctype;
if (!valid_etype(etype))
return KRB5_PROG_ETYPE_NOSUPP;
+ /* Make the reply */
+ 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, keyblock,
+ &auth_context->local_seq_number))
+ return(retval);
+ }
+
+ repl.ctime = auth_context->authentp->ctime;
+ repl.cusec = auth_context->authentp->cusec;
+ repl.subkey = auth_context->authentp->subkey;
+ repl.seq_number = auth_context->local_seq_number;
+
/* encode it before encrypting */
- if (retval = encode_krb5_ap_rep_enc_part(repl, &scratch))
+ if (retval = encode_krb5_ap_rep_enc_part(&repl, &scratch))
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);
reply.enc_part.etype = etype;
reply.enc_part.kvno = 0; /* XXX user set? */
if (!(reply.enc_part.ciphertext.data =
malloc(reply.enc_part.ciphertext.length))) {
retval = ENOMEM;
- goto clean_scratch;
+ goto cleanup_scratch;
}
-#define cleanup_encpart() {\
-(void) memset(reply.enc_part.ciphertext.data, 0,\
- reply.enc_part.ciphertext.length); \
-free(reply.enc_part.ciphertext.data); \
-reply.enc_part.ciphertext.length = 0; reply.enc_part.ciphertext.data = 0;}
-
/* do any necessary key pre-processing */
- if (retval = krb5_process_key(context, &eblock, kblock)) {
- goto clean_encpart;
- }
-
-#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);}
+ if (retval = krb5_process_key(context, &eblock, keyblock))
+ goto cleanup_encpart;
/* call the encryption routine */
if (retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
(krb5_pointer) reply.enc_part.ciphertext.data,
scratch->length, &eblock, 0)) {
- goto clean_prockey;
+ krb5_finish_key(context, &eblock);
+ goto cleanup_encpart;
}
- /* encrypted part now assembled-- do some cleanup */
- cleanup_scratch();
-
- if (retval = krb5_finish_key(context, &eblock)) {
- cleanup_encpart();
- return retval;
- }
+ if (retval = krb5_finish_key(context, &eblock))
+ goto cleanup_encpart;
if (!(retval = encode_krb5_ap_rep(&reply, &toutbuf))) {
*outbuf = *toutbuf;
krb5_xfree(toutbuf);
}
- cleanup_encpart();
- return retval;
- clean_prockey:
- cleanup_prockey();
- clean_encpart:
- cleanup_encpart();
- clean_scratch:
- cleanup_scratch();
+cleanup_encpart:
+ memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
+ free(reply.enc_part.ciphertext.data);
+ reply.enc_part.ciphertext.length = 0;
+ reply.enc_part.ciphertext.data = 0;
+
+cleanup_scratch:
+ memset(scratch->data, 0, scratch->length);
+ krb5_free_data(context, scratch);
return retval;
}
/* Generate checksum, XXX What should the seed be? */
- if ((checksum.contents = (krb5_octet *)malloc(krb5_checksum_size(
- context, CKSUMTYPE_CRC32))) == NULL) {
+ if ((checksum.contents = (krb5_octet *)malloc(krb5_checksum_size(context,
+ (*auth_context)->cksumtype))) == NULL) {
retval = ENOMEM;
goto cleanup;
}
if (in_data == NULL) {
if (retval = krb5_calculate_checksum(context,
- (*auth_context)->cksumtype,
- 0, 0, 0, 0, &checksum))
+ (*auth_context)->cksumtype, 0, 0,
+ (*auth_context)->keyblock->contents,
+ (*auth_context)->keyblock->length,
+ &checksum))
goto cleanup_cksum;
} else
if ((*auth_context)->cksumtype == 0x8003) {
checksum.contents = (krb5_octet *) in_data->data;
} else
if (retval = krb5_calculate_checksum(context,
- (*auth_context)->cksumtype,
- in_data->data, in_data->length,
- 0, 0, &checksum))
+ (*auth_context)->cksumtype,
+ in_data->data, in_data->length,
+ (*auth_context)->keyblock->contents,
+ (*auth_context)->keyblock->length,
+ &checksum))
goto cleanup_cksum;
/* Generate authenticator */
const krb5_data * inbuf;
krb5_ap_rep_enc_part **repl;
{
- krb5_error_code retval;
- krb5_ap_rep *reply;
- krb5_encrypt_block eblock;
- krb5_data scratch;
+ krb5_error_code retval;
+ krb5_ap_rep * reply;
+ krb5_keyblock * keyblock;
+ krb5_encrypt_block eblock;
+ krb5_data scratch;
if (!krb5_is_ap_rep(inbuf))
return KRB5KRB_AP_ERR_MSG_TYPE;
return(ENOMEM);
}
+ if (auth_context->local_subkey)
+ keyblock = auth_context->local_subkey;
+ else
+ keyblock = auth_context->keyblock;
+
/* do any necessary key pre-processing */
- if (retval = krb5_process_key(context, &eblock, auth_context->keyblock)) {
+ if (retval = krb5_process_key(context, &eblock, keyblock)) {
goto errout;
}
*/
#include "k5-int.h"
+#include "auth_con.h"
/*
* Parses a KRB_AP_REQ message, returning its contents.
*
* server specifies the expected server's name for the ticket.
*
- * sender_addr specifies the address(es) expected to be present in the
- * ticket.
- *
- * rcache specifies a replay detection cache used to store authenticators and
- * server names
- *
* keyproc specifies a procedure to generate a decryption key for the
* ticket. If keyproc is non-NULL, keyprocarg is passed to it, and the result
* used as a decryption key. If keyproc is NULL, then fetchfrom is checked;
* decryption key. If fetchfrom is NULL, then the default key store is
* consulted.
*
- * authdat is set to point at allocated storage structures; the caller
- * should free them when finished.
- *
* returns system errors, encryption errors, replay errors
*/
krb5_error_code INTERFACE
-krb5_rd_req(context, inbuf, server, sender_addr, fetchfrom, keyproc,
- keyprocarg, rcache, authdat)
- krb5_context context;
- const krb5_data *inbuf;
- krb5_const_principal server;
- const krb5_address *sender_addr;
- const char * fetchfrom;
- krb5_rdreq_key_proc keyproc;
- krb5_pointer keyprocarg;
- krb5_rcache rcache;
- krb5_tkt_authent **authdat;
+krb5_rd_req(context, auth_context, inbuf, server, keytab,
+ ap_req_options, ticket)
+ krb5_context context;
+ krb5_auth_context ** auth_context;
+ const krb5_data * inbuf;
+ krb5_const_principal server; /* XXX do we really need this */
+ krb5_keytab keytab;
+ krb5_flags * ap_req_options;
+ krb5_ticket ** ticket;
{
- krb5_error_code retval;
- krb5_ap_req *request;
+ krb5_error_code retval;
+ krb5_ap_req * request;
+ krb5_auth_context * new_auth_context;
+ krb5_rcache new_rcache;
+ krb5_keytab new_keytab = NULL;
if (!krb5_is_ap_req(inbuf))
return KRB5KRB_AP_ERR_MSG_TYPE;
default:
return(retval);
}
+ }
+
+ /* Get an auth context if necessary. */
+ new_auth_context = NULL;
+ if (*auth_context == NULL) {
+ if (retval = krb5_auth_con_init(context, &new_auth_context))
+ goto cleanup_request;
+ *auth_context = new_auth_context;
+ }
+ /* Get an rcache if necessary. */
+ if (((*auth_context)->rcache == NULL) && server) {
+ if (retval = krb5_get_server_rcache(context,
+ krb5_princ_component(context,server,0), &(*auth_context)->rcache))
+ goto cleanup_auth_context;
}
- retval = krb5_rd_req_decoded(context, request, server, sender_addr,
- fetchfrom, keyproc, keyprocarg, rcache,
- authdat);
+ /* Get a keytab if necessary. */
+ if (keytab == NULL) {
+ if (retval = krb5_kt_default(context, &new_keytab))
+ goto cleanup_auth_context;
+ keytab = new_keytab;
+ }
+
+ retval = krb5_rd_req_decoded(context, auth_context, request, server,
+ keytab, ap_req_options, ticket);
+
+ if (new_keytab == NULL)
+ (void) krb5_kt_close(context, new_keytab);
+
+cleanup_auth_context:
+ if (new_auth_context && retval)
+ krb5_auth_con_free(context, new_auth_context);
+
+cleanup_request:
krb5_free_ap_req(context, request);
return retval;
}
*/
#include "k5-int.h"
+#include "auth_con.h"
/*
* essentially the same as krb_rd_req, but uses a decoded AP_REQ as
* any server will be accepted if the key can be found, and the caller should
* verify that the principal is something it trusts.
*
- * sender_addr specifies the address(es) expected to be present in the
- * ticket.
- *
* rcache specifies a replay detection cache used to store authenticators and
* server names
*
extern krb5_deltat krb5_clockskew;
#define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew)
-krb5_error_code INTERFACE
-krb5_rd_req_decoded(context, req, server, sender_addr, fetchfrom, keyproc,
- keyprocarg, rcache, authdat)
- krb5_context context;
- const krb5_ap_req *req;
- krb5_const_principal server;
- const krb5_address *sender_addr;
- const char * fetchfrom;
- krb5_rdreq_key_proc keyproc;
- krb5_pointer keyprocarg;
- krb5_rcache rcache;
- krb5_tkt_authent **authdat;
-{
- krb5_keytype keytype;
- krb5_error_code retval = 0;
- krb5_keyblock *tkt_key = NULL;
- krb5_timestamp currenttime, starttime;
- krb5_tkt_authent *tktauthent = NULL;
+static krb5_error_code
+krb5_rd_req_decrypt_tkt_part(context, req, keytab)
+ krb5_context context;
+ const krb5_ap_req * req;
+ krb5_keytab keytab;
- if (server && !krb5_principal_compare(context, server, req->ticket->server))
- return KRB5KRB_AP_WRONG_PRINC;
+{
+ krb5_error_code retval;
+ krb5_keytype keytype;
+ krb5_keytab_entry ktent;
- /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
- do we need special processing here ? */
-
/*
* OK we know the encryption type req->ticket->enc_part.etype,
* and now we need to get the keytype
*/
keytype = krb5_csarray[req->ticket->enc_part.etype]->system->proto_keytype;
- /* fetch a server key */
- if (keyproc) {
- retval = (*keyproc)(context, keyprocarg, req->ticket->server,
- req->ticket->enc_part.kvno, keytype, &tkt_key);
- } else {
- krb5_keytab keytabid;
- krb5_keytab_entry ktentry;
-
- if (fetchfrom) {
- /* use the named keytab */
- retval = krb5_kt_resolve(context, fetchfrom, &keytabid);
- } else {
- /* use default keytab */
- retval = krb5_kt_default(context, &keytabid);
- }
- if (!retval) {
- retval = krb5_kt_get_entry(context, keytabid, req->ticket->server,
- req->ticket->enc_part.kvno, keytype,
- &ktentry);
- (void) krb5_kt_close(context, keytabid);
- if (!retval) {
- retval = krb5_copy_keyblock(context, &ktentry.key, &tkt_key);
- (void) krb5_kt_free_entry(context, &ktentry);
- }
- }
- }
- if (retval)
- return retval; /* some error in getting the key */
+ if (retval = krb5_kt_get_entry(context, keytab, req->ticket->server,
+ req->ticket->enc_part.kvno, keytype, &ktent))
+ return retval;
- /* decrypt the ticket */
- if (retval = krb5_decrypt_tkt_part(context, tkt_key, req->ticket)) {
- krb5_free_keyblock(context, tkt_key);
- return(retval);
- }
+ if (retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket))
+ return retval;
- /*
- * Now we allocate space for the krb5_tkt_authent structure. If
- * we ever have an error, we're responsible for freeing it.
- */
- if (!(tktauthent =
- (krb5_tkt_authent *) malloc(sizeof(*tktauthent)))) {
- retval = ENOMEM;
- goto cleanup;
+ (void) krb5_kt_free_entry(context, &ktent);
+ return retval;
+}
+
+krb5_error_code INTERFACE
+krb5_rd_req_decoded(context, auth_context, req, server, keytab,
+ ap_req_options, ticket)
+ krb5_context context;
+ krb5_auth_context ** auth_context;
+ const krb5_ap_req * req;
+ krb5_const_principal server;
+ krb5_keytab keytab;
+ krb5_flags * ap_req_options;
+ krb5_ticket ** ticket;
+{
+ krb5_error_code retval = 0;
+ krb5_timestamp currenttime, starttime;
+
+ if (server && !krb5_principal_compare(context, server, req->ticket->server))
+ return KRB5KRB_AP_WRONG_PRINC;
+
+ /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
+ do we need special processing here ? */
+
+ /* decrypt the ticket */
+ if ((*auth_context)->keyblock) { /* User to User authentication */
+ if (retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock,
+ req->ticket))
+ return retval;
+ krb5_free_keyblock(context, (*auth_context)->keyblock);
+ (*auth_context)->keyblock = NULL;
+ } else {
+ if (retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab))
+ return retval;
}
-
- memset((char *)tktauthent, 0, sizeof(*tktauthent));
- if (retval = decrypt_authenticator(context, req, &tktauthent->authenticator))
+ if (retval = decrypt_authenticator(context, req,
+ &((*auth_context)->authentp)))
goto cleanup;
- *authdat = NULL; /* Set authdat to tktauthent when we finish */
- if (!krb5_principal_compare(context, tktauthent->authenticator->client,
+ if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
req->ticket->enc_part2->client)) {
retval = KRB5KRB_AP_ERR_BADMATCH;
goto cleanup;
}
- if (sender_addr && !krb5_address_search(context, sender_addr, req->ticket->enc_part2->caddrs)) {
- retval = KRB5KRB_AP_ERR_BADADDR;
- goto cleanup;
- }
-
- if (retval = krb5_timeofday(context, ¤ttime))
- goto cleanup;
- if (!in_clock_skew(tktauthent->authenticator->ctime)) {
- retval = KRB5KRB_AP_ERR_SKEW;
+ if ((*auth_context)->remote_addr &&
+ !krb5_address_search(context, (*auth_context)->remote_addr,
+ req->ticket->enc_part2->caddrs)) {
+ retval = KRB5KRB_AP_ERR_BADADDR;
goto cleanup;
}
/* Single hop cross-realm tickets only */
- { krb5_transited *trans = &(req->ticket->enc_part2->transited);
-
- /* If the transited list is empty, then we have at most one hop */
+ {
+ krb5_transited *trans = &(req->ticket->enc_part2->transited);
- if (trans->tr_contents.data && trans->tr_contents.data[0]) {
- retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
- }
+ /* If the transited list is empty, then we have at most one hop */
+ if (trans->tr_contents.data && trans->tr_contents.data[0])
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
}
#elif defined(_NO_CROSS_REALM)
/* No cross-realm tickets */
- { char *lrealm;
- krb5_data *realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
- krb5_transited *trans = &(req->ticket->enc_part2->transited);
-
- /* If the transited list is empty, then we have at most one hop */
- /* So we also have to check that the client's realm is the local one */
-
- krb5_get_default_realm(context, &lrealm);
- if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
+ {
+ char * lrealm;
+ krb5_data * realm;
+ krb5_transited * trans;
+
+ realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
+ trans = &(req->ticket->enc_part2->transited);
+
+ /*
+ * If the transited list is empty, then we have at most one hop
+ * So we also have to check that the client's realm is the local one
+ */
+ krb5_get_default_realm(context, &lrealm);
+ if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
strlen(lrealm) != realm->length ||
memcmp(lrealm, realm->data, strlen(lrealm))) {
- retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
- }
- free(lrealm);
+ retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
+ }
+ free(lrealm);
}
#else
/* Hierarchical Cross-Realm */
{
- krb5_data lrealm;
- krb5_data *realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
- krb5_transited *trans = &(req->ticket->enc_part2->transited);
+ krb5_data lrealm;
+ krb5_data * realm;
+ krb5_transited * trans;
- /* If the transited list is not empty, then check that all realms */
- /* transited are within the hierarchy between the client's realm */
- /* and the local realm. */
-
- if (trans->tr_contents.data && trans->tr_contents.data[0]) {
- krb5_get_default_realm(context, &(lrealm.data));
- lrealm.length = strlen(lrealm.data);
- retval = krb5_check_transited_list(context, &(trans->tr_contents), realm,
- &lrealm);
- free(lrealm.data);
- }
+ realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
+ trans = &(req->ticket->enc_part2->transited);
+
+ /*
+ * If the transited list is not empty, then check that all realms
+ * transited are within the hierarchy between the client's realm
+ * and the local realm.
+ */
+ if (trans->tr_contents.data && trans->tr_contents.data[0]) {
+ lrealm.length = strlen(lrealm.data);
+ krb5_get_default_realm(context, &(lrealm.data));
+ retval = krb5_check_transited_list(context, &(trans->tr_contents),
+ realm, &lrealm);
+ free(lrealm.data);
+ }
}
#endif
/* only check rcache if sender has provided one---some services
may not be able to use replay caches (such as datagram servers) */
- if (rcache) {
- krb5_donot_replay rep;
- tktauthent->ticket = req->ticket; /* Temporary; allocated below */
- retval = krb5_auth_to_rep(context, tktauthent, &rep);
- tktauthent->ticket = 0; /* Don't allow cleanup to free
- original ticket. */
- if (retval)
- goto cleanup;
- retval = krb5_rc_store(context, rcache, &rep);
- krb5_xfree(rep.server);
- krb5_xfree(rep.client);
+ if ((*auth_context)->rcache) {
+ krb5_donot_replay rep;
+ krb5_tkt_authent tktauthent;
+
+ tktauthent.ticket = req->ticket;
+ tktauthent.authenticator = (*auth_context)->authentp;
+ if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
+ retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
+ krb5_xfree(rep.server);
+ krb5_xfree(rep.client);
+ }
+
if (retval)
goto cleanup;
}
else
starttime = req->ticket->enc_part2->times.authtime;
+ if (retval = krb5_timeofday(context, ¤ttime))
+ goto cleanup;
if (starttime - currenttime > krb5_clockskew) {
retval = KRB5KRB_AP_ERR_TKT_NYV; /* ticket not yet valid */
goto cleanup;
}
+ if (!in_clock_skew((*auth_context)->authentp->ctime)) {
+ retval = KRB5KRB_AP_ERR_SKEW;
+ goto cleanup;
+ }
if (currenttime - req->ticket->enc_part2->times.endtime > krb5_clockskew) {
retval = KRB5KRB_AP_ERR_TKT_EXPIRED; /* ticket expired */
goto cleanup;
retval = KRB5KRB_AP_ERR_TKT_INVALID;
goto cleanup;
}
- retval = krb5_copy_ticket(context, req->ticket, &tktauthent->ticket);
+
+ (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
+ (*auth_context)->remote_subkey = (*auth_context)->authentp->subkey;
+ if (retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session,
+ &((*auth_context)->keyblock)))
+ goto cleanup;
+
+ /*
+ * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used
+ * then the default sequence number is the one's complement of the
+ * sequence number sent ot us.
+ */
+ if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) &&
+ (*auth_context)->remote_seq_number) {
+ (*auth_context)->local_seq_number ^=
+ (*auth_context)->remote_seq_number;
+ }
+
+ if (ticket)
+ if (retval = krb5_copy_ticket(context, req->ticket, ticket))
+ goto cleanup;
+ if (ap_req_options)
+ *ap_req_options = req->ap_options;
+ retval = 0;
cleanup:
- if (tktauthent) {
- if (retval) {
- krb5_free_tkt_authent(context, tktauthent);
- } else {
- tktauthent->ap_options = req->ap_options;
- *authdat = tktauthent;
- }
- }
- if (retval && req->ticket->enc_part2) {
+ if (retval) {
/* only free if we're erroring out...otherwise some
applications will need the output. */
krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
req->ticket->enc_part2 = NULL;
}
- if (tkt_key)
- krb5_free_keyblock(context, tkt_key);
return retval;
}
}
/* call the encryption routine */
- if (retval = krb5_decrypt(context, (krb5_pointer) request->authenticator.ciphertext.data,
- (krb5_pointer) scratch.data,
- scratch.length, &eblock, 0)) {
+ if (retval = krb5_decrypt(context,
+ (krb5_pointer)request->authenticator.ciphertext.data,
+ (krb5_pointer)scratch.data,
+ scratch.length, &eblock, 0)) {
(void) krb5_finish_key(context, &eblock);
free(scratch.data);
return retval;
krb5_error_code INTERFACE
krb5_rd_safe(context, auth_context, inbuf, outbuf, outdata)
krb5_context context;
- krb5_auth_context * auth_context;
+ krb5_auth_context * auth_context;
const krb5_data * inbuf;
krb5_data * outbuf;
krb5_replay_data * outdata;
if (retval = krb5_rd_safe_basic(context, inbuf, auth_context->keyblock,
auth_context->local_addr, auth_context->remote_addr,
- auth_context->cksumtype, &replaydata, outbuf))
+ &replaydata, outbuf))
return retval;
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
#define NEED_SOCKETS
#include "k5-int.h"
+#include "auth_con.h"
#include "com_err.h"
#include <errno.h>
#include <stdio.h>
static char *sendauth_version = "KRB5_SENDAUTH_V1.0";
krb5_error_code INTERFACE
-krb5_recvauth(context,
+krb5_recvauth(context, auth_context,
/* IN */
- fd, appl_version, server, sender_addr, fetch_from,
- keyproc, keyprocarg, rc_type, flags,
+ fd, appl_version, server, rc_type, flags, keytab,
/* OUT */
- seq_number, client, ticket, authent)
- krb5_context context;
- krb5_pointer fd;
- char *appl_version;
- krb5_principal server;
- krb5_address *sender_addr;
- krb5_pointer fetch_from;
- krb5_int32 *seq_number;
- char *rc_type;
- krb5_int32 flags;
- krb5_rdreq_key_proc keyproc;
- krb5_pointer keyprocarg;
- krb5_principal *client;
- krb5_ticket **ticket;
- krb5_authenticator **authent;
+ ticket)
+ krb5_context context;
+ krb5_auth_context ** auth_context;
+ krb5_pointer fd;
+ char * appl_version;
+ krb5_principal server;
+ char * rc_type;
+ krb5_int32 flags;
+ krb5_keytab keytab;
+ krb5_ticket ** ticket;
{
- krb5_error_code retval, problem;
- krb5_data inbuf;
- krb5_tkt_authent *authdat;
- krb5_data outbuf;
- krb5_rcache rcache;
- krb5_octet response;
- krb5_data *server_name, null_server;
- char *cachename;
- extern krb5_deltat krb5_clockskew;
- static char *rc_base = "rc_";
+ krb5_flags ap_option;
+ krb5_error_code retval, problem;
+ krb5_data inbuf;
+ krb5_data outbuf;
+ krb5_rcache rcache;
+ krb5_octet response;
+ krb5_data null_server;
+ extern krb5_deltat krb5_clockskew;
/*
* Zero out problem variable. If problem is set at the end of
* Now we actually write the response. If the response is non-zero,
* exit with a return value of problem
*/
- if ((krb5_net_write(context, *((int *) fd), (char *)&response, 1)) < 0) {
+ if ((krb5_net_write(context, *((int *)fd), (char *)&response, 1)) < 0) {
return(problem); /* We'll return the top-level problem */
}
if (problem)
return(problem);
- rcache = NULL;
/*
* Setup the replay cache.
*/
- if (!(rcache = (krb5_rcache) malloc(sizeof(*rcache))))
- problem = ENOMEM;
- if (!problem)
- problem = krb5_rc_resolve_type(context, &rcache,
- rc_type ? rc_type : "dfl");
- cachename = NULL;
if (server) {
- server_name = krb5_princ_component(context, server, 0);
+ problem = krb5_get_server_rcache(context,
+ krb5_princ_component(context, server, 0), &rcache);
} else {
- null_server.data = "default";
null_server.length = 7;
- server_name = &null_server;
- }
-
- if (!problem && !(cachename = malloc(server_name->length+1+strlen(rc_base))))
- problem = ENOMEM;
- if (!problem) {
- strcpy(cachename, rc_base ? rc_base : "rc_");
- strncat(cachename, server_name->data, server_name->length);
- cachename[server_name->length+strlen(rc_base)] = '\0';
- problem = krb5_rc_resolve(context, rcache, cachename);
+ null_server.data = "default";
+ problem = krb5_get_server_rcache(context, &null_server, &rcache);
}
- if (!problem) {
- if (krb5_rc_recover(context, rcache))
- /*
- * If the rc_recover didn't work, then try
- * initializing the replay cache.
- */
- problem = krb5_rc_initialize(context, rcache, krb5_clockskew);
- if (problem) {
- krb5_rc_close(context, rcache);
- rcache = NULL;
- }
+
+ if (!problem) {
+ if (krb5_rc_recover(context, rcache)) {
+ /*
+ * If the rc_recover() didn't work, then try
+ * initializing the replay cache.
+ */
+ if (krb5_rc_initialize(context, rcache, krb5_clockskew)) {
+ krb5_rc_close(context, rcache);
+ rcache = NULL;
+ }
}
+ }
/*
* Now, let's read the AP_REQ message and decode it
*/
if (retval = krb5_read_message(context, fd, &inbuf)) {
+ if (rcache)
(void) krb5_rc_close(context, rcache);
- if (cachename)
- free(cachename);
return(retval);
}
- authdat = 0; /* so we can tell if we need to
- free it later... */
+
+ if (*auth_context == NULL) {
+ if (retval = krb5_auth_con_init(context, auth_context))
+ return(retval);
+ }
+
+ krb5_auth_con_setrcache(context, *auth_context, rcache);
+
if (!problem)
- problem = krb5_rd_req(context, &inbuf, server, sender_addr, fetch_from,
- keyproc, keyprocarg, rcache, &authdat);
+ problem = krb5_rd_req(context, auth_context, &inbuf, server,
+ keytab, &ap_option, ticket);
krb5_xfree(inbuf.data);
if (rcache)
retval = krb5_rc_close(context, rcache);
if (!problem && retval)
problem = retval;
- if (cachename)
- free(cachename);
/*
* If there was a problem, send back a krb5_error message,
if (retval = krb5_write_message(context, fd, &outbuf)) {
if (outbuf.data)
krb5_xfree(outbuf.data);
- if (!problem)
- krb5_free_tkt_authent(context, authdat);
return(retval);
}
if (problem) {
/*
* We sent back an error, we need to return
*/
- if (authdat) krb5_free_tkt_authent(context, authdat);
return(problem);
}
- /*
- * Here lies the mutual authentication stuff...
- *
- * We're going to compose and send a AP_REP message.
- */
- if ((authdat->ap_options & AP_OPTS_MUTUAL_REQUIRED)) {
- krb5_ap_rep_enc_part repl;
- /*
- * Generate a random sequence number
- */
- if (seq_number &&
- (retval = krb5_generate_seq_number(context,
- authdat->ticket->enc_part2->session, seq_number))) {
- krb5_free_tkt_authent(context, authdat);
- return(retval);
- }
-
- repl.ctime = authdat->authenticator->ctime;
- repl.cusec = authdat->authenticator->cusec;
- repl.subkey = authdat->authenticator->subkey;
- if (seq_number)
- repl.seq_number = *seq_number;
- else
- repl.seq_number = 0;
-
- if (retval = krb5_mk_rep(context, &repl,
- authdat->ticket->enc_part2->session,
- &outbuf)) {
- krb5_free_tkt_authent(context, authdat);
- return(retval);
- }
- if (retval = krb5_write_message(context, fd, &outbuf)) {
- krb5_xfree(outbuf.data);
- krb5_free_tkt_authent(context, authdat);
- return(retval);
- }
- krb5_xfree(outbuf.data);
+ /* Here lies the mutual authentication stuff... */
+ if ((ap_option & AP_OPTS_MUTUAL_REQUIRED)) {
+ if (retval = krb5_mk_rep(context, *auth_context, &outbuf)) {
+ return(retval);
}
- /*
- * At this point, we've won. We just need to copy whatever
- * parts of the authdat structure which the user wants, clean
- * up, and exit.
- */
- if (client)
- if (retval =
- krb5_copy_principal(context, authdat->ticket->enc_part2->client,
- client)) {
- krb5_free_tkt_authent(context, authdat);
- return(retval);
- }
- /*
- * The following efficiency hack assumes knowledge about the
- * structure of krb5_tkt_authent. If we later add additional
- * allocated substructures to krb5_tkt_authent, they will have
- * to be reflected here; otherwise, we will probably have a
- * memory leak.
- *
- * If the user wants that part of the authdat structure,
- * return it; otherwise free it.
- */
- if (ticket)
- *ticket = authdat->ticket;
- else
- krb5_free_ticket(context, authdat->ticket);
- if (authent)
- *authent = authdat->authenticator;
- else
- krb5_free_authenticator(context, authdat->authenticator);
- krb5_xfree(authdat);
- return 0;
+ retval = krb5_write_message(context, fd, &outbuf);
+ krb5_xfree(outbuf.data);
+ }
+ return retval;
}