diff options
Diffstat (limited to 'src/lib/krb4/g_in_tkt.c')
-rw-r--r-- | src/lib/krb4/g_in_tkt.c | 337 |
1 files changed, 185 insertions, 152 deletions
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); } - |