summaryrefslogtreecommitdiffstats
path: root/src/lib/krb5/krb/rd_cred.c
diff options
context:
space:
mode:
authorChris Provenzano <proven@mit.edu>1995-04-26 03:03:26 +0000
committerChris Provenzano <proven@mit.edu>1995-04-26 03:03:26 +0000
commitb512f16eda5d2b4920490d2409d6a900030b32d0 (patch)
tree4985f920985db7c78f7673e0d09209c1b40f8fe3 /src/lib/krb5/krb/rd_cred.c
parent1c97a678883a123b1fb1be6e8954a619511fa093 (diff)
downloadkrb5-b512f16eda5d2b4920490d2409d6a900030b32d0.tar.gz
krb5-b512f16eda5d2b4920490d2409d6a900030b32d0.tar.xz
krb5-b512f16eda5d2b4920490d2409d6a900030b32d0.zip
* Makefile.in : Added gc_via_tkt.c and removed get_fcreds.c
* auth_con.c (krb5_auth_con_setaddrs()) : Fixed so it allocates space and copies addresses, not just pointer. * mk_cred.c: Completely rewritten from sources donated by asriniva. * rd_cred.c: Completely rewritten from sources donated by asriniva. * mk_priv.c (krb5_mk_priv()), mk_safe.c (krb5_mk_safe()), rd_priv.c (krb5_rd_priv()), and rd_safe (krb5_rd_safe()) : Try using a subkey before using the session key for encryption. * recvauth.c (krb5_recvauth()): Don't close the rcache on success. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5489 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/krb5/krb/rd_cred.c')
-rw-r--r--src/lib/krb5/krb/rd_cred.c437
1 files changed, 249 insertions, 188 deletions
diff --git a/src/lib/krb5/krb/rd_cred.c b/src/lib/krb5/krb/rd_cred.c
index dfe774b512..179a922b70 100644
--- a/src/lib/krb5/krb/rd_cred.c
+++ b/src/lib/krb5/krb/rd_cred.c
@@ -1,225 +1,286 @@
-/*
- * lib/krb5/krb/rd_cred.c
- *
- * Copyright 1994 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- * krb5_rd_cred()
- */
+#include <k5-int.h>
+#include "auth_con.h"
-/* XXX This API is going to change; what's here isn't general enough! */
-/* XXX Once we finalize the API, it should go into func-proto.h and */
-/* into the API doc. */
+#include <stddef.h> /* NULL */
+#include <stdlib.h> /* malloc */
+#include <errno.h> /* ENOMEM */
-#include "k5-int.h"
-
-extern krb5_deltat krb5_clockskew;
-#define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew)
+/*-------------------- decrypt_credencdata --------------------*/
-/* Decode the KRB-CRED message, and return creds */
-krb5_error_code
-krb5_rd_cred(context, inbuf, key, creds, sender_addr, recv_addr)
- krb5_context context;
- const krb5_data *inbuf;
- const krb5_keyblock *key;
- krb5_creds *creds; /* Filled in */
- const krb5_address *sender_addr; /* optional */
- const krb5_address *recv_addr; /* optional */
+/*
+ * decrypt the enc_part of a krb5_cred
+ */
+static krb5_error_code
+decrypt_credencdata(context, pcred, pkeyblock, pcredenc)
+ krb5_context context;
+ krb5_cred * pcred;
+ krb5_keyblock * pkeyblock;
+ krb5_cred_enc_part * pcredenc;
{
- krb5_error_code retval;
- krb5_encrypt_block eblock;
- krb5_cred *credmsg;
- krb5_cred_enc_part *credmsg_enc_part;
- krb5_data *scratch;
- krb5_timestamp currenttime;
-
- if (!krb5_is_krb_cred(inbuf))
- return KRB5KRB_AP_ERR_MSG_TYPE;
-
- /* decode private message */
- if (retval = decode_krb5_cred(inbuf, &credmsg)) {
- return retval;
- }
-
-#define cleanup_credmsg() { \
- krb5_xfree(credmsg->enc_part.ciphertext.data); \
- krb5_xfree(credmsg); \
- }
-
- if (!(scratch = (krb5_data *) malloc(sizeof(*scratch)))) {
- cleanup_credmsg();
- return ENOMEM;
- }
-
-#define cleanup_scratch() { \
- (void)memset(scratch->data, 0, scratch->length); \
- krb5_xfree(scratch->data); \
- }
-
- if (retval = encode_krb5_ticket(credmsg->tickets[0], &scratch)) {
- cleanup_credmsg();
- cleanup_scratch();
- return(retval);
- }
+ krb5_cred_enc_part * ppart;
+ krb5_encrypt_block eblock;
+ krb5_error_code retval;
+ krb5_data scratch;
- creds->ticket = *scratch;
- if (!(creds->ticket.data = malloc(scratch->length))) {
- krb5_xfree(creds->ticket.data);
- return ENOMEM;
- }
- memcpy((char *)creds->ticket.data, (char *) scratch->data, scratch->length);
-
- cleanup_scratch();
-
- if (!valid_etype(credmsg->enc_part.etype)) {
- cleanup_credmsg();
- return KRB5_PROG_ETYPE_NOSUPP;
- }
+ if (!valid_etype(pcred->enc_part.etype))
+ return KRB5_PROG_ETYPE_NOSUPP;
/* put together an eblock for this decryption */
-
- krb5_use_cstype(context, &eblock, credmsg->enc_part.etype);
- scratch->length = credmsg->enc_part.ciphertext.length;
+ krb5_use_cstype(context, &eblock, pcred->enc_part.etype);
+ scratch.length = pcred->enc_part.ciphertext.length;
- if (!(scratch->data = malloc(scratch->length))) {
- cleanup_credmsg();
+ if (!(scratch.data = (char *)malloc(scratch.length)))
return ENOMEM;
- }
/* do any necessary key pre-processing */
- if (retval = krb5_process_key(context, &eblock, key)) {
- cleanup_credmsg();
- cleanup_scratch();
- return retval;
- }
-
-#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);}
+ if (retval = krb5_process_key(context, &eblock, pkeyblock))
+ goto cleanup;
/* call the decryption routine */
- if (retval = krb5_decrypt(context, (krb5_pointer) credmsg->enc_part.ciphertext.data,
- (krb5_pointer) scratch->data,
- scratch->length, &eblock,
- 0)) {
- cleanup_credmsg();
- cleanup_scratch();
- cleanup_prockey();
- return retval;
+ if (retval = krb5_decrypt(context,
+ (krb5_pointer) pcred->enc_part.ciphertext.data,
+ (krb5_pointer) scratch.data,
+ scratch.length, &eblock, 0)) {
+ (void)krb5_finish_key(context, &eblock);
+ goto cleanup;
}
- /* cred message is now decrypted -- do some cleanup */
+ if (retval = krb5_finish_key(context, &eblock))
+ goto cleanup;
- cleanup_credmsg();
+ /* now decode the decrypted stuff */
+ if (retval = decode_krb5_enc_cred_part(&scratch, &ppart))
+ goto cleanup_encpart;
- if (retval = krb5_finish_key(context, &eblock)) {
- cleanup_scratch();
- return retval;
- }
+ *pcredenc = *ppart;
+ retval = 0;
- /* now decode the decrypted stuff */
- if (retval = decode_krb5_enc_cred_part(scratch, &credmsg_enc_part)) {
- cleanup_scratch();
- return retval;
- }
- cleanup_scratch();
+cleanup_encpart:
+ memset(ppart, 0, sizeof(*ppart));
+ krb5_xfree(ppart);
-#define cleanup_mesg() {krb5_xfree(credmsg_enc_part);}
+cleanup:
+ memset(scratch.data, 0, scratch.length);
+ krb5_xfree(scratch.data);
- if (retval = krb5_timeofday(context, &currenttime)) {
- cleanup_mesg();
- return retval;
- }
- if (!in_clock_skew(credmsg_enc_part->timestamp)) {
- cleanup_mesg();
- return KRB5KRB_AP_ERR_SKEW;
+ return retval;
+}
+/*----------------------- krb5_rd_cred_basic -----------------------*/
+
+static krb5_error_code
+krb5_rd_cred_basic(context, pcreddata, pkeyblock, local_addr, remote_addr,
+ replaydata, pppcreds)
+ krb5_context context;
+ krb5_data * pcreddata;
+ krb5_keyblock * pkeyblock;
+ krb5_address * local_addr;
+ krb5_address * remote_addr;
+ krb5_replay_data * replaydata;
+ krb5_creds *** pppcreds;
+{
+ krb5_error_code retval;
+ krb5_cred * pcred;
+ krb5_int32 ncreds;
+ krb5_int32 i = 0;
+ krb5_cred_enc_part encpart;
+
+ /* decode cred message */
+ if (retval = decode_krb5_cred(pcreddata, &pcred))
+ return retval;
+
+ if (retval = decrypt_credencdata(context, pcred, pkeyblock, &encpart))
+ goto cleanup_cred;
+
+ if (!krb5_address_compare(context, remote_addr, encpart.s_address)) {
+ KRB5KRB_AP_ERR_BADADDR;
+ goto cleanup_cred;
}
- if (sender_addr && credmsg_enc_part->s_address &&
- !krb5_address_compare(context, sender_addr,
- credmsg_enc_part->s_address)) {
- cleanup_mesg();
- return KRB5KRB_AP_ERR_BADADDR;
- }
- if (recv_addr && credmsg_enc_part->r_address &&
- !krb5_address_compare(context, recv_addr,
- credmsg_enc_part->r_address)) {
- cleanup_mesg();
- return KRB5KRB_AP_ERR_BADADDR;
- }
-
- if (credmsg_enc_part->r_address) {
- krb5_address **our_addrs;
-
- if (retval = krb5_os_localaddr(&our_addrs)) {
- cleanup_mesg();
- return retval;
- }
- if (!krb5_address_search(context, credmsg_enc_part->r_address,
- our_addrs)) {
- krb5_free_addresses(context, our_addrs);
- cleanup_mesg();
- return KRB5KRB_AP_ERR_BADADDR;
- }
- krb5_free_addresses(context, our_addrs);
+ if (encpart.r_address) {
+ if (local_addr) {
+ if (!krb5_address_compare(context, local_addr, encpart.r_address)) {
+ retval = KRB5KRB_AP_ERR_BADADDR;
+ goto cleanup_cred;
+ }
+ } else {
+ krb5_address **our_addrs;
+
+ if (retval = krb5_os_localaddr(&our_addrs)) {
+ goto cleanup_cred;
+ }
+ if (!krb5_address_search(context, encpart.r_address, our_addrs)) {
+ krb5_free_addresses(context, our_addrs);
+ retval = KRB5KRB_AP_ERR_BADADDR;
+ goto cleanup_cred;
+ }
+ krb5_free_addresses(context, our_addrs);
+ }
}
- if (retval = krb5_copy_principal(context, credmsg_enc_part->ticket_info[0]->client,
- &creds->client)) {
- return(retval);
+ replaydata->timestamp = encpart.timestamp;
+ replaydata->usec = encpart.usec;
+ replaydata->seq = encpart.nonce;
+
+ /*
+ * Allocate the list of creds. The memory is allocated so that
+ * krb5_free_tgt_creds can be used to free the list.
+ */
+ for (ncreds = 0; pcred->tickets[ncreds]; ncreds++);
+ if ((*pppcreds =
+ (krb5_creds **)malloc(sizeof(krb5_creds *) * ncreds + 1)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup_cred;
}
- if (retval = krb5_copy_principal(context, credmsg_enc_part->ticket_info[0]->server,
- &creds->server)) {
- return(retval);
- }
+ /*
+ * For each credential, create a strcture in the list of
+ * credentials and copy the information.
+ */
+ while (i < ncreds) {
+ krb5_cred_info * pinfo;
+ krb5_creds * pcur;
+ krb5_data * pdata;
+
+ if ((pcur = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ (*pppcreds)[i] = pcur;
+ pinfo = encpart.ticket_info[i++];
+ memset(pcur, 0, sizeof(krb5_creds));
+
+ if (retval = krb5_copy_principal(context, pinfo->client, &pcur->client))
+ goto cleanup;
- if (retval =
- krb5_copy_keyblock_contents(context, credmsg_enc_part->ticket_info[0]->session,
- &creds->keyblock)) {
- return(retval);
+ if (retval = krb5_copy_principal(context, pinfo->server, &pcur->server))
+ goto cleanup;
+
+ if (retval = krb5_copy_keyblock_contents(context, pinfo->session,
+ &pcur->keyblock))
+ goto cleanup;
+
+ if (retval = krb5_copy_addresses(context, pinfo->caddrs,
+ &pcur->addresses))
+ goto cleanup;
+
+ if (retval = encode_krb5_ticket(pcred->tickets[i - 1], &pdata))
+ goto cleanup;
+
+ pcur->ticket = *pdata;
+ krb5_free_data(context, pdata);
+
+
+ pcur->is_skey = FALSE;
+ pcur->magic = KV5M_CREDS;
+ pcur->times = pinfo->times;
+ pcur->ticket_flags = pinfo->flags;
+ pcur->authdata = NULL; /* not used */
+ memset(&pcur->second_ticket, 0, sizeof(pcur->second_ticket));
}
- creds->keyblock.magic = KV5M_KEYBLOCK;
- creds->keyblock.etype = credmsg->tickets[0]->enc_part.etype;
-#undef clean
-#define clean() {\
- memset((char *)creds->keyblock.contents, 0, creds->keyblock.length);}
+ /*
+ * NULL terminate the list
+ */
+ (*pppcreds)[i] = NULL;
+
+cleanup:
+ if (retval)
+ while (i >= 0)
+ free((*pppcreds)[i--]);
- creds->times = credmsg_enc_part->ticket_info[0]->times;
- creds->is_skey = FALSE;
- creds->ticket_flags = credmsg_enc_part->ticket_info[0]->flags;
+cleanup_cred:
+ krb5_free_cred(context, pcred);
- if (retval = krb5_copy_addresses(context, credmsg_enc_part->ticket_info[0]->caddrs,
- &creds->addresses)) {
- clean();
- return(retval);
+ return retval;
+}
+
+/*----------------------- krb5_rd_cred -----------------------*/
+
+extern krb5_deltat krb5_clockskew;
+#define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew)
+
+/*
+ * This functions takes as input an KRB_CRED message, validates it, and
+ * outputs the nonce and an array of the forwarded credentials.
+ */
+krb5_error_code INTERFACE
+krb5_rd_cred(context, auth_context, pcreddata, pppcreds, outdata)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_data * pcreddata;
+ krb5_creds *** pppcreds;
+ krb5_replay_data * outdata;
+{
+ krb5_error_code retval;
+ krb5_keyblock * keyblock;
+ krb5_replay_data replaydata;
+
+ /* Get keyblock */
+ if ((keyblock = auth_context->local_subkey) == NULL)
+ if ((keyblock = auth_context->remote_subkey) == NULL)
+ keyblock = auth_context->keyblock;
+
+ 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_cred_basic(context, pcreddata, keyblock,
+ auth_context->local_addr, auth_context->remote_addr,
+ &replaydata, pppcreds))
+ 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, &currenttime))
+ 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,
+ "_forw", &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);
}
- creds->second_ticket.length = 0;
+ 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++;
+ }
- creds->authdata = 0;
+ 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;
+ }
- cleanup_mesg();
- return 0;
-#undef clean
-#undef cleanup_credmsg
-#undef cleanup_scratch
-#undef cleanup_prockey
-#undef cleanup_mesg
+error:;
+ if (retval)
+ krb5_xfree(*pppcreds);
+ return retval;
}
+