diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/krb4/ChangeLog | 84 | ||||
-rw-r--r-- | src/lib/krb4/Makefile.in | 2 | ||||
-rw-r--r-- | src/lib/krb4/cr_auth_repl.c | 94 | ||||
-rw-r--r-- | src/lib/krb4/cr_ciph.c | 88 | ||||
-rw-r--r-- | src/lib/krb4/cr_death_pkt.c | 46 | ||||
-rw-r--r-- | src/lib/krb4/cr_err_repl.c | 76 | ||||
-rw-r--r-- | src/lib/krb4/cr_tkt.c | 122 | ||||
-rw-r--r-- | src/lib/krb4/decomp_tkt.c | 150 | ||||
-rw-r--r-- | src/lib/krb4/g_ad_tkt.c | 416 | ||||
-rw-r--r-- | src/lib/krb4/g_in_tkt.c | 337 | ||||
-rw-r--r-- | src/lib/krb4/mk_auth.c | 108 | ||||
-rw-r--r-- | src/lib/krb4/mk_err.c | 50 | ||||
-rw-r--r-- | src/lib/krb4/mk_preauth.c | 22 | ||||
-rw-r--r-- | src/lib/krb4/mk_priv.c | 93 | ||||
-rw-r--r-- | src/lib/krb4/mk_req.c | 186 | ||||
-rw-r--r-- | src/lib/krb4/mk_safe.c | 76 | ||||
-rw-r--r-- | src/lib/krb4/rd_err.c | 59 | ||||
-rw-r--r-- | src/lib/krb4/rd_preauth.c | 43 | ||||
-rw-r--r-- | src/lib/krb4/rd_priv.c | 110 | ||||
-rw-r--r-- | src/lib/krb4/rd_req.c | 255 | ||||
-rw-r--r-- | src/lib/krb4/rd_safe.c | 110 | ||||
-rw-r--r-- | src/lib/krb4/send_to_kdc.c | 1 | ||||
-rw-r--r-- | src/lib/krb4/strnlen.c | 48 |
23 files changed, 1555 insertions, 1021 deletions
diff --git a/src/lib/krb4/ChangeLog b/src/lib/krb4/ChangeLog index bcf59906da..d3b8f6ef5a 100644 --- a/src/lib/krb4/ChangeLog +++ b/src/lib/krb4/ChangeLog @@ -1,3 +1,87 @@ +2000-11-08 Tom Yu <tlyu@mit.edu> + + * Makefile.in (OBJS, SRCS): Add strnlen.o, strnlen.c. + + * cr_auth_repl.c: Audit. Fix up copyright. Use new KRB4_PUT* + macros for encoding so output is always big-endian. Precompute + string lengths for better length-checking. + + * cr_ciph.c: Audit. Fix up copyright. Use new KRB4_PUT* macros + for encoding so that output is always big-endian. Precompute + string lengths for better length-checking. Zero out the key + schedule after encrypting. + + * cr_death_pkt.c: Audit. Fix up copyright. Precompute string + lengths for better length-checking. + + * cr_err_repl.c: Audit. Fix up copyright. Use moving pointer to + do encoding. Precompute string lengths for better + length-checking. Use KRB4_PUT* macros so that output is always + big-endian. + + * cr_tkt.c: Audit. Fix up copyright. Use KRB4_PUT* macros for + encoding so that output is always big-endian. Zero out the key + schedule after encrypting. + + * decomp_tkt.c: Audit. Fix up copyright. Use krb_strnlen() for + actually detecting string length errors. Use a struct in_addr to + retrieve the IP address and assign it to paddress for return. Use + KRB4_GET* macros for decoding to avoid byteswapping problems. + Zero out session key and decrypted ticket on error. + + * g_ad_tkt.c: Audit. Fix up copyright. Break out parsing of + decrypted KDC reply packet into a separate function to simplify + error handling somewhat. Precompute string lengths for better + length-checking. Use KRB4_PUT* macros for encoding so that output + is always big-endian. Use KRB4_GET* macros for decoding to avoid + byteswapping problems. Stomp on session key on error conditions. + + * g_in_tkt.c: Audit. Fix up copyright. Precompute string lengths + for better length-checking. Use KRB4_PUT* macros for encoding so + output is always big-endian. Use KRB4_GET* macros for decoding to + avoid byteswapping problems. Use krb_strnlen() to actually detect + string length errors. Zero out session key and decrypted KDC + reply once they're no longer useful. + + * mk_auth.c: Audit. Fix up copyright. Use moving pointer for + encoding. Use KRB4_PUT* macros for encoding to avoid alignment + issues with using memcpy(). Use KRB4_GET* macros for decoding to + avoid alignment issues with using memcpy(). + + * mk_err.c: Audit. Fix up copyright. Precompute string length. + Use KRB4_PUT* macros to always encode as big-endian. + + * mk_preauth.c: Audit. Zero out key schedule after encryption. + + * mk_priv.c: Audit. Fix up copyright. Use KRB4_PUT* macros for + encoding so output is always big-endian. + + * mk_req.c: Audit. Fix up copyright. Use moving pointer for + encoding. Precompute string lengths for better length-checking. + Use KRB4_PUT* macros for encoding so output is always big-endian. + Zero out session key after encryption. + + * mk_safe.c: Audit. Fix up copyright. Use KRB4_PUT* macros for + encoding so output is always big-endian. + + * rd_err.c: Audit. Fix up copyright. Use KRB4_GET* macros to + avoid alignment issues. + + * rd_preauth.c: Audit. Zero key schedule after decrypting. + + * rd_priv.c: Audit. Fix up copyright. Use KRB4_GET* macros to + avoid alignment issues. + + * rd_req.c: Audit. Fix up copyright. + + * send_to_kdc.c (send_recv): Actually set rpkt->length, since some + callers actually use it now to do length-checking. + + * strnlen.c: New file; compute string length, bounded by a + maximum. If the maximum number of characters has been read + without encountering a NUL character, return -1. This makes + overflow checking of strings in buffers much easier. + 2000-11-01 Ezra Peisach <epeisach@mit.edu> * configure.in: Use AC_C_CONST and AC_CHECK_FUNCS instead of diff --git a/src/lib/krb4/Makefile.in b/src/lib/krb4/Makefile.in index 33206ad0b7..3afd33ced0 100644 --- a/src/lib/krb4/Makefile.in +++ b/src/lib/krb4/Makefile.in @@ -60,6 +60,7 @@ OBJS = \ $(OUTPRE)rd_safe.$(OBJEXT) \ $(OUTPRE)send_to_kdc.$(OBJEXT) \ $(OUTPRE)stime.$(OBJEXT) \ + $(OUTPRE)strnlen.$(OBJEXT) \ $(OUTPRE)rd_preauth.$(OBJEXT) \ $(OUTPRE)mk_preauth.$(OBJEXT) \ $(OSOBJS) $(CACHEOBJS) $(SETENVOBJS) $(STRCASEOBJS) $(SHMOBJS) \ @@ -96,6 +97,7 @@ SRCS = \ $(srcdir)/rd_safe.c \ $(srcdir)/send_to_kdc.c \ $(srcdir)/stime.c \ + $(srcdir)/strnlen.c \ $(srcdir)/rd_preauth.c \ $(srcdir)/mk_preauth.c \ $(srcdir)/unix_time.c \ diff --git a/src/lib/krb4/cr_auth_repl.c b/src/lib/krb4/cr_auth_repl.c index a0562d96f3..16482908ee 100644 --- a/src/lib/krb4/cr_auth_repl.c +++ b/src/lib/krb4/cr_auth_repl.c @@ -1,14 +1,29 @@ /* - * cr_auth_repl.c + * lib/krb4/cr_auth_repl.c * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "krb.h" #include "prot.h" #include <string.h> @@ -58,7 +73,7 @@ */ KTEXT -create_auth_reply(pname,pinst,prealm,time_ws,n,x_date,kvno,cipher) +create_auth_reply(pname, pinst, prealm, time_ws, n, x_date, kvno, cipher) char *pname; /* Principal's name */ char *pinst; /* Principal's instance */ char *prealm; /* Principal's authentication domain */ @@ -69,54 +84,53 @@ create_auth_reply(pname,pinst,prealm,time_ws,n,x_date,kvno,cipher) KTEXT cipher; /* Cipher text with tickets and * session keys */ { - static KTEXT_ST pkt_st; + static KTEXT_ST pkt_st; KTEXT pkt = &pkt_st; - unsigned char *v = pkt->dat; /* Prot vers number */ - unsigned char *t = (pkt->dat+1); /* Prot message type */ - short w_l; /* Cipher length */ + unsigned char *p; + size_t pnamelen, pinstlen, prealmlen; /* Create fixed part of packet */ - *v = (unsigned char) KRB_PROT_VERSION; - *t = (unsigned char) AUTH_MSG_KDC_REPLY; - *t |= HOST_BYTE_ORDER; - + p = pkt->dat; + /* This is really crusty. */ if (n != 0) - *v = 3; + *p++ = 3; + else + *p++ = KRB_PROT_VERSION; + *p++ = AUTH_MSG_KDC_REPLY; /* always big-endian */ /* Make sure the response will actually fit into its buffer. */ - if(sizeof(pkt->dat) < 3 + strlen(pname) + - 1 + strlen(pinst) + - 1 + strlen(prealm) + - 4 + 1 + 4 + - 1 + 2 + cipher->length) { + pnamelen = strlen(pname) + 1; + pinstlen = strlen(pinst) + 1; + prealmlen = strlen(prealm) + 1; + if (sizeof(pkt->dat) < (1 + 1 + pnamelen + pinstlen + prealmlen + + 4 + 1 + 4 + 1 + 2 + cipher->length) + || cipher->length > 65535 || cipher->length < 0) { pkt->length = 0; return NULL; } - /* Add the basic info */ - (void) strcpy((char *) (pkt->dat+2), pname); - pkt->length = 3 + strlen(pname); - (void) strcpy((char *) (pkt->dat+pkt->length),pinst); - pkt->length += 1 + strlen(pinst); - (void) strcpy((char *) (pkt->dat+pkt->length),prealm); - pkt->length += 1 + strlen(prealm); + memcpy(p, pname, pnamelen); + p += pnamelen; + memcpy(p, pinst, pinstlen); + p += pinstlen; + memcpy(p, prealm, prealmlen); + p += prealmlen; + /* Workstation timestamp */ - memcpy((char *) (pkt->dat+pkt->length), (char *) &time_ws, 4); - pkt->length += 4; - *(pkt->dat+(pkt->length)++) = (unsigned char) n; + KRB4_PUT32(p, time_ws); + + *p++ = n; + /* Expiration date */ - memcpy((char *) (pkt->dat+pkt->length), (char *) &x_date, 4); - pkt->length += 4; + KRB4_PUT32(p, x_date); /* Now send the ciphertext and info to help decode it */ - *(pkt->dat+(pkt->length)++) = (unsigned char) kvno; - w_l = (short) cipher->length; - memcpy((char *) (pkt->dat+pkt->length), (char *) &w_l, 2); - pkt->length += 2; - memcpy((char *) (pkt->dat+pkt->length), (char *) (cipher->dat), - cipher->length); - pkt->length += cipher->length; + *p++ = kvno; + KRB4_PUT16(p, cipher->length); + memcpy(p, cipher->dat, (size_t)cipher->length); + p += cipher->length; /* And return the packet */ + pkt->length = p - pkt->dat; return pkt; } diff --git a/src/lib/krb4/cr_ciph.c b/src/lib/krb4/cr_ciph.c index d9c751271f..a2bbdff5c4 100644 --- a/src/lib/krb4/cr_ciph.c +++ b/src/lib/krb4/cr_ciph.c @@ -1,14 +1,29 @@ /* - * cr_ciph.c + * lib/krb4/cr_ciph.c * - * Copyright 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "krb.h" #include "des.h" #include <string.h> @@ -53,6 +68,7 @@ * */ +int create_ciph(c, session, service, instance, realm, life, kvno, tkt, kdc_time, key) KTEXT c; /* Text block to hold ciphertext */ @@ -66,54 +82,54 @@ create_ciph(c, session, service, instance, realm, life, kvno, tkt, unsigned long kdc_time; /* KDC time */ C_Block key; /* Key to encrypt ciphertext with */ { - char *ptr; + unsigned char *ptr; + size_t servicelen, instancelen, realmlen; Key_schedule key_s; - ptr = (char *) c->dat; + ptr = c->dat; - if(sizeof(c->dat) / 8 < (8 + - strlen(service) + 1 + - strlen(instance) + 1 + - strlen(realm) + 1 + - 1 + 1 + 1 + - tkt->length + 4 + - 7) / 8) { + /* Validate lengths. */ + servicelen = strlen(service) + 1; + instancelen = strlen(instance) + 1; + realmlen = strlen(realm) + 1; + if (sizeof(c->dat) / 8 < ((8 + servicelen + instancelen + realmlen + + 1 + 1 + 1 + tkt->length + + 4 + 7) / 8) + || tkt->length > 255 || tkt->length < 0) { c->length = 0; - return(KFAILURE); + return KFAILURE; } - memcpy(ptr, (char *) session, 8); + memcpy(ptr, session, 8); ptr += 8; - (void) strcpy(ptr,service); - ptr += strlen(service) + 1; - - (void) strcpy(ptr,instance); - ptr += strlen(instance) + 1; - - (void) strcpy(ptr,realm); - ptr += strlen(realm) + 1; + memcpy(ptr, service, servicelen); + ptr += servicelen; + memcpy(ptr, instance, instancelen); + ptr += instancelen; + memcpy(ptr, realm, realmlen); + ptr += realmlen; - *(ptr++) = (unsigned char) life; - *(ptr++) = (unsigned char) kvno; - *(ptr++) = (unsigned char) tkt->length; + *ptr++ = life; + *ptr++ = kvno; + *ptr++ = tkt->length; - memcpy(ptr, (char *)(tkt->dat), tkt->length); + memcpy(ptr, tkt->dat, (size_t)tkt->length); ptr += tkt->length; - memcpy(ptr, (char *) &kdc_time, 4); - ptr += 4; + KRB4_PUT32(ptr, kdc_time); /* guarantee null padded encrypted data to multiple of 8 bytes */ memset(ptr, 0, 7); - c->length = (((ptr - (char *) c->dat) + 7) / 8) * 8; + c->length = (((ptr - c->dat) + 7) / 8) * 8; #ifndef NOENCRYPTION - key_sched(key,key_s); - pcbc_encrypt((C_Block *)c->dat,(C_Block *)c->dat, - (long) c->length,key_s,(C_Block*) key,ENCRYPT); + key_sched(key, key_s); + pcbc_encrypt((C_Block *)c->dat, (C_Block *)c->dat, + (long)c->length, key_s, (C_Block*)key, ENCRYPT); + memset(key_s, 0, sizeof(key_s)); #endif /* NOENCRYPTION */ - return(KSUCCESS); + return KSUCCESS; } diff --git a/src/lib/krb4/cr_death_pkt.c b/src/lib/krb4/cr_death_pkt.c index c3562675dc..63d756277e 100644 --- a/src/lib/krb4/cr_death_pkt.c +++ b/src/lib/krb4/cr_death_pkt.c @@ -1,14 +1,29 @@ /* - * cr_death_pkt.c + * lib/krb4/cr_death_pkt.c * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "krb.h" #include "prot.h" #include <string.h> @@ -46,15 +61,18 @@ krb_create_death_packet(a_name) { static KTEXT_ST pkt_st; KTEXT pkt = &pkt_st; + unsigned char *p; + size_t namelen; - unsigned char *v = pkt->dat; - unsigned char *t = (pkt->dat+1); - *v = (unsigned char) KRB_PROT_VERSION; - *t = (unsigned char) AUTH_MSG_DIE; - *t |= HOST_BYTE_ORDER; - (void) strncpy((char *) (pkt->dat+2),a_name,sizeof(pkt->dat) - 3); - pkt->dat[sizeof(pkt->dat) - 1] = '\0'; - pkt->length = 3 + strlen(pkt->dat+2); + p = pkt->dat; + *p++ = KRB_PROT_VERSION; + *p++ = AUTH_MSG_DIE; + namelen = strlen(a_name) + 1; + if (1 + 1 + namelen > sizeof(pkt->dat)) + return NULL; + memcpy(p, a_name, namelen); + p += namelen; + pkt->length = p - pkt->dat; return pkt; } #endif /* DEBUG */ diff --git a/src/lib/krb4/cr_err_repl.c b/src/lib/krb4/cr_err_repl.c index 54e87d82ed..35196df49e 100644 --- a/src/lib/krb4/cr_err_repl.c +++ b/src/lib/krb4/cr_err_repl.c @@ -1,14 +1,29 @@ /* - * cr_err_repl.c + * lib/krb4/cr_err_repl.c * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "krb.h" #include "prot.h" #include <string.h> @@ -66,44 +81,39 @@ cr_err_reply(pkt,pname,pinst,prealm,time_ws,e,e_string) u_long e; /* Error code */ char *e_string; /* Text of error */ { - u_char *v = (u_char *) pkt->dat; /* Prot vers number */ - u_char *t = (u_char *)(pkt->dat+1); /* Prot message type */ + unsigned char *p; + size_t pnamelen, pinstlen, prealmlen, e_stringlen; - /* Create fixed part of packet */ -#if 0 - *v = (unsigned char) req_act_vno; /* KRB_PROT_VERSION; */ -#else - *v = (unsigned char) KRB_PROT_VERSION; -#endif - *t = (unsigned char) AUTH_MSG_ERR_REPLY; - *t |= HOST_BYTE_ORDER; + p = pkt->dat; + *p++ = KRB_PROT_VERSION; + *p++ = AUTH_MSG_ERR_REPLY; /* Make sure the reply will fit into the buffer. */ - if(sizeof(pkt->dat) < 3 + strlen(pname) + - 1 + strlen(pinst) + - 1 + strlen(prealm) + - 4 + 4 + - 1 + strlen(e_string)) { + pnamelen = strlen(pname) + 1; + pinstlen = strlen(pinst) + 1; + prealmlen = strlen(prealm) + 1; + e_stringlen = strlen(e_string) + 1; + if(sizeof(pkt->dat) < (1 + 1 + pnamelen + pinstlen + prealmlen + + 4 + 4 + e_stringlen)) { pkt->length = 0; return; } /* Add the basic info */ - (void) strcpy((char *) (pkt->dat+2),pname); - pkt->length = 3 + strlen(pname); - (void) strcpy((char *)(pkt->dat+pkt->length),pinst); - pkt->length += 1 + strlen(pinst); - (void) strcpy((char *)(pkt->dat+pkt->length),prealm); - pkt->length += 1 + strlen(prealm); + memcpy(p, pname, pnamelen); + p += pnamelen; + memcpy(p, pinst, pinstlen); + p += pinstlen; + memcpy(p, prealm, prealmlen); + p += prealmlen; /* ws timestamp */ - memcpy((char *)(pkt->dat+pkt->length), (char *) &time_ws, 4); - pkt->length += 4; + KRB4_PUT32(p, time_ws); /* err code */ - memcpy((char *)(pkt->dat+pkt->length), (char *) &e, 4); - pkt->length += 4; + KRB4_PUT32(p, e); /* err text */ - (void) strcpy((char *)(pkt->dat+pkt->length),e_string); - pkt->length += 1 + strlen(e_string); + memcpy(p, e_string, e_stringlen); + p += e_stringlen; /* And return */ + pkt->length = p - pkt->dat; return; } diff --git a/src/lib/krb4/cr_tkt.c b/src/lib/krb4/cr_tkt.c index 62d5b54381..46753d820d 100644 --- a/src/lib/krb4/cr_tkt.c +++ b/src/lib/krb4/cr_tkt.c @@ -1,14 +1,29 @@ -/* - * cr_tkt.c +/* + * lib/krb4/cr_tkt.c * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "des.h" #include "krb.h" #include "prot.h" @@ -22,7 +37,6 @@ krb_cr_tkt_int PROTOTYPE((KTEXT tkt, unsigned int flags_in, char *pname, char *sname, char *sinstance, C_Block key, krb5_keyblock *k5key)); - /* * Create ticket takes as arguments information that should be in a * ticket, and the KTEXT object in which the ticket should be @@ -140,60 +154,61 @@ krb_cr_tkt_int(tkt, flags_in, pname, pinstance, prealm, paddress, krb5_keyblock *k5key; /* NULL if not present */ { Key_schedule key_s; - register char *data; /* running index into ticket */ - unsigned char flags = flags_in & 0xFF; /* Must be 1 byte */ + register unsigned char *data; /* running index into ticket */ + size_t pnamelen, pinstlen, prealmlen, snamelen, sinstlen; + struct in_addr paddr; + + /* Be really paranoid. */ + if (sizeof(paddr.s_addr) != 4) + return KFAILURE; tkt->length = 0; /* Clear previous data */ /* Check length of ticket */ - if (sizeof(tkt->dat) < (sizeof(flags) + - 1 + strlen(pname) + - 1 + strlen(pinstance) + - 1 + strlen(prealm) + - 4 + /* address */ - 8 + /* session */ - 1 + /* life */ - 4 + /* issue time */ - 1 + strlen(sname) + - 1 + strlen(sinstance) + - 7) / 8) { /* roundoff */ + pnamelen = strlen(pname) + 1; + pinstlen = strlen(pinstance) + 1; + prealmlen = strlen(prealm) + 1; + snamelen = strlen(sname) + 1; + sinstlen = strlen(sinstance) + 1; + if (sizeof(tkt->dat) / 8 < ((1 + pnamelen + pinstlen + prealmlen + + 4 /* address */ + + 8 /* session */ + + 1 /* life */ + + 4 /* issue time */ + + snamelen + sinstlen + + 7) / 8) /* roundoff */ + || life > 255 || life < 0) { memset(tkt->dat, 0, sizeof(tkt->dat)); return KFAILURE /* XXX */; } - flags |= HOST_BYTE_ORDER; /* ticket byte order */ - memcpy((char *) (tkt->dat), (char *) &flags, sizeof(flags)); - data = ((char *)tkt->dat) + sizeof(flags); - (void) strcpy(data, pname); - data += 1 + strlen(pname); - (void) strcpy(data, pinstance); - data += 1 + strlen(pinstance); - (void) strcpy(data, prealm); - data += 1 + strlen(prealm); - memcpy(data, (char *) &paddress, 4); - data += 4; - - memcpy(data, (char *) session, 8); + data = tkt->dat; + *data++ = flags_in; + memcpy(data, pname, pnamelen); + data += pnamelen; + memcpy(data, pinstance, pinstlen); + data += pinstlen; + memcpy(data, prealm, prealmlen); + data += prealmlen; + + paddr.s_addr = paddress; + memcpy(data, &paddr.s_addr, sizeof(paddr.s_addr)); + data += sizeof(paddr.s_addr); + + memcpy(data, session, 8); data += 8; - *(data++) = (char) life; + *data++ = life; /* issue time */ - memcpy(data, (char *) &time_sec, 4); - data += 4; - (void) strcpy(data, sname); - data += 1 + strlen(sname); - (void) strcpy(data, sinstance); - data += 1 + strlen(sinstance); + KRB4_PUT32(data, time_sec); + + memcpy(data, sname, snamelen); + data += snamelen; + memcpy(data, sinstance, sinstlen); + data += sinstlen; /* guarantee null padded ticket to multiple of 8 bytes */ memset(data, 0, 7); - tkt->length = ((data - ((char *)tkt->dat) + 7)/8)*8; - - /* Check length of ticket */ - if (tkt->length > (sizeof(KTEXT_ST) - 7)) { - memset(tkt->dat, 0, tkt->length); - tkt->length = 0; - return KFAILURE /* XXX */; - } + tkt->length = ((data - tkt->dat + 7) / 8) * 8; #ifndef NOENCRYPTION /* Encrypt the ticket in the services key */ @@ -205,7 +220,7 @@ krb_cr_tkt_int(tkt, flags_in, pname, pinstance, prealm, paddress, size_t enclen; in.length = tkt->length; - in.data = tkt->dat; + in.data = (char *)tkt->dat; /* XXX assumes context arg is ignored */ ret = krb5_c_encrypt_length(NULL, k5key->enctype, (size_t)in.length, &enclen); @@ -229,9 +244,10 @@ krb_cr_tkt_int(tkt, flags_in, pname, pinstance, prealm, paddress, free(out.ciphertext.data); } } else { - key_sched(key,key_s); - pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat, - (long) tkt->length,key_s,(C_Block *)key,1); + key_sched(key, key_s); + pcbc_encrypt((C_Block *)tkt->dat, (C_Block *)tkt->dat, + (long)tkt->length, key_s, (C_Block *)key, 1); + memset(key_s, 0, sizeof(key_s)); } #endif /* !NOENCRYPTION */ return 0; diff --git a/src/lib/krb4/decomp_tkt.c b/src/lib/krb4/decomp_tkt.c index 06e9e316c5..c74cdba3ee 100644 --- a/src/lib/krb4/decomp_tkt.c +++ b/src/lib/krb4/decomp_tkt.c @@ -1,14 +1,29 @@ /* - * decomp_tkt.c - * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * lib/krb4/decomp_tkt.c + * + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "des.h" #include "krb.h" #include "prot.h" @@ -123,9 +138,14 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, Key_schedule key_s; /* The precomputed key schedule */ krb5_keyblock *k5key; /* krb5 keyblock of service */ { - static int tkt_swap_bytes; - unsigned char *uptr; - char *ptr = (char *)tkt->dat; + int tkt_le; /* little-endian ticket? */ + unsigned char *ptr = tkt->dat; + int kret, len; + struct in_addr paddr; + + /* Be really paranoid. */ + if (sizeof(paddr.s_addr) != 4) + return KFAILURE; #ifndef NOENCRYPTION /* Do the decryption */ @@ -150,9 +170,9 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, in.enctype = k5key->enctype; in.kvno = 0; in.ciphertext.length = tkt->length; - in.ciphertext.data = tkt->dat; + in.ciphertext.data = (char *)tkt->dat; out.length = tkt->length; - out.data = malloc(tkt->length); + out.data = malloc((size_t)tkt->length); if (out.data == NULL) return KFAILURE; /* XXX maybe ENOMEM? */ @@ -169,8 +189,8 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, free(out.data); } } else { - pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat, - (long) tkt->length,key_s,(C_Block *) key,0); + pcbc_encrypt((C_Block *)tkt->dat, (C_Block *)tkt->dat, + (long)tkt->length, key_s, (C_Block *)key, 0); } #endif /* ! NOENCRYPTION */ #ifdef KRB_CRYPT_DEBUG @@ -186,58 +206,70 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, } #endif - *flags = *ptr; /* get flags byte */ - ptr += sizeof(*flags); - tkt_swap_bytes = 0; - if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1)) - tkt_swap_bytes++; - - if (strlen(ptr) >= ANAME_SZ) - return(KFAILURE); - (void) strcpy(pname,ptr); /* pname */ - ptr += strlen(pname) + 1; - - if (strlen(ptr) >= INST_SZ) - return(KFAILURE); - (void) strcpy(pinstance,ptr); /* instance */ - ptr += strlen(pinstance) + 1; - - if (strlen(ptr) >= REALM_SZ) - return(KFAILURE); - (void) strcpy(prealm,ptr); /* realm */ - ptr += strlen(prealm) + 1; +#define TKT_REMAIN (tkt->length - (ptr - tkt->dat)) + kret = KFAILURE; + if (TKT_REMAIN < 1) + goto cleanup; + *flags = *ptr++; + tkt_le = (*flags >> K_FLAG_ORDER) & 1; + + len = krb_strnlen((char *)ptr, TKT_REMAIN) + 1; + if (len <= 0 || len > ANAME_SZ) + goto cleanup; + memcpy(pname, ptr, (size_t)len); + ptr += len; + + len = krb_strnlen((char *)ptr, TKT_REMAIN) + 1; + if (len <= 0 || len > INST_SZ) + goto cleanup; + memcpy(pinstance, ptr, (size_t)len); + ptr += len; + + len = krb_strnlen((char *)ptr, TKT_REMAIN) + 1; + if (len <= 0 || len > REALM_SZ) + goto cleanup; + memcpy(prealm, ptr, (size_t)len); + ptr += len; + /* temporary hack until realms are dealt with properly */ - if (*prealm == 0) - (void) strcpy(prealm,KRB_REALM); + if (*prealm == '\0') + strcpy(prealm, KRB_REALM); - memcpy((char *)paddress, ptr, 4); /* net address */ - ptr += 4; + /* + * Ensure there's enough remaining in the ticket to get the + * fixed-size stuff. + */ + if (TKT_REMAIN < 4 + 8 + 1 + 4) + goto cleanup; - memcpy((char *)session, ptr, 8); /* session key */ - ptr+= 8; + memcpy(&paddr.s_addr, ptr, sizeof(paddr.s_addr)); + ptr += sizeof(paddr.s_addr); + *paddress = paddr.s_addr; + + memcpy(session, ptr, 8); /* session key */ + memset(ptr, 0, 8); + ptr += 8; #ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */ if (tkt_swap_bytes) swap_C_Block(session); #endif - /* get lifetime, being certain we don't get negative lifetimes */ - uptr = (unsigned char *) ptr++; - *life = (int) *uptr; + *life = *ptr++; - memcpy((char *) time_sec, ptr, 4); /* issue time */ - ptr += 4; - if (tkt_swap_bytes) - *time_sec = krb4_swab32(*time_sec); + KRB4_GET32(*time_sec, ptr, tkt_le); - if (strlen(ptr) >= ANAME_SZ) - return KFAILURE; - (void) strcpy(sname,ptr); /* service name */ - ptr += 1 + strlen(sname); + len = krb_strnlen((char *)ptr, TKT_REMAIN) + 1; + if (len <= 0 || len > SNAME_SZ) + goto cleanup; + memcpy(sname, ptr, (size_t)len); + ptr += len; - if (strlen (ptr) >= INST_SZ) - return KFAILURE; - (void) strcpy(sinstance,ptr); /* instance */ - ptr += 1 + strlen(sinstance); + len = krb_strnlen((char *)ptr, TKT_REMAIN) + 1; + if (len <= 0 || len > INST_SZ) + goto cleanup; + memcpy(sinstance, ptr, (size_t)len); + ptr += len; + kret = KSUCCESS; #ifdef KRB_CRYPT_DEBUG if (krb_debug) { @@ -247,5 +279,11 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, } #endif - return(KSUCCESS); +cleanup: + if (kret != KSUCCESS) { + memset(session, 0, sizeof(session)); + memset(tkt->dat, 0, (size_t)tkt->length); + return kret; + } + return KSUCCESS; } diff --git a/src/lib/krb4/g_ad_tkt.c b/src/lib/krb4/g_ad_tkt.c index afcd0c6f8b..092be7a225 100644 --- a/src/lib/krb4/g_ad_tkt.c +++ b/src/lib/krb4/g_ad_tkt.c @@ -1,14 +1,29 @@ /* - * g_ad_tkt.c + * lib/krb4/g_ad_tkt.c * - * Copyright 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "krb.h" #include "des.h" #include "prot.h" @@ -19,19 +34,6 @@ extern int krb_debug; extern int swap_bytes; -/* Return the length of the string if a NUL is found within the first - * max_len bytes, otherwise, -1. */ -static int krb_strnlen(const char *str, int max_len) -{ - int i; - for(i = 0; i < max_len; i++) { - if(str[i] == '\0') { - return i; - } - } - return -1; -} - /* * get_ad_tkt obtains a new service ticket from Kerberos, using * the ticket-granting ticket which must be in the ticket file. @@ -65,41 +67,193 @@ static int krb_strnlen(const char *str, int max_len) * extraction macros like pkt_version(), pkt_msg_type(), etc. */ -get_ad_tkt(service,sinstance,realm,lifetime) +/* + * g_ad_tk_parse() + * + * Parse the returned packet from the KDC. + * + * Note that the caller is responsible for clearing the returned + * session key if there is an error; that makes the error handling + * code a little less hairy. + */ +static int +g_ad_tkt_parse(KTEXT rpkt, C_Block tgtses, C_Block ses, + char *s_name, char *s_instance, char *rlm, + char *service, char *sinstance, char *realm, + int *lifetime, int *kvno, KTEXT tkt, + unsigned KRB4_32 *kdc_time, + KRB4_32 *t_local) +{ + unsigned char *ptr; + unsigned int t_switch; + int msg_byte_order; + unsigned long rep_err_code; + unsigned long cip_len; + KTEXT_ST cip_st; + KTEXT cip = &cip_st; /* Returned Ciphertext */ + Key_schedule key_s; + int len, i; + KRB4_32 t_diff; /* Difference between timestamps */ + + ptr = rpkt->dat; +#define RPKT_REMAIN (rpkt->length - (ptr - rpkt->dat)) + if (RPKT_REMAIN < 1 + 1) + return INTK_PROT; + /* check packet version of the returned packet */ + if (*ptr++ != KRB_PROT_VERSION) + return INTK_PROT; + + /* This used to be + switch (pkt_msg_type(rpkt) & ~1) { + but SCO 3.2v4 cc compiled that incorrectly. */ + t_switch = *ptr++; + /* Check byte order (little-endian == 1) */ + msg_byte_order = t_switch & 1; + t_switch &= ~1; + switch (t_switch) { + case AUTH_MSG_KDC_REPLY: + break; + case AUTH_MSG_ERR_REPLY: + if (RPKT_REMAIN < 4) + return INTK_PROT; + KRB4_GET32(rep_err_code, ptr, msg_byte_order); + return rep_err_code; + + default: + return INTK_PROT; + } + /* + * Skip over some stuff (3 strings and various integers -- see + * cr_auth_repl.c for details). Maybe we should actually verify + * these? + */ + for (i = 0; i < 3; i++) { + len = krb_strnlen((char *)ptr, RPKT_REMAIN) + 1; + if (len <= 0) + return INTK_PROT; + ptr += len; + } + if (RPKT_REMAIN < 4 + 1 + 4 + 1) + return INTK_PROT; + ptr += 4 + 1 + 4 + 1; + + /* Extract the ciphertext */ + if (RPKT_REMAIN < 2) + return INTK_PROT; + KRB4_GET16(cip_len, ptr, msg_byte_order); + if (RPKT_REMAIN < cip_len) + return INTK_PROT; + /* + * RPKT_REMAIN will always be non-negative and at most the maximum + * possible value of cip->length, so this assignment is safe. + */ + cip->length = cip_len; + memcpy(cip->dat, ptr, (size_t)cip->length); + ptr += cip->length; + +#ifndef NOENCRYPTION + /* Attempt to decrypt it */ + + key_sched(tgtses, key_s); + DEB (("About to do decryption ...")); + pcbc_encrypt((C_Block *)cip->dat, (C_Block *)cip->dat, + (long)cip->length, key_s, (C_Block *)tgtses, 0); +#endif /* !NOENCRYPTION */ + /* + * Stomp on key schedule. Caller should stomp on tgtses. + */ + memset(key_s, 0, sizeof(key_s)); + + ptr = cip->dat; +#define CIP_REMAIN (cip->length - (ptr - cip->dat)) + if (CIP_REMAIN < 8) + return RD_AP_MODIFIED; + memcpy(ses, ptr, 8); + /* + * Stomp on decrypted session key immediately after copying it. + */ + memset(ptr, 0, 8); + ptr += 8; + + len = krb_strnlen((char *)ptr, CIP_REMAIN) + 1; + if (len <= 0 || len > SNAME_SZ) + return RD_AP_MODIFIED; + memcpy(s_name, ptr, (size_t)len); + ptr += len; + + len = krb_strnlen((char *)ptr, CIP_REMAIN) + 1; + if (len <= 0 || len > INST_SZ) + return RD_AP_MODIFIED; + memcpy(s_instance, ptr, (size_t)len); + ptr += len; + + len = krb_strnlen((char *)ptr, CIP_REMAIN) + 1; + if (len <= 0 || len > REALM_SZ) + return RD_AP_MODIFIED; + memcpy(rlm, ptr, (size_t)len); + ptr += len; + + if (strcmp(s_name, service) || strcmp(s_instance, sinstance) + || strcmp(rlm, realm)) /* not what we asked for */ + return INTK_ERR; /* we need a better code here XXX */ + + if (CIP_REMAIN < 1 + 1 + 1) + return RD_AP_MODIFIED; + *lifetime = *ptr++; + *kvno = *ptr++; + tkt->length = *ptr++; + + if (CIP_REMAIN < tkt->length) + return RD_AP_MODIFIED; + memcpy(tkt->dat, ptr, (size_t)tkt->length); + ptr += tkt->length; + + /* Time (coarse) */ + if (CIP_REMAIN < 4) + return RD_AP_MODIFIED; + KRB4_GET32(*kdc_time, ptr, msg_byte_order); + + /* check KDC time stamp */ + *t_local = TIME_GMT_UNIXSEC; + t_diff = *t_local - *kdc_time; + if (t_diff < 0) + t_diff = -t_diff; /* Absolute value of difference */ + if (t_diff > CLOCK_SKEW) + return RD_AP_TIME; /* XXX should probably be better code */ + + return 0; +} + +int +get_ad_tkt(service, sinstance, realm, lifetime) char *service; char *sinstance; char *realm; int lifetime; { - unsigned long rep_err_code; - KTEXT_ST pkt_st; KTEXT pkt = & pkt_st; /* Packet to KDC */ KTEXT_ST rpkt_st; KTEXT rpkt = &rpkt_st; /* Returned packet */ - KTEXT_ST cip_st; - KTEXT cip = &cip_st; /* Returned Ciphertext */ KTEXT_ST tkt_st; KTEXT tkt = &tkt_st; /* Current ticket */ C_Block ses; /* Session key for tkt */ CREDENTIALS cr; int kvno; /* Kvno for session key */ + int kerror; char lrealm[REALM_SZ]; - Key_schedule key_s; KRB4_32 time_ws = 0; char s_name[SNAME_SZ]; char s_instance[INST_SZ]; - int msg_byte_order; - int kerror; char rlm[REALM_SZ]; - char *ptr; - unsigned KRB4_32 t_local; /* Must be 4 bytes long for memcpy below! */ - KRB4_32 t_diff; /* Difference between timestamps */ + unsigned char *ptr; + KRB4_32 t_local; unsigned KRB4_32 kdc_time; /* KDC time */ - unsigned int t_switch; + size_t snamelen, sinstlen; - if ((kerror = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS) - return(kerror); + kerror = krb_get_tf_realm(TKT_FILE, lrealm); + if (kerror != KSUCCESS) + return kerror; /* Create skeleton of packet to be sent */ pkt->length = 0; @@ -118,157 +272,95 @@ get_ad_tkt(service,sinstance,realm,lifetime) * If that succeeds, the ticket will be in ticket cache, get it * into the "cr" structure by calling krb_get_cred(). */ - - if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) { + kerror = krb_get_cred("krbtgt", realm, lrealm, &cr); + if (kerror != KSUCCESS) { /* * If realm == lrealm, we have no hope, so let's not even try. */ - if ((strncmp(realm, lrealm, REALM_SZ)) == 0) - return(AD_NOTGT); - else{ - if ((kerror = - get_ad_tkt("krbtgt",realm,lrealm,lifetime)) != KSUCCESS) { + if (strncmp(realm, lrealm, sizeof(lrealm)) == 0) + return AD_NOTGT; + else { + kerror = get_ad_tkt("krbtgt", realm, lrealm, lifetime); + if (kerror != KSUCCESS) { if (kerror == KDC_PR_UNKNOWN) /* no cross-realm ticket */ return AD_NOTGT; /* So call it no ticket */ - return(kerror); + return kerror; } - if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) - return(kerror); + kerror = krb_get_cred("krbtgt",realm,lrealm,&cr); + if (kerror != KSUCCESS) + return kerror; } } - + /* * Make up a request packet to the "krbtgt.realm@lrealm". * Start by calling krb_mk_req() which puts ticket+authenticator * into "pkt". Then tack other stuff on the end. */ - - kerror = krb_mk_req(pkt,"krbtgt",realm,lrealm,0L); + kerror = krb_mk_req(pkt, "krbtgt", realm, lrealm, 0L); + if (kerror) { + /* stomp stomp stomp */ + memset(cr.session, 0, sizeof(cr.session)); + return AD_NOTGT; + } - if (kerror) - return(AD_NOTGT); + ptr = pkt->dat + pkt->length; + + snamelen = strlen(service) + 1; + sinstlen = strlen(sinstance) + 1; + if (sizeof(pkt->dat) - (ptr - pkt->dat) < (4 + 1 + + snamelen + + sinstlen)) { + /* stomp stomp stomp */ + memset(cr.session, 0, sizeof(cr.session)); + return INTK_ERR; + } /* timestamp */ /* FIXME -- always 0 now, should we fill it in??? */ - if(pkt->length + 4 > sizeof(pkt->dat)) - return(INTK_ERR); - memcpy((char *) (pkt->dat+pkt->length), (char *) &time_ws, 4); - pkt->length += 4; + KRB4_PUT32(ptr, time_ws); - if(pkt->length + 1 > sizeof(pkt->dat)) - return(INTK_ERR); - *(pkt->dat+(pkt->length)++) = (char) lifetime; + *ptr++ = lifetime; - if(pkt->length + 1 + strlen(service) > sizeof(pkt->dat)) - return(INTK_ERR); - (void) strcpy((char *) (pkt->dat+pkt->length),service); - pkt->length += 1 + strlen(service); + memcpy(ptr, service, snamelen); + ptr += snamelen; + memcpy(ptr, sinstance, sinstlen); + ptr += sinstlen; - if(pkt->length + 1 + strlen(sinstance) > sizeof(pkt->dat)) - return(INTK_ERR); - (void) strcpy((char *)(pkt->dat+pkt->length),sinstance); - pkt->length += 1 + strlen(sinstance); - - rpkt->length = 0; + pkt->length = ptr - pkt->dat; /* Send the request to the local ticket-granting server */ - if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror); - - /* check packet version of the returned packet */ - if (pkt_version(rpkt) != KRB_PROT_VERSION ) - return(INTK_PROT); - - /* Check byte order */ - msg_byte_order = pkt_msg_type(rpkt) & 1; - swap_bytes = 0; - if (msg_byte_order != HOST_BYTE_ORDER) - swap_bytes++; - - /* This used to be - switch (pkt_msg_type(rpkt) & ~1) { - but SCO 3.2v4 cc compiled that incorrectly. */ - t_switch = pkt_msg_type(rpkt); - t_switch &= ~1; - switch (t_switch) { - case AUTH_MSG_KDC_REPLY: - break; - case AUTH_MSG_ERR_REPLY: - memcpy((char *) &rep_err_code, pkt_err_code(rpkt), 4); - if (swap_bytes) - rep_err_code = krb4_swab32(rep_err_code); - return(rep_err_code); - - default: - return(INTK_PROT); + rpkt->length = 0; + kerror = send_to_kdc(pkt, rpkt, realm); + + if (!kerror) { + /* No error; parse return packet from KDC. */ + kerror = g_ad_tkt_parse(rpkt, cr.session, ses, + s_name, s_instance, rlm, + service, sinstance, realm, + &lifetime, &kvno, tkt, + &kdc_time, &t_local); } - - /* Extract the ciphertext */ - cip->length = pkt_clen(rpkt); /* let clen do the swap */ - - memcpy((char *) (cip->dat), (char *) pkt_cipher(rpkt), cip->length); - -#ifndef NOENCRYPTION - /* Attempt to decrypt it */ - - key_sched(cr.session,key_s); - DEB (("About to do decryption ...")); - pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat, - (long) cip->length,key_s,(C_Block *)cr.session,0); -#endif /* !NOENCRYPTION */ - /* Get rid of all traces of key */ - memset((char *) cr.session, 0, sizeof(cr.session)); - memset((char *) key_s, 0, sizeof(key_s)); - - ptr = (char *) cip->dat; - - memcpy((char *)ses, ptr, 8); - ptr += 8; - - if(krb_strnlen(ptr, sizeof(s_name)) < 0) - return RD_AP_MODIFIED; - (void) strncpy(s_name,ptr,sizeof(s_name) - 1); - s_name[sizeof(s_name) - 1] = '\0'; - ptr += strlen(s_name) + 1; - - if(krb_strnlen(ptr, sizeof(s_instance)) < 0) - return RD_AP_MODIFIED; - (void) strncpy(s_instance,ptr,sizeof(s_instance)-1); - s_instance[sizeof(s_instance)-1] = '\0'; - ptr += strlen(s_instance) + 1; - - if(krb_strnlen(ptr, sizeof(rlm)) < 0) - return RD_AP_MODIFIED; - (void) strncpy(rlm,ptr,sizeof(rlm) - 1); - rlm[sizeof(rlm)-1]; - ptr += strlen(rlm) + 1; - - lifetime = (unsigned char) ptr[0]; - kvno = (unsigned char) ptr[1]; - tkt->length = (unsigned char) ptr[2]; - ptr += 3; - memcpy((char *)(tkt->dat), ptr, tkt->length); - ptr += tkt->length; - - if (strcmp(s_name, service) || strcmp(s_instance, sinstance) || - strcmp(rlm, realm)) /* not what we asked for */ - return(INTK_ERR); /* we need a better code here XXX */ - - /* check KDC time stamp */ - memcpy((char *)&kdc_time, ptr, 4); /* Time (coarse) */ - if (swap_bytes) kdc_time = krb4_swab32(kdc_time); - - ptr += 4; - - t_local = TIME_GMT_UNIXSEC; - t_diff = t_local - kdc_time; - if (t_diff < 0) t_diff = -t_diff; /* Absolute value of difference */ - if (t_diff > CLOCK_SKEW) { - return(RD_AP_TIME); /* XXX should probably be better - code */ + /* + * Unconditionally stomp on cr.session because we don't need it + * anymore. + */ + memset(cr.session, 0, sizeof(cr.session)); + if (kerror) { + /* + * Stomp on ses for good measure, since g_ad_tkt_parse() + * doesn't do that for us. + */ + memset(ses, 0, sizeof(ses)); + return kerror; } - if (kerror = krb_save_credentials(s_name,s_instance,rlm,ses,lifetime, - kvno,tkt,t_local)) - return(kerror); - - return(AD_OK); + kerror = krb_save_credentials(s_name, s_instance, rlm, + ses, lifetime, kvno, tkt, t_local); + /* + * Unconditionally stomp on ses because we don't need it anymore. + */ + memset(ses, 0, sizeof(ses)); + if (kerror) + return kerror; + return AD_OK; } diff --git a/src/lib/krb4/g_in_tkt.c b/src/lib/krb4/g_in_tkt.c index 361273c9d7..b7ab0dfc43 100644 --- a/src/lib/krb4/g_in_tkt.c +++ b/src/lib/krb4/g_in_tkt.c @@ -1,22 +1,35 @@ /* - * g_in_tkt.c + * lib/krb4/g_in_tkt.c * - * Copyright 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "krb.h" #include "des.h" #include "prot.h" #include <string.h> -extern int swap_bytes; - /* Define a couple of function types including parameters. These are needed on MS-Windows to convert arguments of the function pointers to the proper types during calls. These declarations are found @@ -39,40 +52,36 @@ typedef int (*decrypt_tkt_type) PROTOTYPE ((char *, char *, char *, char *, static int decrypt_tkt(user, instance, realm, arg, key_proc, cipp) - char *user; - char *instance; - char *realm; - char *arg; - key_proc_type key_proc; - KTEXT *cipp; + char *user; + char *instance; + char *realm; + char *arg; + key_proc_type key_proc; + KTEXT *cipp; { KTEXT cip = *cipp; C_Block key; /* Key for decrypting cipher */ Key_schedule key_s; + register int rc; #ifndef NOENCRYPTION /* Attempt to decrypt it */ #endif - /* generate a key from the supplied arg or password. */ - - { - register int rc; - rc = (*key_proc) (user,instance,realm,arg,key); - if (rc) - return(rc); - } - + rc = (*key_proc)(user, instance, realm, arg, key); + if (rc) + return rc; + #ifndef NOENCRYPTION - key_sched(key,key_s); - pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat, - (long) cip->length,key_s,(C_Block *)key,0); + key_sched(key, key_s); + pcbc_encrypt((C_Block *)cip->dat, (C_Block *)cip->dat, + (long)cip->length, key_s, (C_Block *)key, 0); #endif /* !NOENCRYPTION */ /* Get rid of all traces of key */ - memset((char *)key, 0,sizeof(key)); - memset((char *)key_s, 0,sizeof(key_s)); + memset(key, 0, sizeof(key)); + memset(key_s, 0, sizeof(key_s)); - return(0); + return 0; } /* @@ -118,7 +127,7 @@ decrypt_tkt(user, instance, realm, arg, key_proc, cipp) int krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life, - preauth_p, preauth_len, cip) + preauth_p, preauth_len, cip, byteorder) char *user; char *instance; char *realm; @@ -128,13 +137,15 @@ krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life, char *preauth_p; int preauth_len; KTEXT cip; + int *byteorder; { KTEXT_ST pkt_st; KTEXT pkt = &pkt_st; /* Packet to KDC */ KTEXT_ST rpkt_st; KTEXT rpkt = &rpkt_st; /* Returned packet */ - unsigned char *v = pkt->dat; /* Prot vers no */ - unsigned char *t = (pkt->dat+1); /* Prot msg type */ + unsigned char *p; + size_t userlen, instlen, realmlen, servicelen, sinstlen; + unsigned KRB4_32 t_local; int msg_byte_order; int kerror; @@ -142,112 +153,127 @@ krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life, unsigned long exp_date; #endif unsigned long rep_err_code; + unsigned long cip_len; unsigned int t_switch; - unsigned KRB4_32 t_local; /* Must be 4 bytes long for memcpy below! */ + int i, len; /* BUILD REQUEST PACKET */ - /* Set up the fixed part of the packet */ - *v = (unsigned char) KRB_PROT_VERSION; - *t = (unsigned char) AUTH_MSG_KDC_REQUEST; - *t |= HOST_BYTE_ORDER; + p = pkt->dat; + userlen = strlen(user) + 1; + instlen = strlen(instance) + 1; + realmlen = strlen(realm) + 1; + servicelen = strlen(service) + 1; + sinstlen = strlen(sinstance) + 1; /* Make sure the ticket data will fit into the buffer. */ - if(sizeof(pkt->dat) < 2 + /* protocol version + flags */ - 3 + strlen(user) + - 1 + strlen(instance) + - 1 + strlen(realm) + - 4 + /* timestamp */ - 1 + /* lifetime */ - 1 + strlen(service) + - 1 + strlen(sinstance) + - preauth_len) { + if (sizeof(pkt->dat) < (1 + 1 + userlen + instlen + realmlen + + 4 + 1 + servicelen + sinstlen + + preauth_len)) { pkt->length = 0; return INTK_ERR; } + /* Set up the fixed part of the packet */ + *p++ = KRB_PROT_VERSION; + *p++ = AUTH_MSG_KDC_REQUEST; + /* Now for the variable info */ - (void) strcpy((char *)(pkt->dat+2),user); /* aname */ - pkt->length = 3 + strlen(user); - (void) strcpy((char *)(pkt->dat+pkt->length), - instance); /* instance */ - pkt->length += 1 + strlen(instance); - (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */ - pkt->length += 1 + strlen(realm); + memcpy(p, user, userlen); + p += userlen; + memcpy(p, instance, instlen); + p += instlen; + memcpy(p, realm, realmlen); + p += realmlen; /* timestamp */ t_local = TIME_GMT_UNIXSEC; - memcpy((char *)(pkt->dat+pkt->length), (char *)&t_local, 4); - pkt->length += 4; + KRB4_PUT32(p, t_local); - *(pkt->dat+(pkt->length)++) = (char) life; - (void) strcpy((char *)(pkt->dat+pkt->length),service); - pkt->length += 1 + strlen(service); - (void) strcpy((char *)(pkt->dat+pkt->length),sinstance); + *p++ = life; - pkt->length += 1 + strlen(sinstance); + memcpy(p, service, servicelen); + p += servicelen; + memcpy(p, sinstance, sinstlen); + p += sinstlen; if (preauth_len) - memcpy((char *)(pkt->dat+pkt->length), preauth_p, preauth_len); - pkt->length += preauth_len; + memcpy(p, preauth_p, (size_t)preauth_len); + p += preauth_len; - rpkt->length = 0; + pkt->length = p - pkt->dat; /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */ + rpkt->length = 0; + kerror = send_to_kdc(pkt, rpkt, realm); + if (kerror) + return kerror; - if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror); + p = rpkt->dat; +#define RPKT_REMAIN (rpkt->length - (p - rpkt->dat)) /* check packet version of the returned packet */ - if (pkt_version(rpkt) != KRB_PROT_VERSION) - return(INTK_PROT); - - /* Check byte order */ - msg_byte_order = pkt_msg_type(rpkt) & 1; - swap_bytes = 0; - if (msg_byte_order != HOST_BYTE_ORDER) { - swap_bytes++; - } + if (RPKT_REMAIN < 1 + 1) + return INTK_PROT; + if (*p++ != KRB_PROT_VERSION) + return INTK_PROT; /* This used to be switch (pkt_msg_type(rpkt) & ~1) { but SCO 3.2v4 cc compiled that incorrectly. */ - t_switch = pkt_msg_type(rpkt); + t_switch = *p++; + /* Check byte order */ + msg_byte_order = t_switch & 1; t_switch &= ~1; switch (t_switch) { case AUTH_MSG_KDC_REPLY: break; case AUTH_MSG_ERR_REPLY: - memcpy((char *) &rep_err_code, pkt_err_code(rpkt), 4); - if (swap_bytes) rep_err_code = krb4_swab32(rep_err_code); - return((int)rep_err_code); + if (RPKT_REMAIN < 4) + return INTK_PROT; + KRB4_GET32(rep_err_code, p, msg_byte_order); + return rep_err_code; default: - return(INTK_PROT); + return INTK_PROT; } /* EXTRACT INFORMATION FROM RETURN PACKET */ -#if 0 - /* not used */ - /* get the principal's expiration date */ - memcpy((char *) &exp_date, pkt_x_date(rpkt), sizeof(exp_date)); - if (swap_bytes) exp_data = krb4_swab32(exp_date); -#endif + /* + * Skip over some stuff (3 strings and various integers -- see + * cr_auth_repl.c for details). + */ + for (i = 0; i < 3; i++) { + len = krb_strnlen((char *)p, RPKT_REMAIN) + 1; + if (len <= 0) + return INTK_PROT; + p += len; + } + if (RPKT_REMAIN < 4 + 1 + 4 + 1) + return INTK_PROT; + p += 4 + 1 + 4 + 1; /* Extract the ciphertext */ - cip->length = pkt_clen(rpkt); /* let clen do the swap */ - - if ((cip->length < 0) || (cip->length > sizeof(cip->dat))) - return(INTK_ERR); /* no appropriate error code - currently defined for INTK_ */ - /* copy information from return packet into "cip" */ - memcpy((char *)(cip->dat), (char *) pkt_cipher(rpkt), cip->length); - + if (RPKT_REMAIN < 2) + return INTK_PROT; + KRB4_GET16(cip_len, p, msg_byte_order); + if (RPKT_REMAIN < cip_len) + return INTK_ERR; + /* + * RPKT_REMAIN will always be non-negative and at most the maximum + * possible value of cip->length, so this assignment is safe. + */ + cip->length = cip_len; + memcpy(cip->dat, p, (size_t)cip->length); + p += cip->length; + + *byteorder = msg_byte_order; return INTK_OK; } - int -krb_parse_in_tkt(user, instance, realm, service, sinstance, life, cip) +krb_parse_in_tkt(user, instance, realm, service, sinstance, life, cip, + byteorder) char *user; char *instance; char *realm; @@ -255,9 +281,11 @@ krb_parse_in_tkt(user, instance, realm, service, sinstance, life, cip) char *sinstance; int life; KTEXT cip; + int byteorder; { - char *ptr; + unsigned char *ptr; C_Block ses; /* Session key for tkt */ + int len; int kvno; /* Kvno for session key */ char s_name[SNAME_SZ]; char s_instance[INST_SZ]; @@ -270,79 +298,80 @@ krb_parse_in_tkt(user, instance, realm, service, sinstance, life, cip) int kerror; int lifetime; - ptr = (char *) cip->dat; + ptr = cip->dat; + /* Assume that cip->length >= 0 for now. */ +#define CIP_REMAIN (cip->length - (ptr - cip->dat)) - /* extract session key */ - memcpy((char *)ses, ptr, 8); + /* Skip session key for now */ + if (CIP_REMAIN < 8) + return INTK_BADPW; ptr += 8; - if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) - return(INTK_BADPW); - /* extract server's name */ - (void) strncpy(s_name,ptr, sizeof(s_name)-1); - s_name[sizeof(s_name)-1] = '\0'; - ptr += strlen(s_name) + 1; - - if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) - return(INTK_BADPW); + len = krb_strnlen((char *)ptr, CIP_REMAIN) + 1; + if (len <= 0 || len > sizeof(s_name)) + return INTK_BADPW; + memcpy(s_name, ptr, (size_t)len); + ptr += len; /* extract server's instance */ - (void) strncpy(s_instance,ptr, sizeof(s_instance)-1); - s_instance[sizeof(s_instance)-1] = '\0'; - ptr += strlen(s_instance) + 1; - - if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) - return(INTK_BADPW); + len = krb_strnlen((char *)ptr, CIP_REMAIN) + 1; + if (len <= 0 || len > sizeof(s_instance)) + return INTK_BADPW; + memcpy(s_instance, ptr, (size_t)len); + ptr += len; /* extract server's realm */ - (void) strncpy(rlm,ptr, sizeof(rlm)); - rlm[sizeof(rlm)-1] = '\0'; - ptr += strlen(rlm) + 1; + len = krb_strnlen((char *)ptr, CIP_REMAIN) + 1; + if (len <= 0 || len > sizeof(rlm)) + return INTK_BADPW; + memcpy(rlm, ptr, (size_t)len); + ptr += len; /* extract ticket lifetime, server key version, ticket length */ /* be sure to avoid sign extension on lifetime! */ - lifetime = (unsigned char) ptr[0]; - kvno = (unsigned char) ptr[1]; - tkt->length = (unsigned char) ptr[2]; - ptr += 3; - - if ((tkt->length < 0) || - ((tkt->length + (ptr - (char *) cip->dat)) > cip->length)) - return(INTK_BADPW); + if (CIP_REMAIN < 3) + return INTK_BADPW; + lifetime = *ptr++; + kvno = *ptr++; + tkt->length = *ptr++; /* extract ticket itself */ - memcpy((char *)(tkt->dat), ptr, tkt->length); + if (CIP_REMAIN < tkt->length) + return INTK_BADPW; + memcpy(tkt->dat, ptr, (size_t)tkt->length); ptr += tkt->length; - if (strcmp(s_name, service) || strcmp(s_instance, sinstance) || - strcmp(rlm, realm)) /* not what we asked for */ - return(INTK_ERR); /* we need a better code here XXX */ + if (strcmp(s_name, service) || strcmp(s_instance, sinstance) + || strcmp(rlm, realm)) /* not what we asked for */ + return INTK_ERR; /* we need a better code here XXX */ /* check KDC time stamp */ - memcpy((char *)&kdc_time, ptr, 4); /* Time (coarse) */ - if (swap_bytes) kdc_time = krb4_swab32(kdc_time); - - ptr += 4; + if (CIP_REMAIN < 4) + return INTK_BADPW; + KRB4_GET32(kdc_time, ptr, byteorder); t_local = TIME_GMT_UNIXSEC; t_diff = t_local - kdc_time; - if (t_diff < 0) t_diff = -t_diff; /* Absolute value of difference */ + if (t_diff < 0) + t_diff = -t_diff; /* Absolute value of difference */ if (t_diff > CLOCK_SKEW) { - return(RD_AP_TIME); /* XXX should probably be better - code */ + return RD_AP_TIME; /* XXX should probably be better code */ } /* initialize ticket cache */ if (in_tkt(user,instance) != KSUCCESS) - return(INTK_ERR); - + return INTK_ERR; /* stash ticket, session key, etc. for future use */ - if (kerror = krb_save_credentials(s_name, s_instance, rlm, ses, - lifetime, kvno, tkt, t_local)) - return(kerror); + memcpy(ses, cip->dat, 8); + kerror = krb_save_credentials(s_name, s_instance, rlm, ses, + lifetime, kvno, + tkt, (KRB4_32)t_local); + memset(ses, 0, 8); + if (kerror) + return kerror; - return(INTK_OK); + return INTK_OK; } int @@ -363,21 +392,26 @@ krb_get_in_tkt_preauth(user, instance, realm, service, sinstance, life, KTEXT_ST cip_st; KTEXT cip = &cip_st; /* Returned Ciphertext */ int kerror; - if (kerror = krb_mk_in_tkt_preauth(user, instance, realm, - service, sinstance, - life, preauth_p, preauth_len, cip)) - return kerror; + int byteorder; + kerror = krb_mk_in_tkt_preauth(user, instance, realm, + service, sinstance, + life, preauth_p, preauth_len, + cip, &byteorder); + if (kerror) + return kerror; /* Attempt to decrypt the reply. */ if (decrypt_proc == NULL) decrypt_tkt (user, instance, realm, arg, key_proc, &cip); else (*decrypt_proc)(user, instance, realm, arg, key_proc, &cip); - - return - krb_parse_in_tkt(user, instance, realm, service, sinstance, - life, cip); + kerror = krb_parse_in_tkt(user, instance, realm, + service, sinstance, + life, cip, byteorder); + /* stomp stomp stomp */ + memset(cip->dat, 0, (size_t)cip->length); + return kerror; } int @@ -395,7 +429,6 @@ krb_get_in_tkt(user, instance, realm, service, sinstance, life, { return krb_get_in_tkt_preauth(user, instance, realm, service, sinstance, life, - key_proc, decrypt_proc, arg, (char *)0, 0); - + key_proc, decrypt_proc, arg, + (char *)NULL, 0); } - diff --git a/src/lib/krb4/mk_auth.c b/src/lib/krb4/mk_auth.c index 45952c0f20..45415fed33 100644 --- a/src/lib/krb4/mk_auth.c +++ b/src/lib/krb4/mk_auth.c @@ -1,16 +1,31 @@ /* - * mk_auth.c + * lib/krb4/mk_auth.c * - * CopKRB4_32right 1987, 1988 by the Massachusetts Institute of Technology. + * Copyright 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. * * Derived from sendauth.c by John Gilmore, 10 October 1994. */ -#include "mit-copyright.h" - #define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */ #include <stdio.h> #include "krb.h" @@ -110,30 +125,35 @@ krb_mk_auth(options, ticket, service, inst, realm, checksum, version, buf) char FAR *version; /* version string */ KTEXT buf; /* Output buffer to fill */ { - int rem, i; + int rem; char krb_realm[REALM_SZ]; - KRB4_32 tkt_len; + char *phost; + int phostlen; + unsigned char *p; - rem=KSUCCESS; + rem = KSUCCESS; /* get current realm if not passed in */ if (!realm) { rem = krb_get_lrealm(krb_realm,1); if (rem != KSUCCESS) - return(rem); + return rem; realm = krb_realm; } if (!(options & KOPT_DONT_CANON)) { - (void) strncpy(inst, krb_get_phost(inst), INST_SZ - 1); - inst[INST_SZ-1] = 0; + phost = krb_get_phost(inst); + phostlen = krb_strnlen(phost, INST_SZ) + 1; + if (phostlen <= 0 || phostlen > INST_SZ) + return KFAILURE; + memcpy(inst, phost, (size_t)phostlen); } /* get the ticket if desired */ if (!(options & KOPT_DONT_MK_REQ)) { - rem = krb_mk_req(ticket, service, inst, realm, checksum); + rem = krb_mk_req(ticket, service, inst, realm, (KRB4_32)checksum); if (rem != KSUCCESS) - return(rem); + return rem; } #ifdef ATHENA_COMPAT @@ -146,32 +166,33 @@ krb_mk_auth(options, ticket, service, inst, realm, checksum, version, buf) } #endif /* ATHENA_COMPAT */ + /* Check buffer size */ + if (sizeof(buf->dat) < (KRB_SENDAUTH_VLEN + KRB_SENDAUTH_VLEN + + 4 + ticket->length) + || ticket->length < 0) + return KFAILURE; + /* zero the buffer */ - (void) memset(buf->dat, 0, MAX_KTXT_LEN); + memset(buf->dat, 0, sizeof(buf->dat)); + p = buf->dat; /* insert version strings */ - (void) strncpy((char *)buf->dat, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN); - (void) strncpy((char *)buf->dat+KRB_SENDAUTH_VLEN, version, - KRB_SENDAUTH_VLEN); - - /* increment past vers strings */ - i = 2*KRB_SENDAUTH_VLEN; + strncpy((char *)p, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN); + p += KRB_SENDAUTH_VLEN; + strncpy((char *)p, version, KRB_SENDAUTH_VLEN); + p += KRB_SENDAUTH_VLEN; /* put ticket length into buffer */ - tkt_len = htonl((unsigned KRB4_32) ticket->length); - (void) memcpy(buf->dat+i, (char *) &tkt_len, sizeof(tkt_len)); - i += sizeof(tkt_len); + KRB4_PUT32(p, ticket->length); /* put ticket into buffer */ - (void) memcpy(buf->dat+i, (char *) ticket->dat, ticket->length); - i += ticket->length; + memcpy(p, ticket->dat, (size_t)ticket->length); + p += ticket->length; - buf->length = i; + buf->length = p - buf->dat; return KSUCCESS; } - - /* * For mutual authentication using mk_auth, check the server's response * to validate that we're really talking to the server which holds the @@ -199,22 +220,31 @@ krb_check_auth (buf, checksum, msg_data, session, schedule, laddr, faddr) { int cc; unsigned KRB4_32 cksum; + unsigned char *p; /* decrypt it */ #ifndef NOENCRYPTION key_sched(session, schedule); #endif /* !NOENCRYPTION */ - if (cc = krb_rd_priv(buf->dat, buf->length, schedule, - (C_Block *)session, faddr, laddr, msg_data)) - return(cc); - - /* fetch the (incremented) checksum that we supplied in the request */ - (void) memcpy((char *)&cksum, (char *)msg_data->app_data, - sizeof(cksum)); - cksum = ntohl(cksum); + if (buf->length < 0) + return KFAILURE; + cc = krb_rd_priv(buf->dat, (unsigned KRB4_32)buf->length, schedule, + (C_Block *)session, faddr, laddr, msg_data); + memset(schedule, 0, sizeof(schedule)); + if (cc) + return cc; + + /* + * Fetch the (incremented) checksum that we supplied in the + * request. + */ + if (msg_data->app_length < 4) + return KFAILURE; + p = msg_data->app_data; + KRB4_GET32BE(cksum, p); /* if it doesn't match, fail -- reply wasn't from our real server. */ if (cksum != checksum + 1) - return(KFAILURE); /* XXX */ - return(KSUCCESS); + return KFAILURE; /* XXX */ + return KSUCCESS; } diff --git a/src/lib/krb4/mk_err.c b/src/lib/krb4/mk_err.c index 029aa9f9c7..8fcb2ed21b 100644 --- a/src/lib/krb4/mk_err.c +++ b/src/lib/krb4/mk_err.c @@ -1,14 +1,29 @@ /* - * mk_err.c + * lib/krb4/mk_err.c * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "krb.h" #include "prot.h" #include <string.h> @@ -34,34 +49,35 @@ */ KRB5_DLLIMP long KRB5_CALLCONV -krb_mk_err(p,e,e_string) +krb_mk_err(p, e, e_string) u_char FAR *p; /* Where to build error packet */ KRB4_32 e; /* Error code */ char FAR *e_string; /* Text of error */ { u_char *start; + size_t e_len; + + e_len = strlen(e_string) + 1; /* Just return the buffer length if p is NULL, because writing to the * buffer would be a bad idea. Note that this feature is a change from * previous versions, and can therefore only be used safely in this * source tree, where we know this function supports it. */ - if(p == NULL) { - return 2 + sizeof(e) + strlen(e_string); + if (p == NULL) { + return 1 + 1 + 4 + e_len; } start = p; /* Create fixed part of packet */ - *p++ = (unsigned char) KRB_PROT_VERSION; - *p = (unsigned char) AUTH_MSG_APPL_ERR; - *p++ |= HOST_BYTE_ORDER; + *p++ = KRB_PROT_VERSION; + *p++ = AUTH_MSG_APPL_ERR; /* Add the basic info */ - memcpy((char *)p, (char *)&e, 4); /* err code */ - p += sizeof(e); - (void) strcpy((char *)p,e_string); /* err text */ - p += strlen(e_string); + KRB4_PUT32(p, e); + memcpy(p, e_string, e_len); /* err text */ + p += e_len; /* And return the length */ - return p-start; + return p - start; } diff --git a/src/lib/krb4/mk_preauth.c b/src/lib/krb4/mk_preauth.c index 949fd1d253..5295b22552 100644 --- a/src/lib/krb4/mk_preauth.c +++ b/src/lib/krb4/mk_preauth.c @@ -21,10 +21,9 @@ extern char *malloc(), *calloc(), *realloc(); #endif - int krb_mk_preauth(preauth_p, preauth_len, - key_proc,aname,inst,realm,password,key) + key_proc, aname, inst, realm, password, key) char **preauth_p; int *preauth_len; key_proc_type key_proc; @@ -35,15 +34,15 @@ krb_mk_preauth(preauth_p, preauth_len, C_Block key; { #ifdef NOENCRYPTION - *preauth_len = strlen(aname)+1; /* include the trailing 0 */ + *preauth_len = strlen(aname) + 1; /* include the trailing 0 */ *preauth_p = malloc(*preauth_len); - strcpy(*preauth_p, aname); /* this will copy the trailing 0 */ + strcpy(*preauth_p, aname); /* this will copy the trailing 0 */ #else des_key_schedule key_s; int sl = strlen(aname); #endif - (*key_proc)(aname,inst,realm,password,key); + (*key_proc)(aname, inst, realm, password, key); #ifndef NOENCRYPTION /* @@ -52,17 +51,18 @@ krb_mk_preauth(preauth_p, preauth_len, */ *preauth_len = (((sl + 1) / 8) + 1) * 8; /* allocate memory for preauth_p and fill it with 0 */ - *preauth_p = (char*) malloc(*preauth_len); + *preauth_p = malloc((size_t)*preauth_len); /* create the key schedule */ if (des_key_sched(key, key_s)) { - return 1; + return 1; } /* * encrypt aname using key_s as the key schedule and key as the * initialization vector. */ - des_pcbc_encrypt((des_cblock *) aname, (des_cblock *) *preauth_p, - (long) (sl + 1), key_s, (des_cblock *) key, DES_ENCRYPT); + des_pcbc_encrypt((des_cblock *)aname, (des_cblock *)*preauth_p, + (long)(sl + 1), key_s, (des_cblock *)key, DES_ENCRYPT); + memset(key_s, 0, sizeof(key_s)); #endif return 0; } @@ -72,6 +72,6 @@ krb_free_preauth(preauth_p, preauth_len) char *preauth_p; int preauth_len; { - free(preauth_p); - return; + free(preauth_p); + return; } diff --git a/src/lib/krb4/mk_priv.c b/src/lib/krb4/mk_priv.c index e8ce33358f..0c35548085 100644 --- a/src/lib/krb4/mk_priv.c +++ b/src/lib/krb4/mk_priv.c @@ -1,11 +1,27 @@ /* - * mk_priv.c + * lib/krb4/mk_priv.c * - * CopKRB4_32right 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. * * This routine constructs a Kerberos 'private msg', i.e. * cryptographically sealed with a private session key. @@ -15,8 +31,6 @@ * Steve Miller Project Athena MIT/DEC */ -#include "mit-copyright.h" - #include <stdio.h> #include <string.h> @@ -80,7 +94,7 @@ extern int krb_debug; */ KRB5_DLLIMP long KRB5_CALLCONV -krb_mk_priv(in,out,length,schedule,key,sender,receiver) +krb_mk_priv(in, out, length, schedule, key, sender, receiver) u_char FAR *in; /* application data */ u_char FAR *out; /* put msg here, leave room for * header! breaks if in and out @@ -95,27 +109,31 @@ krb_mk_priv(in,out,length,schedule,key,sender,receiver) u_char *c_length_ptr; extern int private_msg_ver; /* in krb_rd_priv.c */ - unsigned KRB4_32 c_length; + unsigned KRB4_32 c_length, c_length_raw; u_char msg_time_5ms; unsigned KRB4_32 msg_time_sec; unsigned KRB4_32 msg_time_usec; + /* Be really paranoid. */ + if (sizeof(sender->sin_addr.s_addr) != 4) + return -1; /* * get the current time to use instead of a sequence #, since * process lifetime may be shorter than the lifetime of a session * key. */ - msg_time_sec = TIME_GMT_UNIXSEC_US (&msg_time_usec); - msg_time_5ms = msg_time_usec/5000; /* 5ms quanta */ + msg_time_sec = TIME_GMT_UNIXSEC_US(&msg_time_usec); + msg_time_5ms = msg_time_usec / 5000; /* 5ms quanta */ p = out; - *p++ = private_msg_ver?private_msg_ver:KRB_PROT_VERSION; - *p++ = AUTH_MSG_PRIVATE | HOST_BYTE_ORDER; + /* Cruftiness below! */ + *p++ = private_msg_ver ? private_msg_ver : KRB_PROT_VERSION; + *p++ = AUTH_MSG_PRIVATE; - /* calculate cipher length */ + /* save ptr to cipher length */ c_length_ptr = p; - p += sizeof(c_length); + p += 4; #ifndef NOENCRYPTION /* start for encrypted stuff */ @@ -123,23 +141,21 @@ krb_mk_priv(in,out,length,schedule,key,sender,receiver) q = p; /* stuff input length */ - memcpy((char *)p, (char *)&length, sizeof(length)); - p += sizeof(length); + KRB4_PUT32(p, length); #ifdef NOENCRYPTION /* make all the stuff contiguous for checksum */ #else /* make all the stuff contiguous for checksum and encryption */ #endif - memcpy((char *)p, (char *)in, (int) length); + memcpy(p, in, (size_t)length); p += length; /* stuff time 5ms */ - memcpy((char *)p, (char *)&msg_time_5ms, sizeof(msg_time_5ms)); - p += sizeof(msg_time_5ms); + *p++ = msg_time_5ms; /* stuff source address */ - memcpy((char *)p, (char *)&sender->sin_addr.s_addr, + memcpy(p, &sender->sin_addr.s_addr, sizeof(sender->sin_addr.s_addr)); p += sizeof(sender->sin_addr.s_addr); @@ -150,15 +166,15 @@ krb_mk_priv(in,out,length,schedule,key,sender,receiver) /* For compatibility with broken old code, compares are done in VAX byte order (LSBFIRST) */ if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */ - receiver->sin_addr.s_addr)==-1) - msg_time_sec = -msg_time_sec; - else if (lsb_net_ulong_less(sender->sin_addr.s_addr, - receiver->sin_addr.s_addr)==0) - if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1) - msg_time_sec = -msg_time_sec; + receiver->sin_addr.s_addr) == -1) + msg_time_sec = -msg_time_sec; + else if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr) == 0) + if (lsb_net_ushort_less(sender->sin_port, + receiver->sin_port) == -1) + msg_time_sec = -msg_time_sec; /* stuff time sec */ - memcpy((char *)p, (char *)&msg_time_sec, sizeof(msg_time_sec)); - p += sizeof(msg_time_sec); + KRB4_PUT32(p, msg_time_sec); /* * All that for one tiny bit! Heaven help those that talk to @@ -170,10 +186,10 @@ krb_mk_priv(in,out,length,schedule,key,sender,receiver) * calculate the checksum of the length, address, sequence, and * inp data */ - cksum = quad_cksum(q,NULL,p-q,0,key); + cksum = quad_cksum(q,NULL,p-q,0,key); DEB (("\ncksum = %u",cksum)); /* stuff checksum */ - memcpy((char *) p, (char *) &cksum, sizeof(cksum)); + memcpy(p, &cksum, sizeof(cksum)); p += sizeof(cksum); #endif @@ -189,17 +205,18 @@ krb_mk_priv(in,out,length,schedule,key,sender,receiver) */ #endif - c_length = p - q; - c_length = ((c_length + sizeof(C_Block) -1)/sizeof(C_Block)) * - sizeof(C_Block); + c_length_raw = p - q; + c_length = ((c_length_raw + sizeof(C_Block) -1) + / sizeof(C_Block)) * sizeof(C_Block); /* stuff the length */ - memcpy((char *)c_length_ptr, (char *) &c_length, sizeof(c_length)); + p = c_length_ptr; + KRB4_PUT32(p, c_length); #ifndef NOENCRYPTION /* pcbc encrypt, pad as needed, use key as ivec */ - pcbc_encrypt((C_Block *) q,(C_Block *) q, (long) (p-q), schedule, - key, ENCRYPT); + pcbc_encrypt((C_Block *)q,(C_Block *)q, (long)c_length_raw, + schedule, key, ENCRYPT); #endif /* NOENCRYPTION */ - return (q - out + c_length); /* resulting size */ + return q - out + c_length; /* resulting size */ } diff --git a/src/lib/krb4/mk_req.c b/src/lib/krb4/mk_req.c index 468dccdb6d..2d5d240efc 100644 --- a/src/lib/krb4/mk_req.c +++ b/src/lib/krb4/mk_req.c @@ -1,15 +1,30 @@ /* - * mk_req.c + * lib/krb4/mk_req.c * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ #define DEFINE_SOCKADDR -#include "mit-copyright.h" #include "krb.h" #include "prot.h" #include "des.h" @@ -69,7 +84,7 @@ static int lifetime = 255; /* Default based on the TGT */ */ KRB5_DLLIMP int KRB5_CALLCONV -krb_mk_req(authent,service,instance,realm,checksum) +krb_mk_req(authent, service, instance, realm, checksum) register KTEXT authent; /* Place to build the authenticator */ char FAR *service; /* Name of the service */ char FAR *instance; /* Service instance */ @@ -78,36 +93,27 @@ krb_mk_req(authent,service,instance,realm,checksum) { KTEXT_ST req_st; /* Temp storage for req id */ KTEXT req_id = &req_st; - unsigned char *v = authent->dat; /* Prot version number */ - unsigned char *t = (authent->dat+1); /* Message type */ - unsigned char *kv = (authent->dat+2); /* Key version no */ - unsigned char *tl; /* Tkt len */ - unsigned char *idl; /* Reqid len */ + unsigned char *p, *q, *reqid_lenp; + int tl; /* Tkt len */ + int idl; /* Reqid len */ CREDENTIALS cr; /* Credentials used by retr */ register KTEXT ticket = &(cr.ticket_st); /* Pointer to tkt_st */ int retval; /* Returned by krb_get_cred */ Key_schedule key_s; char krb_realm[REALM_SZ]; /* Our local realm, if not specified */ char myrealm[REALM_SZ]; /* Realm of our TGT */ + size_t realmlen, pnamelen, pinstlen, myrealmlen; unsigned KRB4_32 time_secs; unsigned KRB4_32 time_usecs; - /* The fixed parts of the authenticator */ - *v = (unsigned char) KRB_PROT_VERSION; - *t = (unsigned char) AUTH_MSG_APPL_REQUEST; - *t |= HOST_BYTE_ORDER; - /* get current realm if not passed in */ - if (!realm) { - retval = krb_get_lrealm(krb_realm,1); + if (realm == NULL) { + retval = krb_get_lrealm(krb_realm, 1); if (retval != KSUCCESS) - return(retval); + return retval; realm = krb_realm; } - tl = (authent->dat+4+strlen(realm)); /* Tkt len */ - idl = (authent->dat+5+strlen(realm)); /* Reqid len */ - /* Get the ticket and move it into the authenticator */ if (krb_ap_req_debug) DEB (("Realm: %s\n",realm)); @@ -116,97 +122,121 @@ krb_mk_req(authent,service,instance,realm,checksum) * KDC from which we are requesting tickets so it knows what to * with our session key. */ - if ((retval = krb_get_tf_realm(TKT_FILE, myrealm)) != KSUCCESS) - return(retval); - - retval = krb_get_cred(service,instance,realm,&cr); + retval = krb_get_tf_realm(TKT_FILE, myrealm); + if (retval != KSUCCESS) + return retval; + retval = krb_get_cred(service, instance, realm, &cr); if (retval == RET_NOTKT) { - if (retval = get_ad_tkt(service,instance,realm,lifetime)) - return(retval); - if (retval = krb_get_cred(service,instance,realm,&cr)) - return(retval); + retval = get_ad_tkt(service, instance, realm, lifetime); + if (retval) + return retval; + retval = krb_get_cred(service, instance, realm, &cr); + if (retval) + return retval; } + if (retval != KSUCCESS) + return retval; - if (retval != KSUCCESS) return (retval); - - if(sizeof(authent->dat) / 8 < (3 + - strlen(realm) + 1 + 2 + - 3 + ticket->length + - strlen(cr.pname) + 1 + - strlen(cr.pinst) + 1 + - strlen(myrealm) + 1 + - 4 + /* checksum */ - 4 + /* timestamp */ - 7) / 8) { /* round-up */ - authent->length = 0; - return KFAILURE; + realmlen = strlen(realm) + 1; + if (sizeof(authent->dat) < (1 + 1 + 1 + + realmlen + + 1 + 1 + ticket->length) + || ticket->length < 0 || ticket->length > 255) { + authent->length = 0; + memset(cr.session, 0, sizeof(cr.session)); + return KFAILURE; } if (krb_ap_req_debug) DEB (("%s %s %s %s %s\n", service, instance, realm, cr.pname, cr.pinst)); - *kv = (unsigned char) cr.kvno; - (void) strcpy((char *)(authent->dat+3),realm); - *tl = (unsigned char) ticket->length; - memcpy((char *)(authent->dat+6+strlen(realm)), (char *)(ticket->dat), - ticket->length); - authent->length = 6 + strlen(realm) + ticket->length; + + p = authent->dat; + + /* The fixed parts of the authenticator */ + *p++ = KRB_PROT_VERSION; + *p++ = AUTH_MSG_APPL_REQUEST; + *p++ = cr.kvno; + + memcpy(p, realm, realmlen); + p += realmlen; + + tl = ticket->length; + *p++ = tl; + /* Save ptr to where req_id->length goes. */ + reqid_lenp = p; + p++; + memcpy(p, ticket->dat, (size_t)tl); + p += tl; + if (krb_ap_req_debug) DEB (("Ticket->length = %d\n",ticket->length)); if (krb_ap_req_debug) DEB (("Issue date: %d\n",cr.issue_date)); + pnamelen = strlen(cr.pname) + 1; + pinstlen = strlen(cr.pinst) + 1; + myrealmlen = strlen(myrealm) + 1; + if (sizeof(req_id->dat) / 8 < (pnamelen + pinstlen + myrealmlen + + 4 + 1 + 4 + 7) / 8) { + memset(cr.session, 0, sizeof(cr.session)); + return KFAILURE; + } + + q = req_id->dat; + /* Build request id */ - (void) strcpy((char *)(req_id->dat),cr.pname); /* Auth name */ - req_id->length = strlen(cr.pname)+1; + /* Auth name */ + memcpy(q, cr.pname, pnamelen); + q += pnamelen; /* Principal's instance */ - (void) strcpy((char *)(req_id->dat+req_id->length),cr.pinst); - req_id->length += strlen(cr.pinst)+1; + memcpy(q, cr.pinst, pinstlen); + q += pinstlen; /* Authentication domain */ - (void) strcpy((char *)(req_id->dat+req_id->length),myrealm); - req_id->length += strlen(myrealm)+1; + memcpy(q, myrealm, myrealmlen); + q += myrealmlen; /* Checksum */ - memcpy((char *)(req_id->dat+req_id->length), (char *)&checksum, 4); - req_id->length += 4; + KRB4_PUT32(q, checksum); /* Fill in the times on the request id */ - time_secs = TIME_GMT_UNIXSEC_US (&time_usecs); - *(req_id->dat+(req_id->length)++) = - (unsigned char) time_usecs; + *q++ = time_usecs; /* time_usecs % 255 */ /* Time (coarse) */ - memcpy((char *)(req_id->dat+req_id->length), - (char *) &time_secs , 4); - req_id->length += 4; + KRB4_PUT32(q, time_secs); /* Fill to a multiple of 8 bytes for DES */ - req_id->length = ((req_id->length+7)/8)*8; + req_id->length = ((q - req_id->dat + 7) / 8) * 8; #ifndef NOENCRYPTION /* Encrypt the request ID using the session key */ - key_sched(cr.session,key_s); - pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, - (long) req_id->length,key_s, &cr.session,1); + key_sched(cr.session, key_s); + pcbc_encrypt((C_Block *)req_id->dat, (C_Block *)req_id->dat, + (long)req_id->length, key_s, &cr.session, 1); /* clean up */ - memset((char *) key_s, 0, sizeof(key_s)); + memset(key_s, 0, sizeof(key_s)); + memset(cr.session, 0, sizeof(cr.session)); #endif /* NOENCRYPTION */ /* Copy it into the authenticator */ - memcpy((char *)(authent->dat+authent->length), (char *)(req_id->dat), - req_id->length); - authent->length += req_id->length; - /* And set the id length */ - *idl = (unsigned char) req_id->length; + idl = req_id->length; + if (idl > 255) + return KFAILURE; + *reqid_lenp = idl; + memcpy(p, req_id->dat, (size_t)idl); + p += idl; + + authent->length = p - authent->dat; + /* clean up */ - memset((char *)req_id, 0, sizeof(*req_id)); + memset(req_id, 0, sizeof(*req_id)); if (krb_ap_req_debug) DEB (("Authent->length = %d\n",authent->length)); if (krb_ap_req_debug) - DEB (("idl = %d, tl = %d\n",(int) *idl, (int) *tl)); + DEB (("idl = %d, tl = %d\n", idl, tl)); - return(KSUCCESS); + return KSUCCESS; } /* @@ -223,5 +253,5 @@ int newval; int olife = lifetime; lifetime = newval; - return(olife); + return olife; } diff --git a/src/lib/krb4/mk_safe.c b/src/lib/krb4/mk_safe.c index 5d810ea50a..1efff99535 100644 --- a/src/lib/krb4/mk_safe.c +++ b/src/lib/krb4/mk_safe.c @@ -1,11 +1,27 @@ /* - * mk_safe.c + * lib/krb4/mk_req.c * - * Copyright 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. * * This routine constructs a Kerberos 'safe msg', i.e. authenticated * using a private session key to seed a checksum. Msg is NOT @@ -16,7 +32,6 @@ * Steve Miller Project Athena MIT/DEC */ -#include "mit-copyright.h" #include <stdio.h> #include <string.h> @@ -61,7 +76,7 @@ extern int krb_debug; */ KRB5_DLLIMP long KRB5_CALLCONV -krb_mk_safe(in,out,length,key,sender,receiver) +krb_mk_safe(in, out, length, key, sender, receiver) u_char *in; /* application data */ u_char *out; /* * put msg here, leave room for header! @@ -81,37 +96,38 @@ krb_mk_safe(in,out,length,key,sender,receiver) unsigned KRB4_32 msg_usecs; u_char msg_time_5ms; KRB4_32 msg_time_sec; + int i; + /* Be really paranoid. */ + if (sizeof(sender->sin_addr.s_addr) != 4) + return -1; /* * get the current time to use instead of a sequence #, since * process lifetime may be shorter than the lifetime of a session * key. */ - msg_secs = TIME_GMT_UNIXSEC_US(&msg_usecs); msg_time_sec = msg_secs; - msg_time_5ms = msg_usecs/5000; /* 5ms quanta */ + msg_time_5ms = msg_usecs / 5000; /* 5ms quanta */ p = out; *p++ = KRB_PROT_VERSION; - *p++ = AUTH_MSG_SAFE | HOST_BYTE_ORDER; + *p++ = AUTH_MSG_SAFE; q = p; /* start for checksum stuff */ /* stuff input length */ - memcpy((char *)p, (char *)&length, sizeof(length)); - p += sizeof(length); + KRB4_PUT32(p, length); /* make all the stuff contiguous for checksum */ - memcpy((char *)p, (char *)in, (int) length); + memcpy(p, in, length); p += length; /* stuff time 5ms */ - memcpy((char *)p, (char *)&msg_time_5ms, sizeof(msg_time_5ms)); - p += sizeof(msg_time_5ms); + *p++ = msg_time_5ms; /* stuff source address */ - memcpy((char *)p, (char *) &sender->sin_addr.s_addr, + memcpy(p, &sender->sin_addr.s_addr, sizeof(sender->sin_addr.s_addr)); p += sizeof(sender->sin_addr.s_addr); @@ -122,34 +138,34 @@ krb_mk_safe(in,out,length,key,sender,receiver) /* For compatibility with broken old code, compares are done in VAX byte order (LSBFIRST) */ if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */ - receiver->sin_addr.s_addr)==-1) - msg_time_sec = -msg_time_sec; - else if (lsb_net_ulong_less(sender->sin_addr.s_addr, - receiver->sin_addr.s_addr)==0) - if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1) - msg_time_sec = -msg_time_sec; + receiver->sin_addr.s_addr) == -1) + msg_time_sec = -msg_time_sec; + else if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr) == 0) + if (lsb_net_ushort_less(sender->sin_port, + receiver->sin_port) == -1) + msg_time_sec = -msg_time_sec; /* * all that for one tiny bit! Heaven help those that talk to * themselves. */ /* stuff time sec */ - memcpy((char *)p, (char *)&msg_time_sec, sizeof(msg_time_sec)); - p += sizeof(msg_time_sec); + KRB4_PUT32(p, msg_time_sec); #ifdef NOENCRYPTION cksum = 0; - memset((char*) big_cksum, 0, sizeof(big_cksum)); + memset(big_cksum, 0, sizeof(big_cksum)); #else /* Do encryption */ /* calculate the checksum of length, timestamps, and input data */ cksum = quad_cksum(q, (unsigned KRB4_32 *)big_cksum, - p-q, 2, key); + p - q, 2, key); #endif /* NOENCRYPTION */ - DEB (("\ncksum = %u",cksum)); + DEB(("\ncksum = %u",cksum)); /* stuff checksum */ - memcpy((char *)p, (char *)big_cksum, sizeof(big_cksum)); - p += sizeof(big_cksum); + for (i = 0; i < 4; i++) + KRB4_PUT32(p, big_cksum[i]); - return ((long)(p - out)); /* resulting size */ + return p - out; /* resulting size */ } diff --git a/src/lib/krb4/rd_err.c b/src/lib/krb4/rd_err.c index 80f0d3abdb..6ba9a646c7 100644 --- a/src/lib/krb4/rd_err.c +++ b/src/lib/krb4/rd_err.c @@ -1,17 +1,31 @@ /* - * rd_err.c + * lib/krb4/rd_err.c * - * Copyright 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. * * Steve Miller Project Athena MIT/DEC */ -#include "mit-copyright.h" - #include <string.h> #include "krb.h" @@ -33,37 +47,32 @@ */ KRB5_DLLIMP int KRB5_CALLCONV -krb_rd_err(in,in_length,code,m_data) +krb_rd_err(in, in_length, code, m_data) u_char FAR *in; /* pointer to the msg received */ u_long in_length; /* of in msg */ long FAR *code; /* received error code */ MSG_DAT FAR *m_data; { register u_char *p; - int swap_bytes = 0; + int le; + unsigned KRB4_32 raw_code; + p = in; /* beginning of message */ + if (in_length < 1 + 1 + 4) + return RD_AP_MODIFIED; /* XXX should have better error code */ if (*p++ != KRB_PROT_VERSION) - return(RD_AP_VERSION); + return RD_AP_VERSION; if (((*p) & ~1) != AUTH_MSG_APPL_ERR) - return(RD_AP_MSG_TYPE); - if ((*p++ & 1) != HOST_BYTE_ORDER) - swap_bytes++; + return RD_AP_MSG_TYPE; + le = *p++ & 1; - /* safely get code */ - { - unsigned KRB4_32 raw_code; - - memcpy((char *)&raw_code, (char *)p, sizeof(raw_code)); - if (swap_bytes) - raw_code = krb4_swab32(raw_code); - p += sizeof(raw_code); /* skip over */ - *code = raw_code; - } + KRB4_GET32(raw_code, p, le); + *code = raw_code; /* XXX unsigned->signed conversion! */ m_data->app_data = p; /* we're now at the error text * message */ - m_data->app_length = in_length; + m_data->app_length = p - in; - return(RD_AP_OK); /* OK == 0 */ + return RD_AP_OK; /* OK == 0 */ } diff --git a/src/lib/krb4/rd_preauth.c b/src/lib/krb4/rd_preauth.c index a34d713efe..a9c219215a 100644 --- a/src/lib/krb4/rd_preauth.c +++ b/src/lib/krb4/rd_preauth.c @@ -23,38 +23,39 @@ int -krb_rd_preauth(pkt,preauth_p,preauth_len,auth_pr,key) +krb_rd_preauth(pkt, preauth_p, preauth_len, auth_pr, key) KTEXT pkt; char *preauth_p; int preauth_len; Principal *auth_pr; des_cblock key; { - int st; - char *name_p; + int st; + char *name_p; - name_p = auth_pr->name; + name_p = auth_pr->name; #ifndef NOENCRYPTION - /* Decrypt preauth_p using key as the key and initialization vector. */ - /* check preauth_len */ - if ((((strlen(name_p) + 1) / 8) + 1) *8 != preauth_len) - return KERB_ERR_PREAUTH_SHORT; - else { - des_key_schedule key_s; + /* Decrypt preauth_p using key as the key and initialization vector. */ + /* check preauth_len */ + if ((((strlen(name_p) + 1) / 8) + 1) * 8 != preauth_len) + return KERB_ERR_PREAUTH_SHORT; + else { + des_key_schedule key_s; - if (des_key_sched(key, key_s)) { - return 1; - } - des_pcbc_encrypt((des_cblock *) preauth_p, (des_cblock *) preauth_p, - (long) preauth_len, key_s, (des_cblock *) key, - DES_DECRYPT); - } + if (des_key_sched(key, key_s)) { + return 1; + } + des_pcbc_encrypt((des_cblock *)preauth_p, (des_cblock *)preauth_p, + (long)preauth_len, key_s, (des_cblock *)key, + DES_DECRYPT); + memset(key_s, 0, sizeof(key_s)); + } #endif /* R3_NO_MODIFICATIONS */ - /* since the preauth data has the trailing 0, this just works */ - st = strcmp(preauth_p, name_p); - if (st) + /* since the preauth data has the trailing 0, this just works */ + st = strcmp(preauth_p, name_p); + if (st) return KERB_ERR_PREAUTH_MISMATCH; - return 0; + return 0; } diff --git a/src/lib/krb4/rd_priv.c b/src/lib/krb4/rd_priv.c index 9a2bb26d5f..462d91574d 100644 --- a/src/lib/krb4/rd_priv.c +++ b/src/lib/krb4/rd_priv.c @@ -1,11 +1,27 @@ /* - * rd_priv.c + * lib/krb4/rd_priv.c * - * CopKRB4_32right 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1986, 1987, 1988, 2000 by the Massachusetts Institute of + * Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. * * This routine dissects a a Kerberos 'private msg', decrypting it, * checking its integrity, and returning a pointer to the application @@ -18,8 +34,6 @@ * Steve Miller Project Athena MIT/DEC */ -#include "mit-copyright.h" - /* system include files */ #include <stdio.h> #include <string.h> @@ -66,7 +80,7 @@ int private_msg_ver = KRB_PROT_VERSION; */ KRB5_DLLIMP long KRB5_CALLCONV -krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) +krb_rd_priv(in, in_length, schedule, key, sender, receiver, m_data) u_char *in; /* pointer to the msg received */ unsigned KRB4_32 in_length; /* length of "in" msg */ Key_schedule schedule; /* precomputed key schedule */ @@ -76,30 +90,32 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) MSG_DAT *m_data; /*various input/output data from msg */ { register u_char *p,*q; - unsigned KRB4_32 src_addr; + int v, t, le; + struct in_addr src_addr; unsigned KRB4_32 c_length; int swap_bytes; unsigned KRB4_32 t_local; KRB4_32 delta_t; /* Difference between timestamps */ p = in; /* beginning of message */ +#define IN_REMAIN (in_length - (p - in)) swap_bytes = 0; - if (*p++ != KRB_PROT_VERSION && *(p-1) != 3) + if (IN_REMAIN < 1 + 1 + 4) + return RD_AP_MODIFIED; + v = *p++; + if (v != KRB_PROT_VERSION && v != 3) return RD_AP_VERSION; - private_msg_ver = *(p-1); - if (((*p) & ~1) != AUTH_MSG_PRIVATE) + private_msg_ver = v; + t = *p++; + if ((t & ~1) != AUTH_MSG_PRIVATE) return RD_AP_MSG_TYPE; - if ((*p++ & 1) != HOST_BYTE_ORDER) - swap_bytes++; + le = t & 1; /* get cipher length */ - memcpy((char *)&c_length, (char *)p, sizeof(c_length)); - if (swap_bytes) - c_length = krb4_swab32(c_length); - p += sizeof(c_length); + KRB4_GET32(c_length, p, le); /* check for rational length so we don't go comatose */ - if (VERSION_SZ + MSG_TYPE_SZ + c_length > in_length) + if (IN_REMAIN < c_length) return RD_AP_MODIFIED; #ifndef NOENCRYPTION @@ -118,17 +134,10 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) #endif /* safely get application data length */ - memcpy((char *)&(m_data->app_length), (char *) p, - sizeof(m_data->app_length)); - if (swap_bytes) - m_data->app_length = krb4_swab32(m_data->app_length); - p += sizeof(m_data->app_length); /* skip over */ - - if (m_data->app_length + sizeof(c_length) + sizeof(in_length) + - sizeof(m_data->time_sec) + sizeof(m_data->time_5ms) + - sizeof(src_addr) + VERSION_SZ + MSG_TYPE_SZ - > in_length) - return RD_AP_MODIFIED; + KRB4_GET32(m_data->app_length, p, le); + + if (IN_REMAIN < m_data->app_length + 4 + 1 + 4) + return RD_AP_MODIFIED; #ifndef NOENCRYPTION /* we're now at the decrypted application data */ @@ -138,25 +147,19 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) p += m_data->app_length; /* safely get time_5ms */ - memcpy((char *)&(m_data->time_5ms), (char *) p, - sizeof(m_data->time_5ms)); - /* don't need to swap-- one byte for now */ - p += sizeof(m_data->time_5ms); + m_data->time_5ms = *p++; /* safely get src address */ - memcpy((char *)&src_addr, (char *) p, sizeof(src_addr)); + memcpy(&src_addr.s_addr, p, sizeof(src_addr.s_addr)); /* don't swap, net order always */ - p += sizeof(src_addr); + p += sizeof(src_addr.s_addr); - if (!krb_ignore_ip_address && src_addr != (u_long) sender->sin_addr.s_addr) + if (!krb_ignore_ip_address + && src_addr.s_addr != sender->sin_addr.s_addr) return RD_AP_MODIFIED; /* safely get time_sec */ - memcpy((char *)&(m_data->time_sec), (char *) p, - sizeof(m_data->time_sec)); - if (swap_bytes) m_data->time_sec = krb4_swab32(m_data->time_sec); - - p += sizeof(m_data->time_sec); + KRB4_GET32(m_data->time_sec, p, le); /* check direction bit is the sign bit */ /* For compatibility with broken old code, compares are done in VAX @@ -166,17 +169,18 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) back to the receiver, but most higher level protocols can deal with that more directly. */ if (krb_ignore_ip_address) { - if (m_data->time_sec <0) + if (m_data->time_sec < 0) m_data->time_sec = -m_data->time_sec; } else if (lsb_net_ulong_less(sender->sin_addr.s_addr, - receiver->sin_addr.s_addr)==-1) + receiver->sin_addr.s_addr) == -1) /* src < recv */ - m_data->time_sec = - m_data->time_sec; - else if (lsb_net_ulong_less(sender->sin_addr.s_addr, - receiver->sin_addr.s_addr)==0) - if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1) + m_data->time_sec = -m_data->time_sec; + else if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr) == 0) + if (lsb_net_ushort_less(sender->sin_port, + receiver->sin_port) == -1) /* src < recv */ - m_data->time_sec = - m_data->time_sec; + m_data->time_sec = -m_data->time_sec; /* * all that for one tiny bit! * Heaven help those that talk to themselves. @@ -185,12 +189,12 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) /* check the time integrity of the msg */ t_local = TIME_GMT_UNIXSEC; delta_t = t_local - m_data->time_sec; - if (delta_t < 0) delta_t = -delta_t; /* Absolute value of difference */ + if (delta_t < 0) + delta_t = -delta_t; /* Absolute value of difference */ if (delta_t > CLOCK_SKEW) { - return(RD_AP_TIME); /* XXX should probably be better - code */ + return RD_AP_TIME; /* XXX should probably be better code */ } - DEB (("\ndelta_t = %d",delta_t)); + DEB(("\ndelta_t = %d", delta_t)); /* * caller must check timestamps for proper order and diff --git a/src/lib/krb4/rd_req.c b/src/lib/krb4/rd_req.c index 65fe12b0b9..542828d791 100644 --- a/src/lib/krb4/rd_req.c +++ b/src/lib/krb4/rd_req.c @@ -1,14 +1,29 @@ /* - * rd_req.c + * lib/krb4/rd_req.c * - * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. + * Copyright 1985, 1986, 1987, 1988, 2000 by the Massachusetts + * Institute of Technology. All Rights Reserved. * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. */ -#include "mit-copyright.h" #include "des.h" #include "krb.h" #include "prot.h" @@ -68,7 +83,7 @@ static int krb5_key; /* whether krb5 key is used for decrypt */ static krb5_keyblock srv_k5key; int -krb_set_key(key,cvt) +krb_set_key(key, cvt) char *key; int cvt; { @@ -81,10 +96,10 @@ krb_set_key(key,cvt) return KSUCCESS; #else /* Encrypt */ if (cvt) - string_to_key(key,ky); + string_to_key(key, ky); else memcpy((char *)ky, key, 8); - return(des_key_sched(ky,serv_key)); + return des_key_sched(ky,serv_key); #endif /* NOENCRYPTION */ } @@ -108,19 +123,6 @@ krb_clear_key_krb5(ctx) krb5_key = 0; } -/* A helper function to let us see if a buffer is properly terminated. */ -static int -krb_strnlen(const char *str, size_t max_len) -{ - int i = 0; - for(i = 0; i < max_len; i++) { - if(str[i] == '\0') { - return i; - } - } - return -1; -} - /* * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(), @@ -163,7 +165,7 @@ krb_strnlen(const char *str, size_t max_len) */ KRB5_DLLIMP int KRB5_CALLCONV -krb_rd_req(authent,service,instance,from_addr,ad,fn) +krb_rd_req(authent, service, instance, from_addr, ad, fn) register KTEXT authent; /* The received message */ char FAR *service; /* Service name */ char FAR *instance; /* Service instance */ @@ -186,45 +188,48 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) char r_realm[REALM_SZ]; /* Client realm from authenticator */ unsigned int r_time_ms; /* Fine time from authenticator */ unsigned KRB4_32 r_time_sec; /* Coarse time from authenticator */ - register char *ptr; /* For stepping through */ + register unsigned char *ptr; /* For stepping through */ unsigned KRB4_32 t_local; /* Local time on our side of the protocol */ KRB4_32 delta_t; /* Time in authenticator minus local time */ KRB4_32 tkt_age; /* Age of ticket */ - int swap_bytes; /* Need to swap bytes? */ + int le; /* is little endian? */ int mutual; /* Mutual authentication requested? */ + int t; /* msg type */ unsigned char s_kvno; /* Version number of the server's key Kerberos used to encrypt ticket */ + int ret; + int len; krb5_keyblock keyblock; int status; tkt->mbz = req_id->mbz = 0; - if (authent->length <= 0) - return(RD_AP_MODIFIED); + if (authent->length < 1 + 1 + 1) + return RD_AP_MODIFIED; - ptr = (char *) authent->dat; + ptr = authent->dat; +#define AUTHENT_REMAIN (authent->length - (ptr - authent->dat)) /* get msg version, type and byte order, and server key version */ /* check version */ - if (KRB_PROT_VERSION != (unsigned int) *ptr++) - return(RD_AP_VERSION); + if (KRB_PROT_VERSION != *ptr++) + return RD_AP_VERSION; /* byte order */ - swap_bytes = 0; - if ((*ptr & 1) != HOST_BYTE_ORDER) - swap_bytes++; + t = *ptr++; + le = t & 1; /* check msg type */ mutual = 0; - switch (*ptr++ & ~1) { + switch (t & ~1) { case AUTH_MSG_APPL_REQUEST: break; case AUTH_MSG_APPL_REQUEST_MUTUAL: mutual++; break; default: - return(RD_AP_MSG_TYPE); + return RD_AP_MSG_TYPE; } #ifdef lint @@ -234,13 +239,14 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) mutual = 0; #endif /* lint */ s_kvno = *ptr++; /* get server key version */ - if(krb_strnlen(ptr, sizeof(realm)) < 0) { + len = krb_strnlen((char *)ptr, AUTHENT_REMAIN) + 1; + if (len <= 0 || len > sizeof(realm)) { return RD_AP_MODIFIED; /* must have been modified, the client wouldn't try to trick us with wacky data */ } - (void) strncpy(realm,ptr,REALM_SZ); /* And the realm of the issuing KDC */ - realm[REALM_SZ-1] = '\0'; - ptr += strlen(realm) + 1; /* skip the realm "hint" */ + /* And the realm of the issuing KDC */ + (void)memcpy(realm, ptr, (size_t)len); + ptr += len; /* skip the realm "hint" */ /* * If "fn" is NULL, key info should already be set; don't @@ -250,38 +256,50 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) * from the ticket file. If "fn" is the null string, use the * default ticket file. */ - if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) || - strcmp(st_rlm,realm) || (st_kvno != s_kvno))) { - if (*fn == 0) fn = KEYFILE; + if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) + || strcmp(st_rlm,realm) || (st_kvno != s_kvno))) { + if (*fn == 0) + fn = KEYFILE; st_kvno = s_kvno; #ifndef NOENCRYPTION - if (read_service_key(service,instance,realm,(int) s_kvno, - fn,(char *)skey) == 0) { - if ((status = krb_set_key((char *)skey,0))) - return(status); + if (read_service_key(service,instance,realm, (int)s_kvno, + fn, (char *)skey) == 0) { + if ((status = krb_set_key((char *)skey,0))) + return(status); #ifdef KRB4_USE_KEYTAB - } else if (krb54_get_service_keyblock(service,instance, - realm, (int) s_kvno,fn, &keyblock) == 0) { - krb_set_key_krb5(krb5__krb4_context, &keyblock); - krb5_free_keyblock_contents(krb5__krb4_context, &keyblock); + } else if (krb54_get_service_keyblock(service, instance, + realm, (int)s_kvno, + fn, &keyblock) == 0) { + krb_set_key_krb5(krb5__krb4_context, &keyblock); + krb5_free_keyblock_contents(krb5__krb4_context, &keyblock); #endif } else - return(RD_AP_UNDEC); - + return RD_AP_UNDEC; #endif /* !NOENCRYPTION */ - (void) strncpy(st_rlm,realm, sizeof(st_rlm) - 1); - st_rlm[sizeof(st_rlm) - 1] = '\0'; - (void) strncpy(st_nam,service, sizeof(st_nam) - 1); - st_nam[sizeof(st_nam) - 1] = '\0'; - (void) strncpy(st_inst,instance, sizeof(st_inst) - 1); - st_inst[sizeof(st_inst) - 1] = '\0'; + + len = krb_strnlen(realm, sizeof(st_rlm)) + 1; + if (len <= 0) + return KFAILURE; + memcpy(st_rlm, realm, (size_t)len); + len = krb_strnlen(service, sizeof(st_nam)) + 1; + if (len <= 0) + return KFAILURE; + memcpy(st_nam, service, (size_t)len); + len = krb_strnlen(instance, sizeof(st_inst)) + 1; + if (len <= 0) + return KFAILURE; + memcpy(st_inst, instance, (size_t)len); } - /* Get ticket from authenticator */ - tkt->length = (int) *ptr++ & 0xff; - if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length) - return(RD_AP_MODIFIED); - memcpy((char *)(tkt->dat), ptr+1, tkt->length); + /* Get ticket length */ + tkt->length = *ptr++; + /* Get authenticator length while we're at it. */ + req_id->length = *ptr++; + if (AUTHENT_REMAIN < tkt->length + req_id->length) + return RD_AP_MODIFIED; + /* Copy ticket */ + memcpy(tkt->dat, ptr, (size_t)tkt->length); + ptr += tkt->length; #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) @@ -312,7 +330,6 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) } } - #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) { log("Ticket Contents."); @@ -325,73 +342,81 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) #endif /* Extract the authenticator */ - req_id->length = (int) *(ptr++); - if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) > - authent->length) - return(RD_AP_MODIFIED); - memcpy((char *)(req_id->dat), ptr + tkt->length, req_id->length); + memcpy(req_id->dat, ptr, (size_t)req_id->length); #ifndef NOENCRYPTION /* And decrypt it with the session key from the ticket */ #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) log("About to decrypt authenticator"); #endif - key_sched(ad->session,seskey_sched); - pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, - (long) req_id->length, seskey_sched,&ad->session,DES_DECRYPT); + + key_sched(ad->session, seskey_sched); + pcbc_encrypt((C_Block *)req_id->dat, (C_Block *)req_id->dat, + (long)req_id->length, + seskey_sched, &ad->session, DES_DECRYPT); + memset(seskey_sched, 0, sizeof(seskey_sched)); + #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) log("Done."); #endif #endif /* NOENCRYPTION */ -#define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED); - - ptr = (char *) req_id->dat; - (void) strncpy(r_aname,ptr,ANAME_SZ); /* Authentication name */ - r_aname[ANAME_SZ-1] = '\0'; - ptr += strlen(r_aname)+1; - check_ptr(); - (void) strncpy(r_inst,ptr,INST_SZ); /* Authentication instance */ - r_inst[INST_SZ-1] = '\0'; - ptr += strlen(r_inst)+1; - check_ptr(); - (void) strncpy(r_realm,ptr,REALM_SZ); /* Authentication name */ - r_realm[REALM_SZ-1] = '\0'; - ptr += strlen(r_realm)+1; - check_ptr(); - memcpy((char *)&ad->checksum, ptr, 4); /* Checksum */ - ptr += 4; - check_ptr(); - if (swap_bytes) ad->checksum = krb4_swab32(ad->checksum); - r_time_ms = *(ptr++); /* Time (fine) */ + ptr = req_id->dat; +#define REQID_REMAIN (req_id->length - (ptr - req_id->dat)) + + ret = RD_AP_MODIFIED; + + len = krb_strnlen((char *)ptr, REQID_REMAIN) + 1; + if (len <= 0 || len > ANAME_SZ) + goto cleanup; + memcpy(r_aname, ptr, (size_t)len); /* Authentication name */ + ptr += len; + len = krb_strnlen((char *)ptr, REQID_REMAIN) + 1; + if (len <= 0 || len > INST_SZ) + goto cleanup; + memcpy(r_inst, ptr, (size_t)len); /* Authentication instance */ + ptr += len; + len = krb_strnlen((char *)ptr, REQID_REMAIN) + 1; + if (len <= 0 || len > REALM_SZ) + goto cleanup; + memcpy(r_realm, ptr, (size_t)len); /* Authentication name */ + ptr += len; + + if (REQID_REMAIN < 4 + 1 + 4) + goto cleanup; + KRB4_GET32(ad->checksum, ptr, le); + r_time_ms = *ptr++; /* Time (fine) */ #ifdef lint /* XXX r_time_ms is set but not used. why??? */ /* this is a crock to get lint to shut up */ if (r_time_ms) r_time_ms = 0; #endif /* lint */ - check_ptr(); - /* assume sizeof(r_time_sec) == 4 ?? */ - memcpy((char *)&r_time_sec, ptr, 4); /* Time (coarse) */ - if (swap_bytes) r_time_sec = krb4_swab32(r_time_sec); + /* Time (coarse) */ + KRB4_GET32(r_time_sec, ptr, le); /* Check for authenticity of the request */ #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) log("Pname: %s %s",ad->pname,r_aname); #endif + + ret = RD_AP_INCON; if (strcmp(ad->pname,r_aname) != 0) - return(RD_AP_INCON); + goto cleanup; if (strcmp(ad->pinst,r_inst) != 0) - return(RD_AP_INCON); + goto cleanup; + #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) log("Realm: %s %s",ad->prealm,r_realm); #endif - if ((strcmp(ad->prealm,r_realm) != 0)) - return(RD_AP_INCON); + + if (strcmp(ad->prealm,r_realm) != 0) + goto cleanup; /* check the time integrity of the msg */ + ret = RD_AP_TIME; t_local = TIME_GMT_UNIXSEC; delta_t = t_local - r_time_sec; if (delta_t < 0) delta_t = -delta_t; /* Absolute value of difference */ @@ -401,11 +426,12 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) log("Time out of range: %d - %d = %d", time_secs, r_time_sec, delta_t); #endif - return(RD_AP_TIME); + goto cleanup; } /* Now check for expiration of ticket */ + ret = RD_AP_NYV; tkt_age = t_local - ad->time_sec; #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) @@ -414,21 +440,34 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) #endif if (t_local < ad->time_sec) { if ((ad->time_sec - t_local) > CLOCK_SKEW) - return(RD_AP_NYV); + goto cleanup; + } else if (krb_life_to_time((KRB4_32)ad->time_sec, ad->life) + < t_local + CLOCK_SKEW) { + ret = RD_AP_EXP; + goto cleanup; } - else if (krb_life_to_time((KRB4_32)ad->time_sec, ad->life) - < t_local + CLOCK_SKEW) - return(RD_AP_EXP); #ifdef KRB_CRYPT_DEBUG if (krb_ap_req_debug) log("Address: %d %d",ad->address,from_addr); #endif - if (!krb_ignore_ip_address && from_addr && (ad->address != from_addr)) - return(RD_AP_BADD); + + if (!krb_ignore_ip_address + && from_addr && (ad->address != from_addr)) { + ret = RD_AP_BADD; + goto cleanup; + } /* All seems OK */ ad->reply.length = 0; + ret = 0; + +cleanup: + if (ret) { + /* Stomp on session key if there is an error. */ + memset(ad->session, 0, sizeof(ad->session)); + return ret; + } - return(RD_AP_OK); + return RD_AP_OK; } diff --git a/src/lib/krb4/rd_safe.c b/src/lib/krb4/rd_safe.c index cade67b628..23578a2209 100644 --- a/src/lib/krb4/rd_safe.c +++ b/src/lib/krb4/rd_safe.c @@ -1,12 +1,28 @@ /* - * rd_safe.c + * lib/krb4/rd_safe.c * - * CopKRB4_32right 1986, 1987, 1988 by the Massachusetts Institute - * of Technology. - * - * For copying and distribution information, please see the file - * <mit-copyright.h>. + * Copyright 1986, 1987, 1988, 2000 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. + * * This routine dissects a a Kerberos 'safe msg', checking its * integrity, and returning a pointer to the application data * contained and its length. @@ -16,8 +32,6 @@ * Steve Miller Project Athena MIT/DEC */ -#include "mit-copyright.h" - /* system include files */ #include <stdio.h> #include <string.h> @@ -57,45 +71,45 @@ krb_rd_safe(in,in_length,key,sender,receiver,m_data) struct sockaddr_in FAR *receiver; /* receiver's address -- me */ MSG_DAT FAR *m_data; /* where to put message information */ { + int i; unsigned KRB4_32 calc_cksum[4]; unsigned KRB4_32 big_cksum[4]; - int swap_bytes; + int le; u_char *p,*q; - unsigned KRB4_32 src_addr; /* Can't send structs since no - * guarantees on size */ + int t; + struct in_addr src_addr; unsigned KRB4_32 t_local; /* Local time in our machine */ KRB4_32 delta_t; /* Difference between timestamps */ /* Be very conservative */ - if (sizeof(src_addr) != sizeof(struct in_addr)) { + if (sizeof(src_addr.s_addr) != 4) { #ifdef DEBUG - fprintf(stderr,"\n\ -krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); + fprintf(stderr, "\nkrb_rd_safe protocol err " + "sizeof(src_addr.s_addr) != 4\n"); #endif - return RD_AP_VERSION; + return RD_AP_VERSION; } p = in; /* beginning of message */ - swap_bytes = 0; +#define IN_REMAIN (in_length - (p - in)) + if (IN_REMAIN < 1 + 1 + 4) + return RD_AP_MODIFIED; - if (*p++ != KRB_PROT_VERSION) return RD_AP_VERSION; - if (((*p) & ~1) != AUTH_MSG_SAFE) return RD_AP_MSG_TYPE; - if ((*p++ & 1) != HOST_BYTE_ORDER) swap_bytes++; + if (*p++ != KRB_PROT_VERSION) + return RD_AP_VERSION; + t = *p++; + if ((t & ~1) != AUTH_MSG_SAFE) + return RD_AP_MSG_TYPE; + le = t & 1; q = p; /* mark start of cksum stuff */ /* safely get length */ - memcpy((char *)&(m_data->app_length), (char *)p, - sizeof(m_data->app_length)); - if (swap_bytes) m_data->app_length = krb4_swab32(m_data->app_length); - p += sizeof(m_data->app_length); /* skip over */ + KRB4_GET32(m_data->app_length, p, le); - if (m_data->app_length + sizeof(in_length) - + sizeof(m_data->time_sec) + sizeof(m_data->time_5ms) - + sizeof(big_cksum) + sizeof(src_addr) - + VERSION_SZ + MSG_TYPE_SZ > in_length) - return(RD_AP_MODIFIED); + if (IN_REMAIN < m_data->app_length + 1 + 4 + 4 + 4 * 4) + return RD_AP_MODIFIED; m_data->app_data = p; /* we're now at the application data */ @@ -103,28 +117,19 @@ krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); p += m_data->app_length; /* safely get time_5ms */ - memcpy((char *)&(m_data->time_5ms), (char *)p, - sizeof(m_data->time_5ms)); - - /* don't need to swap-- one byte for now */ - p += sizeof(m_data->time_5ms); + m_data->time_5ms = *p++; /* safely get src address */ - memcpy((char *)&src_addr, (char *)p, sizeof(src_addr)); - + (void)memcpy(&src_addr.s_addr, p, sizeof(src_addr.s_addr)); /* don't swap, net order always */ - p += sizeof(src_addr); + p += sizeof(src_addr.s_addr); - if (!krb_ignore_ip_address && - src_addr != (unsigned KRB4_32) sender->sin_addr.s_addr) + if (!krb_ignore_ip_address + && src_addr.s_addr != sender->sin_addr.s_addr) return RD_AP_MODIFIED; /* safely get time_sec */ - memcpy((char *)&(m_data->time_sec), (char *)p, - sizeof(m_data->time_sec)); - if (swap_bytes) - m_data->time_sec = krb4_swab32(m_data->time_sec); - p += sizeof(m_data->time_sec); + KRB4_GET32(m_data->time_sec, p, le); /* check direction bit is the sign bit */ /* For compatibility with broken old code, compares are done in VAX @@ -166,15 +171,6 @@ krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); * and we don't assume tightly synchronized clocks. */ - memcpy((char *)big_cksum, (char *)p, sizeof(big_cksum)); - if (swap_bytes) { - /* swap_u_16(big_cksum); */ - unsigned KRB4_32 *bb; - bb = (unsigned KRB4_32*)big_cksum; - bb[0] = krb4_swab32(bb[0]); bb[1] = krb4_swab32(bb[1]); - bb[2] = krb4_swab32(bb[2]); bb[3] = krb4_swab32(bb[3]); - } - #ifdef NOENCRYPTION memset(calc_cksum, 0, sizeof(calc_cksum)); #else /* Do encryption */ @@ -183,13 +179,17 @@ krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); quad_cksum(q,calc_cksum,p-q,2,key); #endif /* NOENCRYPTION */ + for (i = 0; i < 4; i++) + KRB4_GET32(big_cksum[i], p, le); + DEB (("\n0: calc %l big %lx\n1: calc %lx big %lx\n2: calc %lx big %lx\n3: calc %lx big %lx\n", calc_cksum[0], big_cksum[0], calc_cksum[1], big_cksum[1], calc_cksum[2], big_cksum[2], calc_cksum[3], big_cksum[3])); - if (memcmp((char *)big_cksum,(char *)calc_cksum,sizeof(big_cksum))) - return(RD_AP_MODIFIED); + for (i = 0; i < 4; i++) + if (big_cksum[i] != calc_cksum[i]) + return RD_AP_MODIFIED; - return(RD_AP_OK); /* OK == 0 */ + return RD_AP_OK; /* OK == 0 */ } diff --git a/src/lib/krb4/send_to_kdc.c b/src/lib/krb4/send_to_kdc.c index f93b9d0793..5897f67618 100644 --- a/src/lib/krb4/send_to_kdc.c +++ b/src/lib/krb4/send_to_kdc.c @@ -370,6 +370,7 @@ send_recv(pkt,rpkt,f,_to,addrs) DEB (("Recvfrom error %d\n", SOCKET_ERRNO)); return 0; } + rpkt->length = recvresult; #ifdef DEBUG if (krb_debug) { printf("received packet from "); diff --git a/src/lib/krb4/strnlen.c b/src/lib/krb4/strnlen.c new file mode 100644 index 0000000000..2c9a026f92 --- /dev/null +++ b/src/lib/krb4/strnlen.c @@ -0,0 +1,48 @@ +/* + * lib/krb4/strnlen.c + * + * Copyright 2000 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. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * 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. + * + */ + +#include <stddef.h> +#include "krb.h" +/* + * krb_strnlen() + * + * Return the length of the string if a NUL is found in the first n + * bytes, otherwise, -1. + */ + +KRB5_CALLCONV int +krb_strnlen(const char *s, int n) +{ + int i = 0; + + for (i = 0; i < n; i++) { + if (s[i] == '\0') { + return i; + } + } + return -1; +} |