diff options
author | Marc Horowitz <marc@mit.edu> | 1998-10-30 02:56:35 +0000 |
---|---|---|
committer | Marc Horowitz <marc@mit.edu> | 1998-10-30 02:56:35 +0000 |
commit | 1440ab035ba04550ddbbfbff1ee9b5571e3d95db (patch) | |
tree | 9d5e8d2e151a930e044c7d0f7c64053d244577a0 /src/lib/krb5 | |
parent | 61ddbf948ba6ee70c1bc049268c3dfa73bc9983e (diff) | |
download | krb5-1440ab035ba04550ddbbfbff1ee9b5571e3d95db.tar.gz krb5-1440ab035ba04550ddbbfbff1ee9b5571e3d95db.tar.xz krb5-1440ab035ba04550ddbbfbff1ee9b5571e3d95db.zip |
pull up 3des implementation from the marc-3des branch
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11001 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/krb5')
55 files changed, 1451 insertions, 1896 deletions
diff --git a/src/lib/krb5/ChangeLog b/src/lib/krb5/ChangeLog index f7922150e..f1e1e81f9 100644 --- a/src/lib/krb5/ChangeLog +++ b/src/lib/krb5/ChangeLog @@ -1,3 +1,11 @@ +Thu Jul 30 13:12:57 1998 Sam Hartman <hartmans@utwig.mesas.com> + + * configure.in: Test for sa_len so localaddr works on NetBSD. + +Sun Jul 26 17:46:47 1998 Sam Hartman <hartmans@utwig.mesas.com> + + * Makefile.in (LIBMAJOR): bump to 2 + Wed Apr 15 18:07:20 1998 Tom Yu <tlyu@mit.edu> * Makefile.in (SHLIB_EXPDEPS): diff --git a/src/lib/krb5/Makefile.in b/src/lib/krb5/Makefile.in index 4864a2f94..12ce18512 100644 --- a/src/lib/krb5/Makefile.in +++ b/src/lib/krb5/Makefile.in @@ -28,8 +28,8 @@ LIBDONE= error_tables/DONE asn.1/DONE ccache/DONE ccache/stdio/DONE \ #SHLIB_LIBDIRS= @SHLIB_LIBDIRS@ LIB=krb5 -LIBMAJOR=1 -LIBMINOR=2 +LIBMAJOR=2 +LIBMINOR=1 STOBJLISTS= \ error_tables/OBJS.ST \ diff --git a/src/lib/krb5/asn.1/ChangeLog b/src/lib/krb5/asn.1/ChangeLog index a42ad235c..ca3f679f5 100644 --- a/src/lib/krb5/asn.1/ChangeLog +++ b/src/lib/krb5/asn.1/ChangeLog @@ -1,3 +1,10 @@ +1998-10-27 Marc Horowitz <marc@mit.edu> + + * asn1buf.c (asn1buf_sync): interoperation testing against heimdal + revealed a bug. if extra fields are present in a SEQUENCE, they + are not ignored and skipped. This caused the decoder to get out + of sync. + Thu Jul 2 15:30:25 1998 Theodore Y. Ts'o <tytso@mit.edu> * asn1_encode.c: Make the magic Macintosh EPOCH offset be 70 years diff --git a/src/lib/krb5/asn.1/asn1buf.c b/src/lib/krb5/asn.1/asn1buf.c index 30dad8b49..52ac387d5 100644 --- a/src/lib/krb5/asn.1/asn1buf.c +++ b/src/lib/krb5/asn.1/asn1buf.c @@ -93,7 +93,7 @@ void asn1buf_sync(buf, subbuf) asn1buf * buf; asn1buf * subbuf; { - buf->next = subbuf->next; + buf->next = subbuf->bound + 1; } asn1_error_code asn1buf_destroy(buf) diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog index 2a4d39551..71aa06dc8 100644 --- a/src/lib/krb5/ccache/ChangeLog +++ b/src/lib/krb5/ccache/ChangeLog @@ -7,6 +7,10 @@ Fri Aug 20 18:30:00 1998 Miro Jurisic <meeroh@mit.edu> * Added Frank's CCache API cache implementation and made it default on the Mac +Thu Jul 30 13:12:30 1998 Sam Hartman <hartmans@utwig.mesas.com> + + * ccbase.c: Enable memory ccache (merge adapted from Kerbnet) + 1998-05-27 Theodore Ts'o <tytso@rsts-11.mit.edu> * Makefile.in: Add ccache/memory as a directory to be recursively diff --git a/src/lib/krb5/ccache/ccapi/Makefile.in b/src/lib/krb5/ccache/ccapi/Makefile.in deleted file mode 100644 index e47ded443..000000000 --- a/src/lib/krb5/ccache/ccapi/Makefile.in +++ /dev/null @@ -1,21 +0,0 @@ -thisconfigdir=./../.. -BUILDTOP=$(REL)$(U)$(S)$(U)$(S)$(U)$(S)$(U) -CFLAGS = $(CCOPTS) $(DEFS) - -##DOS##BUILDTOP = ..\..\..\.. -##DOS##PREFIXDIR = ccache\file -##DOS##OBJFILE = file.lst -##WIN16##LIBNAME=..\..\krb5.lib - -STLIBOBJS = \ - stdcc.o \ - stdcc_util.o - -OBJS = stdcc.${OBJEXT} stdcc_util.${OBJEXT} - -SRCS = $(srcdir)/stdcc.c $(srcdir)/stdcc_util.c - -##DOS##LIBOBJS = $(OBJS) - -all-unix:: all-libobjs -clean-unix:: clean-libobjs diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c deleted file mode 100644 index 2b9007bf8..000000000 --- a/src/lib/krb5/ccache/ccapi/stdcc.c +++ /dev/null @@ -1,394 +0,0 @@ -/********************************************************** - * - * stdcc.c - additions to the Kerberos 5 library to support the memory credentical cache API - * - * Revision 1.1.1.1 - Frank Dabek July 1998 - * - **********************************************************/ - -#include "stdcc.h" -#include "string.h" - -//declare our global object wanna-be -//must be installed in ccdefops.c -krb5_cc_ops krb5_cc_stdcc_ops = { - 0, - "API", - krb5_stdcc_get_name, - krb5_stdcc_resolve, - krb5_stdcc_generate_new, - krb5_stdcc_initialize, - krb5_stdcc_destroy, - krb5_stdcc_close, - krb5_stdcc_store, - krb5_stdcc_retrieve, - krb5_stdcc_get_principal, - krb5_stdcc_start_seq_get, - krb5_stdcc_next_cred, - krb5_stdcc_end_seq_get, - krb5_stdcc_remove, - krb5_stdcc_set_flags, -}; - -// -- generate_new -------------------------------- -// - create a new cache with a unique name, corresponds to creating a named cache -// - iniitialize the API here if we have to. -krb5_error_code krb5_stdcc_generate_new - (krb5_context context, krb5_ccache *id ) - - { - - krb5_ccache newCache; - char name[kStringLiteralLen]; - cc_time_t time; - int err; - - //make sure the API has been intialized - if (gCntrlBlock == NULL) { - err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL); - if (err != CC_NOERROR) return err; - } - - //allocate the cache structure - newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); - if (newCache == NULL) return KRB5_CC_NOMEM; - - //create a unique name - cc_get_change_time(gCntrlBlock, &time); - sprintf(name, "gen_new_cache%d", time); - - //create the new cache - err = cc_create(gCntrlBlock, name, CC_CRED_V5, - name, 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache) ); - if (err != CC_NOERROR) return err; - - //setup some fields - newCache->ops = &krb5_cc_stdcc_ops; - newCache->data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData)); - - //return a pointer to the new cache - *id = newCache; - - return CC_NOERROR; - } - -// -- resolve ------------------------------ -// -// - create a new cache with the name stored in residual -krb5_error_code krb5_stdcc_resolve - (krb5_context context, krb5_ccache *id , const char *residual ) { - - krb5_ccache newCache; - int err,pos; - char *cName; - - //make sure the API has been intialized - if (gCntrlBlock == NULL) { - err = cc_initialize(&gCntrlBlock, CC_API_VER_1, NULL, NULL); - if (err != CC_NOERROR) return err; - } - - newCache = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); - if (newCache == NULL) return KRB5_CC_NOMEM; - - newCache->ops = &krb5_cc_stdcc_ops; - newCache->data = (stdccCacheDataPtr)malloc(sizeof(stdccCacheData)); - if (newCache->data == NULL) return KRB5_CC_NOMEM; - - cName = residual; - //attempt to find a cache by the same name before creating it - err = cc_open(gCntrlBlock, cName, CC_CRED_V5, 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache)); - //we didn't find it.. create it. - if (err) { - err = cc_create(gCntrlBlock, cName, CC_CRED_V5, cName, - 0L, &(((stdccCacheDataPtr)(newCache->data))->NamedCache) ); - if (err != CC_NOERROR) return err; //still an error, return it - } - - //return new cache structure - *id = newCache; - return CC_NOERROR; - } - - // -- initialize -------------------------------- - //-initialize the cache, check to see if one already exists for this principal - // if not set our principal to this principal. This searching enables ticket sharing - krb5_error_code krb5_stdcc_initialize - (krb5_context context, krb5_ccache id, krb5_principal princ) - - { - - int err, err1, found; - //char cName[kStringLiteralLen]; - char *cName = nil; - ccache_p *testNC = NULL; - ccache_it *it; - char *p = NULL, *targetName = NULL; - - //test id for null - if (id == NULL) return KRB5_CC_NOMEM; - - //test for initialized API - if (gCntrlBlock == NULL) - return CC_NO_EXIST; - - //create a principal name for the named cache - err = krb5_unparse_name(context, princ, &cName); - if (err) - return(err); - - //sprintf(cName, "%s@%s", krb5_princ_name(context, princ)->data, krb5_princ_realm(context, princ)->data); - - //look for a cache already extant for this principal - it = NULL; - found = err = 0; - while ((err != CC_END) && (!found)) { - err = cc_seq_fetch_NCs(gCntrlBlock, &testNC, &it); - if (err == CC_NOERROR) { - cc_get_principal(gCntrlBlock, testNC, &p); - if (strcmp(p, cName) == 0) { - found = 1; - cc_get_name(gCntrlBlock, testNC, &targetName); - } - cc_free_principal(gCntrlBlock, p); - err1 = cc_close(gCntrlBlock, &testNC); - } - } - - if (!found) - //we didn't find one with the name we were looking for, use the one we had and change the name - cc_set_principal(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), CC_CRED_V5, cName); - else { - //we found a cache for this guy, lets trash ours and use that one - let's not; sgm 10/7/98 - //cc_destroy(gCntrlBlock, &(((stdccCacheDataPtr)(id->data))->NamedCache)); - err = cc_open(gCntrlBlock, targetName, CC_CRED_V5, 0L, &(((stdccCacheDataPtr)(id->data))->NamedCache)); - if (err != CC_NOERROR) return err; //error opening - cc_free_name(gCntrlBlock, targetName); - } - - free(cName); - - return CC_NOERROR; - - } - - -// -- store ---------------------------------- -// - store some credentials in our cache - krb5_error_code krb5_stdcc_store - (krb5_context context, krb5_ccache id , krb5_creds *creds ) { - - cred_union *cu = NULL; - int err; - - - //copy the fields from the almost identical structures - dupK52cc(context, creds, &cu); - - //finally store the credential - //store will copy (that is duplicate) everything - err = cc_store(gCntrlBlock, ((stdccCacheDataPtr)(id->data))->NamedCache, *cu); - if (err != CC_NOERROR) return err; - - //free the cred union - err = cc_free_creds(gCntrlBlock, &cu); - - return err; -} - - -// -- start_seq_get -------------------------- -// - begin an iterator call to get all of the credentials in the cache -krb5_error_code krb5_stdcc_start_seq_get -(krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor ) { - - //all we have to do is initialize the cursor - *cursor = NULL; - return CC_NOERROR; -} - -// -- next cred --------------------------- -// - get the next credential in the cache as part of an iterator call -// - this maps to call to cc_seq_fetch_creds -krb5_error_code krb5_stdcc_next_cred - (krb5_context context, - krb5_ccache id , - krb5_cc_cursor *cursor , - krb5_creds *creds ) { - - int err; - cred_union *credU = NULL; - cc_creds *c = NULL; - - err = cc_seq_fetch_creds(gCntrlBlock, ((stdccCacheDataPtr)(id->data))->NamedCache, - &credU, (ccache_it **)cursor); - - if (err != CC_NOERROR) - return err; - - //copy data (with translation) - dupCCtoK5(context, credU->cred.pV5Cred, creds); - - //free our version of the cred - cc_free_creds(gCntrlBlock, &credU); - - return CC_NOERROR; - -} - - -// -- retreive ------------------- -// - try to find a matching credential in the cache -krb5_error_code krb5_stdcc_retrieve - (krb5_context context, - krb5_ccache id, - krb5_flags whichfields, - krb5_creds *mcreds, - krb5_creds *creds ) { - - krb5_cc_cursor curs = NULL; - krb5_creds *fetchcreds; - - fetchcreds = (krb5_creds *)malloc(sizeof(krb5_creds)); - if (fetchcreds == NULL) return KRB5_CC_NOMEM; - - //we're going to use the iterators - krb5_stdcc_start_seq_get(context, id, &curs); - - while (krb5_stdcc_next_cred(context, id, &curs, fetchcreds) == CC_NOERROR) { - //look at each credential for a match - //use this match routine since it takes the whichfields and the API doesn't - if (stdccCredsMatch(context, fetchcreds, mcreds, whichfields)) { - //we found it, copy and exit - *creds = *fetchcreds; - krb5_stdcc_end_seq_get(context, id, &curs); - return CC_NOERROR; - } - //free copy allocated by next_cred - krb5_free_cred_contents(context, fetchcreds); - } - - //no luck, end get and exti - krb5_stdcc_end_seq_get(context, id, &curs); - - return KRB5_CC_NOTFOUND; -} - -// -- end seq ------------------------ -// - just free up the storage assoicated with the cursor (if we could) - krb5_error_code krb5_stdcc_end_seq_get - (krb5_context context, krb5_ccache id , krb5_cc_cursor *cursor ) { - - //the limitation of the Ccache api and the seq calls - //causes trouble. cursor might have already been freed - //and anyways it is in the mac's heap so we need FreePtr - //but all i have is free - // FreePtr(*cursor); - - //LEAK IT! - *cursor = NULL; - } - -// -- close --------------------------- -// - free our pointers to the NC -krb5_error_code -krb5_stdcc_close(context, id, princ) - krb5_context context; - krb5_ccache id; - krb5_principal princ; -{ - - //free it - free((stdccCacheDataPtr)(id->data)); - //null it out - (stdccCacheDataPtr)(id->data) = NULL; - - return CC_NOERROR; -} - -// -- destroy ------------- -// - free our storage and the cache -krb5_error_code -krb5_stdcc_destroy (krb5_context context, krb5_ccache id ) { - - int err; - - //destroy the named cache - err = cc_destroy(gCntrlBlock, &(((stdccCacheDataPtr)(id->data))->NamedCache)); - //free the pointer to the record that held the pointer to the cache - free((stdccCacheDataPtr)(id->data)); - //null it out - (stdccCacheDataPtr)(id->data) = NULL; - - return err; -} - - -// -- getname --------------------------- -// - return the name of the named cache -char * krb5_stdcc_get_name - (krb5_context context, krb5_ccache id ) { - - char *ret = NULL; - int err; - - //just a wrapper - err = cc_get_name(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), &ret); - - if (err != CC_NOERROR) - return ret; - else - return NULL; - -} - -// -- get_principal --------------------------- -// - return the principal associated with the named cache -krb5_error_code -krb5_stdcc_get_principal (krb5_context context, krb5_ccache id , krb5_principal *princ ) { - - int err; - char *name = NULL; - - //another wrapper - err = cc_get_principal(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), &name); - - if (err != CC_NOERROR) - return err; - - //turn it into a krb principal - err = krb5_parse_name(context, name, princ); - - return err; -} - -// -- set_flags --------------------------- -// - currently a NOP since we don't store any flags in the NC -krb5_error_code krb5_stdcc_set_flags - (krb5_context context, krb5_ccache id , krb5_flags flags ) { - - return CC_NOERROR; -} - -// - remove --------------------------- -// - remove the specified credentials from the NC -krb5_error_code krb5_stdcc_remove - (krb5_context context, krb5_ccache id , krb5_flags flags, krb5_creds *creds ) { - - cred_union *cu = NULL; - int err; - - //convert to a cred union - dupK52cc(context, creds, &cu); - - //remove it - err = cc_remove_cred(gCntrlBlock, (((stdccCacheDataPtr)(id->data))->NamedCache), *cu); - if (err != CC_NOERROR) return err; - - //free the temp cred union - err = cc_free_creds(gCntrlBlock, &cu); - if (err != CC_NOERROR) return err; - - return CC_NOERROR; - } -
\ No newline at end of file diff --git a/src/lib/krb5/ccache/ccapi/stdcc.h b/src/lib/krb5/ccache/ccapi/stdcc.h deleted file mode 100644 index c157770c4..000000000 --- a/src/lib/krb5/ccache/ccapi/stdcc.h +++ /dev/null @@ -1,73 +0,0 @@ -//#include "k5-int.h" -#include "krb5.h" - -#if defined(macintosh) -#include "CCache.h" -#endif - -#if defined(_MSDOS) || defined(_WIN32) -#include "cacheapi.h" -#endif - -#define kStringLiteralLen 255 - -//globals to be exported -extern krb5_cc_ops krb5_cc_stdcc_ops; - -//structure to stash in the cache's data field -//only holds another pointer to the actual cache right now -typedef struct _stdccCacheData { - ccache_p *NamedCache; -} stdccCacheData, *stdccCacheDataPtr; - - -//function protoypes complete with bogus windowsesque macros.. - -KRB5_DLLIMP krb5_error_code krb5_stdcc_close - KRB5_PROTOTYPE((krb5_context, krb5_ccache id )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_destroy - KRB5_PROTOTYPE((krb5_context, krb5_ccache id )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_end_seq_get - KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_cc_cursor *cursor )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_generate_new - KRB5_PROTOTYPE((krb5_context, krb5_ccache *id )); - -KRB5_DLLIMP char * krb5_stdcc_get_name - KRB5_PROTOTYPE((krb5_context, krb5_ccache id )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_get_principal - KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_principal *princ )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_initialize - KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_principal princ )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_next_cred - KRB5_PROTOTYPE((krb5_context, - krb5_ccache id , - krb5_cc_cursor *cursor , - krb5_creds *creds )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_resolve - KRB5_PROTOTYPE((krb5_context, krb5_ccache *id , const char *residual )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_retrieve - KRB5_PROTOTYPE((krb5_context, - krb5_ccache id , - krb5_flags whichfields , - krb5_creds *mcreds , - krb5_creds *creds )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_start_seq_get - KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_cc_cursor *cursor )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_store - KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_creds *creds )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_set_flags - KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_flags flags )); - -KRB5_DLLIMP krb5_error_code krb5_stdcc_remove - KRB5_PROTOTYPE((krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds)); diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c deleted file mode 100644 index 4f4fcfc50..000000000 --- a/src/lib/krb5/ccache/ccapi/stdcc_util.c +++ /dev/null @@ -1,368 +0,0 @@ -// stdcc_util.c -// utility functions used in implementing the ccache api for krb5 -// not publicly exported -// Frank Dabek, July 1998 - -#include <stdlib.h> -#include <string.h> -#include "stdcc_util.h" -#include "krb5.h" -#include "kv5m_err.h" - -#define fieldSize 255 - -/* on the Mac, we need the calls which allocate memory for the Credentials Cache to use - Ptr's in the system help, so that they stay global and so that bad things don't happen - when we call DisposePtr() on them. However, on other systems, malloc is probably the - right thing to use. - So for any place where we allocate memory for the Credentials Cache, use sys_alloc() and - define it accordingly. -*/ - -#if defined(macintosh) -#define sys_alloc(size) NewSafePtrSys(size) -#else -#define sys_alloc(size) malloc(size) -#endif - -#if defined(macintosh) -//stolen from CCacheUtils.c -// -- NewSafePtrSys ----------------- -// - analagous to NewSafePtr but memory is allocated in the system heap -Ptr NewSafePtrSys(long size) { - - Ptr retPtr; - - retPtr = NewPtrSys(size); - - if (retPtr != NULL) - HoldMemory(retPtr, size); - - return retPtr; -} -#endif - -// CopyCCDataArrayToK5 -// - copy and translate the null terminated arrays of data records -// used in k5 tickets -int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray) { - - cc_data *ccAdr, **cbase; - krb5_address *kAdr, **kbase, **constKBase; - int numRecords = 0; - - - if (whichArray == kAddressArray) { - //check pointer - if (cc->addresses == NULL) { - kc->addresses = NULL; - return 0; } - } else if (whichArray == kAuthDataArray) { - //check pointer - if (cc->authdata == NULL) { - kc->authdata = NULL; - return 0; } - } else return -1; - - - cbase = (whichArray == kAddressArray) ? cc->addresses : cc->authdata; - //calc number of records - while (*cbase++ != NULL) numRecords++; - //allocate new array - constKBase = kbase = (krb5_address **)malloc((numRecords+1)*sizeof(char *)); - //reset base - cbase = (whichArray == kAddressArray) ? cc->addresses : cc->authdata; - - - //copy records - while (*cbase != NULL) { - *kbase = (krb5_address *)malloc(sizeof(krb5_address)); - kAdr = *kbase; - ccAdr = *cbase; - kAdr->magic = (whichArray == kAddressArray) ? KV5M_ADDRESS : KV5M_AUTHDATA; - kAdr->addrtype = ccAdr->type; - kAdr->length = ccAdr->length; - kAdr->contents = (krb5_octet *)malloc(kAdr->length); - memcpy(kAdr->contents, ccAdr->data, kAdr->length); - //next element please - kbase++; cbase++; - } - - //write terminator - *kbase = NULL; - if (whichArray == kAddressArray) kc->addresses = constKBase; - else kc->authdata = (krb5_authdata **)constKBase; - - return 0; -} - -// copyK5DataArrayToCC -// - analagous to above, but in the other direction -int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray) { - - cc_data *ccAdr, **cbase, **constCBase; - krb5_address *kAdr, **kbase; - int numRecords = 0; - - - if (whichArray == kAddressArray) { - //check pointer - if (kc->addresses == NULL) { - cc->addresses = NULL; - return 0; } - } else if (whichArray == kAuthDataArray) { - //check pointer - if (kc->authdata == NULL) { - cc->authdata = NULL; - return 0; } - } else return -1; - - - kbase = (whichArray == kAddressArray) ? kc->addresses : (krb5_address **)kc->authdata; - //calc number of records - while (*kbase++ != NULL) numRecords++; - //allocate new array - constCBase = cbase = (cc_data **)sys_alloc((numRecords+1)*sizeof(char *)); - //reset base - kbase = (whichArray == kAddressArray) ? kc->addresses : (krb5_address **)kc->authdata; - - - //copy records - while (*kbase != NULL) { - *cbase = (cc_data *)sys_alloc(sizeof(krb5_address)); - kAdr = *kbase; - ccAdr = *cbase; - ccAdr->type = kAdr->addrtype; - ccAdr->length = kAdr->length; - ccAdr->data = (unsigned char *)sys_alloc(ccAdr->length); - memcpy(ccAdr->data, kAdr->contents, kAdr->length); - //next element please - kbase++; cbase++; - } - - //write terminator - *cbase = NULL; - if (whichArray == kAddressArray) cc->addresses = (cc_data **)constCBase; - else cc->authdata = (cc_data **)constCBase; - - return 0; -} - - -// dupcctok5 -// - allocate an empty k5 style ticket and copy info from the cc_creds ticket -void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest) { - - int err; - - //allocate and copy - //copy all of those damn fields back - err = krb5_parse_name(context, src->client, &(dest->client)); - err = krb5_parse_name(context, src->server, &(dest->server)); - if (err) return; //parsename fails w/o krb5.ini for example - - //copy keyblock - dest->keyblock.enctype = src->keyblock.type; - dest->keyblock.length = src->keyblock.length; - dest->keyblock.contents = (krb5_octet *)malloc(dest->keyblock.length); - memcpy(dest->keyblock.contents, src->keyblock.data, dest->keyblock.length); - - //copy times - dest->times.authtime = src->authtime; - dest->times.starttime = src->starttime; - dest->times.endtime = src->endtime; - dest->times.renew_till = src->renew_till; - dest->is_skey = src->is_skey; - dest->ticket_flags = src->ticket_flags; - - //more branching fields - copyCCDataArrayToK5(src, dest, kAddressArray); - dest->ticket.length = src->ticket.length; - dest->ticket.data = (char *)malloc(src->ticket.length); - memcpy(dest->ticket.data, src->ticket.data, src->ticket.length); - dest->second_ticket.length = src->second_ticket.length; - (dest->second_ticket).data = ( char *)malloc(src->second_ticket.length); - memcpy(dest->second_ticket.data, src->second_ticket.data, src->second_ticket.length); - - //zero out magic number - dest->magic = 0; - //later - //copyCCDataArrayToK5(src, dest, kAuthDataArray); - //krb5 docs say that authdata can be nulled out if we - //only want default behavior - dest->authdata = NULL; - - return; -} - -// dupK52CC -// - analagous to above but in the reverse direction -void dupK52cc(krb5_context context, krb5_creds *creds, cred_union **cu) { - - krb5_address **tA; - krb5_authdata **tAd; - cc_creds *c; - int err; - #ifdef macintosh - char *tempname = NULL; - #endif - - if (cu == NULL) return; - - //allocate the cred_union - *cu = (cred_union *)sys_alloc(sizeof(cred_union)); - if ((*cu) == NULL) return; - (*cu)->cred_type = CC_CRED_V5; - - //allocate creds structure (and install) - c = (cc_creds *)sys_alloc(sizeof(cc_creds)); - if (c == NULL) return; - (*cu)->cred.pV5Cred = c; - - //convert krb5 principals to flat principals - #ifdef macintosh - //and make sure the memory for c->client and c->server is on the system heap with NewPtr - //for the Mac (krb5_unparse_name puts it in appl heap with malloc) - err = krb5_unparse_name(context, creds->client, &tempname); - c->client = sys_alloc(strlen(tempname)); - if (c->client != NULL) - strcpy(c->client,tempname); - free(tempname); - tempname = NULL; - - err = krb5_unparse_name(context, creds->server, &tempname); - c->server = sys_alloc(strlen(tempname)); - if (c->server != NULL) - strcpy(c->server,tempname); - free(tempname); - #else - err = krb5_unparse_name(context, creds->client, &(c->client)); - err = krb5_unparse_name(context, creds->server, &(c->server)); - #endif - if (err) return; - - //copy more fields - c->keyblock.type = creds->keyblock.enctype; - c->keyblock.length = creds->keyblock.length; - - if (creds->keyblock.contents != NULL) { - c->keyblock.data = (unsigned char *)sys_alloc(creds->keyblock.length); - memcpy(c->keyblock.data, creds->keyblock.contents, creds->keyblock.length); - } else { - c->keyblock.data = NULL; - } - - c->authtime = creds->times.authtime; - c->starttime = creds->times.starttime; - c->endtime = creds->times.endtime; - c->renew_till = creds->times.renew_till; - c->is_skey = creds->is_skey; - c->ticket_flags = creds->ticket_flags; - - copyK5DataArrayToCC(creds, c, kAddressArray); - - c->ticket.length = creds->ticket.length; - if (creds->ticket.data != NULL) { - c->ticket.data = (unsigned char *)sys_alloc(creds->ticket.length); - memcpy(c->ticket.data, creds->ticket.data, creds->ticket.length); - } else { - c->ticket.data = NULL; - } - - c->second_ticket.length = creds->second_ticket.length; - if (creds->second_ticket.data != NULL) { - c->second_ticket.data = (unsigned char *)sys_alloc(creds->second_ticket.length); - memcpy(c->second_ticket.data, creds->second_ticket.data, creds->second_ticket.length); - } else { - c->second_ticket.data = NULL; - } - - c->authdata = NULL; - - return; -} - - -// bitTst -// - utility function for below function -int bitTst(int var, int mask) { - - return var & mask; -} - -// stdccCredsMatch -// - check to see if the creds match based on the whichFields variable -// NOTE: if whichfields is zero we are now comparing 'standard fields.' -// This is the bug that was killing fetch for a week. The behaviour -// is what krb5 expects, however. -int stdccCredsMatch(krb5_context context, krb5_creds *base, krb5_creds *match, int whichfields) { - - krb5_ticket_times b, m; - krb5_authdata **bp, **mp; - krb5_boolean retval; - krb5_principal_data p1, p2; - - - //always check the standard fields - if ((krb5_principal_compare(context, base->client, match->client) && - krb5_principal_compare(context, base->server, match->server)) == false) - return FALSE; - - if (bitTst(whichfields, KRB5_TC_MATCH_TIMES)) { - //test for matching times - //according to the file cache implementation we do: - if (match->times.renew_till) { - if (match->times.renew_till > base->times.renew_till) - return FALSE; /* this one expires too late */ - } - if (match->times.endtime) { - if (match->times.endtime > base->times.endtime) - return FALSE; /* this one expires too late */ - } - } //continue search - - if (bitTst(whichfields, KRB5_TC_MATCH_IS_SKEY)) - if (base->is_skey != match->is_skey) return false; - - if (bitTst(whichfields, KRB5_TC_MATCH_FLAGS)) - if (base->ticket_flags != match->ticket_flags) return false; - - if (bitTst(whichfields, KRB5_TC_MATCH_TIMES_EXACT)) { - b = base->times; m = match->times; - if ((b.authtime != m.authtime) || - (b.starttime != m.starttime) || - (b.endtime != m.endtime) || - (b.renew_till != m.renew_till)) return false; - } - - if (bitTst(whichfields, KRB5_TC_MATCH_AUTHDATA)) { - bp = base->authdata; - mp = match->authdata; - if ((bp != NULL) && (mp != NULL)) { - while ( (bp) && (*bp != NULL) ){ - if (( (*bp)->ad_type != (*mp)->ad_type) || - ( (*bp)->length != (*mp)->length) || - ( memcmp( (*bp)->contents, (*mp)->contents, (*bp)->length) != 0)) return false; - mp++; bp++; - } - } - } - - if (bitTst(whichfields, KRB5_TC_MATCH_SRV_NAMEONLY)) { - //taken from cc_retrv.c - retval = krb5_principal_compare(context, base->client,match->client); - if (!retval) return false; - - } - - if (bitTst(whichfields, KRB5_TC_MATCH_2ND_TKT)) - if ( (base->second_ticket.length != match->second_ticket.length) || - (memcmp(base->second_ticket.data, match->second_ticket.data, base->second_ticket.length) != 0)) - return false; - - if (bitTst(whichfields, KRB5_TC_MATCH_KTYPE)) - if (base->keyblock.enctype != match->keyblock.enctype) return false; - - //if we fall through to here, they must match - return true; -} diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.h b/src/lib/krb5/ccache/ccapi/stdcc_util.h deleted file mode 100644 index 7d0af3dcb..000000000 --- a/src/lib/krb5/ccache/ccapi/stdcc_util.h +++ /dev/null @@ -1,25 +0,0 @@ -//stdcc_util.h -// -// Frank Dabek, July 1998 - -#if defined(macintosh) -#include "CCache.h" -#endif - -#if defined(_MSDOS) || defined(_WIN32) -#include "cacheapi.h" -#endif - -#include "krb5.h" - -//protoypes for private functions declared in stdcc_util.c -int copyCCDataArrayToK5(cc_creds *cc, krb5_creds *kc, char whichArray); -int copyK5DataArrayToCC(krb5_creds *kc, cc_creds *cc, char whichArray); -void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest); -void dupK52cc(krb5_context context, krb5_creds *creds, cred_union **cu); -int stdccCredsMatch(krb5_context context, krb5_creds *base, krb5_creds *match, int whichfields); -int bitTst(int var, int mask); -void typeK52cc(krb5_context context, krb5_creds *creds, cc_creds *c, char **client, char **server); -#define kAddressArray 4 -#define kAuthDataArray 5 - diff --git a/src/lib/krb5/ccache/ccbase.c b/src/lib/krb5/ccache/ccbase.c index 4570f8053..ae89334a0 100644 --- a/src/lib/krb5/ccache/ccbase.c +++ b/src/lib/krb5/ccache/ccbase.c @@ -31,7 +31,11 @@ struct krb5_cc_typelist krb5_cc_ops *ops; struct krb5_cc_typelist *next; }; -static struct krb5_cc_typelist *cc_typehead = 0; +extern krb5_cc_ops krb5_mcc_ops; + +static struct krb5_cc_typelist cc_entry = { &krb5_mcc_ops, NULL }; + +static struct krb5_cc_typelist *cc_typehead = &cc_entry; /* * Register a new credentials cache type diff --git a/src/lib/krb5/configure.in b/src/lib/krb5/configure.in index 1f924319a..b42fbf0ce 100644 --- a/src/lib/krb5/configure.in +++ b/src/lib/krb5/configure.in @@ -12,6 +12,7 @@ AC_CHECK_FUNCS(flock fchmod chmod strftime strptime geteuid setenv unsetenv gete AC_REPLACE_FUNCS(vfprintf vsprintf strdup strcasecmp strerror memmove daemon getuid sscanf syslog) KRB5_AC_REGEX_FUNCS dnl +KRB5_SOCKADDR_SA_LEN KRB5_BUILD_LIBRARY_WITH_DEPS KRB5_BUILD_LIBOBJS KRB5_BUILD_PROGRAM diff --git a/src/lib/krb5/error_tables/krb5_err.et b/src/lib/krb5/error_tables/krb5_err.et index d8f8533c8..b483116e1 100644 --- a/src/lib/krb5/error_tables/krb5_err.et +++ b/src/lib/krb5/error_tables/krb5_err.et @@ -315,4 +315,6 @@ error_code KRB5_CHPW_PWDNULL, "New password cannot be zero length" error_code KRB5_CHPW_FAIL, "Password change failed" error_code KRB5_KT_FORMAT, "Bad format in keytab" +error_code KRB5_NOPERM_ETYPE, "Encryption type not permitted" + end diff --git a/src/lib/krb5/keytab/file/ChangeLog b/src/lib/krb5/keytab/file/ChangeLog index 2120127db..4e575b651 100644 --- a/src/lib/krb5/keytab/file/ChangeLog +++ b/src/lib/krb5/keytab/file/ChangeLog @@ -1,3 +1,8 @@ +1998-10-27 Marc Horowitz <marc@mit.edu> + + * ktf_g_ent.c (krb5_ktfile_get_entry): restructure the code to use + the compare_enctypes function and not leak memory + Fri Feb 27 18:03:33 1998 Theodore Ts'o <tytso@rsts-11.mit.edu> * Makefile.in: Changed thisconfigdir to point at the lib/krb5 diff --git a/src/lib/krb5/keytab/file/ktf_g_ent.c b/src/lib/krb5/keytab/file/ktf_g_ent.c index 7122cb41d..57d6edabd 100644 --- a/src/lib/krb5/keytab/file/ktf_g_ent.c +++ b/src/lib/krb5/keytab/file/ktf_g_ent.c @@ -41,6 +41,7 @@ krb5_ktfile_get_entry(context, id, principal, kvno, enctype, entry) krb5_keytab_entry cur_entry, new_entry; krb5_error_code kerror = 0; int found_wrong_kvno = 0; + krb5_boolean similar; /* Open the keyfile for reading */ if ((kerror = krb5_ktfileint_openr(context, id))) @@ -53,53 +54,69 @@ krb5_ktfile_get_entry(context, id, principal, kvno, enctype, entry) cur_entry.principal = 0; cur_entry.vno = 0; cur_entry.key.contents = 0; + while (TRUE) { - krb5_enctype entry_type; - if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry))) break; - switch (enctype) { - case ENCTYPE_DES_CBC_CRC: - case ENCTYPE_DES_CBC_MD5: - case ENCTYPE_DES_CBC_MD4: - case ENCTYPE_DES_CBC_RAW: - enctype = ENCTYPE_DES_CBC_CRC; - break; + /* by the time this loop exits, it must either free cur_entry, + and copy new_entry there, or free new_entry. Otherwise, it + leaks. */ + + /* if the enctype is not ignored and doesn't match, free new_entry + and continue to the next */ + + if (enctype != IGNORE_ENCTYPE) { + if ((kerror = krb5_c_enctype_compare(context, enctype, + new_entry.key.enctype, + &similar))) { + krb5_kt_free_entry(context, &new_entry); + break; + } + + if (!similar) { + krb5_kt_free_entry(context, &new_entry); + continue; + } } - entry_type = new_entry.key.enctype; - switch(entry_type) { - case ENCTYPE_DES_CBC_CRC: - case ENCTYPE_DES_CBC_MD5: - case ENCTYPE_DES_CBC_MD4: - case ENCTYPE_DES_CBC_RAW: - entry_type = ENCTYPE_DES_CBC_CRC; - break; + /* if the principal isn't the one requested, free new_entry + and continue to the next. */ + + if (!krb5_principal_compare(context, principal, new_entry.principal)) { + krb5_kt_free_entry(context, &new_entry); + continue; } - if (((enctype == IGNORE_ENCTYPE)|| - (entry_type == enctype))&& - krb5_principal_compare(context, principal, new_entry.principal)) { - if (kvno == IGNORE_VNO) { - if (! cur_entry.principal || - (cur_entry.vno < new_entry.vno)) - { - krb5_kt_free_entry(context, &cur_entry); - cur_entry = new_entry; - } - } else { - if (new_entry.vno == kvno) { - krb5_kt_free_entry(context, &cur_entry); - cur_entry = new_entry; - break; - } else - found_wrong_kvno++; - } + if (kvno == IGNORE_VNO) { + /* if this is the first match, or if the new vno is + bigger, free the current and keep the new. Otherwise, + free the new. */ + + if (! cur_entry.principal || + (new_entry.vno > cur_entry.vno)) { + krb5_kt_free_entry(context, &cur_entry); + cur_entry = new_entry; + } else { + krb5_kt_free_entry(context, &new_entry); + } } else { + /* if this kvno matches, free the current (will there ever + be one?), keep the new, and break out. Otherwise, remember + that we were here so we can return the right error, and + free the new */ + + if (new_entry.vno == kvno) { + krb5_kt_free_entry(context, &cur_entry); + cur_entry = new_entry; + break; + } else { + found_wrong_kvno++; krb5_kt_free_entry(context, &new_entry); + } } } + if (kerror == KRB5_KT_END) { if (cur_entry.principal) kerror = 0; diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog index 49d6ef3bb..9d1cfb02a 100644 --- a/src/lib/krb5/krb/ChangeLog +++ b/src/lib/krb5/krb/ChangeLog @@ -1,3 +1,39 @@ +1998-10-27 Marc Horowitz <marc@mit.edu> + + * vfy_increds.c: rearrange the code a bit to make it more clear + that the logic is correct. + + * str_conv.c: remove enctype and cksumtype string converstions. + They're in the crypto library now, since the information drops + right into the enctype table. + + * ser_eblk.c: ifdef the whole file out, since it's not used + anywhere. it should probably be deleted, but I'm not sure about + backward-compatibility issues yet. + + * rd_req_dec.c: check the auth_context permit-all flag and + permitted_enctypes list, and reject the request if the policy + check fails. + + * init_ctx.c: add code to initialize the prng. It's not great, + but can be improved, and the prng is reseeded when new keys are + processed. Read permitted_enctypes from the krb5.conf file, and + provide accessor functions for it. Make the various etype list + parsers share code as a side effect. + + * get_creds.c: add krb5_get_{validat,renew}ed_creds functions, + which are part of the new init_creds api. The prototypes were + already in, krb5.hin but there was no implementing code. + + * auth_con.c, auth_con.h: add a list of permitted enctypes to the + auth_context for rd_req to check, and create accessor functions + for this list. + + * Makefile.in, enc_helper.c: add enc_helper.c. This provides a + wrapper around the conventional way the library encrypts and wraps + encoded asn.1 structures, so the code isn't repeated in a dozen + places. + Wed Aug 19 17:27:51 1998 Tom Yu <tlyu@mit.edu> * conv_princ.c: Add some additional entries to sconv_list that diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index ec6384e07..3c734210c 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -32,6 +32,7 @@ STLIBOBJS= \ cp_key_cnt.o \ decode_kdc.o \ decrypt_tk.o \ + enc_helper.o \ encode_kdc.o \ encrypt_tk.o \ free_rtree.o \ @@ -114,6 +115,7 @@ OBJS= addr_comp.$(OBJEXT) \ cp_key_cnt.$(OBJEXT) \ decode_kdc.$(OBJEXT) \ decrypt_tk.$(OBJEXT) \ + enc_helper.$(OBJEXT) \ encode_kdc.$(OBJEXT) \ encrypt_tk.$(OBJEXT) \ free_rtree.$(OBJEXT) \ @@ -197,6 +199,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/cp_key_cnt.c \ $(srcdir)/decode_kdc.c \ $(srcdir)/decrypt_tk.c \ + $(srcdir)/enc_helper.c \ $(srcdir)/encode_kdc.c \ $(srcdir)/encrypt_tk.c \ $(srcdir)/free_rtree.c \ diff --git a/src/lib/krb5/krb/auth_con.c b/src/lib/krb5/krb/auth_con.c index 379508623..335f7ae7d 100644 --- a/src/lib/krb5/krb/auth_con.c +++ b/src/lib/krb5/krb/auth_con.c @@ -1,4 +1,3 @@ - #include "k5-int.h" #include "auth_con.h" @@ -71,6 +70,8 @@ krb5_auth_con_free(context, auth_context) krb5_free_keyblock(context, auth_context->remote_subkey); if (auth_context->rcache) krb5_rc_close(context, auth_context->rcache); + if (auth_context->permitted_etypes) + krb5_xfree(auth_context->permitted_etypes); free(auth_context); return 0; } @@ -274,12 +275,16 @@ krb5_auth_con_initivector(context, auth_context) krb5_context context; krb5_auth_context auth_context; { + krb5_error_code ret; + if (auth_context->keyblock) { - int size = krb5_enctype_array[auth_context->keyblock->enctype]-> - system->block_length; + size_t blocksize; - if ((auth_context->i_vector = (krb5_pointer)malloc(size))) { - memset(auth_context->i_vector, 0, size); + if ((ret = krb5_c_block_size(context, auth_context->keyblock->enctype, + &blocksize))) + return(ret); + if ((auth_context->i_vector = (krb5_pointer)malloc(blocksize))) { + memset(auth_context->i_vector, 0, blocksize); return 0; } return ENOMEM; @@ -347,3 +352,58 @@ krb5_auth_con_getrcache(context, auth_context, rcache) return 0; } +krb5_error_code +krb5_auth_con_setpermetypes(context, auth_context, permetypes) + krb5_context context; + krb5_auth_context auth_context; + const krb5_enctype * permetypes; +{ + krb5_enctype * newpe; + int i; + + for (i=0; permetypes[i]; i++) + ; + i++; /* include the zero */ + + if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype))) + == NULL) + return(ENOMEM); + + if (auth_context->permitted_etypes) + krb5_xfree(auth_context->permitted_etypes); + + auth_context->permitted_etypes = newpe; + + memcpy(newpe, permetypes, i*sizeof(krb5_enctype)); + + return 0; +} + +krb5_error_code +krb5_auth_con_getpermetypes(context, auth_context, permetypes) + krb5_context context; + krb5_auth_context auth_context; + krb5_enctype ** permetypes; +{ + krb5_enctype * newpe; + int i; + + if (! auth_context->permitted_etypes) { + *permetypes = NULL; + return(0); + } + + for (i=0; auth_context->permitted_etypes[i]; i++) + ; + i++; /* include the zero */ + + if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype))) + == NULL) + return(ENOMEM); + + *permetypes = newpe; + + memcpy(newpe, auth_context->permitted_etypes, i*sizeof(krb5_enctype)); + + return(0); +} diff --git a/src/lib/krb5/krb/auth_con.h b/src/lib/krb5/krb/auth_con.h index 9d9df0e86..e6704169e 100644 --- a/src/lib/krb5/krb/auth_con.h +++ b/src/lib/krb5/krb/auth_con.h @@ -20,6 +20,7 @@ struct _krb5_auth_context { krb5_cksumtype safe_cksumtype; /* mk_safe, ... */ krb5_pointer i_vector; /* mk_priv, rd_priv only */ krb5_rcache rcache; + krb5_enctype * permitted_etypes; /* rd_req */ }; diff --git a/src/lib/krb5/krb/decode_kdc.c b/src/lib/krb5/krb/decode_kdc.c index 71e01a811..60c983878 100644 --- a/src/lib/krb5/krb/decode_kdc.c +++ b/src/lib/krb5/krb/decode_kdc.c @@ -48,18 +48,28 @@ krb5_decode_kdc_rep(context, enc_rep, key, dec_rep) { krb5_error_code retval; krb5_kdc_rep *local_dec_rep; + krb5_keyusage usage; - if (krb5_is_as_rep(enc_rep)) + if (krb5_is_as_rep(enc_rep)) { + usage = KRB5_KEYUSAGE_AS_REP_ENCPART; retval = decode_krb5_as_rep(enc_rep, &local_dec_rep); - else if (krb5_is_tgs_rep(enc_rep)) + } else if (krb5_is_tgs_rep(enc_rep)) { + usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY; + /* KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY would go here, except + that this client code base doesn't ever put a subkey in the + tgs_req authenticator, so the tgs_rep is never encrypted in + one. (Check send_tgs.c:krb5_send_tgs_basic(), near the top + where authent.subkey is set to 0) */ retval = decode_krb5_tgs_rep(enc_rep, &local_dec_rep); - else + } else { return KRB5KRB_AP_ERR_MSG_TYPE; + } if (retval) return retval; - if (retval = krb5_kdc_rep_decrypt_proc(context, key, 0, local_dec_rep)) + if (retval = krb5_kdc_rep_decrypt_proc(context, key, &usage, + local_dec_rep)) krb5_free_kdc_rep(context, local_dec_rep); else *dec_rep = local_dec_rep; diff --git a/src/lib/krb5/krb/decrypt_tk.c b/src/lib/krb5/krb/decrypt_tk.c index 354a3f2a0..47f675591 100644 --- a/src/lib/krb5/krb/decrypt_tk.c +++ b/src/lib/krb5/krb/decrypt_tk.c @@ -42,43 +42,27 @@ krb5_decrypt_tkt_part(context, srv_key, ticket) register krb5_ticket FAR *ticket; { krb5_enc_tkt_part *dec_tkt_part; - krb5_encrypt_block eblock; krb5_data scratch; krb5_error_code retval; if (!valid_enctype(ticket->enc_part.enctype)) return KRB5_PROG_ETYPE_NOSUPP; - /* put together an eblock for this encryption */ - krb5_use_enctype(context, &eblock, ticket->enc_part.enctype); - scratch.length = ticket->enc_part.ciphertext.length; if (!(scratch.data = malloc(ticket->enc_part.ciphertext.length))) return(ENOMEM); - /* do any necessary key pre-processing */ - if (retval = krb5_process_key(context, &eblock, srv_key)) { - free(scratch.data); - return(retval); - } - /* call the encryption routine */ - if (retval = krb5_decrypt(context, - (krb5_pointer) ticket->enc_part.ciphertext.data, - (krb5_pointer) scratch.data, scratch.length, - &eblock, 0)) { - (void) krb5_finish_key(context, &eblock); + if (retval = krb5_c_decrypt(context, srv_key, + KRB5_KEYUSAGE_KDC_REP_TICKET, 0, + &ticket->enc_part, &scratch)) { free(scratch.data); return retval; } + #define clean_scratch() {memset(scratch.data, 0, scratch.length); \ free(scratch.data);} - retval = krb5_finish_key(context, &eblock); - if (retval) { - clean_scratch(); - return retval; - } /* now decode the decrypted stuff */ retval = decode_krb5_enc_tkt_part(&scratch, &dec_tkt_part); if (!retval) { diff --git a/src/lib/krb5/krb/enc_helper.c b/src/lib/krb5/krb/enc_helper.c new file mode 100644 index 000000000..ff4214937 --- /dev/null +++ b/src/lib/krb5/krb/enc_helper.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" + +krb5_error_code +krb5_encrypt_helper(context, key, usage, plain, cipher) + krb5_context context; + krb5_const krb5_keyblock *key; + krb5_keyusage usage; + krb5_const krb5_data *plain; + krb5_enc_data *cipher; +{ + krb5_error_code ret; + size_t enclen; + + if (ret = krb5_c_encrypt_length(context, key->enctype, plain->length, + &enclen)) + return(ret); + + cipher->ciphertext.length = enclen; + if ((cipher->ciphertext.data = (char *) malloc(enclen)) == NULL) + return(ret); + + if (ret = krb5_c_encrypt(context, key, usage, 0, plain, cipher)) + free(cipher->ciphertext.data); + + return(ret); +} + diff --git a/src/lib/krb5/krb/encode_kdc.c b/src/lib/krb5/krb/encode_kdc.c index bb9311f6a..e20c1f536 100644 --- a/src/lib/krb5/krb/encode_kdc.c +++ b/src/lib/krb5/krb/encode_kdc.c @@ -41,10 +41,12 @@ /* due to argument promotion rules, we need to use the DECLARG/OLDDECLARG stuff... */ krb5_error_code -krb5_encode_kdc_rep(context, type, encpart, client_key, dec_rep, enc_rep) +krb5_encode_kdc_rep(context, type, encpart, using_subkey, client_key, + dec_rep, enc_rep) krb5_context context; const krb5_msgtype type; const krb5_enc_kdc_rep_part * encpart; + int using_subkey; const krb5_keyblock * client_key; krb5_kdc_rep * dec_rep; krb5_data ** enc_rep; @@ -52,14 +54,20 @@ krb5_encode_kdc_rep(context, type, encpart, client_key, dec_rep, enc_rep) krb5_data *scratch; krb5_error_code retval; krb5_enc_kdc_rep_part tmp_encpart; - krb5_encrypt_block eblock; + krb5_keyusage usage; if (!valid_enctype(dec_rep->enc_part.enctype)) return KRB5_PROG_ETYPE_NOSUPP; switch (type) { case KRB5_AS_REP: + usage = KRB5_KEYUSAGE_AS_REP_ENCPART; + break; case KRB5_TGS_REP: + if (using_subkey) + usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY; + else + usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY; break; default: return KRB5_BADMSGTYPE; @@ -89,23 +97,8 @@ krb5_encode_kdc_rep(context, type, encpart, client_key, dec_rep, enc_rep) #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \ krb5_free_data(context, scratch); } - krb5_use_enctype(context, &eblock, client_key->enctype); - dec_rep->enc_part.ciphertext.length = - krb5_encrypt_size(scratch->length, eblock.crypto_entry); - /* add padding area, and zero it */ - if (!(scratch->data = realloc(scratch->data, - dec_rep->enc_part.ciphertext.length))) { - /* may destroy scratch->data */ - krb5_xfree(scratch); - return ENOMEM; - } - memset(scratch->data + scratch->length, 0, - dec_rep->enc_part.ciphertext.length - scratch->length); - if (!(dec_rep->enc_part.ciphertext.data = - malloc(dec_rep->enc_part.ciphertext.length))) { - retval = ENOMEM; - goto clean_scratch; - } + retval = krb5_encrypt_helper(context, client_key, usage, scratch, + &dec_rep->enc_part); #define cleanup_encpart() { \ (void) memset(dec_rep->enc_part.ciphertext.data, 0, \ @@ -114,30 +107,10 @@ free(dec_rep->enc_part.ciphertext.data); \ dec_rep->enc_part.ciphertext.length = 0; \ dec_rep->enc_part.ciphertext.data = 0;} - retval = krb5_process_key(context, &eblock, client_key); - if (retval) { - goto clean_encpart; - } - -#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);} - - retval = krb5_encrypt(context, (krb5_pointer) scratch->data, - (krb5_pointer) dec_rep->enc_part.ciphertext.data, - scratch->length, &eblock, 0); - if (retval) { - goto clean_prockey; - } - - dec_rep->enc_part.enctype = krb5_eblock_enctype(context, &eblock); - - /* do some cleanup */ cleanup_scratch(); - retval = krb5_finish_key(context, &eblock); - if (retval) { - cleanup_encpart(); - return retval; - } + if (retval) + return(retval); /* now it's ready to be encoded for the wire! */ @@ -149,18 +122,9 @@ dec_rep->enc_part.ciphertext.data = 0;} retval = encode_krb5_tgs_rep(dec_rep, enc_rep); break; } + if (retval) cleanup_encpart(); - return retval; - - clean_prockey: - cleanup_prockey(); - clean_encpart: - cleanup_encpart(); - clean_scratch: - cleanup_scratch(); return retval; } - - diff --git a/src/lib/krb5/krb/encrypt_tk.c b/src/lib/krb5/krb/encrypt_tk.c index cb1fb28b9..e1a1b1850 100644 --- a/src/lib/krb5/krb/encrypt_tk.c +++ b/src/lib/krb5/krb/encrypt_tk.c @@ -44,7 +44,6 @@ krb5_encrypt_tkt_part(context, srv_key, dec_ticket) const krb5_keyblock *srv_key; register krb5_ticket *dec_ticket; { - krb5_encrypt_block eblock; krb5_data *scratch; krb5_error_code retval; register krb5_enc_tkt_part *dec_tkt_part = dec_ticket->enc_part2; @@ -57,64 +56,12 @@ krb5_encrypt_tkt_part(context, srv_key, dec_ticket) #define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \ krb5_free_data(context, scratch); } - krb5_use_enctype(context, &eblock, srv_key->enctype); - - dec_ticket->enc_part.ciphertext.length = - krb5_encrypt_size(scratch->length, eblock.crypto_entry); - /* add padding area, and zero it */ - if (!(scratch->data = realloc(scratch->data, - dec_ticket->enc_part.ciphertext.length))) { - /* may destroy scratch->data */ - krb5_xfree(scratch); - return ENOMEM; - } - memset(scratch->data + scratch->length, 0, - dec_ticket->enc_part.ciphertext.length - scratch->length); - if (!(dec_ticket->enc_part.ciphertext.data = - malloc(dec_ticket->enc_part.ciphertext.length))) { - retval = ENOMEM; - goto clean_scratch; - } - -#define cleanup_encpart() {\ -(void) memset(dec_ticket->enc_part.ciphertext.data, 0,\ - dec_ticket->enc_part.ciphertext.length); \ -free(dec_ticket->enc_part.ciphertext.data); \ -dec_ticket->enc_part.ciphertext.length = 0; \ -dec_ticket->enc_part.ciphertext.data = 0;} - - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, srv_key))) { - goto clean_encpart; - } - -#define cleanup_prockey() {(void) krb5_finish_key(context, &eblock);} - /* call the encryption routine */ - if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data, - (krb5_pointer) dec_ticket->enc_part.ciphertext.data, - scratch->length, &eblock, 0))) { - goto clean_prockey; - } - - dec_ticket->enc_part.enctype = srv_key->enctype; - - /* ticket is now assembled-- do some cleanup */ - cleanup_scratch(); - - if ((retval = krb5_finish_key(context, &eblock))) { - cleanup_encpart(); - return retval; - } - - return 0; + retval = krb5_encrypt_helper(context, srv_key, + KRB5_KEYUSAGE_KDC_REP_TICKET, scratch, + &dec_ticket->enc_part); - clean_prockey: - cleanup_prockey(); - clean_encpart: - cleanup_encpart(); - clean_scratch: cleanup_scratch(); - return retval; + return(retval); } diff --git a/src/lib/krb5/krb/gen_seqnum.c b/src/lib/krb5/krb/gen_seqnum.c index 3694d2cd0..4b3cd6fe6 100644 --- a/src/lib/krb5/krb/gen_seqnum.c +++ b/src/lib/krb5/krb/gen_seqnum.c @@ -38,71 +38,15 @@ krb5_generate_seq_number(context, key, seqno) const krb5_keyblock *key; krb5_int32 *seqno; { - krb5_pointer random_state; - krb5_encrypt_block eblock; - krb5_keyblock *subkey = 0; + krb5_data seed; krb5_error_code retval; - struct tval { - krb5_int32 seconds; - krb5_int32 microseconds; - } timenow; - krb5_octet *intmp = 0, *outtmp = 0; - int esize; - if (!valid_enctype(key->enctype)) - return KRB5_PROG_ETYPE_NOSUPP; - - krb5_use_enctype(context, &eblock, key->enctype); - - if ((retval = krb5_init_random_key(context, &eblock, key, &random_state))) + seed.length = key->length; + seed.data = key->contents; + if ((retval = krb5_c_random_seed(context, &seed))) return(retval); - - if ((retval = krb5_random_key(context, &eblock, random_state, &subkey))) { - (void) krb5_finish_random_key(context, &eblock, &random_state); - return retval; - } - /* ignore the error if any, since we've already gotten the key out */ - if ((retval = krb5_finish_random_key(context, &eblock, &random_state))) { - krb5_free_keyblock(context, subkey); - return retval; - } - - esize = krb5_encrypt_size(sizeof(timenow), eblock.crypto_entry); - intmp = (krb5_octet *)malloc(esize); - if (!intmp) { - retval = ENOMEM; - goto cleanup; - } - outtmp = (krb5_octet *)malloc(esize); - if (!outtmp) { - retval = ENOMEM; - goto cleanup; - } - if ((retval = krb5_process_key(context, &eblock, subkey))) { - goto cleanup; - } - if ((retval = krb5_us_timeofday(context, &timenow.seconds, - &timenow.microseconds))) { - goto cleanup; - } - memcpy((char *)intmp, (char *)&timenow, sizeof(timenow)); - - retval = krb5_encrypt(context, (krb5_pointer)intmp, (krb5_pointer)outtmp, - sizeof(timenow), &eblock, 0); - (void) krb5_finish_key(context, &eblock); - if (retval) - goto cleanup; - - memcpy((char *) seqno, (char *)outtmp, sizeof(krb5_int32)); - -cleanup: - if (subkey) - krb5_free_keyblock(context, subkey); - if (intmp) - krb5_xfree(intmp); - if (outtmp) - krb5_xfree(outtmp); - return retval; + seed.length = sizeof(*seqno); + seed.data = (char *) seqno; + return(krb5_c_random_make_octets(context, &seed)); } - diff --git a/src/lib/krb5/krb/gen_subkey.c b/src/lib/krb5/krb/gen_subkey.c index 89e21a1b7..861d61e72 100644 --- a/src/lib/krb5/krb/gen_subkey.c +++ b/src/lib/krb5/krb/gen_subkey.c @@ -32,24 +32,21 @@ krb5_generate_subkey(context, key, subkey) const krb5_keyblock *key; krb5_keyblock **subkey; { - krb5_pointer random_state; - krb5_encrypt_block eblock; krb5_error_code retval; + krb5_data seed; - if (!valid_enctype(key->enctype)) - return KRB5_PROG_ETYPE_NOSUPP; + seed.length = key->length; + seed.data = key->contents; + if ((retval = krb5_c_random_seed(context, &seed))) + return(retval); - krb5_use_enctype(context, &eblock, key->enctype); + if ((*subkey = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL) + return(ENOMEM); - if ((retval = krb5_init_random_key(context, &eblock, key, &random_state))) - return(retval); - if ((retval = krb5_random_key(context, &eblock, random_state, subkey))) { - (void) krb5_finish_random_key(context, &eblock, &random_state); + if ((retval = krb5_c_make_random_key(context, key->enctype, *subkey))) { krb5_xfree(*subkey); - return retval; - } - /* ignore the error if any, since we've already gotten the key out */ - (void) krb5_finish_random_key(context, &eblock, &random_state); - return 0; -} + return(retval); + } + return(0); +} diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c index 3a1ec526b..37f2bb5a9 100644 --- a/src/lib/krb5/krb/get_creds.c +++ b/src/lib/krb5/krb/get_creds.c @@ -160,12 +160,6 @@ krb5_get_credentials_val_renew_core(context, options, ccache, krb5_creds **tgts = 0; krb5_flags fields; - retval = krb5_get_credentials_core(context, options, ccache, - in_creds, out_creds, - &mcreds, &fields); - - if (retval) return retval; - switch(which) { case INT_GC_VALIDATE: retval = krb5_get_cred_from_kdc_validate(context, ccache, @@ -219,3 +213,104 @@ krb5_get_credentials_renew(context, options, ccache, in_creds, out_creds) in_creds, out_creds, INT_GC_RENEW)); } + +static krb5_error_code +krb5_validate_or_renew_creds(context, creds, client, ccache, in_tkt_service, + validate) + krb5_context context; + krb5_creds *creds; + krb5_principal client; + krb5_ccache ccache; + char *in_tkt_service; + int validate; +{ + krb5_error_code ret; + krb5_creds in_creds; /* only client and server need to be filled in */ + krb5_creds *out_creds; + krb5_creds **tgts; + + memset((char *)&in_creds, 0, sizeof(krb5_creds)); + + in_creds.server = NULL; + tgts = NULL; + + in_creds.client = client; + + if (in_tkt_service) { + /* this is ugly, because so are the data structures involved. I'm + in the library, so I'm going to manipulate the data structures + directly, otherwise, it will be worse. */ + + if (ret = krb5_parse_name(context, in_tkt_service, &in_creds.server)) + goto cleanup; + + /* stuff the client realm into the server principal. + realloc if necessary */ + if (in_creds.server->realm.length < in_creds.client->realm.length) + if ((in_creds.server->realm.data = + (char *) realloc(in_creds.server->realm.data, + in_creds.client->realm.length)) == NULL) { + ret = ENOMEM; + goto cleanup; + } + + in_creds.server->realm.length = in_creds.client->realm.length; + memcpy(in_creds.server->realm.data, in_creds.client->realm.data, + in_creds.client->realm.length); + } else { + if (ret = krb5_build_principal_ext(context, &in_creds.server, + in_creds.client->realm.length, + in_creds.client->realm.data, + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME, + in_creds.client->realm.length, + in_creds.client->realm.data, + 0)) + goto cleanup; + } + + if (validate) + ret = krb5_get_cred_from_kdc_validate(context, ccache, + &in_creds, &out_creds, &tgts); + else + ret = krb5_get_cred_from_kdc_renew(context, ccache, + &in_creds, &out_creds, &tgts); + + /* ick. copy the struct contents, free the container */ + + *creds = *out_creds; + krb5_xfree(out_creds); + +cleanup: + + if (in_creds.server) + krb5_free_principal(context, in_creds.server); + if (tgts) + krb5_free_tgt_creds(context, tgts); + + return(ret); +} + +KRB5_DLLIMP krb5_error_code KRB5_CALLCONV +krb5_get_validated_creds(context, creds, client, ccache, in_tkt_service) + krb5_context context; + krb5_creds *creds; + krb5_principal client; + krb5_ccache ccache; + char *in_tkt_service; +{ + return(krb5_validate_or_renew_creds(context, creds, client, ccache, + in_tkt_service, 1)); +} + +KRB5_DLLIMP krb5_error_code KRB5_CALLCONV +krb5_get_renewed_creds(context, creds, client, ccache, in_tkt_service) + krb5_context context; + krb5_creds *creds; + krb5_principal client; + krb5_ccache ccache; + char *in_tkt_service; +{ + return(krb5_validate_or_renew_creds(context, creds, client, ccache, + in_tkt_service, 0)); +} diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c index 45a076246..c517062f8 100644 --- a/src/lib/krb5/krb/gic_pwd.c +++ b/src/lib/krb5/krb/gic_pwd.c @@ -16,7 +16,6 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data, krb5_data *password; krb5_error_code ret; krb5_data defsalt; - krb5_encrypt_block eblock; char *clientstr; char promptstr[1024]; krb5_prompt prompt; @@ -35,11 +34,6 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data, as_key->length = 0; } - if (!valid_enctype(etype)) - return(KRB5_PROG_ETYPE_NOSUPP); - - krb5_use_enctype(context, &eblock, etype); - if (password->data[0] == '\0') { if (prompter == NULL) return(EIO); @@ -70,7 +64,7 @@ krb5_get_as_key_password(context, client, etype, prompter, prompter_data, defsalt.length = 0; } - ret = krb5_string_to_key(context, &eblock, as_key, password, salt); + ret = krb5_c_string_to_key(context, etype, password, salt, as_key); if (defsalt.length) krb5_xfree(defsalt.data); diff --git a/src/lib/krb5/krb/in_tkt_pwd.c b/src/lib/krb5/krb/in_tkt_pwd.c index 7373f62f1..e03883e9d 100644 --- a/src/lib/krb5/krb/in_tkt_pwd.c +++ b/src/lib/krb5/krb/in_tkt_pwd.c @@ -47,15 +47,9 @@ pwd_keyproc(context, type, salt, keyseed, key) krb5_keyblock ** key; { krb5_error_code retval; - krb5_encrypt_block eblock; krb5_data * password; int pwsize; - if (!valid_enctype(type)) - return KRB5_PROG_ETYPE_NOSUPP; - - krb5_use_enctype(context, &eblock, type); - password = (krb5_data *)keyseed; if (!password->length) { @@ -73,8 +67,9 @@ pwd_keyproc(context, type, salt, keyseed, key) if (!(*key = (krb5_keyblock *)malloc(sizeof(**key)))) return ENOMEM; - if ((retval = krb5_string_to_key(context, &eblock, *key, password, salt))) + if ((retval = krb5_c_string_to_key(context, type, password, salt, *key))) krb5_xfree(*key); + return(retval); } diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index daa9fd95f..2285b0f42 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -23,6 +23,32 @@ * krb5_init_contex() */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * 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 FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + #include "k5-int.h" #include <ctype.h> #include "brand.c" @@ -37,6 +63,8 @@ krb5_init_context(context) { krb5_context ctx = 0; krb5_error_code retval; + krb5_timestamp now; + krb5_data seed; int tmp; /* Initialize error tables */ @@ -70,6 +98,14 @@ krb5_init_context(context) if ((retval = krb5_os_init_context(ctx))) goto cleanup; + /* initialize the prng (not well, but passable) */ + if ((retval = krb5_timeofday(ctx, &now))) + goto cleanup; + seed.length = sizeof(now); + seed.data = (char *) &now; + if ((retval = krb5_c_random_seed(ctx, &seed))) + goto cleanup; + ctx->default_realm = 0; profile_get_integer(ctx->profile, "libdefaults", "clockskew", 0, 5 * 60, &tmp); @@ -197,26 +233,27 @@ krb5_set_default_in_tkt_ktypes(context, ktypes) return 0; } -krb5_error_code -krb5_get_default_in_tkt_ktypes(context, ktypes) - krb5_context context; - krb5_enctype **ktypes; +static krb5_error_code +get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list) + krb5_context context; + krb5_enctype **ktypes; + char *profstr; + int ctx_count; + krb5_enctype FAR *ctx_list; { - krb5_enctype * old_ktypes; + krb5_enctype *old_ktypes; if (context->in_tkt_ktype_count) { - /* application-set defaults */ - if ((old_ktypes = - (krb5_enctype *)malloc(sizeof(krb5_enctype) * - (context->in_tkt_ktype_count + 1)))) { - memcpy(old_ktypes, context->in_tkt_ktypes, sizeof(krb5_enctype) * - context->in_tkt_ktype_count); - old_ktypes[context->in_tkt_ktype_count] = 0; - } else { - return ENOMEM; - } + /* application-set defaults */ + if ((old_ktypes = + (krb5_enctype *)malloc(sizeof(krb5_enctype) * + (ctx_count + 1)))) { + memcpy(old_ktypes, ctx_list, sizeof(krb5_enctype) * ctx_count); + old_ktypes[ctx_count] = 0; + } else { + return ENOMEM; + } } else { - /* taken directly from krb5_get_tgs_ktypes... */ /* XXX - For now, we only support libdefaults Perhaps this should be extended to allow for per-host / per-realm @@ -228,9 +265,9 @@ krb5_get_default_in_tkt_ktypes(context, ktypes) int i, j, count; krb5_error_code code; - code = profile_get_string(context->profile, - "libdefaults", "default_tkt_enctypes", NULL, - "des-cbc-md5 des-cbc-crc", + code = profile_get_string(context->profile, "libdefaults", profstr, + NULL, + "des3-hmac-sha1 des-cbc-md5 des-cbc-crc", &retval); if (code) return code; @@ -280,6 +317,16 @@ krb5_get_default_in_tkt_ktypes(context, ktypes) } krb5_error_code +krb5_get_default_in_tkt_ktypes(context, ktypes) + krb5_context context; + krb5_enctype **ktypes; +{ + return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes", + context->in_tkt_ktype_count, + context->in_tkt_ktypes)); +} + +krb5_error_code krb5_set_default_tgs_ktypes(context, ktypes) krb5_context context; const krb5_enctype *ktypes; @@ -317,80 +364,40 @@ krb5_get_tgs_ktypes(context, princ, ktypes) krb5_const_principal princ; krb5_enctype **ktypes; { - krb5_enctype * old_ktypes; - - if (context->tgs_ktype_count) { - - /* Application-set defaults */ - - if ((old_ktypes = - (krb5_enctype *)malloc(sizeof(krb5_enctype) * - (context->tgs_ktype_count + 1)))) { - memcpy(old_ktypes, context->tgs_ktypes, sizeof(krb5_enctype) * - context->tgs_ktype_count); - old_ktypes[context->tgs_ktype_count] = 0; - } else { - return ENOMEM; - } - } else { - /* - XXX - For now, we only support libdefaults - Perhaps this should be extended to allow for per-host / per-realm - session key types. - */ - - char *retval; - char *sp, *ep; - int i, j, count; - krb5_error_code code; + return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes", + context->tgs_ktype_count, + context->tgs_ktypes)); +} - code = profile_get_string(context->profile, - "libdefaults", "default_tgs_enctypes", NULL, - "des-cbc-md5 des-cbc-crc", - &retval); - if (code) - return code; +krb5_error_code +krb5_get_permitted_enctypes(context, ktypes) + krb5_context context; + krb5_enctype **ktypes; +{ + return(get_profile_etype_list(context, ktypes, "permitted_enctypes", + context->tgs_ktype_count, + context->tgs_ktypes)); +} - count = 0; - sp = retval; - while (sp) { - for (ep = sp; *ep && (*ep != ',') && !isspace(*ep); ep++) - ; - if (*ep) { - *ep++ = '\0'; - while (isspace(*ep)) - ep++; - } else - ep = (char *) NULL; +krb5_boolean +krb5_is_permitted_enctype(context, etype) + krb5_context context; + krb5_enctype etype; +{ + krb5_enctype *list, *ptr; + krb5_boolean ret; - count++; - sp = ep; - } - - if ((old_ktypes = - (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) == - (krb5_enctype *) NULL) - return ENOMEM; - - sp = retval; - j = 0; - i = 1; - while (1) { - if (! krb5_string_to_enctype(sp, &old_ktypes[j])) - j++; + if (krb5_get_permitted_enctypes(context, &list)) + return(0); - if (i++ >= count) - break; + + ret = 0; - /* skip to next token */ - while (*sp) sp++; - while (! *sp) sp++; - } + for (ptr = list; *ptr; ptr++) + if (*ptr == etype) + ret = 1; - old_ktypes[j] = (krb5_enctype) 0; - free(retval); - } + krb5_xfree(list); - *ktypes = old_ktypes; - return 0; + return(ret); } diff --git a/src/lib/krb5/krb/kdc_rep_dc.c b/src/lib/krb5/krb/kdc_rep_dc.c index e9431aef9..a9cbcf39b 100644 --- a/src/lib/krb5/krb/kdc_rep_dc.c +++ b/src/lib/krb5/krb/kdc_rep_dc.c @@ -41,12 +41,15 @@ krb5_kdc_rep_decrypt_proc(context, key, decryptarg, dec_rep) krb5_kdc_rep * dec_rep; { krb5_error_code retval; - krb5_encrypt_block eblock; krb5_data scratch; krb5_enc_kdc_rep_part *local_encpart; + krb5_keyusage usage; - if (!valid_enctype(dec_rep->enc_part.enctype)) - return KRB5_PROG_ETYPE_NOSUPP; + if (decryptarg) { + usage = *(const krb5_keyusage *) decryptarg; + } else { + usage = KRB5_KEYUSAGE_AS_REP_ENCPART; + } /* set up scratch decrypt/decode area */ @@ -55,30 +58,16 @@ krb5_kdc_rep_decrypt_proc(context, key, decryptarg, dec_rep) return(ENOMEM); } - /* put together an eblock for this encryption */ - - krb5_use_enctype(context, &eblock, dec_rep->enc_part.enctype); + dec_rep->enc_part.enctype; - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, key))) { + if ((retval = krb5_c_decrypt(context, key, usage, 0, &dec_rep->enc_part, + &scratch))) { free(scratch.data); return(retval); } - /* call the decryption routine */ - if ((retval = krb5_decrypt(context, (krb5_pointer) dec_rep->enc_part.ciphertext.data, - (krb5_pointer) scratch.data, - scratch.length, &eblock, 0))) { - (void) krb5_finish_key(context, &eblock); - free(scratch.data); - return retval; - } #define clean_scratch() {memset(scratch.data, 0, scratch.length); \ free(scratch.data);} - if ((retval = krb5_finish_key(context, &eblock))) { - clean_scratch(); - return retval; - } /* and do the decode */ retval = decode_krb5_enc_kdc_rep_part(&scratch, &local_encpart); diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index 17c4f8c7f..87eeca961 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -149,6 +149,16 @@ krb5_free_checksum(context, val) } KRB5_DLLIMP void KRB5_CALLCONV +krb5_free_checksum_contents(context, val) + krb5_context context; + register krb5_checksum *val; +{ + if (val->contents) + krb5_xfree(val->contents); + return; +} + +KRB5_DLLIMP void KRB5_CALLCONV krb5_free_cred(context, val) krb5_context context; register krb5_cred FAR *val; @@ -572,3 +582,4 @@ krb5_free_unparsed_name(context, val) krb5_xfree(val); return; } + diff --git a/src/lib/krb5/krb/mk_cred.c b/src/lib/krb5/krb/mk_cred.c index 23545fb61..cdda80d06 100644 --- a/src/lib/krb5/krb/mk_cred.c +++ b/src/lib/krb5/krb/mk_cred.c @@ -28,12 +28,8 @@ encrypt_credencpart(context, pcredpart, pkeyblock, pencdata) krb5_enc_data * pencdata; { krb5_error_code retval; - krb5_encrypt_block eblock; krb5_data * scratch; - if (pkeyblock && !valid_enctype(pkeyblock->enctype)) - return KRB5_PROG_ETYPE_NOSUPP; - /* start by encoding to-be-encrypted part of the message */ if ((retval = encode_krb5_enc_cred_part(pcredpart, &scratch))) return retval; @@ -49,47 +45,11 @@ encrypt_credencpart(context, pcredpart, pkeyblock, pencdata) return 0; } - /* put together an eblock for this encryption */ - - pencdata->kvno = 0; - pencdata->enctype = pkeyblock->enctype; - - krb5_use_enctype(context, &eblock, pkeyblock->enctype); - pencdata->ciphertext.length = krb5_encrypt_size(scratch->length, - eblock.crypto_entry); - - /* add padding area, and zero it */ - if (!(scratch->data = (char *)realloc(scratch->data, - pencdata->ciphertext.length))) { - /* may destroy scratch->data */ - krb5_xfree(scratch); - return ENOMEM; - } - - memset(scratch->data + scratch->length, 0, - pencdata->ciphertext.length - scratch->length); - if (!(pencdata->ciphertext.data = - (char *)malloc(pencdata->ciphertext.length))) { - retval = ENOMEM; - goto clean_scratch; - } - - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, pkeyblock))) { - goto clean_encpart; - } - /* call the encryption routine */ - if ((retval = krb5_encrypt(context, (krb5_pointer)scratch->data, - (krb5_pointer)pencdata->ciphertext.data, - scratch->length, &eblock, 0))) { - krb5_finish_key(context, &eblock); - goto clean_encpart; - } - - retval = krb5_finish_key(context, &eblock); + retval = krb5_encrypt_helper(context, pkeyblock, + KRB5_KEYUSAGE_KRB_CRED_ENCPART, + scratch, pencdata); -clean_encpart: if (retval) { memset(pencdata->ciphertext.data, 0, pencdata->ciphertext.length); free(pencdata->ciphertext.data); @@ -97,7 +57,6 @@ clean_encpart: pencdata->ciphertext.data = 0; } -clean_scratch: memset(scratch->data, 0, scratch->length); krb5_free_data(context, scratch); diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c index 7986e1856..2e7f2ce25 100644 --- a/src/lib/krb5/krb/mk_priv.c +++ b/src/lib/krb5/krb/mk_priv.c @@ -41,13 +41,10 @@ krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr, krb5_data * outbuf; { krb5_error_code retval; - krb5_encrypt_block eblock; krb5_priv privmsg; krb5_priv_enc_part privmsg_enc_part; - krb5_data *scratch1, *scratch2; - - if (!valid_enctype(keyblock->enctype)) - return KRB5_PROG_ETYPE_NOSUPP; + krb5_data *scratch1, *scratch2, ivdata; + size_t blocksize, enclen; privmsg.enc_part.kvno = 0; /* XXX allow user-set? */ privmsg.enc_part.enctype = keyblock->enctype; @@ -66,52 +63,42 @@ krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr, return retval; /* put together an eblock for this encryption */ - krb5_use_enctype(context, &eblock, keyblock->enctype); - privmsg.enc_part.ciphertext.length = krb5_encrypt_size(scratch1->length, - eblock.crypto_entry); - /* add padding area, and zero it */ - if (!(scratch1->data = realloc(scratch1->data, - privmsg.enc_part.ciphertext.length))) { - /* may destroy scratch1->data */ - krb5_xfree(scratch1); - return ENOMEM; - } + if ((retval = krb5_c_encrypt_length(context, keyblock->enctype, + scratch1->length, &enclen))) + goto clean_scratch; - memset(scratch1->data + scratch1->length, 0, - privmsg.enc_part.ciphertext.length - scratch1->length); + privmsg.enc_part.ciphertext.length = enclen; if (!(privmsg.enc_part.ciphertext.data = malloc(privmsg.enc_part.ciphertext.length))) { retval = ENOMEM; goto clean_scratch; } - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, keyblock))) - goto clean_encpart; - /* call the encryption routine */ - if ((retval = krb5_encrypt(context, (krb5_pointer) scratch1->data, - (krb5_pointer) privmsg.enc_part.ciphertext.data, - scratch1->length, &eblock, i_vector))) { - krb5_finish_key(context, &eblock); - goto clean_encpart; + if (i_vector) { + if ((retval = krb5_c_block_size(context, keyblock->enctype, + &blocksize))) + goto clean_encpart; + + ivdata.length = blocksize; + ivdata.data = i_vector; } + if ((retval = krb5_c_encrypt(context, keyblock, + KRB5_KEYUSAGE_KRB_PRIV_ENCPART, + i_vector?&ivdata:0, + scratch1, &privmsg.enc_part))) + goto clean_encpart; + /* put last block into the i_vector */ + if (i_vector) memcpy(i_vector, privmsg.enc_part.ciphertext.data + - (privmsg.enc_part.ciphertext.length - - eblock.crypto_entry->block_length), - eblock.crypto_entry->block_length); + (privmsg.enc_part.ciphertext.length - blocksize), + blocksize); - if ((retval = encode_krb5_priv(&privmsg, &scratch2))) { - krb5_finish_key(context, &eblock); - goto clean_encpart; - } - - /* encode private message */ - if ((retval = krb5_finish_key(context, &eblock))) + if ((retval = encode_krb5_priv(&privmsg, &scratch2))) goto clean_encpart; *outbuf = *scratch2; diff --git a/src/lib/krb5/krb/mk_rep.c b/src/lib/krb5/krb/mk_rep.c index 45784284c..f0398475f 100644 --- a/src/lib/krb5/krb/mk_rep.c +++ b/src/lib/krb5/krb/mk_rep.c @@ -45,14 +45,11 @@ krb5_mk_rep(context, auth_context, outbuf) krb5_error_code retval; krb5_enctype enctype; krb5_ap_rep_enc_part repl; - krb5_encrypt_block eblock; krb5_ap_rep reply; krb5_data * scratch; krb5_data * toutbuf; - /* verify a valid enctype is available */ - if (!valid_enctype(enctype = auth_context->keyblock->enctype)) - return KRB5_PROG_ETYPE_NOSUPP; + enctype = auth_context->keyblock->enctype; /* Make the reply */ if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || @@ -72,49 +69,16 @@ krb5_mk_rep(context, auth_context, outbuf) if ((retval = encode_krb5_ap_rep_enc_part(&repl, &scratch))) return retval; - /* put together an eblock for this encryption */ - krb5_use_enctype(context, &eblock, enctype); - reply.enc_part.enctype = enctype; - reply.enc_part.kvno = 0; /* XXX user set? */ - - reply.enc_part.ciphertext.length = krb5_encrypt_size(scratch->length, - eblock.crypto_entry); - /* add padding area, and zero it */ - if (!(scratch->data = realloc(scratch->data, - reply.enc_part.ciphertext.length))) { - /* may destroy scratch->data */ - krb5_xfree(scratch); - return ENOMEM; - } - memset(scratch->data + scratch->length, 0, - reply.enc_part.ciphertext.length - scratch->length); - if (!(reply.enc_part.ciphertext.data = - malloc(reply.enc_part.ciphertext.length))) { - retval = ENOMEM; + if ((retval = krb5_encrypt_helper(context, auth_context->keyblock, + KRB5_KEYUSAGE_AP_REP_ENCPART, + scratch, &reply.enc_part))) goto cleanup_scratch; - } - - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, auth_context->keyblock))) - goto cleanup_encpart; - - /* call the encryption routine */ - if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data, - (krb5_pointer) reply.enc_part.ciphertext.data, - scratch->length, &eblock, 0))) { - krb5_finish_key(context, &eblock); - goto cleanup_encpart; - } - - if ((retval = krb5_finish_key(context, &eblock))) - goto cleanup_encpart; if (!(retval = encode_krb5_ap_rep(&reply, &toutbuf))) { *outbuf = *toutbuf; krb5_xfree(toutbuf); } -cleanup_encpart: memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length); free(reply.enc_part.ciphertext.data); reply.enc_part.ciphertext.length = 0; diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index 726bb434b..1530f7961 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -84,7 +84,6 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds, krb5_ap_req request; krb5_data *scratch = 0; - krb5_encrypt_block eblock; krb5_data *toutbuf; request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK; @@ -98,12 +97,6 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds, if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket))) return(retval); - /* verify a valid enctype is available */ - if (!valid_enctype(in_creds->keyblock.enctype)) { - retval = KRB5_PROG_ETYPE_NOSUPP; - goto cleanup; - } - /* verify that the ticket is not expired */ if ((retval = krb5_validate_times(context, &in_creds->times)) != 0) goto cleanup; @@ -135,27 +128,18 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds, &(*auth_context)->local_subkey))) goto cleanup; - if (in_data) { if ((*auth_context)->req_cksumtype == 0x8003) { /* XXX Special hack for GSSAPI */ checksum.checksum_type = 0x8003; checksum.length = in_data->length; checksum.contents = (krb5_octet *) in_data->data; - } else { - /* Generate checksum, XXX What should the seed be? */ - checksum.length = - krb5_checksum_size(context, (*auth_context)->req_cksumtype); - if ((checksum.contents = (krb5_octet *)malloc(checksum.length)) == NULL) { - retval = ENOMEM; - goto cleanup; - } - if ((retval = krb5_calculate_checksum(context, - (*auth_context)->req_cksumtype, - in_data->data, in_data->length, - (*auth_context)->keyblock->contents, - (*auth_context)->keyblock->length, - &checksum))) + } else { + if ((retval = krb5_c_make_checksum(context, + (*auth_context)->req_cksumtype, + (*auth_context)->keyblock, + KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, + in_data, &checksum))) goto cleanup_cksum; } checksump = &checksum; @@ -188,43 +172,12 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds, (*auth_context)->authentp->checksum = NULL; (*auth_context)->authentp->authorization_data = NULL; - /* put together an eblock for this encryption */ - - krb5_use_enctype(context, &eblock, in_creds->keyblock.enctype); - request.authenticator.enctype = in_creds->keyblock.enctype; - request.authenticator.kvno = 0; - request.authenticator.ciphertext.length = - krb5_encrypt_size(scratch->length, eblock.crypto_entry); - /* add padding area, and zero it */ - if (!(scratch->data = realloc(scratch->data, - request.authenticator.ciphertext.length))) { - /* may destroy scratch->data */ - retval = ENOMEM; - goto cleanup_cksum; - } - memset(scratch->data + scratch->length, 0, - request.authenticator.ciphertext.length - scratch->length); - if (!(request.authenticator.ciphertext.data = - malloc(request.authenticator.ciphertext.length))) { - retval = ENOMEM; - goto cleanup_cksum; - } - - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, &(in_creds)->keyblock))) - goto cleanup; - /* call the encryption routine */ - if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data, - (krb5_pointer) request.authenticator.ciphertext.data, - scratch->length, &eblock, 0))) { - krb5_finish_key(context, &eblock); + if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock, + KRB5_KEYUSAGE_AP_REQ_AUTH, + scratch, &request.authenticator))) goto cleanup_cksum; - } - if ((retval = krb5_finish_key(context, &eblock))) - goto cleanup_cksum; - if ((retval = encode_krb5_ap_req(&request, &toutbuf))) goto cleanup_cksum; #ifdef HAVE_C_STRUCTURE_ASSIGNMENT diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c index 1a44a75e5..0d5a49080 100644 --- a/src/lib/krb5/krb/mk_safe.c +++ b/src/lib/krb5/krb/mk_safe.c @@ -90,18 +90,11 @@ krb5_mk_safe_basic(context, userdata, keyblock, replaydata, local_addr, if ((retval = encode_krb5_safe(&safemsg, &scratch1))) return retval; - safe_checksum.length = krb5_checksum_size(context, sumtype); - if (!(safe_checksum.contents = (krb5_octet *) malloc(safe_checksum.length))) { - - retval = ENOMEM; - goto cleanup_scratch; - } - if ((retval = krb5_calculate_checksum(context, sumtype, scratch1->data, - scratch1->length, - (krb5_pointer) keyblock->contents, - keyblock->length, &safe_checksum))) { + if ((retval = krb5_c_make_checksum(context, sumtype, keyblock, + KRB5_KEYUSAGE_KRB_SAFE_CKSUM, + scratch1, &safe_checksum))) goto cleanup_checksum; - } + safemsg.checksum = &safe_checksum; if ((retval = encode_krb5_safe(&safemsg, &scratch2))) { goto cleanup_checksum; diff --git a/src/lib/krb5/krb/preauth.c b/src/lib/krb5/krb/preauth.c index c106dd15a..ab1432fdb 100644 --- a/src/lib/krb5/krb/preauth.c +++ b/src/lib/krb5/krb/preauth.c @@ -160,6 +160,10 @@ krb5_error_code krb5_obtain_padata(context, preauth_to_use, key_proc, for (pa = preauth_to_use, size=0; *pa; pa++, size++) { if ((*pa)->pa_type == KRB5_PADATA_ETYPE_INFO) { + /* XXX use the first one. Is there another way to disambiguate? */ + if (etype_info) + continue; + scratch.length = (*pa)->length; scratch.data = (char *) (*pa)->contents; retval = decode_krb5_etype_info(&scratch, &etype_info); @@ -219,6 +223,8 @@ krb5_error_code krb5_obtain_padata(context, preauth_to_use, key_proc, } cleanup: + if (etype_info) + krb5_free_etype_info(context, etype_info); if (f_salt) krb5_xfree(salt.data); if (send_pa_list) @@ -294,9 +300,6 @@ obtain_enc_ts_padata(context, in_padata, etype_info, def_enc_key, krb5_data * scratch; krb5_enc_data enc_data; krb5_pa_data * pa; - - - enc_data.ciphertext.data = 0; retval = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec); if (retval) @@ -305,8 +308,11 @@ obtain_enc_ts_padata(context, in_padata, etype_info, def_enc_key, if ((retval = encode_krb5_pa_enc_ts(&pa_enc, &scratch)) != 0) return retval; - if ((retval = krb5_encrypt_data(context, def_enc_key, 0, scratch, - &enc_data))) + enc_data.ciphertext.data = 0; + + if ((retval = krb5_encrypt_helper(context, def_enc_key, + KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, + scratch, &enc_data))) goto cleanup; krb5_free_data(context, scratch); diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index 0a154f6e1..86d325d7b 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -117,12 +117,16 @@ krb5_error_code pa_enc_timestamp(krb5_context context, if (ret = encode_krb5_pa_enc_ts(&pa_enc, &tmp)) return(ret); - ret = krb5_encrypt_data(context, as_key, 0, tmp, &enc_data); + ret = krb5_encrypt_helper(context, as_key, + KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, + tmp, &enc_data); krb5_free_data(context, tmp); - if (ret) + if (ret) { + krb5_xfree(enc_data.ciphertext.data); return(ret); + } ret = encode_krb5_enc_data(&enc_data, &tmp); @@ -215,7 +219,6 @@ krb5_error_code pa_sam(krb5_context context, char banner[100], prompt[100], response[100]; krb5_data response_data; krb5_prompt kprompt; - krb5_encrypt_block eblock; krb5_data defsalt; krb5_sam_challenge *sam_challenge = 0; krb5_sam_response sam_response; @@ -281,13 +284,6 @@ krb5_error_code pa_sam(krb5_context context, as_key->length = 0; } - /* XXX the server uses this fixed enctype, so we will, too. */ - - if (!valid_enctype(ENCTYPE_DES_CBC_MD5)) - return(KRB5_PROG_ETYPE_NOSUPP); - - krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_MD5); - #if 0 if ((salt->length == -1) && (salt->data == NULL)) { if (ret = krb5_principal2salt(context, request->client, @@ -305,8 +301,11 @@ krb5_error_code pa_sam(krb5_context context, salt = NULL; #endif - ret = krb5_string_to_key(context, &eblock, as_key, - &response_data, salt); + /* XXX the server uses this fixed enctype, so we will, too. */ + + ret = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5, + &response_data, salt, as_key); + if (defsalt.length) krb5_xfree(defsalt.data); diff --git a/src/lib/krb5/krb/rd_cred.c b/src/lib/krb5/krb/rd_cred.c index 7537ac990..86c5ccf72 100644 --- a/src/lib/krb5/krb/rd_cred.c +++ b/src/lib/krb5/krb/rd_cred.c @@ -19,7 +19,6 @@ decrypt_credencdata(context, pcred, pkeyblock, pcredenc) krb5_cred_enc_part * pcredenc; { krb5_cred_enc_part * ppart; - krb5_encrypt_block eblock; krb5_error_code retval; krb5_data scratch; @@ -28,28 +27,9 @@ decrypt_credencdata(context, pcred, pkeyblock, pcredenc) return ENOMEM; if (pkeyblock != NULL) { - if (!valid_enctype(pcred->enc_part.enctype)) { - free(scratch.data); - return KRB5_PROG_ETYPE_NOSUPP; - } - - /* put together an eblock for this decryption */ - krb5_use_enctype(context, &eblock, pcred->enc_part.enctype); - - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, pkeyblock))) - goto cleanup; - - /* call the decryption routine */ - if ((retval = krb5_decrypt(context, - (krb5_pointer) pcred->enc_part.ciphertext.data, - (krb5_pointer) scratch.data, - scratch.length, &eblock, 0))) { - (void)krb5_finish_key(context, &eblock); - goto cleanup; - } - - if ((retval = krb5_finish_key(context, &eblock))) + if ((retval = krb5_c_decrypt(context, pkeyblock, + KRB5_KEYUSAGE_KRB_CRED_ENCPART, 0, + &pcred->enc_part, &scratch))) goto cleanup; } else { memcpy(scratch.data, pcred->enc_part.ciphertext.data, scratch.length); diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index c4e1ed0b6..f08975f22 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -66,8 +66,9 @@ krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr, krb5_error_code retval; krb5_priv * privmsg; krb5_data scratch; - krb5_encrypt_block eblock; krb5_priv_enc_part * privmsg_enc_part; + size_t blocksize; + krb5_data ivdata; if (!krb5_is_krb_priv(inbuf)) return KRB5KRB_AP_ERR_MSG_TYPE; @@ -76,43 +77,33 @@ krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr, if ((retval = decode_krb5_priv(inbuf, &privmsg))) return retval; - if (!valid_enctype(privmsg->enc_part.enctype)) { - retval = KRB5_PROG_ETYPE_NOSUPP; - goto cleanup_privmsg; + if (i_vector) { + if ((retval = krb5_c_block_size(context, keyblock->enctype, + &blocksize))) + goto cleanup_privmsg; + + ivdata.length = blocksize; + ivdata.data = i_vector; } - - /* put together an eblock for this decryption */ - krb5_use_enctype(context, &eblock, privmsg->enc_part.enctype); + scratch.length = privmsg->enc_part.ciphertext.length; - if (!(scratch.data = malloc(scratch.length))) { retval = ENOMEM; goto cleanup_privmsg; } - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, keyblock))) + if ((retval = krb5_c_decrypt(context, keyblock, + KRB5_KEYUSAGE_KRB_PRIV_ENCPART, + i_vector?&ivdata:0, + &privmsg->enc_part, &scratch))) goto cleanup_scratch; - /* call the decryption routine */ - if ((retval = krb5_decrypt(context, - (krb5_pointer) privmsg->enc_part.ciphertext.data, - (krb5_pointer) scratch.data, - scratch.length, &eblock, i_vector))) { - krb5_finish_key(context, &eblock); - goto cleanup_scratch; - } - /* if i_vector is set, put last block into the i_vector */ if (i_vector) memcpy(i_vector, privmsg->enc_part.ciphertext.data + - (privmsg->enc_part.ciphertext.length - - eblock.crypto_entry->block_length), - eblock.crypto_entry->block_length); - - if ((retval = krb5_finish_key(context, &eblock))) - goto cleanup_scratch; + (privmsg->enc_part.ciphertext.length - blocksize), + blocksize); /* now decode the decrypted stuff */ if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part))) diff --git a/src/lib/krb5/krb/rd_rep.c b/src/lib/krb5/krb/rd_rep.c index d4d559d14..411a61ddb 100644 --- a/src/lib/krb5/krb/rd_rep.c +++ b/src/lib/krb5/krb/rd_rep.c @@ -47,7 +47,6 @@ krb5_rd_rep(context, auth_context, inbuf, repl) { krb5_error_code retval; krb5_ap_rep * reply; - krb5_encrypt_block eblock; krb5_data scratch; if (!krb5_is_ap_rep(inbuf)) @@ -60,35 +59,15 @@ krb5_rd_rep(context, auth_context, inbuf, repl) /* put together an eblock for this encryption */ - if (!valid_enctype(reply->enc_part.enctype)) { - krb5_free_ap_rep(context, reply); - return KRB5_PROG_ETYPE_NOSUPP; - } - krb5_use_enctype(context, &eblock, reply->enc_part.enctype); - scratch.length = reply->enc_part.ciphertext.length; if (!(scratch.data = malloc(scratch.length))) { krb5_free_ap_rep(context, reply); return(ENOMEM); } - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, - auth_context->keyblock))) { - goto errout; - } - - /* call the encryption routine */ - if ((retval = krb5_decrypt(context, - (krb5_pointer) reply->enc_part.ciphertext.data, - (krb5_pointer) scratch.data, - scratch.length, &eblock, 0))) { - (void) krb5_finish_key(context, &eblock); - goto errout; - } - - /* finished with the top-level encoding of the ap_rep */ - if ((retval = krb5_finish_key(context, &eblock))) + if ((retval = krb5_c_decrypt(context, auth_context->keyblock, + KRB5_KEYUSAGE_AP_REP_ENCPART, 0, + &reply->enc_part, &scratch))) goto clean_scratch; /* now decode the decrypted stuff */ diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c index 0c62c19df..cdbdc81df 100644 --- a/src/lib/krb5/krb/rd_req_dec.c +++ b/src/lib/krb5/krb/rd_req_dec.c @@ -57,7 +57,8 @@ */ static krb5_error_code decrypt_authenticator - PROTOTYPE((krb5_context, const krb5_ap_req *, krb5_authenticator **)); + PROTOTYPE((krb5_context, const krb5_ap_req *, krb5_authenticator **, + int)); #define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew) @@ -119,8 +120,12 @@ krb5_rd_req_decoded_opt(context, auth_context, req, server, keytab, return retval; } + /* XXX this is an evil hack. check_valid_flag is set iff the call + is not from inside the kdc. we can use this to determine which + key usage to use */ if ((retval = decrypt_authenticator(context, req, - &((*auth_context)->authentp)))) + &((*auth_context)->authentp), + check_valid_flag))) goto cleanup; if (!krb5_principal_compare(context, (*auth_context)->authentp->client, @@ -243,14 +248,66 @@ krb5_rd_req_decoded_opt(context, auth_context, req, server, keytab, } } + /* check if the various etypes are permitted */ + + if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) { + /* no etype check needed */; + } else if ((*auth_context)->permitted_etypes == NULL) { + /* check against the default set */ + if ((!krb5_is_permitted_enctype(context, + req->ticket->enc_part.enctype)) || + (!krb5_is_permitted_enctype(context, + req->ticket->enc_part2->session->enctype)) || + (((*auth_context)->authentp->subkey) && + !krb5_is_permitted_enctype(context, + (*auth_context)->authentp->subkey->enctype))) { + retval = KRB5_NOPERM_ETYPE; + goto cleanup; + } + } else { + /* check against the set in the auth_context */ + int i; + + for (i=0; (*auth_context)->permitted_etypes[i]; i++) + if ((*auth_context)->permitted_etypes[i] == + req->ticket->enc_part.enctype) + break; + if (!(*auth_context)->permitted_etypes[i]) { + retval = KRB5_NOPERM_ETYPE; + goto cleanup; + } + + for (i=0; (*auth_context)->permitted_etypes[i]; i++) + if ((*auth_context)->permitted_etypes[i] == + req->ticket->enc_part2->session->enctype) + break; + if (!(*auth_context)->permitted_etypes[i]) { + retval = KRB5_NOPERM_ETYPE; + goto cleanup; + } + + if ((*auth_context)->authentp->subkey) { + for (i=0; (*auth_context)->permitted_etypes[i]; i++) + if ((*auth_context)->permitted_etypes[i] == + (*auth_context)->authentp->subkey->enctype) + break; + if (!(*auth_context)->permitted_etypes[i]) { + retval = KRB5_NOPERM_ETYPE; + goto cleanup; + } + } + } + (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number; if ((*auth_context)->authentp->subkey) { if ((retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey, &((*auth_context)->remote_subkey)))) goto cleanup; - } else + } else { (*auth_context)->remote_subkey = 0; + } + if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session, &((*auth_context)->keyblock)))) goto cleanup; @@ -322,52 +379,34 @@ krb5_rd_req_decoded_anyflag(context, auth_context, req, server, keytab, } static krb5_error_code -decrypt_authenticator(context, request, authpp) +decrypt_authenticator(context, request, authpp, is_ap_req) krb5_context context; const krb5_ap_req *request; krb5_authenticator **authpp; + int is_ap_req; { krb5_authenticator *local_auth; krb5_error_code retval; - krb5_encrypt_block eblock; krb5_data scratch; krb5_keyblock *sesskey; sesskey = request->ticket->enc_part2->session; - if (!valid_enctype(sesskey->enctype)) - return KRB5_PROG_ETYPE_NOSUPP; - - /* put together an eblock for this encryption */ - - krb5_use_enctype(context, &eblock, request->authenticator.enctype); - scratch.length = request->authenticator.ciphertext.length; if (!(scratch.data = malloc(scratch.length))) return(ENOMEM); - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, sesskey))) { + if ((retval = krb5_c_decrypt(context, sesskey, + is_ap_req?KRB5_KEYUSAGE_AP_REQ_AUTH: + KRB5_KEYUSAGE_TGS_REQ_AUTH, 0, + &request->authenticator, &scratch))) { free(scratch.data); return(retval); } - /* call the encryption routine */ - if ((retval = krb5_decrypt(context, - (krb5_pointer)request->authenticator.ciphertext.data, - (krb5_pointer)scratch.data, - scratch.length, &eblock, 0))) { - (void) krb5_finish_key(context, &eblock); - free(scratch.data); - return retval; - } #define clean_scratch() {memset(scratch.data, 0, scratch.length); \ free(scratch.data);} - if ((retval = krb5_finish_key(context, &eblock))) { - clean_scratch(); - return retval; - } /* now decode the decrypted stuff */ if (!(retval = decode_krb5_authenticator(&scratch, &local_auth))) { *authpp = local_auth; diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c index 5f0fcd6ca..1c5aca21c 100644 --- a/src/lib/krb5/krb/rd_safe.c +++ b/src/lib/krb5/krb/rd_safe.c @@ -59,6 +59,7 @@ krb5_rd_safe_basic(context, inbuf, keyblock, recv_addr, sender_addr, krb5_checksum our_cksum, *his_cksum; krb5_octet zero_octet = 0; krb5_data *scratch; + krb5_boolean valid; if (!krb5_is_krb_safe(inbuf)) return KRB5KRB_AP_ERR_MSG_TYPE; @@ -122,14 +123,14 @@ krb5_rd_safe_basic(context, inbuf, keyblock, recv_addr, sender_addr, message->checksum = his_cksum; - retval = krb5_verify_checksum(context, his_cksum->checksum_type, - his_cksum, scratch->data, scratch->length, - (krb5_pointer) keyblock->contents, - keyblock->length); + retval = krb5_c_verify_checksum(context, keyblock, + KRB5_KEYUSAGE_KRB_SAFE_CKSUM, + scratch, his_cksum, &valid); + (void) memset((char *)scratch->data, 0, scratch->length); krb5_free_data(context, scratch); - if (retval) { + if (!valid) { retval = KRB5KRB_AP_ERR_MODIFIED; goto cleanup; } diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c index b06ef2bfc..19de14e1a 100644 --- a/src/lib/krb5/krb/send_tgs.c +++ b/src/lib/krb5/krb/send_tgs.c @@ -55,21 +55,15 @@ krb5_send_tgs_basic(context, in_data, in_cred, outbuf) krb5_checksum checksum; krb5_authenticator authent; krb5_ap_req request; - krb5_encrypt_block eblock; krb5_data * scratch; krb5_data * toutbuf; /* Generate checksum */ - checksum.length = krb5_checksum_size(context, context->kdc_req_sumtype); - if ((checksum.contents = (krb5_octet *) malloc(checksum.length)) == NULL) - return(ENOMEM); - - if ((retval = krb5_calculate_checksum(context, context->kdc_req_sumtype, - in_data->data, in_data->length, - (krb5_pointer) in_cred->keyblock.contents, - in_cred->keyblock.length, - &checksum))) { - free(checksum.contents); + if ((retval = krb5_c_make_checksum(context, context->kdc_req_sumtype, + &in_cred->keyblock, + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + in_data, &checksum))) { + free(checksum.contents); return(retval); } @@ -102,43 +96,11 @@ krb5_send_tgs_basic(context, in_data, in_cred, outbuf) /* Cleanup scratch and scratch data */ goto cleanup_data; - /* put together an eblock for this encryption */ - krb5_use_enctype(context, &eblock, in_cred->keyblock.enctype); - request.authenticator.enctype = in_cred->keyblock.enctype; - request.authenticator.ciphertext.length = - krb5_encrypt_size(scratch->length, eblock.crypto_entry); - - /* add padding area, and zero it */ - if (!(scratch->data = realloc(scratch->data, - request.authenticator.ciphertext.length))) { - /* may destroy scratch->data */ - krb5_free_ticket(context, request.ticket); - retval = ENOMEM; - goto cleanup_scratch; - } - memset(scratch->data + scratch->length, 0, - request.authenticator.ciphertext.length - scratch->length); - - if (!(request.authenticator.ciphertext.data = - malloc(request.authenticator.ciphertext.length))) { - retval = ENOMEM; - goto cleanup_ticket; - } - - /* do any necessary key pre-processing */ - if ((retval = krb5_process_key(context, &eblock, &(in_cred)->keyblock))) - goto cleanup; - /* call the encryption routine */ - if ((retval=krb5_encrypt(context, (krb5_pointer) scratch->data, - (krb5_pointer)request.authenticator.ciphertext.data, - scratch->length, &eblock, 0))) { - krb5_finish_key(context, &eblock); - goto cleanup; - } - - if ((retval = krb5_finish_key(context, &eblock))) - goto cleanup; + if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock, + KRB5_KEYUSAGE_TGS_REQ_AUTH, + scratch, &request.authenticator))) + goto cleanup_ticket; retval = encode_krb5_ap_req(&request, &toutbuf); *outbuf = *toutbuf; @@ -185,6 +147,7 @@ krb5_send_tgs(context, kdcoptions, timestruct, ktypes, sname, addrs, krb5_timestamp time_now; krb5_pa_data **combined_padata; krb5_pa_data ap_req_padata; + size_t enclen; /* * in_creds MUST be a valid credential NOT just a partially filled in @@ -212,50 +175,21 @@ krb5_send_tgs(context, kdcoptions, timestruct, ktypes, sname, addrs, if (authorization_data) { /* need to encrypt it in the request */ - krb5_encrypt_block eblock; if ((retval = encode_krb5_authdata((const krb5_authdata**)authorization_data, &scratch))) return(retval); - krb5_use_enctype(context, &eblock, in_cred->keyblock.enctype); - tgsreq.authorization_data.enctype = in_cred->keyblock.enctype; - tgsreq.authorization_data.kvno = 0; /* ticket session key has */ - /* no version */ - tgsreq.authorization_data.ciphertext.length = - krb5_encrypt_size(scratch->length, eblock.crypto_entry); - /* add padding area, and zero it */ - if (!(scratch->data = realloc(scratch->data, - tgsreq.authorization_data.ciphertext.length))) { - /* may destroy scratch->data */ - krb5_xfree(scratch); - return ENOMEM; - } - memset(scratch->data + scratch->length, 0, - tgsreq.authorization_data.ciphertext.length - scratch->length); - if (!(tgsreq.authorization_data.ciphertext.data = - malloc(tgsreq.authorization_data.ciphertext.length))) { - krb5_free_data(context, scratch); - return ENOMEM; - } - if ((retval = krb5_process_key(context, &eblock, - &in_cred->keyblock))) { - krb5_free_data(context, scratch); - return retval; - } - /* call the encryption routine */ - if ((retval = krb5_encrypt(context, (krb5_pointer) scratch->data, - (krb5_pointer) tgsreq.authorization_data.ciphertext.data, - scratch->length, &eblock, 0))) { - (void) krb5_finish_key(context, &eblock); + + if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock, + KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY, + scratch, + &tgsreq.authorization_data))) { krb5_xfree(tgsreq.authorization_data.ciphertext.data); krb5_free_data(context, scratch); return retval; - } - krb5_free_data(context, scratch); - if ((retval = krb5_finish_key(context, &eblock))) { - krb5_xfree(tgsreq.authorization_data.ciphertext.data); - return retval; } + + krb5_free_data(context, scratch); } /* Get the encryption types list */ diff --git a/src/lib/krb5/krb/ser_actx.c b/src/lib/krb5/krb/ser_actx.c index 5705b711f..42b9bfeb6 100644 --- a/src/lib/krb5/krb/ser_actx.c +++ b/src/lib/krb5/krb/ser_actx.c @@ -56,7 +56,6 @@ krb5_error_code krb5_ser_authdata_init KRB5_PROTOTYPE((krb5_context)); krb5_error_code krb5_ser_address_init KRB5_PROTOTYPE((krb5_context)); krb5_error_code krb5_ser_authenticator_init KRB5_PROTOTYPE((krb5_context)); krb5_error_code krb5_ser_checksum_init KRB5_PROTOTYPE((krb5_context)); -krb5_error_code krb5_ser_encrypt_block_init KRB5_PROTOTYPE((krb5_context)); krb5_error_code krb5_ser_keyblock_init KRB5_PROTOTYPE((krb5_context)); krb5_error_code krb5_ser_principal_init KRB5_PROTOTYPE((krb5_context)); @@ -95,17 +94,20 @@ krb5_auth_context_size(kcontext, arg, sizep) */ kret = EINVAL; if ((auth_context = (krb5_auth_context) arg)) { - required = sizeof(krb5_int32)*8; - kret = 0; + /* Calculate size required by i_vector - ptooey */ - if (auth_context->i_vector && auth_context->keyblock) - required += (size_t) - krb5_enctype_array[auth_context->keyblock->enctype]-> - system->block_length; + if (auth_context->i_vector && auth_context->keyblock) { + kret = krb5_c_block_size(kcontext, auth_context->keyblock->enctype, + &required); + } else { + required = 0; + } + + required += sizeof(krb5_int32)*8; /* Calculate size required by remote_addr, if appropriate */ - if (auth_context->remote_addr) { + if (!kret && auth_context->remote_addr) { kret = krb5_size_opaque(kcontext, KV5M_ADDRESS, (krb5_pointer) auth_context->remote_addr, @@ -226,18 +228,25 @@ krb5_auth_context_externalize(kcontext, arg, buffer, lenremain) (void) krb5_ser_pack_int32((krb5_int32) auth_context->safe_cksumtype, &bp, &remain); + kret = 0; + /* Now figure out the number of bytes for i_vector and write it */ - obuf = (!auth_context->i_vector) ? 0 : (krb5_int32) - krb5_enctype_array[auth_context->keyblock->enctype]-> - system->block_length; - (void) krb5_ser_pack_int32(obuf, &bp, &remain); + if (auth_context->i_vector) { + kret = krb5_c_block_size(kcontext, + auth_context->keyblock->enctype, + &obuf); + } else { + obuf = 0; + } + + if (!kret) + (void) krb5_ser_pack_int32(obuf, &bp, &remain); /* Now copy i_vector */ - if (auth_context->i_vector) + if (!kret && auth_context->i_vector) (void) krb5_ser_pack_bytes(auth_context->i_vector, (size_t) obuf, &bp, &remain); - kret = 0; /* Now handle remote_addr, if appropriate */ if (!kret && auth_context->remote_addr) { @@ -556,8 +565,6 @@ krb5_ser_auth_context_init(kcontext) if (!kret) kret = krb5_ser_checksum_init(kcontext); if (!kret) - kret = krb5_ser_encrypt_block_init(kcontext); - if (!kret) kret = krb5_ser_keyblock_init(kcontext); if (!kret) kret = krb5_ser_principal_init(kcontext); diff --git a/src/lib/krb5/krb/ser_eblk.c b/src/lib/krb5/krb/ser_eblk.c index 20b3da672..04e21faab 100644 --- a/src/lib/krb5/krb/ser_eblk.c +++ b/src/lib/krb5/krb/ser_eblk.c @@ -22,6 +22,8 @@ * */ +#if 0 /* i don't believe this is used anywhere --marc */ + /* * ser_eblk.c - Serialize a krb5_encblock structure. */ @@ -249,3 +251,5 @@ krb5_ser_encrypt_block_init(kcontext) { return(krb5_register_serializer(kcontext, &krb5_encrypt_block_ser_entry)); } + +#endif diff --git a/src/lib/krb5/krb/str_conv.c b/src/lib/krb5/krb/str_conv.c index 6346aef23..b30638d4f 100644 --- a/src/lib/krb5/krb/str_conv.c +++ b/src/lib/krb5/krb/str_conv.c @@ -31,17 +31,13 @@ * * String decoding: * ---------------- - * krb5_string_to_enctype() - Convert string to krb5_enctype. * krb5_string_to_salttype() - Convert string to salttype (krb5_int32) - * krb5_string_to_cksumtype() - Convert string to krb5_cksumtype; * krb5_string_to_timestamp() - Convert string to krb5_timestamp. * krb5_string_to_deltat() - Convert string to krb5_deltat. * * String encoding: * ---------------- - * krb5_enctype_to_string() - Convert krb5_enctype to string. * krb5_salttype_to_string() - Convert salttype (krb5_int32) to string. - * krb5_cksumtype_to_string() - Convert krb5_cksumtype to string. * krb5_timestamp_to_string() - Convert krb5_timestamp to string. * krb5_timestamp_to_sfstring() - Convert krb5_timestamp to short filled string * krb5_deltat_to_string() - Convert krb5_deltat to string. @@ -52,24 +48,12 @@ /* * Local data structures. */ -struct enctype_lookup_entry { - krb5_enctype ktt_enctype; /* Keytype */ - const char * ktt_specifier; /* How to recognize it */ - const char * ktt_output; /* How to spit it out */ -}; - struct salttype_lookup_entry { krb5_int32 stt_enctype; /* Salt type */ const char * stt_specifier; /* How to recognize it */ const char * stt_output; /* How to spit it out */ }; -struct cksumtype_lookup_entry { - krb5_cksumtype cst_cksumtype; /* Checksum type */ - const char * cst_specifier; /* How to recognize it */ - const char * cst_output; /* How to spit it out */ -}; - struct deltat_match_entry { const char * dt_scan_format; /* sscanf format */ int dt_nmatch; /* Number to match */ @@ -83,21 +67,6 @@ struct deltat_match_entry { * Local strings */ -/* Keytype strings */ -static const char enctype_des_in[] = "des"; -static const char enctype_null_in[] = "null"; -static const char enctype_descbccrc_in[] = "des-cbc-crc"; -static const char enctype_descbcmd4_in[] = "des-cbc-md4"; -static const char enctype_descbcmd5_in[] = "des-cbc-md5"; -static const char enctype_des3cbcsha_in[] = "des3-cbc-sha"; -static const char enctype_descbcraw_in[] = "des-cbc-raw"; -static const char enctype_null_out[] = "Null"; -static const char enctype_descbccrc_out[] = "DES cbc mode with CRC-32"; -static const char enctype_descbcmd4_out[] = "DES cbc mode with RSA-MD4"; -static const char enctype_descbcmd5_out[] = "DES cbc mode with RSA-MD5"; -static const char enctype_des3cbcsha_out[] = "DES-3 cbc mode with NIST-SHA"; -static const char enctype_descbcraw_out[] = "DES cbc mode raw"; - /* Salttype strings */ static const char stype_v5_in[] = "normal"; static const char stype_v4_in[] = "v4"; @@ -112,24 +81,6 @@ static const char stype_olrealm_out[] = "Version 5 - Realm Only"; static const char stype_special_out[] = "Special"; static const char stype_afs3_out[] = "AFS version 3"; -/* Checksum type strings */ -static const char cstype_crc32_in[] = "crc32"; -static const char cstype_md4_in[] = "md4"; -static const char cstype_md4des_in[] = "md4-des"; -static const char cstype_descbc_in[] = "des-cbc"; -static const char cstype_md5_in[] = "md5"; -static const char cstype_md5des_in[] = "md5-des"; -static const char cstype_sha_in[] = "sha"; -static const char cstype_hmacsha_in[] = "hmac-sha"; -static const char cstype_crc32_out[] = "CRC-32"; -static const char cstype_md4_out[] = "RSA-MD4"; -static const char cstype_md4des_out[] = "RSA-MD4 with DES cbc mode"; -static const char cstype_descbc_out[] = "DES cbc mode"; -static const char cstype_md5_out[] = "RSA-MD5"; -static const char cstype_md5des_out[] = "RSA-MD5 with DES cbc mode"; -static const char cstype_sha_out[] = "NIST-SHA"; -static const char cstype_hmacsha_out[] = "HMAC-SHA"; - /* Absolute time strings */ static const char atime_full_digits[] = "%y%m%d%H%M%S"; static const char atime_full_digits_d[] = "%y.%m.%d.%H.%M.%S"; @@ -184,20 +135,6 @@ static const char dt_output_hms[] = "%d:%02d:%02d"; * Lookup tables. */ -static const struct enctype_lookup_entry enctype_table[] = { -/* krb5_enctype input specifier output string */ -/*------------- ----------------------- ------------------------*/ -{ ENCTYPE_NULL, enctype_null_in, enctype_null_out }, -{ ENCTYPE_DES_CBC_MD5, enctype_des_in, enctype_descbcmd5_out }, -{ ENCTYPE_DES_CBC_CRC, enctype_descbccrc_in, enctype_descbccrc_out }, -{ ENCTYPE_DES_CBC_MD4, enctype_descbcmd4_in, enctype_descbcmd4_out }, -{ ENCTYPE_DES_CBC_MD5, enctype_descbcmd5_in, enctype_descbcmd5_out }, -{ ENCTYPE_DES3_CBC_SHA, enctype_des3cbcsha_in, enctype_des3cbcsha_out }, -{ ENCTYPE_DES_CBC_RAW, enctype_descbcraw_in, enctype_descbcraw_out } -}; -static const int enctype_table_nents = sizeof(enctype_table)/ - sizeof(enctype_table[0]); - static const struct salttype_lookup_entry salttype_table[] = { /* salt type input specifier output string */ /*----------------------------- ----------------------- ------------------*/ @@ -211,21 +148,6 @@ static const struct salttype_lookup_entry salttype_table[] = { static const int salttype_table_nents = sizeof(salttype_table)/ sizeof(salttype_table[0]); -static const struct cksumtype_lookup_entry cksumtype_table[] = { -/* krb5_cksumtype input specifier output string */ -/*----------------------- --------------------- ------------------------*/ -{ CKSUMTYPE_CRC32, cstype_crc32_in, cstype_crc32_out }, -{ CKSUMTYPE_RSA_MD4, cstype_md4_in, cstype_md4_out }, -{ CKSUMTYPE_RSA_MD4_DES, cstype_md4des_in, cstype_md4des_out }, -{ CKSUMTYPE_DESCBC, cstype_descbc_in, cstype_descbc_out }, -{ CKSUMTYPE_RSA_MD5, cstype_md5_in, cstype_md5_out }, -{ CKSUMTYPE_RSA_MD5_DES, cstype_md5des_in, cstype_md5des_out }, -{ CKSUMTYPE_NIST_SHA, cstype_sha_in, cstype_sha_out }, -{ CKSUMTYPE_HMAC_SHA, cstype_hmacsha_in, cstype_hmacsha_out } -}; -static const int cksumtype_table_nents = sizeof(cksumtype_table)/ - sizeof(cksumtype_table[0]); - static const char * const atime_format_table[] = { atime_full_digits_Y, /* yyyymmddhhmmss */ atime_full_digits_Yd, /* yyyy.mm.dd.hh.mm.ss */ @@ -403,30 +325,6 @@ strptime(buf, format, tm) } #endif /* HAVE_STRPTIME */ -/* - * String to internal datatype routines. - * - * These routines return 0 for success, EINVAL for invalid entry. - */ -KRB5_DLLIMP krb5_error_code KRB5_CALLCONV -krb5_string_to_enctype(string, enctypep) - char FAR * string; - krb5_enctype FAR * enctypep; -{ - int i; - int found; - - found = 0; - for (i=0; i<enctype_table_nents; i++) { - if (!strcasecmp(string, enctype_table[i].ktt_specifier)) { - found = 1; - *enctypep = enctype_table[i].ktt_enctype; - break; - } - } - return((found) ? 0 : EINVAL); -} - KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_string_to_salttype(string, salttypep) char FAR * string; @@ -447,25 +345,6 @@ krb5_string_to_salttype(string, salttypep) } KRB5_DLLIMP krb5_error_code KRB5_CALLCONV -krb5_string_to_cksumtype(string, cksumtypep) - char FAR * string; - krb5_cksumtype FAR * cksumtypep; -{ - int i; - int found; - - found = 0; - for (i=0; i<cksumtype_table_nents; i++) { - if (!strcasecmp(string, cksumtype_table[i].cst_specifier)) { - found = 1; - *cksumtypep = cksumtype_table[i].cst_cksumtype; - break; - } - } - return((found) ? 0 : EINVAL); -} - -KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_string_to_timestamp(string, timestampp) char FAR * string; krb5_timestamp FAR * timestampp; @@ -545,33 +424,6 @@ krb5_string_to_deltat(string, deltatp) * if the supplied buffer/length will not contain the output. */ KRB5_DLLIMP krb5_error_code KRB5_CALLCONV -krb5_enctype_to_string(enctype, buffer, buflen) - krb5_enctype enctype; - char FAR * buffer; - size_t buflen; -{ - int i; - const char *out; - - out = (char *) NULL; - for (i=0; i<enctype_table_nents; i++) { - if (enctype == enctype_table[i].ktt_enctype) { - out = enctype_table[i].ktt_output; - break; - } - } - if (out) { - if (buflen > strlen(out)) - strcpy(buffer, out); - else - out = (char *) NULL; - return((out) ? 0 : ENOMEM); - } - else - return(EINVAL); -} - -KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_salttype_to_string(salttype, buffer, buflen) krb5_int32 salttype; char FAR * buffer; diff --git a/src/lib/krb5/krb/vfy_increds.c b/src/lib/krb5/krb/vfy_increds.c index bb8ea349b..85a846503 100644 --- a/src/lib/krb5/krb/vfy_increds.c +++ b/src/lib/krb5/krb/vfy_increds.c @@ -68,12 +68,7 @@ krb5_verify_init_creds(krb5_context context, krb5_creds in_creds, *out_creds; krb5_auth_context authcon; krb5_data ap_req; - int keytab_key_exists, rd_req_succeeds, nofail; - keytab_key_exists = 0; - rd_req_succeeds = 0; - nofail = 0; - /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */ server = NULL; @@ -103,11 +98,31 @@ krb5_verify_init_creds(krb5_context context, goto cleanup; } - if (ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte)) - goto cleanup; + if (ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte)) { + /* this means there is no keying material. This is ok, as long as + it is not prohibited by the configuration */ + + krb5_error_code ret2; + int nofail; + + if (options && + (options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL)) { + if (options->ap_req_nofail) + goto cleanup; + } else if ((ret2 = krb5_appdefault_boolean(context, + &creds->client->realm, + "verify_ap_req_nofail", + &nofail)) + == 0) { + if (nofail) + goto cleanup; + } + + ret = 0; + goto cleanup; + } krb5_kt_free_entry(context, &kte); - keytab_key_exists = 1; /* If the creds are for the server principal, we're set, just do a mk_req. Otherwise, do a get_credentials first. */ @@ -166,61 +181,37 @@ krb5_verify_init_creds(krb5_context context, NULL, NULL)) goto cleanup; - rd_req_succeeds = 1; - -cleanup: - /* I could test the error case first, but then there would be a - chance that the verification would succeed when there was - actually a significant failure (some transient condition could - make rd_req fail, and this would not be a problem if nofail was - not set */ - - if (!keytab_key_exists) { - krb5_error_code ret2; - - if (options && - (options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL)) - nofail = options->ap_req_nofail; - else if ((ret2 = krb5_appdefault_boolean(context, &creds->client->realm, - "verify_ap_req_nofail", - &nofail)) - == 0) - ; - else - nofail = 0; - } - - if ((keytab_key_exists && rd_req_succeeds) || - (!keytab_key_exists && !nofail)) { - ret = 0; + /* if we get this far, then the verification succeeded. We can + still fail if the library stuff here fails, but that's it */ - if (ccache_arg && ccache) { - if (*ccache_arg == NULL) { - krb5_ccache retcc; + if (ccache_arg && ccache) { + if (*ccache_arg == NULL) { + krb5_ccache retcc; - retcc = NULL; + retcc = NULL; - if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) || - (ret = krb5_cc_initialize(context, retcc, creds->client)) || - (ret = krb5_cc_copy_creds_except(context, ccache, retcc, - creds->server))) { + if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) || + (ret = krb5_cc_initialize(context, retcc, creds->client)) || + (ret = krb5_cc_copy_creds_except(context, ccache, retcc, + creds->server))) { if (retcc) - krb5_cc_destroy(context, retcc); - } else { + krb5_cc_destroy(context, retcc); + } else { *ccache_arg = retcc; - } - } else { - /* if this returns an error, then that's the return - from this function */ - ret = krb5_cc_copy_creds_except(context, ccache, *ccache_arg, - server); - } - } + } + } else { + ret = krb5_cc_copy_creds_except(context, ccache, *ccache_arg, + server); + } } - if (!server_arg) + /* if any of the above paths returned an errors, then ret is set + accordingly. either that, or it's zero, which is fine, too */ + +cleanup: + if (!server_arg && server) krb5_free_principal(context, server); - if (!keytab_arg) + if (!keytab_arg && keytab) krb5_kt_close(context, keytab); if (ccache) krb5_cc_destroy(context, ccache); @@ -233,6 +224,3 @@ cleanup: return(ret); } - - - diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog index 0ee4a7192..84f0dec67 100644 --- a/src/lib/krb5/os/ChangeLog +++ b/src/lib/krb5/os/ChangeLog @@ -1,3 +1,16 @@ +1998-10-27 Marc Horowitz <marc@mit.edu> + + * c_ustime.c, localaddr.c: moved here from lib/crypto + + * ktdefname.c (krb5_kt_default_name): there is code in the tree + (notably, the admin server code) which uses globals to set the + keytab which will be used by gssapi. this is gross, and we need a + better answer. However, even that didn't work if there was an env + var or krb5.conf variable, since those override krb5_defkeyname. + Add a new global, krb5_overridekeyname, which really does override + all the other keytab locators. While I'm at it, make the buffer + overflow checks sane. + Fri Sep 25 22:32:16 1998 Theodore Y. Ts'o <tytso@mit.edu> * ccdefname.c: We shouldn't try to use the CCache API on Unix diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in index 9e132dbc8..56edfac36 100644 --- a/src/lib/krb5/os/Makefile.in +++ b/src/lib/krb5/os/Makefile.in @@ -12,6 +12,7 @@ PROG_RPATH=$(KRB5_LIBDIR) STLIBOBJS= \ an_to_ln.o \ + c_ustime.o \ def_realm.o \ DNR.o \ ccdefname.o \ @@ -54,6 +55,7 @@ STLIBOBJS= \ OBJS= \ an_to_ln.$(OBJEXT) \ + c_ustime.$(OBJEXT) \ def_realm.$(OBJEXT) \ DNR.$(OBJEXT) \ ccdefname.$(OBJEXT) \ @@ -96,6 +98,7 @@ OBJS= \ SRCS= \ $(srcdir)/an_to_ln.c \ + $(srcdir)/c_ustime.c \ $(srcdir)/def_realm.c \ $(srcdir)/DNR.c \ $(srcdir)/ccdefname.c \ diff --git a/src/lib/krb5/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c new file mode 100644 index 000000000..350c1aa5c --- /dev/null +++ b/src/lib/krb5/os/c_ustime.c @@ -0,0 +1,316 @@ +/* + * lib/crypto/os/c_ustime.c + * + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * krb5_mstimeofday for BSD 4.3 + */ + +#define NEED_SOCKETS +#include "k5-int.h" + +#ifdef _MACINTOSH + +/* We're a Macintosh -- do Mac time things. */ + +/* + * This code is derived from kerberos/src/lib/des/mac_time.c from + * the Cygnus Support release of Kerberos V4: + * + * mac_time.c + * (Originally time_stuff.c) + * Copyright 1989 by the Massachusetts Institute of Technology. + * Macintosh ooperating system interface for Kerberos. + */ + +#include "AddressXlation.h" /* for ip_addr, for #if 0'd net-time stuff */ + +#include <script.h> /* Defines MachineLocation, used by getTimeZoneOffset */ +#include <ToolUtils.h> /* Defines BitTst(), called by getTimeZoneOffset() */ +#include <OSUtils.h> /* Defines GetDateTime */ + +/* Mac Cincludes */ +#include <string.h> +#include <stddef.h> + +static krb5_int32 last_sec = 0, last_usec = 0; + +/* + * The Unix epoch is 1/1/70, the Mac epoch is 1/1/04. + * + * 70 - 4 = 66 year differential + * + * Thus the offset is: + * + * (66 yrs) * (365 days/yr) * (24 hours/day) * (60 mins/hour) * (60 secs/min) + * plus + * (17 leap days) * (24 hours/day) * (60 mins/hour) * (60 secs/min) + * + * Don't forget the offset from GMT. + */ + +/* returns the offset in hours between the mac local time and the GMT */ +/* unsigned krb5_int32 */ +krb5_int32 +getTimeZoneOffset() +{ + MachineLocation macLocation; + long gmtDelta; + + macLocation.u.gmtDelta=0L; + ReadLocation(&macLocation); + gmtDelta=macLocation.u.gmtDelta & 0x00FFFFFF; + if (BitTst((void *)&gmtDelta,23L)) + gmtDelta |= 0xFF000000; + gmtDelta /= 3600L; + return(gmtDelta); +} + +/* Returns the GMT in seconds (and fake microseconds) using the Unix epoch */ + +krb5_error_code +krb5_crypto_us_timeofday(seconds, microseconds) + krb5_int32 *seconds, *microseconds; +{ + krb5_int32 sec, usec; + time_t the_time; + + GetDateTime (&the_time); + + sec = the_time - + ((66 * 365 * 24 * 60 * 60) + (17 * 24 * 60 * 60) + + (getTimeZoneOffset() * 60 * 60)); + + usec = 0; /* Mac is too slow to count faster than once a second */ + + if ((sec == last_sec) && (usec == last_usec)) { + if (++last_usec >= 1000000) { + last_usec = 0; + last_sec++; + } + sec = last_sec; + usec = last_usec; + } + else { + last_sec = sec; + last_usec = usec; + } + + *seconds = sec; + *microseconds = usec; + + return 0; +} + + +#elif defined(_WIN32) + + /* Microsoft Windows NT and 95 (32bit) */ + /* This one works for WOW (Windows on Windows, ntvdm on Win-NT) */ + +#include <time.h> +#include <sys/timeb.h> +#include <string.h> + +krb5_error_code +krb5_crypto_us_timeofday(seconds, microseconds) +register krb5_int32 *seconds, *microseconds; +{ + struct _timeb timeptr; + krb5_int32 sec, usec; + static krb5_int32 last_sec = 0; + static krb5_int32 last_usec = 0; + + _ftime(&timeptr); /* Get the current time */ + sec = timeptr.time; + usec = timeptr.millitm * 1000; + + if ((sec == last_sec) && (usec <= last_usec)) { /* Same as last time??? */ + usec = ++last_usec; + if (usec >= 1000000) { + ++sec; + usec = 0; + } + } + last_sec = sec; /* Remember for next time */ + last_usec = usec; + + *seconds = sec; /* Return the values */ + *microseconds = usec; + + return 0; +} + +#elif defined (_MSDOS) + + +/* + * Originally written by John Gilmore, Cygnus Support, May '94. + * Public Domain. + */ + +#include <time.h> +#include <sys/timeb.h> +#include <dos.h> +#include <string.h> + +/* + * Time handling. Translate Unix time calls into Kerberos internal + * procedure calls. + * + * Due to the fact that DOS time can be unreliable we have reverted + * to using the AT hardware clock and converting it to Unix time. + */ + +static time_t win_gettime (); +static long win_time_get_epoch(); /* Adjust for MSC 7.00 bug */ + +krb5_error_code +krb5_crypto_us_timeofday(seconds, microseconds) +register krb5_int32 *seconds, *microseconds; +{ + krb5_int32 sec, usec; + static krb5_int32 last_sec = 0; + static krb5_int32 last_usec = 0; + + sec = win_gettime (); /* Get the current time */ + usec = 0; /* Can't do microseconds */ + + if (sec == last_sec) { /* Same as last time??? */ + usec = ++last_usec; /* Yep, so do microseconds */ + if (usec >= 1000000) { + ++sec; + usec = 0; + } + } + last_sec = sec; /* Remember for next time */ + last_usec = usec; + + *seconds = sec; /* Return the values */ + *microseconds = usec; + + return 0; +} + + +static time_t +win_gettime () { + struct tm tm; + union _REGS inregs; /* For calling BIOS */ + union _REGS outregs; + struct _timeb now; + time_t time; + long convert; /* MSC 7.00 bug work around */ + + _ftime(&now); /* Daylight savings time */ + + /* Get time from AT hardware clock INT 0x1A, AH=2 */ + memset(&inregs, 0, sizeof(inregs)); + inregs.h.ah = 2; + _int86(0x1a, &inregs, &outregs); + + /* 0x13 = decimal 13, hence the decoding below */ + tm.tm_sec = 10 * ((outregs.h.dh & 0xF0) >> 4) + (outregs.h.dh & 0x0F); + tm.tm_min = 10 * ((outregs.h.cl & 0xF0) >> 4) + (outregs.h.cl & 0x0F); + tm.tm_hour = 10 * ((outregs.h.ch & 0xF0) >> 4) + (outregs.h.ch & 0x0F); + + /* Get date from AT hardware clock INT 0x1A, AH=4 */ + memset(&inregs, 0, sizeof(inregs)); + inregs.h.ah = 4; + _int86(0x1a, &inregs, &outregs); + + tm.tm_mday = 10 * ((outregs.h.dl & 0xF0) >> 4) + (outregs.h.dl & 0x0F); + tm.tm_mon = 10 * ((outregs.h.dh & 0xF0) >> 4) + (outregs.h.dh & 0x0F) - 1; + tm.tm_year = 10 * ((outregs.h.cl & 0xF0) >> 4) + (outregs.h.cl & 0x0F); + tm.tm_year += 100 * ((10 * (outregs.h.ch & 0xF0) >> 4) + + (outregs.h.ch & 0x0F) - 19); + + tm.tm_wday = 0; + tm.tm_yday = 0; + tm.tm_isdst = now.dstflag; + + time = mktime(&tm); + + convert = win_time_get_epoch(); + return time + convert; + +} + + +/* + * This routine figures out the current time epoch and returns the + * conversion factor. It exists because + * Microloss screwed the pooch on the time() and _ftime() calls in + * its release 7.0 libraries. They changed the epoch to Dec 31, 1899! + * Idiots... We try to cope. + */ + +static struct tm jan_1_70 = {0, 0, 0, 1, 0, 70}; +static long epoch = 0; +static int epoch_set = 0; + +long +win_time_get_epoch() +{ + + if (!epoch_set) { + epoch = 0 - mktime (&jan_1_70); /* Seconds til 1970 localtime */ + epoch += _timezone; /* Seconds til 1970 GMT */ + epoch_set = 1; + } + return epoch; +} + + +#else + + +/* We're a Unix machine -- do Unix time things. */ + +extern int errno; + +static struct timeval last_tv = {0, 0}; + +krb5_error_code +krb5_crypto_us_timeofday(seconds, microseconds) + register krb5_int32 *seconds, *microseconds; +{ + struct timeval tv; + + if (gettimeofday(&tv, (struct timezone *)0) == -1) { + /* failed, return errno */ + return (krb5_error_code) errno; + } + if ((tv.tv_sec == last_tv.tv_sec) && (tv.tv_usec == last_tv.tv_usec)) { + if (++last_tv.tv_usec >= 1000000) { + last_tv.tv_usec = 0; + last_tv.tv_sec++; + } + tv = last_tv; + } else + last_tv = tv; + + *seconds = tv.tv_sec; + *microseconds = tv.tv_usec; + return 0; +} + +#endif diff --git a/src/lib/krb5/os/ktdefname.c b/src/lib/krb5/os/ktdefname.c index c645635ab..0493244f6 100644 --- a/src/lib/krb5/os/ktdefname.c +++ b/src/lib/krb5/os/ktdefname.c @@ -30,6 +30,9 @@ extern char *krb5_defkeyname; +/* this is a an exceedinly gross thing. */ +char *krb5_overridekeyname = NULL; + KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_kt_default_name(context, name, namesize) krb5_context context; @@ -40,19 +43,24 @@ krb5_kt_default_name(context, name, namesize) krb5_error_code code; char *retval; - if ((context->profile_secure == FALSE) && + if (krb5_overridekeyname) { + if ((size_t) namesize < (strlen(krb5_overridekeyname)+1)) + return KRB5_CONFIG_NOTENUFSPACE; + strcpy(name, krb5_overridekeyname); + } else if ((context->profile_secure == FALSE) && (cp = getenv("KRB5_KTNAME"))) { - strncpy(name, cp, namesize); - if (strlen(cp) >= (size_t) namesize) + if ((size_t) namesize < (strlen(cp)+1)) return KRB5_CONFIG_NOTENUFSPACE; + strcpy(name, cp); } else if (((code = profile_get_string(context->profile, "libdefaults", "default_keytab_name", NULL, NULL, &retval)) == 0) && retval) { - strncpy(name, retval, namesize); - if ((size_t) namesize < strlen(retval)) + if ((size_t) namesize < (strlen(retval)+1)) return KRB5_CONFIG_NOTENUFSPACE; + strcpy(name, retval); + free(retval); } else { #if defined (_MSDOS) || defined(_WIN32) { @@ -66,9 +74,9 @@ krb5_kt_default_name(context, name, namesize) sprintf(name, krb5_defkeyname, defname); } #else - strncpy(name, krb5_defkeyname, namesize); - if ((size_t) namesize < strlen(krb5_defkeyname)) + if ((size_t) namesize < (strlen(krb5_defkeyname)+1)) return KRB5_CONFIG_NOTENUFSPACE; + strcpy(name, krb5_defkeyname); #endif } return 0; diff --git a/src/lib/krb5/os/localaddr.c b/src/lib/krb5/os/localaddr.c index cb204b597..9f33e5d98 100644 --- a/src/lib/krb5/os/localaddr.c +++ b/src/lib/krb5/os/localaddr.c @@ -20,16 +20,329 @@ * this software for any purpose. It is provided "as is" without express * or implied warranty. * - * Just a stub that calls krb5_crypto_os_localaddr(). * + * Return the protocol addresses supported by this host. + * + * XNS support is untested, but "Should just work". */ +#define NEED_SOCKETS #include "k5-int.h" +#if !defined(HAVE_MACSOCK_H) && !defined(_MSDOS) && !defined(_WIN32) + +/* needed for solaris, harmless elsewhere... */ +#define BSD_COMP +#include <sys/ioctl.h> +#include <sys/time.h> +#include <errno.h> + +/* + * The SIOCGIF* ioctls require a socket. + * It doesn't matter *what* kind of socket they use, but it has to be + * a socket. + * + * Of course, you can't just ask the kernel for a socket of arbitrary + * type; you have to ask for one with a valid type. + * + */ +#ifdef HAVE_NETINET_IN_H + +#include <netinet/in.h> + +#ifndef USE_AF +#define USE_AF AF_INET +#define USE_TYPE SOCK_DGRAM +#define USE_PROTO 0 +#endif + +#endif + +#ifdef KRB5_USE_NS + +#include <netns/ns.h> + +#ifndef USE_AF +#define USE_AF AF_NS +#define USE_TYPE SOCK_DGRAM +#define USE_PROTO 0 /* guess */ +#endif + +#endif +/* + * Add more address families here. + */ + +/* + * BSD 4.4 defines the size of an ifreq to be + * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len + * However, under earlier systems, sa_len isn't present, so the size is + * just sizeof(struct ifreq) + */ +#ifdef HAVE_SA_LEN +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif +#define ifreq_size(i) max(sizeof(struct ifreq),\ + sizeof((i).ifr_name)+(i).ifr_addr.sa_len) +#else +#define ifreq_size(i) sizeof(struct ifreq) +#endif /* HAVE_SA_LEN*/ + + + +extern int errno; + +/* + * Return all the protocol addresses of this host. + * + * We could kludge up something to return all addresses, assuming that + * they're valid kerberos protocol addresses, but we wouldn't know the + * real size of the sockaddr or know which part of it was actually the + * host part. + * + * This uses the SIOCGIFCONF, SIOCGIFFLAGS, and SIOCGIFADDR ioctl's. + */ + KRB5_DLLIMP krb5_error_code KRB5_CALLCONV krb5_os_localaddr(context, addr) krb5_context context; krb5_address FAR * FAR * FAR *addr; { - return krb5_crypto_os_localaddr(addr); + struct ifreq *ifr, ifreq; + struct ifconf ifc; + int s, code, n, i; + char buf[1024]; + krb5_address *addr_temp [ 1024/sizeof(struct ifreq) ]; + int n_found; + int mem_err = 0; + + memset(buf, 0, sizeof(buf)); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + + s = socket (USE_AF, USE_TYPE, USE_PROTO); + if (s < 0) + return errno; + + code = ioctl (s, SIOCGIFCONF, (char *)&ifc); + if (code < 0) { + int retval = errno; + closesocket (s); + return retval; + } + n = ifc.ifc_len; + +n_found = 0; + for (i = 0; i < n; i+= ifreq_size(*ifr) ) { + krb5_address *address; + ifr = (struct ifreq *)((caddr_t) ifc.ifc_buf+i); + + strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name)); + if (ioctl (s, SIOCGIFFLAGS, (char *)&ifreq) < 0) + continue; + +#ifdef IFF_LOOPBACK + if (ifreq.ifr_flags & IFF_LOOPBACK) + continue; +#endif + + if (!(ifreq.ifr_flags & IFF_UP)) + /* interface is down; skip */ + continue; + + /* ifr->ifr_addr has what we want! */ + switch (ifr->ifr_addr.sa_family) { +#ifdef HAVE_NETINET_IN_H + case AF_INET: + { + struct sockaddr_in *in = + (struct sockaddr_in *)&ifr->ifr_addr; + + address = (krb5_address *) + malloc (sizeof(krb5_address)); + if (address) { + address->magic = KV5M_ADDRESS; + address->addrtype = ADDRTYPE_INET; + address->length = sizeof(struct in_addr); + address->contents = (unsigned char *)malloc(address->length); + if (!address->contents) { + krb5_xfree(address); + address = 0; + mem_err++; + } else { + memcpy ((char *)address->contents, + (char *)&in->sin_addr, + address->length); + break; + } + } else mem_err++; + } +#endif +#ifdef KRB5_USE_NS + case AF_XNS: + { + struct sockaddr_ns *ns = + (struct sockaddr_ns *)&ifr->ifr_addr; + address = (krb5_address *) + malloc (sizeof (krb5_address) + sizeof (struct ns_addr)); + if (address) { + address->magic = KV5M_ADDRESS; + address->addrtype = ADDRTYPE_XNS; + + /* XXX should we perhaps use ns_host instead? */ + + address->length = sizeof(struct ns_addr); + address->contents = (unsigned char *)malloc(address->length); + if (!address->contents) { + krb5_xfree(address); + address = 0; + mem_err++; + } else { + memcpy ((char *)address->contents, + (char *)&ns->sns_addr, + address->length); + break; + } + } else mem_err++; + break; + } +#endif + /* + * Add more address families here.. + */ + default: + continue; + } + if (address) + addr_temp[n_found++] = address; + address = 0; + } + closesocket(s); + + *addr = (krb5_address **)malloc (sizeof (krb5_address *) * (n_found+1)); + if (*addr == 0) + mem_err++; + + if (mem_err) { + for (i=0; i<n_found; i++) { + krb5_xfree(addr_temp[i]); + addr_temp[i] = 0; + } + return ENOMEM; + } + + for (i=0; i<n_found; i++) { + (*addr)[i] = addr_temp[i]; + } + (*addr)[n_found] = 0; + return 0; +} + +#else /* Windows/Mac version */ + +/* + * Hold on to your lunch! Backup kludge method of obtaining your + * local IP address, courtesy of Windows Socket Network Programming, + * by Robert Quinn + */ +#if defined(_MSDOS) || defined(_WIN32) +static struct hostent *local_addr_fallback_kludge() +{ + static struct hostent host; + static SOCKADDR_IN addr; + static char * ip_ptrs[2]; + SOCKET sock; + int size = sizeof(SOCKADDR); + int err; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == INVALID_SOCKET) + return NULL; + + /* connect to arbitrary port and address (NOT loopback) */ + addr.sin_family = AF_INET; + addr.sin_port = htons(IPPORT_ECHO); + addr.sin_addr.s_addr = inet_addr("204.137.220.51"); + + err = connect(sock, (LPSOCKADDR) &addr, sizeof(SOCKADDR)); + if (err == SOCKET_ERROR) + return NULL; + + err = getsockname(sock, (LPSOCKADDR) &addr, (int FAR *) size); + if (err == SOCKET_ERROR) + return NULL; + + closesocket(sock); + + host.h_name = 0; + host.h_aliases = 0; + host.h_addrtype = AF_INET; + host.h_length = 4; + host.h_addr_list = ip_ptrs; + ip_ptrs[0] = (char *) &addr.sin_addr.s_addr; + ip_ptrs[1] = NULL; + + return &host; +} +#endif + +/* No ioctls in winsock so we just assume there is only one networking + * card per machine, so gethostent is good enough. + */ +krb5_error_code +krb5_os_localaddr (krb5_context context, krb5_address ***addr) { + char host[64]; /* Name of local machine */ + struct hostent *hostrec; + int err; + + *addr = calloc (2, sizeof (krb5_address *)); + if (*addr == NULL) + return ENOMEM; + +#ifdef HAVE_MACSOCK_H + hostrec = getmyipaddr(); +#else /* HAVE_MACSOCK_H */ + err = 0; + + if (gethostname (host, sizeof(host))) { + err = WSAGetLastError(); + } + + if (!err) { + hostrec = gethostbyname (host); + if (hostrec == NULL) { + err = WSAGetLastError(); + } + } + + if (err) { + hostrec = local_addr_fallback_kludge(); + if (!hostrec) + return err; + } +#endif /* HAVE_MACSOCK_H */ + + (*addr)[0] = calloc (1, sizeof(krb5_address)); + if ((*addr)[0] == NULL) { + free (*addr); + return ENOMEM; + } + (*addr)[0]->magic = KV5M_ADDRESS; + (*addr)[0]->addrtype = hostrec->h_addrtype; + (*addr)[0]->length = hostrec->h_length; + (*addr)[0]->contents = (unsigned char *)malloc((*addr)[0]->length); + if (!(*addr)[0]->contents) { + free((*addr)[0]); + free(*addr); + return ENOMEM; + } else { + memcpy ((*addr)[0]->contents, + hostrec->h_addr, + (*addr)[0]->length); + } + /* FIXME, deal with the case where gethostent returns multiple addrs */ + + return(0); } +#endif diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c index c0ccf7e38..d8187ac3a 100644 --- a/src/lib/krb5/os/locate_kdc.c +++ b/src/lib/krb5/os/locate_kdc.c @@ -46,7 +46,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters) const char *realm_kdc_names[4]; char **masterlist, **hostlist, *host, *port, *cp; krb5_error_code code; - int i, j, out, count; + int i, j, out, count, ismaster; struct sockaddr *addr_p; struct sockaddr_in *sin_p; struct hostent *hp; @@ -103,6 +103,9 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters) } if (master_index) { + *master_index = 0; + *nmasters = 0; + realm_kdc_names[0] = "realms"; realm_kdc_names[1] = host; realm_kdc_names[2] = "admin_server"; @@ -113,10 +116,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters) krb5_xfree(host); - if (code) { - *master_index = 0; - *nmasters = 0; - } else { + if (code == 0) { for (i=0; masterlist[i]; i++) { host = masterlist[i]; @@ -138,11 +138,10 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters) krb5_xfree(host); } - /* at this point, is master is non-NULL, then either the master kdc + /* at this point, if master is non-NULL, then either the master kdc is required, and there is one, or the master kdc is not required, and there may or may not be one. */ - #ifdef HAVE_NETINET_IN_H if (sec_udpport) count = count * 2; @@ -175,10 +174,15 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters) continue; } - if (masterlist) - for (j=0; masterlist[j]; j++) - if (strcasecmp(hostlist[i], masterlist[j]) == 0) + ismaster = 0; + if (masterlist) { + for (j=0; masterlist[j]; j++) { + if (strcasecmp(hostlist[i], masterlist[j]) == 0) { *master_index = out; + ismaster = 1; + } + } + } switch (hp->h_addrtype) { @@ -211,7 +215,7 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters) default: break; } - if (masterlist) + if (ismaster) *nmasters = out - *master_index; /* Free the hostlist entry we are looping over. */ @@ -219,6 +223,11 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, master_index, nmasters) hostlist[i] = 0; } + if (masterlist) { + for (i=0; masterlist[i]; i++) + free(masterlist[i]); + free(masterlist); + } free ((char *)hostlist); |