+Tue Apr 25 21:58:23 1995 Chris Provenzano (proven@mit.edu)
+
+ * 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.
+
Mon Apr 24 23:12:21 1995 Theodore Y. Ts'o <tytso@dcl>
* Makefile.in, configure.in (t_walk_rtree): Add WITH_NETLIBS and
faddr_ordr.$(OBJEXT) \
gc_frm_kdc.$(OBJEXT) \
gc_via_tgt.$(OBJEXT) \
+ gc_via_tkt.$(OBJEXT) \
gc_2tgt.$(OBJEXT) \
gen_seqnum.$(OBJEXT) \
gen_subkey.$(OBJEXT) \
get_creds.$(OBJEXT) \
- get_fcreds.$(OBJEXT) \
get_in_tkt.$(OBJEXT) \
in_tkt_ktb.$(OBJEXT) \
in_tkt_pwd.$(OBJEXT) \
$(srcdir)/faddr_ordr.c \
$(srcdir)/gc_frm_kdc.c \
$(srcdir)/gc_via_tgt.c \
+ $(srcdir)/gc_via_tkt.c \
$(srcdir)/gc_2tgt.c \
$(srcdir)/gen_seqnum.c \
$(srcdir)/gen_subkey.c \
$(srcdir)/get_creds.c \
- $(srcdir)/get_fcreds.c \
$(srcdir)/get_in_tkt.c \
$(srcdir)/in_tkt_ktb.c \
$(srcdir)/in_tkt_pwd.c \
krb5_address * local_addr;
krb5_address * remote_addr;
{
- auth_context->remote_addr = remote_addr;
- auth_context->local_addr = local_addr;
+ /* Free old addresses */
+ if (auth_context->local_addr)
+ free(auth_context->local_addr);
+ if (auth_context->remote_addr)
+ free(auth_context->remote_addr);
+
+ if (local_addr) {
+ if ((auth_context->local_addr = (krb5_address *)
+ malloc(sizeof(krb5_address) + local_addr->length)) == NULL) {
+ return ENOMEM;
+ }
+ auth_context->local_addr->addrtype = local_addr->addrtype;
+ auth_context->local_addr->length = local_addr->length;
+ auth_context->local_addr->contents = (krb5_octet *)
+ auth_context->local_addr + sizeof(krb5_address);
+ memcpy(auth_context->local_addr->contents,
+ local_addr->contents, local_addr->length);
+ } else {
+ auth_context->local_addr = NULL;
+ }
+
+ if (remote_addr) {
+ if ((auth_context->remote_addr = (krb5_address *)
+ malloc(sizeof(krb5_address) + remote_addr->length)) == NULL) {
+ if (auth_context->local_addr)
+ free(auth_context->local_addr);
+ return ENOMEM;
+ }
+ auth_context->remote_addr->addrtype = remote_addr->addrtype;
+ auth_context->remote_addr->length = remote_addr->length;
+ auth_context->remote_addr->contents = (krb5_octet *)
+ auth_context->remote_addr + sizeof(krb5_address);
+ memcpy(auth_context->remote_addr->contents,
+ remote_addr->contents, remote_addr->length);
+ } else {
+ auth_context->remote_addr = NULL;
+ }
return 0;
}
--- /dev/null
+/*
+ * lib/krb5/krb/gc_via_tgt.c
+ *
+ * Copyright 1990,1991 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.
+ *
+ *
+ * Given a tkt, and a target cred, get it.
+ * Assumes that the kdc_rep has been decrypted.
+ */
+
+#include "k5-int.h"
+#include "int-proto.h"
+
+static krb5_error_code
+krb5_kdcrep2creds(context, pkdcrep, address, ppcreds)
+ krb5_context context;
+ krb5_kdc_rep * pkdcrep;
+ krb5_address *const * address;
+ krb5_creds ** ppcreds;
+{
+ krb5_error_code retval;
+ krb5_data *pdata;
+
+ if ((*ppcreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
+ return ENOMEM;
+ }
+
+ memset(*ppcreds, 0, sizeof(krb5_creds));
+
+ if (retval = krb5_copy_principal(context, pkdcrep->client,
+ &(*ppcreds)->client))
+ goto cleanup;
+
+ if (retval = krb5_copy_principal(context, pkdcrep->enc_part2->server,
+ &(*ppcreds)->server))
+ goto cleanup;
+
+ if (retval = krb5_copy_keyblock_contents(context,
+ pkdcrep->enc_part2->session,
+ &(*ppcreds)->keyblock))
+ goto cleanup;
+
+ (*ppcreds)->keyblock.etype = pkdcrep->ticket->enc_part.etype;
+
+ (*ppcreds)->magic = KV5M_CREDS;
+ (*ppcreds)->is_skey = 0; /* unused */
+ (*ppcreds)->times = pkdcrep->enc_part2->times;
+ (*ppcreds)->ticket_flags = pkdcrep->enc_part2->flags;
+
+ (*ppcreds)->authdata = NULL; /* not used */
+ memset(&(*ppcreds)->second_ticket, 0, sizeof((*ppcreds)->second_ticket));
+
+ if (pkdcrep->enc_part2->caddrs) {
+ if (retval = krb5_copy_addresses(context, pkdcrep->enc_part2->caddrs,
+ &(*ppcreds)->addresses))
+ goto cleanup_keyblock;
+ } else {
+ /* no addresses in the list means we got what we had */
+ if (retval = krb5_copy_addresses(context, address,
+ &(*ppcreds)->addresses))
+ goto cleanup_keyblock;
+ }
+
+ if (retval = encode_krb5_ticket(pkdcrep->ticket, &pdata))
+ goto cleanup_keyblock;
+
+ (*ppcreds)->ticket = *pdata;
+ return 0;
+
+cleanup_keyblock:
+ memset((*ppcreds)->keyblock.contents, 0, (*ppcreds)->keyblock.length);
+
+cleanup:
+ free (*ppcreds);
+ return retval;
+}
+
+/* XXX This is to move to krb5_send_tgs, RSN -- CAP 950411 */
+extern krb5_cksumtype krb5_kdc_req_sumtype;
+
+krb5_error_code INTERFACE
+krb5_get_cred_via_tkt (context, tkt, kdcoptions, address, in_cred, out_cred)
+ krb5_context context;
+ krb5_creds * tkt;
+ const krb5_flags kdcoptions;
+ krb5_address *const * address;
+ krb5_creds * in_cred;
+ krb5_creds ** out_cred;
+{
+ krb5_error_code retval;
+ krb5_principal tempprinc;
+ krb5_kdc_rep *dec_rep;
+ krb5_error *err_reply;
+ krb5_response tgsrep;
+
+ /* tkt->client must be equal to in_cred->client */
+ if (!krb5_principal_compare(context, tkt->client, in_cred->client))
+ return KRB5_PRINC_NOMATCH;
+
+ if (!tkt->ticket.length)
+ return KRB5_NO_TKT_SUPPLIED;
+
+ /* check if we have the right TGT */
+ /* tkt->server must be equal to */
+ /* krbtgt/realmof(cred->server)@realmof(tgt->server) */
+
+/*
+ if (retval = krb5_tgtname(context,
+ krb5_princ_realm(context, in_cred->server),
+ krb5_princ_realm(context, tkt->server), &tempprinc))
+ return(retval);
+
+ if (!krb5_principal_compare(context, tempprinc, tkt->server)) {
+ retval = KRB5_PRINC_NOMATCH;
+ goto error_5;
+ }
+*/
+
+ if (retval = krb5_send_tgs(context, kdcoptions, &in_cred->times, NULL,
+ krb5_kdc_req_sumtype, /* To be removed */
+ in_cred->server, address, in_cred->authdata,
+ 0, /* no padata */
+ 0, /* no second ticket */
+ tkt, &tgsrep))
+ goto error_5;
+
+ switch (tgsrep.message_type) {
+ case KRB5_TGS_REP:
+ break;
+ case KRB5_ERROR:
+ default:
+ if (krb5_is_krb_error(&tgsrep.response))
+ retval = decode_krb5_error(&tgsrep.response, &err_reply);
+ else
+ retval = KRB5KRB_AP_ERR_MSG_TYPE;
+
+ if (retval) /* neither proper reply nor error! */
+ goto error_4;
+
+#if 0
+ /* XXX need access to the actual assembled request...
+ need a change to send_tgs */
+ if ((err_reply->ctime != request.ctime) ||
+ !krb5_principal_compare(context, err_reply->server, request.server) ||
+ !krb5_principal_compare(context, err_reply->client, request.client))
+ retval = KRB5_KDCREP_MODIFIED;
+ else
+#endif
+ retval = err_reply->error + ERROR_TABLE_BASE_krb5;
+
+ krb5_free_error(context, err_reply);
+ goto error_4;
+ }
+
+ if (retval = krb5_decode_kdc_rep(context, &tgsrep.response, &tkt->keyblock,
+ tkt->keyblock.etype, &dec_rep))
+ goto error_4;
+
+ if (dec_rep->msg_type != KRB5_TGS_REP) {
+ retval = KRB5KRB_AP_ERR_MSG_TYPE;
+ goto error_3;
+ }
+
+ /* now it's decrypted and ready for prime time */
+ if (!krb5_principal_compare(context, dec_rep->client, tkt->client)) {
+ retval = KRB5_KDCREP_MODIFIED;
+ goto error_3;
+ }
+
+ retval = krb5_kdcrep2creds(context, dec_rep, address, out_cred);
+
+
+#if 0
+ /* XXX probably need access to the request */
+ /* check the contents for sanity: */
+ if (!krb5_principal_compare(context, dec_rep->client, request.client)
+ || !krb5_principal_compare(context, dec_rep->enc_part2->server, request.server)
+ || !krb5_principal_compare(context, dec_rep->ticket->server, request.server)
+ || (request.nonce != dec_rep->enc_part2->nonce)
+ /* XXX check for extraneous flags */
+ /* XXX || (!krb5_addresses_compare(context, addrs, dec_rep->enc_part2->caddrs)) */
+ || ((request.from != 0) &&
+ (request.from != dec_rep->enc_part2->times.starttime))
+ || ((request.till != 0) &&
+ (dec_rep->enc_part2->times.endtime > request.till))
+ || ((request.kdc_options & KDC_OPT_RENEWABLE) &&
+ (request.rtime != 0) &&
+ (dec_rep->enc_part2->times.renew_till > request.rtime))
+ || ((request.kdc_options & KDC_OPT_RENEWABLE_OK) &&
+ (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
+ (request.till != 0) &&
+ (dec_rep->enc_part2->times.renew_till > request.till))
+ )
+ retval = KRB5_KDCREP_MODIFIED;
+
+ if (!request.from && !in_clock_skew(dec_rep->enc_part2->times.starttime)) {
+ retval = KRB5_KDCREP_SKEW;
+ goto error_1;
+ }
+
+#endif
+
+error_1:;
+ if (retval)
+
+error_3:;
+ memset(dec_rep->enc_part2->session->contents, 0,
+ dec_rep->enc_part2->session->length);
+ krb5_free_kdc_rep(context, dec_rep);
+
+error_4:;
+ free(tgsrep.response.data);
+
+error_5:;
+ krb5_free_principal(context, tempprinc);
+ return retval;
+}
-/*
- * lib/krb5/krb/mk_cred.c
+/*
+ * NAME
+ * cred.c
+ *
+ * DESCRIPTION
+ * Provide an interface to assemble and disassemble krb5_cred
+ * structures.
*
- * Copyright 1994 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
+ * MODIFIED
+ * $Log$
+ * Revision 5.8 1995/04/26 03:03:11 proven
+ * * 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.
+ *
+ * Revision 1.3 1995/01/26 00:09:24 asriniva
+ * Completely rewrote API to credential passing code.
+ *
+ * Revision 1.2 1994/12/30 21:57:17 asriniva
+ * Killed compile time warnings/errors.
+ * Fixed runtime bugs.
+ * Require a ticket when calling krb5_initcred.
+ * Cleaned up krb5_addticket.
+ *
+ * Revision 1.1 1994/12/29 17:03:30 asriniva
+ * Initial revision
*
- * 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_mk_cred()
*/
+#include <k5-int.h>
+#include "auth_con.h"
+#include <stddef.h> /* NULL */
+#include <stdlib.h> /* malloc */
+#include <errno.h> /* ENOMEM */
-/* 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 "k5-int.h"
+/*-------------------- encrypt_credencpart --------------------*/
-/* Create asn.1 encoded KRB-CRED message from the kdc reply. */
-krb5_error_code
-krb5_mk_cred(context, dec_rep, etype, key, sender_addr, recv_addr, outbuf)
- krb5_context context;
- krb5_kdc_rep *dec_rep;
- krb5_enctype etype;
- krb5_keyblock *key;
- krb5_address *sender_addr;
- krb5_address *recv_addr;
- krb5_data *outbuf;
+/*
+ * encrypt the enc_part of krb5_cred
+ */
+static krb5_error_code
+encrypt_credencpart(context, pcredpart, pkeyblock, pencdata)
+ krb5_context context;
+ krb5_cred_enc_part * pcredpart;
+ krb5_keyblock * pkeyblock;
+ krb5_enc_data * pencdata;
{
- krb5_error_code retval;
- krb5_encrypt_block eblock;
- krb5_cred ret_cred;
- krb5_cred_enc_part cred_enc_part;
- krb5_data *scratch;
-
- if (!valid_etype(etype))
- return KRB5_PROG_ETYPE_NOSUPP;
-
- ret_cred.tickets = (krb5_ticket **) calloc(2, sizeof(*ret_cred.tickets));
- if (!ret_cred.tickets)
- return ENOMEM;
- ret_cred.tickets[0] = dec_rep->ticket;
- ret_cred.tickets[1] = 0;
-
- ret_cred.enc_part.etype = etype;
- ret_cred.enc_part.kvno = 0;
-
- cred_enc_part.ticket_info = (krb5_cred_info **)
- calloc(2, sizeof(*cred_enc_part.ticket_info));
- if (!cred_enc_part.ticket_info) {
- krb5_free_tickets(context, ret_cred.tickets);
- return ENOMEM;
+ krb5_error_code retval;
+ krb5_encrypt_block eblock;
+ krb5_data * scratch;
+
+ if (!valid_etype(pkeyblock->etype))
+ return KRB5_PROG_ETYPE_NOSUPP;
+
+ /* start by encoding to-be-encrypted part of the message */
+ if (retval = encode_krb5_enc_cred_part(pcredpart, &scratch))
+ return retval;
+
+ /* put together an eblock for this encryption */
+
+ pencdata->kvno = 0;
+ pencdata->etype = pkeyblock->etype;
+
+ krb5_use_cstype(context, &eblock, pkeyblock->etype);
+ pencdata->ciphertext.length = krb5_encrypt_size(scratch->length,
+ eblock.crypto_entry);
+
+ /* add padding area, and zero it */
+ if (!(scratch->data = (char *)realloc(scratch->data,
+ pencdata->ciphertext.length))) {
+ /* may destroy scratch->data */
+ krb5_xfree(scratch);
+ return ENOMEM;
}
- cred_enc_part.ticket_info[0] = (krb5_cred_info *)
- malloc(sizeof(*cred_enc_part.ticket_info[0]));
- if (!cred_enc_part.ticket_info[0]) {
- krb5_free_tickets(context, ret_cred.tickets);
- krb5_free_cred_enc_part(context, &cred_enc_part);
- return ENOMEM;
+
+ memset(scratch->data + scratch->length, 0,
+ pencdata->ciphertext.length - scratch->length);
+ if (!(pencdata->ciphertext.data =
+ (char *)malloc(pencdata->ciphertext.length))) {
+ retval = ENOMEM;
+ goto clean_scratch;
}
- cred_enc_part.nonce = 0;
- if (retval = krb5_us_timeofday(context, &cred_enc_part.timestamp,
- &cred_enc_part.usec))
- return retval;
+ /* do any necessary key pre-processing */
+ if (retval = krb5_process_key(context, &eblock, pkeyblock)) {
+ goto clean_encpart;
+ }
- cred_enc_part.s_address = (krb5_address *)sender_addr;
- cred_enc_part.r_address = (krb5_address *)recv_addr;
+ /* call the encryption routine */
+ if (retval = krb5_encrypt(context, (krb5_pointer)scratch->data,
+ (krb5_pointer)pencdata->ciphertext.data,
+ scratch->length, &eblock, 0)) {
+ krb5_finish_key(context, &eblock);
+ goto clean_encpart;
+ }
+
+ retval = krb5_finish_key(context, &eblock);
- cred_enc_part.ticket_info[0]->session = dec_rep->enc_part2->session;
- cred_enc_part.ticket_info[0]->client = dec_rep->client;
- cred_enc_part.ticket_info[0]->server = dec_rep->enc_part2->server;
- cred_enc_part.ticket_info[0]->flags = dec_rep->enc_part2->flags;
- cred_enc_part.ticket_info[0]->times = dec_rep->enc_part2->times;
- cred_enc_part.ticket_info[0]->caddrs = dec_rep->enc_part2->caddrs;
+clean_encpart:
+ if (retval) {
+ memset(pencdata->ciphertext.data, 0, pencdata->ciphertext.length);
+ free(pencdata->ciphertext.data);
+ pencdata->ciphertext.length = 0;
+ pencdata->ciphertext.data = 0;
+ }
- cred_enc_part.ticket_info[1] = 0;
+clean_scratch:
+ memset(scratch->data, 0, scratch->length);
+ krb5_free_data(context, scratch);
- /* start by encoding to-be-encrypted part of the message */
+ return retval;
+}
- if (retval = encode_krb5_enc_cred_part(&cred_enc_part, &scratch))
- return retval;
+/*----------------------- krb5_mk_ncred_basic -----------------------*/
-#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); krb5_free_data(context, scratch); }
+static krb5_error_code
+krb5_mk_ncred_basic(context, ppcreds, nppcreds, keyblock,
+ replaydata, local_addr, remote_addr, pcred)
+ krb5_context context;
+ krb5_creds ** ppcreds;
+ krb5_int32 nppcreds;
+ krb5_keyblock * keyblock;
+ krb5_replay_data * replaydata;
+ krb5_address * local_addr;
+ krb5_address * remote_addr;
+ krb5_cred * pcred;
+{
+ krb5_cred_enc_part credenc;
+ krb5_error_code retval;
+ char * tmp;
+ int i;
- /* put together an eblock for this encryption */
+ credenc.magic = KV5M_CRED_ENC_PART;
- krb5_use_cstype(context, &eblock, etype);
- ret_cred.enc_part.ciphertext.length = krb5_encrypt_size(scratch->length,
- eblock.crypto_entry);
- /* add padding area, and zero it */
- if (!(scratch->data = realloc(scratch->data,
- ret_cred.enc_part.ciphertext.length))) {
- /* may destroy scratch->data */
- krb5_xfree(scratch);
- return ENOMEM;
+ credenc.s_address = local_addr;
+ credenc.r_address = remote_addr;
+ credenc.nonce = replaydata->seq;
+ credenc.usec = replaydata->usec;
+ credenc.timestamp = replaydata->timestamp;
+
+ /* Get memory for creds and initialize it */
+ if ((credenc.ticket_info = (krb5_cred_info **)
+ malloc(sizeof(krb5_cred_info *) * (nppcreds + 1))) == NULL) {
+ return ENOMEM;
}
- memset(scratch->data + scratch->length, 0,
- ret_cred.enc_part.ciphertext.length - scratch->length);
- if (!(ret_cred.enc_part.ciphertext.data =
- malloc(ret_cred.enc_part.ciphertext.length))) {
- retval = ENOMEM;
- goto clean_scratch;
+ if ((tmp = (char *)malloc(sizeof(krb5_cred_info) * nppcreds)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup_info;
}
+ memset(tmp, 0, sizeof(krb5_cred_info) * nppcreds);
-#define cleanup_encpart() {\
- (void) memset(ret_cred.enc_part.ciphertext.data, 0, \
- ret_cred.enc_part.ciphertext.length); \
- free(ret_cred.enc_part.ciphertext.data); \
- ret_cred.enc_part.ciphertext.length = 0; \
- ret_cred.enc_part.ciphertext.data = 0;}
+ /*
+ * For each credential in the list, initialize a cred info
+ * structure and copy the ticket into the ticket list.
+ */
+ for (i = 0; i < nppcreds; i++) {
+ credenc.ticket_info[i] = (krb5_cred_info *)tmp + i;
- /* do any necessary key pre-processing */
- if (retval = krb5_process_key(context, &eblock, key)) {
- goto clean_encpart;
+ credenc.ticket_info[i]->magic = KV5M_CRED_INFO;
+ credenc.ticket_info[i]->times = ppcreds[i]->times;
+ credenc.ticket_info[i]->flags = ppcreds[i]->ticket_flags;
+
+ if (retval = decode_krb5_ticket(&ppcreds[i]->ticket,
+ &pcred->tickets[i]))
+ goto cleanup_info_ptrs;
+
+ if (retval = krb5_copy_keyblock(context, &ppcreds[i]->keyblock,
+ &credenc.ticket_info[i]->session))
+ goto cleanup_info_ptrs;
+
+ if (retval = krb5_copy_principal(context, ppcreds[i]->client,
+ &credenc.ticket_info[i]->client))
+ goto cleanup_info_ptrs;
+
+ if (retval = krb5_copy_principal(context, ppcreds[i]->server,
+ &credenc.ticket_info[i]->server))
+ goto cleanup_info_ptrs;
+
+ if (retval = krb5_copy_addresses(context, ppcreds[i]->addresses,
+ &credenc.ticket_info[i]->caddrs))
+ goto cleanup_info_ptrs;
}
-#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);}
+ /*
+ * NULL terminate the lists.
+ */
+ credenc.ticket_info[i] = NULL;
+ pcred->tickets[i] = NULL;
- /* call the encryption routine */
- if (retval = krb5_encrypt(context, (krb5_pointer) scratch->data,
- (krb5_pointer)
- ret_cred.enc_part.ciphertext.data,
- scratch->length, &eblock,
- 0)) {
- goto clean_prockey;
+ retval = encrypt_credencpart(context, &credenc, keyblock, &pcred->enc_part);
+
+cleanup_info_ptrs:
+ free(tmp);
+
+cleanup_info:
+ free(credenc.ticket_info);
+ return retval;
+}
+
+/*----------------------- krb5_mk_ncred -----------------------*/
+
+/*
+ * This functions takes as input an array of krb5_credentials, and
+ * outputs an encoded KRB_CRED message suitable for krb5_rd_cred
+ */
+krb5_error_code INTERFACE
+krb5_mk_ncred(context, auth_context, ppcreds, ppdata, outdata)
+
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_creds ** ppcreds;
+ krb5_data ** ppdata;
+ krb5_replay_data * outdata;
+{
+ krb5_error_code retval;
+ krb5_keyblock * keyblock;
+ krb5_replay_data replaydata;
+ krb5_cred * pcred;
+ int ncred;
+
+ if (ppcreds == NULL) {
+ return KRB5KRB_AP_ERR_BADADDR;
}
-
- /* private message is now assembled-- do some cleanup */
- cleanup_scratch();
- if (retval = krb5_finish_key(context, &eblock)) {
- cleanup_encpart();
- return retval;
+ /*
+ * Allocate memory for a NULL terminated list of tickets.
+ */
+ for (ncred = 0; ppcreds[ncred]; ncred++);
+
+ if ((pcred = (krb5_cred *)malloc(sizeof(krb5_cred))) == NULL)
+ return ENOMEM;
+
+ if ((pcred->tickets
+ = (krb5_ticket **)malloc(sizeof(krb5_ticket *) * (ncred + 1))) == NULL) {
+ retval = ENOMEM;
+ free(pcred);
}
- /* encode private message */
- if (retval = encode_krb5_cred(&ret_cred, &scratch)) {
- cleanup_encpart();
- return retval;
+
+ /* Get keyblock */
+ if ((keyblock = auth_context->local_subkey) == NULL)
+ if ((keyblock = auth_context->remote_subkey) == NULL)
+ keyblock = auth_context->keyblock;
+
+ /* Get replay info */
+ 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_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;
+ }
+ }
+
+ /* Setup creds structure */
+ if (retval = krb5_mk_ncred_basic(context, ppcreds, ncred, keyblock,
+ &replaydata, auth_context->local_addr,
+ auth_context->remote_addr, pcred))
+ goto cleanup_tickets;
+
+ 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,
+ "_forw", &replay.client))
+ goto cleanup_tickets;
+
+ replay.server = ""; /* XXX */
+ 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 */
+ krb5_xfree(replay.client);
+ goto cleanup_tickets;
+ }
+ krb5_xfree(replay.client);
+ }
+
+ /* Encode creds structure */
+ retval = encode_krb5_cred(pcred, ppdata);
+
+cleanup_tickets:
+ if (retval) {
+ 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--;
+ free(pcred->tickets);
+ free(pcred);
}
+ return retval;
+}
- cleanup_encpart();
+/*----------------------- krb5_mk_1cred -----------------------*/
+
+/*
+ * A convenience function that calls krb5_mk_ncred.
+ */
+krb5_error_code INTERFACE
+krb5_mk_1cred(context, auth_context, pcreds, ppdata, outdata)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_creds * pcreds;
+ krb5_data ** ppdata;
+ krb5_replay_data * outdata;
+{
+ krb5_error_code retval;
+ krb5_creds **ppcreds;
- *outbuf = *scratch;
- krb5_xfree(scratch);
- return 0;
+ if ((ppcreds = (krb5_creds **)malloc(sizeof(*ppcreds) * 2)) == NULL) {
+ return ENOMEM;
+ }
- clean_prockey:
- cleanup_prockey();
- clean_encpart:
- cleanup_encpart();
- clean_scratch:
- cleanup_scratch();
+ ppcreds[0] = pcreds;
+ ppcreds[1] = NULL;
+ if (retval = krb5_mk_ncred(context, auth_context, ppcreds, ppdata, outdata))
+ free(ppcreds);
return retval;
-#undef cleanup_prockey
-#undef cleanup_encpart
-#undef cleanup_scratch
}
krb5_error_code
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_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;
+ 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;
+
+ /* Get replay info */
if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
(auth_context->rcache == NULL))
return KRB5_RC_REQUIRED;
}
}
- 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))
+ if (retval = krb5_mk_priv_basic(context, userdata, keyblock, &replaydata,
+ auth_context->local_addr,
+ auth_context->remote_addr,
+ auth_context->i_vector, outbuf))
goto error;
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
replay.ctime = replaydata.timestamp;
if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) {
/* should we really error out here? XXX */
- krb5_xfree(outbuf);
+ krb5_xfree(replay.client);
goto error;
}
krb5_xfree(replay.client);
krb5_error_code
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_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;
+ 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;
+ /* Get replay info */
if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
(auth_context->rcache == NULL))
return KRB5_RC_REQUIRED;
}
}
- if (retval = krb5_mk_safe_basic(context, userdata, auth_context->keyblock,
- &replaydata, auth_context->local_addr, auth_context->remote_addr,
- auth_context->cksumtype, outbuf))
+ if (retval = krb5_mk_safe_basic(context, userdata, 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) {
-/*
- * 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;
}
+
if (retval = krb5_os_localaddr(&our_addrs)) {
goto cleanup_data;
}
- if (!krb5_address_search(context, privmsg_enc_part->r_address, our_addrs)) {
+ if (!krb5_address_search(context, privmsg_enc_part->r_address,
+ our_addrs)) {
krb5_free_addresses(context, our_addrs);
retval = KRB5KRB_AP_ERR_BADADDR;
goto cleanup_data;
krb5_error_code
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_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;
+ 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)) &&
(auth_context->rcache == NULL))
return KRB5_RC_REQUIRED;
- if (retval = krb5_rd_priv_basic(context, inbuf, auth_context->keyblock,
+ if (retval = krb5_rd_priv_basic(context, inbuf, keyblock,
auth_context->local_addr, auth_context->remote_addr,
auth_context->i_vector, &replaydata, outbuf))
return retval;
krb5_error_code
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_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;
+ krb5_error_code retval;
+ krb5_keyblock * keyblock;
+ 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)) &&
(auth_context->rcache == NULL))
return KRB5_RC_REQUIRED;
- if (retval = krb5_rd_safe_basic(context, inbuf, auth_context->keyblock,
+ /* Get keyblock */
+ if ((keyblock = auth_context->local_subkey) == NULL)
+ if ((keyblock = auth_context->remote_subkey) == NULL)
+ keyblock = auth_context->keyblock;
+
+ if (retval = krb5_rd_safe_basic(context, inbuf, keyblock,
auth_context->local_addr, auth_context->remote_addr,
&replaydata, outbuf))
return retval;
krb5_keytab keytab;
krb5_ticket ** ticket;
{
+ krb5_auth_context * new_auth_context;
krb5_flags ap_option;
krb5_error_code retval, problem;
krb5_data inbuf;
}
if (problem)
return(problem);
- /*
- * Setup the replay cache.
- */
- if (server) {
- problem = krb5_get_server_rcache(context,
+
+/* Were clear here */
+ /*
+ * Setup the replay cache.
+ */
+ if (server) {
+ problem = krb5_get_server_rcache(context,
krb5_princ_component(context, server, 0), &rcache);
- } else {
- null_server.length = 7;
- null_server.data = "default";
- problem = krb5_get_server_rcache(context, &null_server, &rcache);
- }
+ } else {
+ null_server.length = 7;
+ 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.
*/
- if (krb5_rc_initialize(context, rcache, krb5_clockskew)) {
+ if (problem = 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);
- return(retval);
- }
+ /*
+ * Now, let's read the AP_REQ message and decode it
+ */
+ if (retval = krb5_read_message(context, fd, &inbuf)) {
+ if (problem) /* Return top level problem */
+ retval = problem;
+ goto cleanup;
+ }
- if (*auth_context == NULL) {
- if (retval = krb5_auth_con_init(context, auth_context))
- return(retval);
+ if (!problem) {
+ if (*auth_context == NULL) {
+ problem = krb5_auth_con_init(context, &new_auth_context);
+ *auth_context = new_auth_context;
}
-
- krb5_auth_con_setrcache(context, *auth_context, rcache);
-
- if (!problem)
- problem = krb5_rd_req(context, auth_context, &inbuf, server,
+ }
+ if (!problem) {
+ problem = krb5_auth_con_setrcache(context, *auth_context, rcache);
+ }
+ if (!problem) {
+ 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 there was a problem, send back a krb5_error message,
- * preceeded by the length of the krb5_error message. If
- * everything's ok, send back 0 for the length.
- */
- if (problem) {
- krb5_error error;
- const char *message;
+ /*
+ * If there was a problem, send back a krb5_error message,
+ * preceeded by the length of the krb5_error message. If
+ * everything's ok, send back 0 for the length.
+ */
+ if (problem) {
+ krb5_error error;
+ const char *message;
- memset((char *)&error, 0, sizeof(error));
- krb5_us_timeofday(context, &error.stime, &error.susec);
- error.server = server;
- error.error = problem - ERROR_TABLE_BASE_krb5;
- if (error.error > 127)
- error.error = KRB_ERR_GENERIC;
- message = error_message(problem);
- error.text.length = strlen(message) + 1;
- if (!(error.text.data = malloc(error.text.length)))
- return(ENOMEM);
- strcpy(error.text.data, message);
- if (retval = krb5_mk_error(context, &error, &outbuf)) {
- free(error.text.data);
- return(retval);
- }
- free(error.text.data);
- } else {
- outbuf.length = 0;
- outbuf.data = 0;
+ memset((char *)&error, 0, sizeof(error));
+ krb5_us_timeofday(context, &error.stime, &error.susec);
+ error.server = server;
+ error.error = problem - ERROR_TABLE_BASE_krb5;
+ if (error.error > 127)
+ error.error = KRB_ERR_GENERIC;
+ message = error_message(problem);
+ error.text.length = strlen(message) + 1;
+ if (!(error.text.data = malloc(error.text.length))) {
+ retval = ENOMEM;
+ goto cleanup;
}
- if (retval = krb5_write_message(context, fd, &outbuf)) {
- if (outbuf.data)
- krb5_xfree(outbuf.data);
- return(retval);
- }
- if (problem) {
- /*
- * We sent back an error, we need to return
- */
- return(problem);
+ strcpy(error.text.data, message);
+ if (retval = krb5_mk_error(context, &error, &outbuf)) {
+ free(error.text.data);
+ goto cleanup;
}
+ free(error.text.data);
+ } else {
+ outbuf.length = 0;
+ outbuf.data = 0;
+ }
+
+ if (!problem) {
+ retval = krb5_write_message(context, fd, &outbuf);
+ if (outbuf.data)
+ krb5_xfree(outbuf.data);
+ if (retval)
+ goto cleanup;
+ } else {
+ /* We sent back an error, we need cleanup then return */
+ retval = problem;
+ goto cleanup;
+ }
/* Here lies the mutual authentication stuff... */
if ((ap_option & AP_OPTS_MUTUAL_REQUIRED)) {
retval = krb5_write_message(context, fd, &outbuf);
krb5_xfree(outbuf.data);
}
+
+cleanup:;
+ if (retval) {
+ if (rcache)
+ krb5_rc_close(context, rcache);
+ }
return retval;
}