From bf45f66f9f50d680d71794e14e0c3467138bd0c3 Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Sat, 5 Dec 1998 05:38:29 +0000 Subject: [PATCH] rd_svc_key.c (krb54_get_service_keyblock): New function which searches the appropaite krb5 keytab file for the key to be used by the krb4 library. rd_req.c (krb_rd_req): If the appropriate key cannot be found in the krb4 srvtab file, try calling krb54_get_service_keyblock. decomp_tkt.c (dcmp_tkt_int): g_in_tkt.c (krb_mk_in_tkt_preauth): g_ad_tkt.c (get_ad_tkt): pkt_clen.c (pkt_clen): rd_err.c (krb_rd_err): rd_priv.c (krb_rd_priv): rd_req.c (krb_rd_req): rd_safe.c (krb_rd_safe): Use krb4_swab32 and krb4_swab16 instead of swap_u_long and swap_u_short. The new byte swapping routines are faster and cleaner. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11067 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb4/ChangeLog | 20 +++++ src/lib/krb4/decomp_tkt.c | 2 +- src/lib/krb4/g_ad_tkt.c | 4 +- src/lib/krb4/g_in_tkt.c | 6 +- src/lib/krb4/pkt_clen.c | 9 +-- src/lib/krb4/rd_err.c | 2 +- src/lib/krb4/rd_priv.c | 8 +- src/lib/krb4/rd_req.c | 24 ++++-- src/lib/krb4/rd_safe.c | 12 ++- src/lib/krb4/rd_svc_key.c | 159 ++++++++++++++++++++++++++------------ 10 files changed, 165 insertions(+), 81 deletions(-) diff --git a/src/lib/krb4/ChangeLog b/src/lib/krb4/ChangeLog index 8f1b77952..5b1554a2a 100644 --- a/src/lib/krb4/ChangeLog +++ b/src/lib/krb4/ChangeLog @@ -1,3 +1,23 @@ +1998-12-05 Theodore Ts'o + + * rd_svc_key.c (krb54_get_service_keyblock): New function which + searches the appropaite krb5 keytab file for the key to be + used by the krb4 library. + + * rd_req.c (krb_rd_req): If the appropriate key cannot be found in + the krb4 srvtab file, try calling krb54_get_service_keyblock. + + * decomp_tkt.c (dcmp_tkt_int): + * g_in_tkt.c (krb_mk_in_tkt_preauth): + * g_ad_tkt.c (get_ad_tkt): + * pkt_clen.c (pkt_clen): + * rd_err.c (krb_rd_err): + * rd_priv.c (krb_rd_priv): + * rd_req.c (krb_rd_req): + * rd_safe.c (krb_rd_safe): Use krb4_swab32 and krb4_swab16 instead + of swap_u_long and swap_u_short. The new byte swapping + routines are faster and cleaner. + 1998-11-13 Theodore Ts'o * Makefile.in: Set the myfulldir and mydir variables (which are diff --git a/src/lib/krb4/decomp_tkt.c b/src/lib/krb4/decomp_tkt.c index d4dfd4edc..03398acd5 100644 --- a/src/lib/krb4/decomp_tkt.c +++ b/src/lib/krb4/decomp_tkt.c @@ -221,7 +221,7 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, memcpy((char *) time_sec, ptr, 4); /* issue time */ ptr += 4; if (tkt_swap_bytes) - swap_u_long(*time_sec); + *time_sec = krb4_swab32(*time_sec); (void) strcpy(sname,ptr); /* service name */ ptr += 1 + strlen(sname); diff --git a/src/lib/krb4/g_ad_tkt.c b/src/lib/krb4/g_ad_tkt.c index 55a82bb71..b3abb2ddc 100644 --- a/src/lib/krb4/g_ad_tkt.c +++ b/src/lib/krb4/g_ad_tkt.c @@ -170,7 +170,7 @@ get_ad_tkt(service,sinstance,realm,lifetime) case AUTH_MSG_ERR_REPLY: memcpy((char *) &rep_err_code, pkt_err_code(rpkt), 4); if (swap_bytes) - swap_u_long(rep_err_code); + rep_err_code = krb4_swab32(rep_err_code); return(rep_err_code); default: @@ -221,7 +221,7 @@ get_ad_tkt(service,sinstance,realm,lifetime) /* check KDC time stamp */ memcpy((char *)&kdc_time, ptr, 4); /* Time (coarse) */ - if (swap_bytes) swap_u_long(kdc_time); + if (swap_bytes) kdc_time = krb4_swab32(kdc_time); ptr += 4; diff --git a/src/lib/krb4/g_in_tkt.c b/src/lib/krb4/g_in_tkt.c index 3fc784e77..c9d618382 100644 --- a/src/lib/krb4/g_in_tkt.c +++ b/src/lib/krb4/g_in_tkt.c @@ -204,7 +204,7 @@ krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life, break; case AUTH_MSG_ERR_REPLY: memcpy((char *) &rep_err_code, pkt_err_code(rpkt), 4); - if (swap_bytes) swap_u_long(rep_err_code); + if (swap_bytes) rep_err_code = krb4_swab32(rep_err_code); return((int)rep_err_code); default: return(INTK_PROT); @@ -216,7 +216,7 @@ krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life, /* not used */ /* get the principal's expiration date */ memcpy((char *) &exp_date, pkt_x_date(rpkt), sizeof(exp_date)); - if (swap_bytes) swap_u_long(exp_date); + if (swap_bytes) exp_data = krb4_swab32(exp_date); #endif /* Extract the ciphertext */ @@ -307,7 +307,7 @@ krb_parse_in_tkt(user, instance, realm, service, sinstance, life, cip) /* check KDC time stamp */ memcpy((char *)&kdc_time, ptr, 4); /* Time (coarse) */ - if (swap_bytes) swap_u_long(kdc_time); + if (swap_bytes) kdc_time = krb4_swab32(kdc_time); ptr += 4; diff --git a/src/lib/krb4/pkt_clen.c b/src/lib/krb4/pkt_clen.c index 99a712b8d..352c91d4e 100644 --- a/src/lib/krb4/pkt_clen.c +++ b/src/lib/krb4/pkt_clen.c @@ -27,7 +27,7 @@ int swap_bytes; pkt_clen(pkt) KTEXT pkt; { - static unsigned short temp,temp2; + static unsigned short temp; int clen = 0; /* Start of ticket list */ @@ -36,11 +36,8 @@ pkt_clen(pkt) /* Finally the length */ memcpy((char *)&temp, (char *)(++ptr), 2); /* alignment */ - if (swap_bytes) { - /* assume a short is 2 bytes?? */ - swab((char *)&temp,(char *)&temp2,2); - temp = temp2; - } + if (swap_bytes) + temp = krb4_swab16(temp); clen = (int) temp; diff --git a/src/lib/krb4/rd_err.c b/src/lib/krb4/rd_err.c index b7f6a8cc9..80f0d3abd 100644 --- a/src/lib/krb4/rd_err.c +++ b/src/lib/krb4/rd_err.c @@ -56,7 +56,7 @@ krb_rd_err(in,in_length,code,m_data) memcpy((char *)&raw_code, (char *)p, sizeof(raw_code)); if (swap_bytes) - swap_u_long(raw_code); + raw_code = krb4_swab32(raw_code); p += sizeof(raw_code); /* skip over */ *code = raw_code; } diff --git a/src/lib/krb4/rd_priv.c b/src/lib/krb4/rd_priv.c index 4a3088616..44add9a76 100644 --- a/src/lib/krb4/rd_priv.c +++ b/src/lib/krb4/rd_priv.c @@ -96,7 +96,7 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) /* get cipher length */ memcpy((char *)&c_length, (char *)p, sizeof(c_length)); if (swap_bytes) - swap_u_long(c_length); + c_length = krb4_swab32(c_length); p += sizeof(c_length); /* check for rational length so we don't go comatose */ if (VERSION_SZ + MSG_TYPE_SZ + c_length > in_length) @@ -121,7 +121,7 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) memcpy((char *)&(m_data->app_length), (char *) p, sizeof(m_data->app_length)); if (swap_bytes) - swap_u_long(m_data->app_length); + 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) + @@ -154,7 +154,7 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) /* safely get time_sec */ memcpy((char *)&(m_data->time_sec), (char *) p, sizeof(m_data->time_sec)); - if (swap_bytes) swap_u_long(m_data->time_sec); + if (swap_bytes) m_data->time_sec = krb4_swab32(m_data->time_sec); p += sizeof(m_data->time_sec); @@ -201,7 +201,7 @@ krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) #ifdef notdef memcpy((char *)&cksum, (char *) p, sizeof(cksum)); - if (swap_bytes) swap_u_long(cksum) + if (swap_bytes) cksum = krb4_swab32(cksum) /* * calculate the checksum of the length, sequence, * and input data, on the sending byte order!! diff --git a/src/lib/krb4/rd_req.c b/src/lib/krb4/rd_req.c index a78aadc88..8da0b625b 100644 --- a/src/lib/krb4/rd_req.c +++ b/src/lib/krb4/rd_req.c @@ -13,6 +13,8 @@ #include "krb.h" #include "prot.h" #include +#include +#include extern int krb_ap_req_debug; @@ -63,7 +65,6 @@ static int krb5_key; /* whether krb5 key is used for decrypt */ * krb_rd_req(). */ -#include static krb5_keyblock srv_k5key; int @@ -180,6 +181,7 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) int mutual; /* Mutual authentication requested? */ unsigned char s_kvno; /* Version number of the server's key Kerberos used to encrypt ticket */ + krb5_keyblock keyblock; int status; if (authent->length <= 0) @@ -234,10 +236,16 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) st_kvno = s_kvno; #ifndef NOENCRYPTION if (read_service_key(service,instance,realm,(int) s_kvno, - fn,(char *)skey)) - return(RD_AP_UNDEC); - if (status = krb_set_key((char *)skey,0)) - return(status); + fn,(char *)skey) == 0) { + if ((status = krb_set_key((char *)skey,0))) + return(status); + } 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 + return(RD_AP_UNDEC); + #endif /* !NOENCRYPTION */ (void) strcpy(st_rlm,realm); (void) strcpy(st_nam,service); @@ -274,7 +282,7 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) if (decomp_tkt_krb5(tkt, &ad->k_flags, ad->pname, ad->pinst, ad->prealm, &ad->address, ad->session, &ad->life, &ad->time_sec, sname, iname, - srv_k5key)) { + &srv_k5key)) { return RD_AP_UNDEC; } } @@ -326,7 +334,7 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) memcpy((char *)&ad->checksum, ptr, 4); /* Checksum */ ptr += 4; check_ptr(); - if (swap_bytes) swap_u_long(ad->checksum); + if (swap_bytes) ad->checksum = krb4_swab32(ad->checksum); r_time_ms = *(ptr++); /* Time (fine) */ #ifdef lint /* XXX r_time_ms is set but not used. why??? */ @@ -337,7 +345,7 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) check_ptr(); /* assume sizeof(r_time_sec) == 4 ?? */ memcpy((char *)&r_time_sec, ptr, 4); /* Time (coarse) */ - if (swap_bytes) swap_u_long(r_time_sec); + if (swap_bytes) r_time_sec = krb4_swab32(r_time_sec); /* Check for authenticity of the request */ #ifdef KRB_CRYPT_DEBUG diff --git a/src/lib/krb4/rd_safe.c b/src/lib/krb4/rd_safe.c index 52fdf3ab1..f60e05922 100644 --- a/src/lib/krb4/rd_safe.c +++ b/src/lib/krb4/rd_safe.c @@ -88,7 +88,7 @@ krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); /* safely get length */ memcpy((char *)&(m_data->app_length), (char *)p, sizeof(m_data->app_length)); - if (swap_bytes) swap_u_long(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(in_length) @@ -123,7 +123,7 @@ krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); memcpy((char *)&(m_data->time_sec), (char *)p, sizeof(m_data->time_sec)); if (swap_bytes) - swap_u_long(m_data->time_sec); + m_data->time_sec = krb4_swab32(m_data->time_sec); p += sizeof(m_data->time_sec); /* check direction bit is the sign bit */ @@ -169,12 +169,10 @@ krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); memcpy((char *)big_cksum, (char *)p, sizeof(big_cksum)); if (swap_bytes) { /* swap_u_16(big_cksum); */ - unsigned KRB4_32 tt, *bb; + unsigned KRB4_32 *bb; bb = (unsigned KRB4_32*)big_cksum; - tt = bb[0]; swap_u_long(tt); bb[0] = tt; - tt = bb[1]; swap_u_long(tt); bb[1] = tt; - tt = bb[2]; swap_u_long(tt); bb[2] = tt; - tt = bb[3]; swap_u_long(tt); bb[3] = tt; + 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 diff --git a/src/lib/krb4/rd_svc_key.c b/src/lib/krb4/rd_svc_key.c index 34924baf5..0ee9717a8 100644 --- a/src/lib/krb4/rd_svc_key.c +++ b/src/lib/krb4/rd_svc_key.c @@ -14,6 +14,7 @@ #include #include "k5-int.h" +#include extern char *krb__get_srvtabname(); @@ -113,78 +114,138 @@ int vxworks_srvtab_read(fd, s, n) } #endif -KRB5_DLLIMP int KRB5_CALLCONV -read_service_key(service,instance,realm,kvno,file,key) +#ifdef KRB4_USE_KEYTAB +/* + * This function looks up the requested Krb4 srvtab key using the krb5 + * keytab format, if possible. + */ +extern krb5_error_code +krb54_get_service_keyblock(service,instance,realm,kvno,file,keyblock) char FAR *service; /* Service Name */ char FAR *instance; /* Instance name or "*" */ char FAR *realm; /* Realm */ int kvno; /* Key version number */ char FAR *file; /* Filename */ - char FAR *key; /* Pointer to key to be filled in */ + krb5_keyblock FAR * keyblock; { - int kret; - -#ifdef KRB4_USE_KEYTAB krb5_error_code retval; - krb5_context context; - krb5_principal princ; + krb5_principal princ = NULL; krb5_keytab kt_id; krb5_keytab_entry kt_entry; char sname[ANAME_SZ+1]; char sinst[INST_SZ+1]; char srealm[REALM_SZ+1]; char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */ + + if (!krb5__krb4_context) { + retval = krb5_init_context(&krb5__krb4_context); + if (retval) + return retval; + } + + if (!strcmp(instance, "*")) { + if ((retval = krb5_sname_to_principal(krb5__krb4_context, NULL, NULL, + KRB5_NT_SRV_HST, &princ))) + goto errout; + + if ((retval = krb5_524_conv_principal(krb5__krb4_context, princ, + sname, sinst, srealm))) + goto errout; + + instance = sinst; + krb5_free_principal(krb5__krb4_context, princ); + princ = 0; + } + + if ((retval = krb5_425_conv_principal(krb5__krb4_context, service, + instance, realm, &princ))) + goto errout; + + /* + * Figure out what name to use; if the name is one of the standard + * /etc/srbtab, /etc/athena/srvtab, etc., use the default keytab + * name. Otherwise, append .krb5 to the filename and try to use + * that. + */ + if (file && + strcmp(file, "/etc/srvtab") && + strcmp(file, "/etc/athena/srvtab") && + strcmp(file, KEYFILE)) { + strncpy(keytabname, file, sizeof(keytabname)); + keytabname[sizeof(keytabname)-1] = 0; + if (strlen(keytabname)+6 < sizeof(keytabname)) + strcat(keytabname, ".krb5"); + } else { + if ((retval = krb5_kt_default_name(krb5__krb4_context, + (char *)keytabname, sizeof(keytabname)-1))) + goto errout; + } + + if ((retval = krb5_kt_resolve(krb5__krb4_context, keytabname, &kt_id))) + goto errout; + + if ((retval = krb5_kt_get_entry(krb5__krb4_context, kt_id, princ, kvno, + 0, &kt_entry))) { + krb5_kt_close(krb5__krb4_context, kt_id); + goto errout; + } + + retval = krb5_copy_keyblock_contents(krb5__krb4_context, + &kt_entry.key, keyblock); + + krb5_kt_free_entry(krb5__krb4_context, &kt_entry); + +errout: + if (princ) + krb5_free_principal(krb5__krb4_context, princ); + return retval; +} #endif - kret = get_service_key(service,instance,realm,&kvno,file,key); +KRB5_DLLIMP int KRB5_CALLCONV +read_service_key(service,instance,realm,kvno,file,key) + char FAR *service; /* Service Name */ + char FAR *instance; /* Instance name or "*" */ + char FAR *realm; /* Realm */ + int kvno; /* Key version number */ + char FAR *file; /* Filename */ + char FAR *key; /* Pointer to key to be filled in */ +{ + int kret; + #ifdef KRB4_USE_KEYTAB + krb5_error_code retval; + krb5_keyblock keyblock; +#endif + + kret = get_service_key(service,instance,realm,&kvno,file,key); + if (! kret) return KSUCCESS; - krb5_init_context(&context); +#ifdef KRB4_USE_KEYTAB + kret = KFAILURE; + keyblock.magic = KV5M_KEYBLOCK; + keyblock.contents = 0; + + retval = krb54_get_service_keyblock(service,instance,realm,kvno,file, + &keyblock); + if (retval) + goto errout; - if (!strcmp(instance, "*")) { - retval = krb5_sname_to_principal(context, NULL, NULL, KRB5_NT_SRV_HST, - &princ); - if (!retval) { - retval = krb5_524_conv_principal(context, princ, - sname, sinst, srealm); - krb5_free_principal(context, princ); - } - if (!retval) - instance = sinst; + if ((keyblock.length != sizeof(C_Block)) || + ((keyblock.enctype != ENCTYPE_DES_CBC_CRC) && + (keyblock.enctype != ENCTYPE_DES_CBC_MD4) && + (keyblock.enctype != ENCTYPE_DES_CBC_MD5))) { + goto errout; } + (void) memcpy(key, keyblock.contents, sizeof(C_Block)); + kret = KSUCCESS; - retval = krb5_425_conv_principal(context, - service, - instance, - realm, - &princ); - if (!retval) - retval = krb5_kt_default_name(context, (char *)keytabname, - sizeof(keytabname)-1); - if (!retval) { - retval = krb5_kt_resolve(context, (char *)keytabname, &kt_id); - if (!retval) { - retval = krb5_kt_get_entry(context, kt_id, princ, kvno, - ENCTYPE_DES_CBC_CRC, &kt_entry); - krb5_kt_close(context, kt_id); - } - krb5_free_principal(context, princ); - } - if (!retval) { - if (kt_entry.key.length == sizeof(C_Block)) { - (void) memcpy(key, kt_entry.key.contents, sizeof(C_Block)); - } else { - retval = KRB5_BAD_KEYSIZE; - } - krb5_kt_free_entry(context, &kt_entry); - } - krb5_free_context(context); - - if (! retval) - return KSUCCESS; +errout: + if (keyblock.contents) + krb5_free_keyblock_contents(krb5__krb4_context, &keyblock); #endif return kret; -- 2.26.2