diff options
author | Ezra Peisach <epeisach@mit.edu> | 1995-12-06 02:02:51 +0000 |
---|---|---|
committer | Ezra Peisach <epeisach@mit.edu> | 1995-12-06 02:02:51 +0000 |
commit | dd2c9915ba7c893516e0d6f455c1009dd1b5649c (patch) | |
tree | 9f751c4fa5308e239165d5ad370d5448697c9708 /src/lib/krb5util/compat_recv.c | |
parent | 83e31fdeb3171b2e19552339c81e71e257afb062 (diff) | |
download | krb5-dd2c9915ba7c893516e0d6f455c1009dd1b5649c.tar.gz krb5-dd2c9915ba7c893516e0d6f455c1009dd1b5649c.tar.xz krb5-dd2c9915ba7c893516e0d6f455c1009dd1b5649c.zip |
Move compat_recvauth to this library so that krb4 can depend on krb5
(for configurable paths support).
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7177 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/krb5util/compat_recv.c')
-rw-r--r-- | src/lib/krb5util/compat_recv.c | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/src/lib/krb5util/compat_recv.c b/src/lib/krb5util/compat_recv.c new file mode 100644 index 000000000..46a4172a0 --- /dev/null +++ b/src/lib/krb5util/compat_recv.c @@ -0,0 +1,302 @@ +/* + * lib/krb5/krb/compat_recv.c + * + * 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. + */ + +#define NEED_SOCKETS +#include "k5-int.h" +#if !defined(_MSDOS) && !defined(_MACINTOSH) +#include <kerberosIV/krb.h> +#include <kerberosIV/krb4-proto.h> +#include "com_err.h" +#include <errno.h> + +#include <stdio.h> +#include <string.h> + +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(context, auth_context, + /* IN */ + fdp, appl_version, server, flags, keytab, + v4_options, v4_service, v4_instance, v4_faddr, v4_laddr, + v4_filename, + /* OUT */ + 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_int32 flags; + krb5_keytab keytab; + krb5_ticket ** ticket; + 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); +#ifdef KRB5_KRB4_COMPAT + KTEXT v4_ticket; /* storage for client's ticket */ +#endif + + if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4) + return((retval < 0) ? errno : ECONNABORTED); + +#ifdef KRB5_KRB4_COMPAT + 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(context, 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; + } + } +#endif + + /* + * Assume that we're talking to a V5 recvauth; read in the + * the version string, and make sure it matches. + */ + + len = (int) ntohl(vers.len); + + if (len < 0 || len > 255) + return KRB5_SENDAUTH_BADAUTHVERS; + + buf = malloc(len); + if (!buf) + return ENOMEM; + + length = krb5_net_read(context, 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(context, auth_context, fdp, appl_version, server, + flags | KRB5_RECVAUTH_SKIP_VERSION, + keytab, ticket); + + return retval; +} + + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif /* max */ + +#ifdef KRB5_KRB4_COMPAT +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 cc, old_vers = 0; + int rem; + krb5_int32 tkt_len, priv_len; + krb5_ui_4 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); +} +#endif +#endif |