diff options
author | Chris Provenzano <proven@mit.edu> | 1995-04-26 03:03:26 +0000 |
---|---|---|
committer | Chris Provenzano <proven@mit.edu> | 1995-04-26 03:03:26 +0000 |
commit | b512f16eda5d2b4920490d2409d6a900030b32d0 (patch) | |
tree | 4985f920985db7c78f7673e0d09209c1b40f8fe3 /src/lib/krb5/krb/rd_cred.c | |
parent | 1c97a678883a123b1fb1be6e8954a619511fa093 (diff) | |
download | krb5-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.c | 437 |
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, ¤ttime)) { - 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, ¤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, + "_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; } + |