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