From 2e33b77deb78102d4182ca6024714f683e1f9fc7 Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Wed, 15 Dec 1993 18:11:18 +0000 Subject: [PATCH] Added function which does V4/V5 compatibility for sendauth/recvauth git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@3181 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/krb/Imakefile | 2 + src/lib/krb5/krb/compat_recv.c | 323 +++++++++++++++++++++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 src/lib/krb5/krb/compat_recv.c diff --git a/src/lib/krb5/krb/Imakefile b/src/lib/krb5/krb/Imakefile index 839791657..c649daa01 100644 --- a/src/lib/krb5/krb/Imakefile +++ b/src/lib/krb5/krb/Imakefile @@ -29,6 +29,7 @@ OBJS= addr_comp.o \ addr_srch.o \ bld_pr_ext.o \ bld_princ.o \ + compat_recv.o \ conv_princ.o \ copy_addrs.o \ copy_auth.o \ @@ -87,6 +88,7 @@ SRCS= $(SRCDIR)addr_comp.c \ $(SRCDIR)addr_srch.c \ $(SRCDIR)bld_pr_ext.c \ $(SRCDIR)bld_princ.c \ + $(SRCDIR)compat_recv.c \ $(SRCDIR)conv_princ.c \ $(SRCDIR)copy_addrs.c \ $(SRCDIR)copy_auth.c \ diff --git a/src/lib/krb5/krb/compat_recv.c b/src/lib/krb5/krb/compat_recv.c new file mode 100644 index 000000000..a6c6bc8cf --- /dev/null +++ b/src/lib/krb5/krb/compat_recv.c @@ -0,0 +1,323 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1993 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. + * + * + * convenience sendauth/recvauth functions, with compatibility with V4 + * recvauth. + * + * NOTE: linking in this function will pull in V4 kerberos routines. + * + * WARNING: In the V4-style arguments, the ticket and kdata arguments + * have different types than the V4 recvauth; in V4, they were KTEXT + * and AUTH_DAT *, respectively. Here, they are KTEXT * and AUTH_DAT ** + * and they are allocated by recvauth if and only if we end up talking + * to a V4 sendauth. + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_recvauth_c [] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static int krb_v4_recvauth(); + +#define KRB_V4_SENDAUTH_VERS "AUTHV0.1" /* MUST be 8 chars long */ +#define KRB_V5_SENDAUTH_VERS "KRB5_SENDAUTH_V1.0" + +#define KRB5_RECVAUTH_V4 4 +#define KRB5_RECVAUTH_V5 5 + +krb5_error_code +krb5_compat_recvauth(/* IN */ + fdp, appl_version, server, sender_addr, fetch_from, + keyproc, keyprocarg, rc_type, flags, + 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) + 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; + /* + * Version 4 arguments + */ + krb5_int32 v4_options; /* bit-pattern of options */ + char *v4_service; /* service expected */ + char *v4_instance; /* inst expected (may be filled in) */ + struct sockaddr_in *v4_faddr; /* foreign address */ + struct sockaddr_in *v4_laddr; /* local address */ + AUTH_DAT **v4_kdata; /* kerberos data (returned) */ + char *v4_filename; /* name of file with service keys */ + Key_schedule v4_schedule; /* key schedule (return) */ + char *v4_version; /* version string (filled in) */ +{ + union verslen { + krb5_int32 len; + char vers[4]; + } vers; + char *buf; + int len, length; + krb5_int32 retval; + int fd = *( (int *) fdp); + KTEXT v4_ticket; /* storage for client's ticket */ + + if ((retval = krb5_net_read(fd, vers.vers, 4)) != 4) + return((retval < 0) ? errno : ECONNABORTED); + + if (!strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) { + /* + * We must be talking to a V4 sendauth; read in the + * rest of the version string and make sure. + */ + if ((retval = krb5_net_read(fd, vers.vers, 4)) != 4) + return((retval < 0) ? errno : ECONNABORTED); + + if (strncmp(vers.vers, KRB_V4_SENDAUTH_VERS+4, 4)) + return KRB5_SENDAUTH_BADAUTHVERS; + + *auth_sys = KRB5_RECVAUTH_V4; + + *v4_kdata = (AUTH_DAT *) malloc( sizeof(AUTH_DAT) ); + v4_ticket = (KTEXT) malloc(sizeof(KTEXT_ST)); + + retval = krb_v4_recvauth(v4_options, fd, v4_ticket, + v4_service, v4_instance, v4_faddr, + v4_laddr, *v4_kdata, v4_filename, + v4_schedule, v4_version); + krb5_xfree(v4_ticket); + /* + * XXX error code translation? + */ + switch (retval) { + case RD_AP_OK: + return 0; + case RD_AP_TIME: + return KRB5KRB_AP_ERR_SKEW; + case RD_AP_EXP: + return KRB5KRB_AP_ERR_TKT_EXPIRED; + case RD_AP_NYV: + return KRB5KRB_AP_ERR_TKT_NYV; + case RD_AP_NOT_US: + return KRB5KRB_AP_ERR_NOT_US; + case RD_AP_UNDEC: + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + case RD_AP_REPEAT: + return KRB5KRB_AP_ERR_REPEAT; + case RD_AP_MSG_TYPE: + return KRB5KRB_AP_ERR_MSG_TYPE; + case RD_AP_MODIFIED: + return KRB5KRB_AP_ERR_MODIFIED; + case RD_AP_ORDER: + return KRB5KRB_AP_ERR_BADORDER; + case RD_AP_BADD: + return KRB5KRB_AP_ERR_BADADDR; + default: + return KRB5_SENDAUTH_BADRESPONSE; + } + } + + /* + * Assume that we're talking to a V5 recvauth; read in the + * the version string, and make sure it matches. + */ + + len = ntohl(vers.len); + + if (len < 0 || len > 255) + return KRB5_SENDAUTH_BADAUTHVERS; + + buf = malloc(len); + if (!buf) + return ENOMEM; + + length = krb5_net_read(fd, buf, len); + if (len != length) { + krb5_xfree(buf); + if (len < 0) + return errno; + else + return ECONNABORTED; + } + + if (strcmp(buf, KRB_V5_SENDAUTH_VERS)) { + krb5_xfree(buf); + return KRB5_SENDAUTH_BADAUTHVERS; + } + krb5_xfree(buf); + + *auth_sys = KRB5_RECVAUTH_V5; + + retval = krb5_recvauth(fdp, appl_version, server, sender_addr, + fetch_from, + keyproc, keyprocarg, rc_type, + flags | KRB5_RECVAUTH_SKIP_VERSION, + seq_number, client, ticket, authent); + + return retval; +} + + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif /* max */ + +static int +krb_v4_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata, + filename, schedule, version) +long options; /* bit-pattern of options */ +int fd; /* file descr. to read from */ +KTEXT ticket; /* storage for client's ticket */ +char *service; /* service expected */ +char *instance; /* inst expected (may be filled in) */ +struct sockaddr_in *faddr; /* address of foreign host on fd */ +struct sockaddr_in *laddr; /* local address */ +AUTH_DAT *kdata; /* kerberos data (returned) */ +char *filename; /* name of file with service keys */ +Key_schedule schedule; /* key schedule (return) */ +char *version; /* version string (filled in) */ +{ + int i, cc, old_vers = 0; + char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */ + char *cp; + int rem; + long tkt_len, priv_len; + u_long cksum; + u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)]; + + /* read the application version string */ + if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) != + KRB_SENDAUTH_VLEN) + return(errno); + version[KRB_SENDAUTH_VLEN] = '\0'; + + /* get the length of the ticket */ + if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) != + sizeof(tkt_len)) + return(errno); + + /* sanity check */ + ticket->length = ntohl((unsigned long)tkt_len); + if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) { + if (options & KOPT_DO_MUTUAL) { + rem = KFAILURE; + goto mutual_fail; + } else + return(KFAILURE); /* XXX there may still be junk on the fd? */ + } + + /* read the ticket */ + if (krb_net_read(fd, (char *) ticket->dat, ticket->length) + != ticket->length) + return(errno); + + /* + * now have the ticket. decrypt it to get the authenticated + * data. + */ + rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr, + kdata,filename); + + if (old_vers) return(rem); /* XXX can't do mutual with old client */ + + /* if we are doing mutual auth, compose a response */ + if (options & KOPT_DO_MUTUAL) { + if (rem != KSUCCESS) + /* the krb_rd_req failed */ + goto mutual_fail; + + /* add one to the (formerly) sealed checksum, and re-seal it + for return to the client */ + cksum = kdata->checksum + 1; + cksum = htonl(cksum); +#ifndef NOENCRYPTION + key_sched(kdata->session,schedule); +#endif /* !NOENCRYPTION */ + priv_len = krb_mk_priv((unsigned char *)&cksum, + tmp_buf, + (unsigned long) sizeof(cksum), + schedule, + kdata->session, + laddr, + faddr); + if (priv_len < 0) { + /* re-sealing failed; notify the client */ + rem = KFAILURE; /* XXX */ +mutual_fail: + priv_len = -1; + tkt_len = htonl((unsigned long) priv_len); + /* a length of -1 is interpreted as an authentication + failure by the client */ + if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len))) + != sizeof(tkt_len)) + return(cc); + return(rem); + } else { + /* re-sealing succeeded, send the private message */ + tkt_len = htonl((unsigned long)priv_len); + if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len))) + != sizeof(tkt_len)) + return(cc); + if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len)) + != (int) priv_len) + return(cc); + } + } + return(rem); +} + + + + + + + + + + -- 2.26.2