diff options
Diffstat (limited to 'src/lib')
126 files changed, 2906 insertions, 2661 deletions
diff --git a/src/lib/ChangeLog b/src/lib/ChangeLog index b54a447..66d1fd6 100644 --- a/src/lib/ChangeLog +++ b/src/lib/ChangeLog @@ -1,10 +1,36 @@ +2000-06-02 Danilo Almeida <dalmeida@mit.edu> + + * win_glue.c (GetCallingAppVerInfo, krb5_vercheck): Use + APPVERINFO_SIZE-sized buffers instead of hard-coding a number + everywhere. Document the buffer size in funciton documentation. + + * krb5_32.def: Add krb5int_cc_default for the benefit of GSS API DLL. + +2000-05-23 Nalin Dahyabhai <nalin@redhat.com> + + * win_glue.c (GetCallingAppVerInfo): Don't overfill buffers + "AppTitle", "AppVer", and "AppIni". + 2000-05-15 Jeffrey Altman <jaltman@columbia.edu> - * krb5_32.def Added exports for new public functions + * krb5_32.def -- Added exports for new public functions krb5_appdefault_string krb5_appdefault_boolean +2000-05-04 Danilo Almeida <dalmeida@mit.edu> + + * krb5_32.def: Reflect something closer to the reality of + what we would like to do for 1.3. + +2000-05-03 Nalin Dahyabhai <nalin@redhat.com> + + * win_glue.c (do_timebomb): Don't overflow buffer "buf". + +2000-04-29 Jeffrey Altman <jaltman@columbia.edu> + + * krb5_32.def: Add krb5_get_tgs_ktypes, krb5_free_ktypes for gssapi + 2000-03-15 Danilo Almeida <dalmeida@mit.edu> * krb5_32.def: Add krb5_get_prompt_types. diff --git a/src/lib/crypto/ChangeLog b/src/lib/crypto/ChangeLog index f451cbe..f1fbfff 100644 --- a/src/lib/crypto/ChangeLog +++ b/src/lib/crypto/ChangeLog @@ -1,3 +1,7 @@ +2000-06-03 Tom Yu <tlyu@mit.edu> + + * Makefile.in(LIBMAJOR, LIBMINOR): Bump library version. + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * configure.in, nfold.c: Check for existance of <memory.h>. diff --git a/src/lib/crypto/Makefile.in b/src/lib/crypto/Makefile.in index 71bddf5..64f19d1 100644 --- a/src/lib/crypto/Makefile.in +++ b/src/lib/crypto/Makefile.in @@ -106,8 +106,8 @@ SRCS=\ LIB=k5crypto -LIBMAJOR=2 -LIBMINOR=1 +LIBMAJOR=3 +LIBMINOR=0 RELDIR=crypto STOBJLISTS=crc32/OBJS.ST des/OBJS.ST dk/OBJS.ST enc_provider/OBJS.ST \ diff --git a/src/lib/crypto/dk/ChangeLog b/src/lib/crypto/dk/ChangeLog index a9bdafe..1929ff6 100644 --- a/src/lib/crypto/dk/ChangeLog +++ b/src/lib/crypto/dk/ChangeLog @@ -1,3 +1,17 @@ +2000-06-03 Tom Yu <tlyu@mit.edu> + + * dk_encrypt.c (krb5_dk_encrypt, krb5_marc_dk_encrypt): Chain + ivecs. + + * dk_decrypt.c (krb5_dk_decrypt, krb5_marc_dk_decrypt): Chain + ivecs. + +2000-04-28 Ken Raeburn <raeburn@mit.edu> + + * derive.c (krb5_derive_key): If memory allocation fails, release + other allocated blocks before returning, instead of trying to + release them after returning. + 2000-01-21 Ken Raeburn <raeburn@mit.edu> * checksum.c (krb5_dk_make_checksum): enc_providers are now diff --git a/src/lib/crypto/dk/derive.c b/src/lib/crypto/dk/derive.c index 8765605..dbd4a2a 100644 --- a/src/lib/crypto/dk/derive.c +++ b/src/lib/crypto/dk/derive.c @@ -51,14 +51,14 @@ krb5_derive_key(enc, inkey, outkey, in_constant) return(ENOMEM); if ((outblockdata = (unsigned char *) malloc(blocksize)) == NULL) { - return(ENOMEM); free(inblockdata); + return(ENOMEM); } if ((rawkey = (unsigned char *) malloc(keybytes)) == NULL) { - return(ENOMEM); free(outblockdata); free(inblockdata); + return(ENOMEM); } inblock.data = inblockdata; diff --git a/src/lib/crypto/dk/dk_decrypt.c b/src/lib/crypto/dk/dk_decrypt.c index d307761..d6e7c0d 100644 --- a/src/lib/crypto/dk/dk_decrypt.c +++ b/src/lib/crypto/dk/dk_decrypt.c @@ -41,7 +41,7 @@ krb5_dk_decrypt(enc, hash, key, usage, ivec, input, output) { krb5_error_code ret; size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen; - unsigned char *plaindata, *kedata, *kidata, *cksum; + unsigned char *plaindata, *kedata, *kidata, *cksum, *cn; krb5_keyblock ke, ki; krb5_data d1, d2; unsigned char constantdata[K5CLENGTH]; @@ -108,6 +108,11 @@ krb5_dk_decrypt(enc, hash, key, usage, ivec, input, output) if ((ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2))) != 0) goto cleanup; + if (ivec != NULL && ivec->length == blocksize) + cn = d1.data + d1.length - blocksize; + else + cn = NULL; + /* verify the hash */ d1.length = hashsize; @@ -134,6 +139,9 @@ krb5_dk_decrypt(enc, hash, key, usage, ivec, input, output) memcpy(output->data, d2.data+blocksize, output->length); + if (cn != NULL) + memcpy(ivec->data, cn, blocksize); + ret = 0; cleanup: @@ -163,7 +171,7 @@ krb5_marc_dk_decrypt(enc, hash, key, usage, ivec, input, output) { krb5_error_code ret; size_t hashsize, blocksize, keybytes, keylength, enclen, plainlen; - unsigned char *plaindata, *kedata, *kidata, *cksum; + unsigned char *plaindata, *kedata, *kidata, *cksum, *cn; krb5_keyblock ke, ki; krb5_data d1, d2; unsigned char constantdata[K5CLENGTH]; @@ -230,6 +238,11 @@ krb5_marc_dk_decrypt(enc, hash, key, usage, ivec, input, output) if ((ret = ((*(enc->decrypt))(&ke, ivec, &d1, &d2))) != 0) goto cleanup; + if (ivec != NULL && ivec->length == blocksize) + cn = d1.data + d1.length - blocksize; + else + cn = NULL; + /* verify the hash */ d1.length = hashsize; @@ -264,6 +277,9 @@ krb5_marc_dk_decrypt(enc, hash, key, usage, ivec, input, output) memcpy(output->data, d2.data+4+blocksize, output->length); + if (cn != NULL) + memcpy(ivec->data, cn, blocksize); + ret = 0; cleanup: diff --git a/src/lib/crypto/dk/dk_encrypt.c b/src/lib/crypto/dk/dk_encrypt.c index 8627353..2bc2b6b 100644 --- a/src/lib/crypto/dk/dk_encrypt.c +++ b/src/lib/crypto/dk/dk_encrypt.c @@ -65,7 +65,7 @@ krb5_dk_encrypt(enc, hash, key, usage, ivec, input, output) krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data d1, d2; - unsigned char *plaintext, *kedata, *kidata; + unsigned char *plaintext, *kedata, *kidata, *cn; krb5_keyblock ke, ki; /* allocate and set up plaintext and to-be-derived keys */ @@ -142,6 +142,11 @@ krb5_dk_encrypt(enc, hash, key, usage, ivec, input, output) if ((ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2)))) goto cleanup; + if (ivec != NULL && ivec->length == blocksize) + cn = d2.data + d2.length - blocksize; + else + cn = NULL; + /* hash the plaintext */ d2.length = enclen - plainlen; @@ -149,8 +154,14 @@ krb5_dk_encrypt(enc, hash, key, usage, ivec, input, output) output->length = enclen; - if ((ret = krb5_hmac(hash, &ki, 1, &d1, &d2))) + if ((ret = krb5_hmac(hash, &ki, 1, &d1, &d2))) { memset(d2.data, 0, d2.length); + goto cleanup; + } + + /* update ivec */ + if (cn != NULL) + memcpy(ivec->data, cn, blocksize); /* ret is set correctly by the prior call */ @@ -196,7 +207,7 @@ krb5_marc_dk_encrypt(enc, hash, key, usage, ivec, input, output) krb5_error_code ret; unsigned char constantdata[K5CLENGTH]; krb5_data d1, d2; - unsigned char *plaintext, *kedata, *kidata; + unsigned char *plaintext, *kedata, *kidata, *cn; krb5_keyblock ke, ki; /* allocate and set up plaintext and to-be-derived keys */ @@ -278,6 +289,11 @@ krb5_marc_dk_encrypt(enc, hash, key, usage, ivec, input, output) if ((ret = ((*(enc->encrypt))(&ke, ivec, &d1, &d2)))) goto cleanup; + if (ivec != NULL && ivec->length == blocksize) + cn = d2.data + d2.length - blocksize; + else + cn = NULL; + /* hash the plaintext */ d2.length = enclen - plainlen; @@ -285,8 +301,14 @@ krb5_marc_dk_encrypt(enc, hash, key, usage, ivec, input, output) output->length = enclen; - if ((ret = krb5_hmac(hash, &ki, 1, &d1, &d2))) + if ((ret = krb5_hmac(hash, &ki, 1, &d1, &d2))) { memset(d2.data, 0, d2.length); + goto cleanup; + } + + /* update ivec */ + if (cn != NULL) + memcpy(ivec->data, cn, blocksize); /* ret is set correctly by the prior call */ diff --git a/src/lib/crypto/old/ChangeLog b/src/lib/crypto/old/ChangeLog index 0bee167..7446daa 100644 --- a/src/lib/crypto/old/ChangeLog +++ b/src/lib/crypto/old/ChangeLog @@ -1,3 +1,9 @@ +2000-06-03 Tom Yu <tlyu@mit.edu> + + * old_encrypt.c (krb5_old_encrypt): Chain ivecs. + + * old_decrypt.c (krb5_old_decrypt): Chain ivecs. + 2000-01-21 Ken Raeburn <raeburn@mit.edu> * des_stringtokey.c (mit_des_string_to_key_int): Declare. diff --git a/src/lib/crypto/old/old_decrypt.c b/src/lib/crypto/old/old_decrypt.c index 1bcb0d3..bfbe56a 100644 --- a/src/lib/crypto/old/old_decrypt.c +++ b/src/lib/crypto/old/old_decrypt.c @@ -45,7 +45,7 @@ krb5_old_decrypt(enc, hash, key, usage, ivec, input, arg_output) { krb5_error_code ret; size_t blocksize, hashsize, plainsize; - unsigned char *cksumdata; + unsigned char *cksumdata, *cn; krb5_data output, cksum, crcivec; int alloced; @@ -82,6 +82,17 @@ krb5_old_decrypt(enc, hash, key, usage, ivec, input, arg_output) /* decrypt it */ + /* save last ciphertext block in case we decrypt in place */ + if (ivec != NULL && ivec->length == blocksize) { + cn = malloc(blocksize); + if (cn == NULL) { + ret = ENOMEM; + goto cleanup; + } + memcpy(cn, input->data + input->length - blocksize, blocksize); + } else + cn = NULL; + /* XXX this is gross, but I don't have much choice */ if ((key->enctype == ENCTYPE_DES_CBC_CRC) && (ivec == 0)) { crcivec.length = key->length; @@ -119,6 +130,10 @@ krb5_old_decrypt(enc, hash, key, usage, ivec, input, arg_output) } arg_output->length = plainsize; + /* update ivec */ + if (cn != NULL) + memcpy(ivec->data, cn, blocksize); + ret = 0; cleanup: @@ -127,6 +142,8 @@ cleanup: free(output.data); } + if (cn != NULL) + free(cn); memset(cksumdata, 0, hashsize); free(cksumdata); return(ret); diff --git a/src/lib/crypto/old/old_encrypt.c b/src/lib/crypto/old/old_encrypt.c index d90d0f8..8860ba5 100644 --- a/src/lib/crypto/old/old_encrypt.c +++ b/src/lib/crypto/old/old_encrypt.c @@ -55,6 +55,7 @@ krb5_old_encrypt(enc, hash, key, usage, ivec, input, output) krb5_error_code ret; size_t blocksize, hashsize, enclen; krb5_data datain, crcivec; + int real_ivec; (*(enc->block_size))(&blocksize); (*(hash->hash_size))(&hashsize); @@ -92,11 +93,17 @@ krb5_old_encrypt(enc, hash, key, usage, ivec, input, output) crcivec.length = key->length; crcivec.data = key->contents; ivec = &crcivec; - } + real_ivec = 0; + } else + real_ivec = 1; if ((ret = ((*(enc->encrypt))(key, ivec, output, output)))) goto cleanup; + /* update ivec */ + if (real_ivec && ivec != NULL && ivec->length == blocksize) + memcpy(ivec->data, output->data + output->length - blocksize, + blocksize); cleanup: if (ret) memset(output->data, 0, output->length); diff --git a/src/lib/crypto/prng.c b/src/lib/crypto/prng.c index 6d401a9..b22131e 100644 --- a/src/lib/crypto/prng.c +++ b/src/lib/crypto/prng.c @@ -158,4 +158,4 @@ void prng_cleanup (void) { free (random_state); inited = 0; -}
\ No newline at end of file +} diff --git a/src/lib/gssapi/ChangeLog b/src/lib/gssapi/ChangeLog index 7dc9b00..b8da271 100644 --- a/src/lib/gssapi/ChangeLog +++ b/src/lib/gssapi/ChangeLog @@ -1,3 +1,7 @@ +2000-06-03 Tom Yu <tlyu@mit.edu> + + * Makefile.in(LIBMINOR): Bump library version. + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * configure.in: Check for existance of <memory.h>. diff --git a/src/lib/gssapi/Makefile.in b/src/lib/gssapi/Makefile.in index bee2b85..20936da 100644 --- a/src/lib/gssapi/Makefile.in +++ b/src/lib/gssapi/Makefile.in @@ -24,7 +24,7 @@ SRCS=\ LIB=gssapi_krb5 LIBMAJOR=2 -LIBMINOR=1 +LIBMINOR=2 STOBJLISTS=OBJS.ST generic/OBJS.ST krb5/OBJS.ST SHLIB_EXPDEPS=\ $(TOPLIBD)/libkrb5$(SHLIBEXT) \ diff --git a/src/lib/gssapi/krb5/ChangeLog b/src/lib/gssapi/krb5/ChangeLog index ccb16f4..087104e 100644 --- a/src/lib/gssapi/krb5/ChangeLog +++ b/src/lib/gssapi/krb5/ChangeLog @@ -1,3 +1,62 @@ +2000-06-09 Tom Yu <tlyu@mit.edu> + Ken Raeburn <raeburn@mit.edu> + + * accept_sec_context.c (krb5_gss_accept_sec_context): Remove + explicit check of mech OID against credential. + + * util_crypt.c (kg_encrypt): Copy ivec, since c_encrypt() now + updates ivecs. + (kg_decrypt): Copy ivec, since c_decrypt() now updates ivecs. + + * init_sec_context.c (get_credentials): Don't check each enctype + against a list from the krb5 library; instead, just try to use it, + and go on to the next if the error code indicates we can't use it. + + * gssapiP_krb5.h (enum qop): New type, derived from spec but + currently not used. + * util_crypt.c (kg_encrypt, kg_decrypt): Added key derivation + usage value as an argument. Prototypes and callers updated; all + callers use KG_USAGE_SEAL, except KG_USAGE_SEQ when encrypting + sequence numbers. + * 3des.txt: New file. + + * gssapiP_krb5.h (struct _krb5_gss_ctx_id_rec): Delete field + gsskrb5_version. + (struct _krb5_gss_cred_id_rec): Delete field rfcv2_mech. + * accept_sec_context.c, acquire_cred.c, add_cred.c, inq_cred.c, + k5seal.c, k5unseal.c, ser_ctx.c: + Delete krb5-mech2 support. + + * init_sec_context.c (get_credentials): Enctype argument is now a + pointer to a list of enctypes. Explicitly try each in order until + success or an error other than cryptosystem not being supported. + (krb5_gss_init_sec_context): Pass list of cryptosystems, starting + with 3DES. + + * gssapiP_krb5.h (enum sgn_alg, enum seal_alg): New types, + giving symbolic names for values from RFC 1964, a Microsoft win2k + I-D, and our proposed 3des-sha1 values. + (KG_USAGE_SEAL, KG_USAGE_SIGN, KG_USAGE_SEQ): New macros. + + * accept_sec_context.c (rd_req_keyproc): Already-disabled routine + deleted. + (krb5_gss_accept_sec_context): Use sgn_alg and seal_alg symbolic + names. Add a case for des3-hmac-sha1. + * k5seal.c (make_seal_token_v1): Likewise. Do key derivation for + checksums. + * k5unseal.c (kg_unseal_v1): Likewise. + * util_crypt.c (kg_encrypt, kg_decrypt): Do key derivation for + encryption. + + * util_crypt.c (zeros): Unused variable deleted. + + * wrap_size_limit.c: Remove mech2 support. Add MIT copyright. + +2000-06-09 Nalin Dahyabhai <nalin@redhat.com> + + * add_cred.c (krb5_gss_add_cred): Don't overflow buffers "ktboth" + or "ccboth". + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * accept_sec_context.c, gssapiP_krb5.h, init_sec_context.c, @@ -21,7 +80,7 @@ The rfc1964 mech always pads and confounds regardless of whether confidentiality is requested. -2000-01-27 Ken Raeburn <raeburn@raeburn.org> +2000-01-27 Ken Raeburn <raeburn@mit.edu> * init_sec_context.c (krb5_gss_init_sec_context): Default to des-cbc-crc. diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c index 075d0e4..0d2aaa5 100644 --- a/src/lib/gssapi/krb5/accept_sec_context.c +++ b/src/lib/gssapi/krb5/accept_sec_context.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -51,38 +75,7 @@ #ifdef HAVE_MEMORY_H #include <memory.h> #endif - -/* - * $Id$ - */ - -#if 0 - -/* XXXX This widen/narrow stuff is bletcherous, but it seems to be - necessary. Perhaps there is a "better" way, but I don't know what it - is */ - -#include <krb5/widen.h> -static krb5_error_code -rd_req_keyproc(krb5_pointer keyprocarg, krb5_principal server, - krb5_kvno kvno, krb5_keyblock **keyblock) -#include <krb5/narrow.h> -{ - krb5_error_code code; - krb5_keytab_entry ktentry; - - if (code = krb5_kt_get_entry((krb5_keytab) keyprocarg, server, kvno, - &ktentry)) - return(code); - - code = krb5_copy_keyblock(&ktentry.key, keyblock); - - (void) krb5_kt_free_entry(&ktentry); - - return(code); -} - -#endif +#include <assert.h> /* Decode, decrypt and store the forwarded creds in the local ccache. */ static krb5_error_code @@ -147,7 +140,6 @@ rd_and_store_for_creds(context, inbuf, out_cred) /* cred->princ already set */ cred->prerfc_mech = 1; /* this cred will work with all three mechs */ cred->rfc_mech = 1; - cred->rfcv2_mech = 1; cred->keytab = NULL; /* no keytab associated with this... */ cred->ccache = ccache; /* but there is a credential cache */ cred->tgt_expire = creds[0]->times.endtime; /* store the end time */ @@ -208,11 +200,10 @@ krb5_gss_accept_sec_context(minor_status, context_handle, krb5_ui_4 gss_flags = 0; int decode_req_message = 0; krb5_gss_ctx_id_rec *ctx = 0; -#if 0 krb5_enctype enctype; -#endif krb5_timestamp now; gss_buffer_desc token; + int err; krb5_auth_context auth_context = NULL; krb5_ticket * ticket = NULL; int option_id; @@ -224,7 +215,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, gss_cred_id_t cred_handle = NULL; krb5_gss_cred_id_t deleg_cred = NULL; int token_length; - int gsskrb5_vers; int nctypes; krb5_cksumtype *ctypes = 0; struct kg2_option fwcred; @@ -298,13 +288,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle, &(ap_req.length), &ptr, KG_TOK_CTX_AP_REQ, input_token->length))) { - if (! cred->rfc_mech) { - code = G_WRONG_MECH; - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } mech_used = gss_mech_krb5; - gsskrb5_vers = 1000; } else if ((code == G_WRONG_MECH) && !(code = g_verify_token_header((gss_OID) gss_mech_krb5_old, &(ap_req.length), @@ -317,56 +301,15 @@ krb5_gss_accept_sec_context(minor_status, context_handle, * compatibility, and use it to decide when to use the * old behavior. */ - if (! cred->prerfc_mech) { - code = G_WRONG_MECH; - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } mech_used = gss_mech_krb5_old; - gsskrb5_vers = 1000; - } else if ((code == G_WRONG_MECH) && - !(code = g_verify_token_header((gss_OID) gss_mech_krb5_v2, - &token_length, - &ptr, KG2_TOK_INITIAL, - input_token->length))) { - if (! cred->rfcv2_mech) { - code = G_WRONG_MECH; - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } - mech_used = gss_mech_krb5_v2; - gsskrb5_vers = 2000; } else { major_status = GSS_S_DEFECTIVE_TOKEN; goto fail; } - if (gsskrb5_vers == 2000) { - /* gss krb5 v2 */ - - fwcred.option_id = KRB5_GSS_FOR_CREDS_OPTION; - fwcred.data = NULL; - - if (GSS_ERROR(major_status = - kg2_parse_token(&code, ptr, token_length, - &gss_flags, &nctypes, &ctypes, - delegated_cred_handle?1:0, - &fwcred, &ap_req, NULL))) { - goto fail; - } - - gss_flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]; - - gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag; - if there's a delegation, we'll - set it below */ - } else { - /* gss krb5 v1 */ - - sptr = (char *) ptr; - TREAD_STR(sptr, ap_req.data, ap_req.length); - decode_req_message = 1; - } + sptr = (char *) ptr; + TREAD_STR(sptr, ap_req.data, ap_req.length); + decode_req_message = 1; /* construct the sender_addr */ @@ -418,9 +361,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle, } #endif - if (gsskrb5_vers == 2000) { - bigend = 1; - } else { + { /* gss krb5 v1 */ /* stash this now, for later. */ @@ -559,7 +500,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, ctx->gss_flags = KG_IMPLFLAGS(gss_flags); ctx->seed_init = 0; ctx->big_endian = bigend; - ctx->gsskrb5_version = gsskrb5_vers; /* Intern the ctx pointer so that delete_sec_context works */ if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) { @@ -605,114 +545,37 @@ krb5_gss_accept_sec_context(minor_status, context_handle, goto fail; } - if (gsskrb5_vers == 2000) { - int cblen; - krb5_boolean valid; - - /* intersect the token ctypes with the local ctypes */ - - if (code = krb5_c_keyed_checksum_types(context, ctx->subkey->enctype, - &ctx->nctypes, &ctx->ctypes)) - goto fail; - - if (nctypes == 0) { - code = KRB5_CRYPTO_INTERNAL; - goto fail; - } - - kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes); + switch(ctx->subkey->enctype) { + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_CRC: + ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; + ctx->signalg = SGN_ALG_DES_MAC_MD5; + ctx->cksum_size = 8; + ctx->sealalg = SEAL_ALG_DES; - if (nctypes == 0) { - code = KG_NO_CTYPES; - goto fail; - } - - /* process the delegated cred, if any */ - - if (fwcred.data) { - krb5_data option; - - option.length = fwcred.length; - option.data = fwcred.data; - - if (code = rd_and_store_for_creds(context, &option, &deleg_cred)) { - major_status = GSS_S_FAILURE; - goto fail; - } - - gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */ - } - - /* construct the checksum buffer */ - - cblen = 4*5; - if (input_chan_bindings) - cblen += (input_chan_bindings->initiator_address.length+ - input_chan_bindings->acceptor_address.length+ - input_chan_bindings->application_data.length); - - cksumdata.length = cblen + ((char *)(ap_req.data-2) - (char *)(ptr-2)); + /* fill in the encryption descriptors */ - if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) { - code = ENOMEM; + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) { major_status = GSS_S_FAILURE; goto fail; } - ptr2 = cksumdata.data; - - if (input_chan_bindings) { - TWRITE_INT(ptr2, input_chan_bindings->initiator_addrtype, 1); - TWRITE_BUF(ptr2, input_chan_bindings->initiator_address, 1); - TWRITE_INT(ptr2, input_chan_bindings->acceptor_addrtype, 1); - TWRITE_BUF(ptr2, input_chan_bindings->acceptor_address, 1); - TWRITE_BUF(ptr2, input_chan_bindings->application_data, 1); - } else { - memset(ptr2, 0, cblen); - ptr2 += cblen; - } - - memcpy(ptr2, ptr-2, ((char *)(ap_req.data-2) - (char *)(ptr-2))); + for (i=0; i<ctx->enc->length; i++) + /*SUPPRESS 113*/ + ctx->enc->contents[i] ^= 0xf0; - if (code = krb5_c_verify_checksum(context, ctx->subkey, - KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, - &cksumdata, authdat->checksum, - &valid)) { + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) { major_status = GSS_S_FAILURE; goto fail; } - free(cksumdata.data); - cksumdata.data = 0; + break; - if (!valid) { - code = 0; - major_status = GSS_S_BAD_SIG; - goto fail; - } - } else { - /* gss krb5 v1 */ - - switch(ctx->subkey->enctype) { - case ENCTYPE_DES_CBC_MD5: - case ENCTYPE_DES_CBC_CRC: - ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; - ctx->signalg = 0; - ctx->cksum_size = 8; - ctx->sealalg = 0; - break; -#if 0 - case ENCTYPE_DES3_CBC_MD5: - enctype = ENCTYPE_DES3_CBC_RAW; - ctx->signalg = 3; - ctx->cksum_size = 16; - ctx->sealalg = 1; - break; -#endif - default: - code = KRB5_BAD_ENCTYPE; - goto fail; - } + case ENCTYPE_DES3_CBC_SHA1: + ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW; + ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; + ctx->cksum_size = 20; + ctx->sealalg = SEAL_ALG_DES3KD; /* fill in the encryption descriptors */ @@ -721,14 +584,16 @@ krb5_gss_accept_sec_context(minor_status, context_handle, goto fail; } - for (i=0; i<ctx->enc->length; i++) - /*SUPPRESS 113*/ - ctx->enc->contents[i] ^= 0xf0; - if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) { major_status = GSS_S_FAILURE; goto fail; } + + break; + + default: + code = KRB5_BAD_ENCTYPE; + goto fail; } ctx->endtime = ticket->enc_part2->times.endtime; @@ -771,122 +636,22 @@ krb5_gss_accept_sec_context(minor_status, context_handle, /* the reply token hasn't been sent yet, but that's ok. */ ctx->established = 1; - if (ctx->gsskrb5_version == 2000) { - krb5_ui_4 tok_flags; - - tok_flags = - (ctx->gss_flags & GSS_C_DELEG_FLAG)?KG2_RESP_FLAG_DELEG_OK:0; - - cksumdata.length = 8 + 4*ctx->nctypes + 4; - - if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) { - code = ENOMEM; - major_status = GSS_S_FAILURE; - goto fail; - } - - /* construct the token fields */ - - ptr = cksumdata.data; - - ptr[0] = (KG2_TOK_RESPONSE >> 8) & 0xff; - ptr[1] = KG2_TOK_RESPONSE & 0xff; - - ptr[2] = (tok_flags >> 24) & 0xff; - ptr[3] = (tok_flags >> 16) & 0xff; - ptr[4] = (tok_flags >> 8) & 0xff; - ptr[5] = tok_flags & 0xff; - - ptr[6] = (ctx->nctypes >> 8) & 0xff; - ptr[7] = ctx->nctypes & 0xff; - - ptr += 8; - - for (i=0; i<ctx->nctypes; i++) { - ptr[i] = (ctx->ctypes[i] >> 24) & 0xff; - ptr[i+1] = (ctx->ctypes[i] >> 16) & 0xff; - ptr[i+2] = (ctx->ctypes[i] >> 8) & 0xff; - ptr[i+3] = ctx->ctypes[i] & 0xff; - - ptr += 4; - } - - memset(ptr, 0, 4); - - /* make the MIC token */ + token.length = g_token_size((gss_OID) mech_used, ap_rep.length); - { - gss_buffer_desc text, token; - - text.length = cksumdata.length; - text.value = cksumdata.data; - - /* ctx->seq_send must be set before this call */ - - if (GSS_ERROR(major_status = - krb5_gss_get_mic(&code, ctx, - GSS_C_QOP_DEFAULT, - &text, &token))) - goto fail; - - mic.length = token.length; - mic.data = token.value; - } - - token.length = g_token_size((gss_OID) mech_used, - (cksumdata.length-2)+4+ap_rep.length+ - mic.length); - - if ((token.value = (unsigned char *) xmalloc(token.length)) - == NULL) { - code = ENOMEM; - major_status = GSS_S_FAILURE; - goto fail; - } - ptr = token.value; - g_make_token_header((gss_OID) mech_used, - (cksumdata.length-2)+4+ap_rep.length+mic.length, - &ptr, KG2_TOK_RESPONSE); - - memcpy(ptr, cksumdata.data+2, cksumdata.length-2); - ptr += cksumdata.length-2; - - ptr[0] = (ap_rep.length >> 8) & 0xff; - ptr[1] = ap_rep.length & 0xff; - memcpy(ptr+2, ap_rep.data, ap_rep.length); - - ptr += (2+ap_rep.length); - - ptr[0] = (mic.length >> 8) & 0xff; - ptr[1] = mic.length & 0xff; - memcpy(ptr+2, mic.data, mic.length); - - ptr += (2+mic.length); - - free(cksumdata.data); - cksumdata.data = 0; - - /* gss krb5 v2 */ - } else { - /* gss krb5 v1 */ - - token.length = g_token_size((gss_OID) mech_used, ap_rep.length); - - if ((token.value = (unsigned char *) xmalloc(token.length)) - == NULL) { - major_status = GSS_S_FAILURE; - code = ENOMEM; - goto fail; - } - ptr = token.value; - g_make_token_header((gss_OID) mech_used, ap_rep.length, - &ptr, KG_TOK_CTX_AP_REP); + if ((token.value = (unsigned char *) xmalloc(token.length)) + == NULL) { + major_status = GSS_S_FAILURE; + code = ENOMEM; + goto fail; + } + ptr = token.value; + g_make_token_header((gss_OID) mech_used, ap_rep.length, + &ptr, KG_TOK_CTX_AP_REP); - TWRITE_STR(ptr, ap_rep.data, ap_rep.length); + TWRITE_STR(ptr, ap_rep.data, ap_rep.length); - ctx->established = 1; + ctx->established = 1; - } } else { token.length = 0; token.value = NULL; @@ -1016,13 +781,8 @@ krb5_gss_accept_sec_context(minor_status, context_handle, if (code) return (major_status); - if (gsskrb5_vers == 2000) { - tmsglen = 12+scratch.length; - toktype = KG2_TOK_RESPONSE; - } else { - tmsglen = scratch.length; - toktype = KG_TOK_CTX_ERROR; - } + tmsglen = scratch.length; + toktype = KG_TOK_CTX_ERROR; token.length = g_token_size((gss_OID) mech_used, tmsglen); token.value = (unsigned char *) xmalloc(token.length); @@ -1032,24 +792,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle, ptr = token.value; g_make_token_header((gss_OID) mech_used, tmsglen, &ptr, toktype); - if (gsskrb5_vers == 2000) { - krb5_ui_4 flags; - - flags = KG2_RESP_FLAG_ERROR; - - ptr[0] = (flags << 24) & 0xff; - ptr[1] = (flags << 16) & 0xff; - ptr[2] = (flags << 8) & 0xff; - ptr[3] = flags & 0xff; - - memset(ptr+4, 0, 6); - - ptr[10] = (scratch.length << 8) & 0xff; - ptr[11] = scratch.length & 0xff; - - ptr += 12; - } - TWRITE_STR(ptr, scratch.data, scratch.length); xfree(scratch.data); diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c index 78e8c29..33946e7 100644 --- a/src/lib/gssapi/krb5/acquire_cred.c +++ b/src/lib/gssapi/krb5/acquire_cred.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -53,10 +77,6 @@ #include <strings.h> #endif -/* - * $Id$ - */ - /* get credentials corresponding to a key in the krb5 keytab. If the default name is requested, return the name in output_princ. If output_princ is non-NULL, the caller will use or free it, regardless @@ -283,7 +303,7 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, size_t i; krb5_gss_cred_id_t cred; gss_OID_set ret_mechs; - int req_old, req_new, req_v2; + int req_old, req_new; OM_uint32 ret; krb5_error_code code; @@ -313,22 +333,18 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, if (desired_mechs == GSS_C_NULL_OID_SET) { req_old = 1; req_new = 1; - req_v2 = 1; } else { req_old = 0; req_new = 0; - req_v2 = 0; for (i=0; i<desired_mechs->count; i++) { if (g_OID_equal(gss_mech_krb5_old, &(desired_mechs->elements[i]))) req_old++; if (g_OID_equal(gss_mech_krb5, &(desired_mechs->elements[i]))) req_new++; - if (g_OID_equal(gss_mech_krb5_v2, &(desired_mechs->elements[i]))) - req_v2++; } - if (!req_old && !req_new && !req_v2) { + if (!req_old && !req_new) { *minor_status = 0; return(GSS_S_BAD_MECH); } @@ -347,7 +363,6 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, cred->princ = NULL; cred->prerfc_mech = req_old; cred->rfc_mech = req_new; - cred->rfcv2_mech = req_v2; cred->keytab = NULL; cred->ccache = NULL; @@ -447,10 +462,6 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req, (cred->rfc_mech && GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, gss_mech_krb5, - &ret_mechs))) || - (cred->rfcv2_mech && - GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5_v2, &ret_mechs)))) { if (cred->ccache) (void)krb5_cc_close(context, cred->ccache); diff --git a/src/lib/gssapi/krb5/add_cred.c b/src/lib/gssapi/krb5/add_cred.c index 2a6fdb4..918c264 100644 --- a/src/lib/gssapi/krb5/add_cred.c +++ b/src/lib/gssapi/krb5/add_cred.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright (C) 1998 by the FundsXpress, INC. * * All rights reserved. @@ -110,8 +134,7 @@ krb5_gss_add_cred(minor_status, input_cred_handle, /* check that desired_mech isn't already in the credential */ if ((g_OID_equal(desired_mech, gss_mech_krb5_old) && cred->prerfc_mech) || - (g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech) || - (g_OID_equal(desired_mech, gss_mech_krb5_v2) && cred->rfcv2_mech)) { + (g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech)) { *minor_status = 0; return(GSS_S_DUPLICATE_ELEMENT); } @@ -156,7 +179,6 @@ krb5_gss_add_cred(minor_status, input_cred_handle, new_cred->usage = cred_usage; new_cred->prerfc_mech = cred->prerfc_mech; new_cred->rfc_mech = cred->rfc_mech; - new_cred->rfcv2_mech = cred->rfcv2_mech; new_cred->tgt_expire = cred->tgt_expire; if (code = krb5_copy_principal(context, cred->princ, @@ -177,8 +199,9 @@ krb5_gss_add_cred(minor_status, input_cred_handle, return(GSS_S_FAILURE); } - strcpy(ktboth, kttype); - strcat(ktboth, ":"); + strncpy(ktboth, kttype, sizeof(ktboth) - 1); + ktboth[sizeof(ktboth) - 1] = '\0'; + strncat(ktboth, ":", sizeof(ktboth) - 1 - strlen(ktboth)); if (code = krb5_kt_get_name(context, cred->keytab, ktboth+strlen(ktboth), @@ -234,9 +257,10 @@ krb5_gss_add_cred(minor_status, input_cred_handle, return(GSS_S_FAILURE); } - strcpy(ccboth, cctype); - strcat(ccboth, ":"); - strcat(ccboth, ccname); + strncpy(ccboth, cctype, sizeof(ccboth) - 1); + ccboth[sizeof(ccboth) - 1] = '\0'; + strncat(ccboth, ":", sizeof(ccboth) - 1 - strlen(ccboth)); + strncat(ccboth, ccname, sizeof(ccboth) - 1 - strlen(ccboth)); if (code = krb5_cc_resolve(context, ccboth, &new_cred->ccache)) { if (new_cred->rcache) @@ -280,8 +304,6 @@ krb5_gss_add_cred(minor_status, input_cred_handle, cred->prerfc_mech = 1; else if (g_OID_equal(desired_mech, gss_mech_krb5)) cred->rfc_mech = 1; - else if (g_OID_equal(desired_mech, gss_mech_krb5_v2)) - cred->rfcv2_mech = 1; /* set the outputs */ diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index a22cd8d..ed09569 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -23,10 +47,6 @@ #ifndef _GSSAPIP_KRB5_H_ #define _GSSAPIP_KRB5_H_ -/* - * $Id$ - */ - #include <krb5.h> #ifdef HAVE_MEMORY_H #include <memory.h> @@ -81,6 +101,39 @@ #define KG2_RESP_FLAG_ERROR 0x0001 #define KG2_RESP_FLAG_DELEG_OK 0x0002 +/* These are to be stored in little-endian order, i.e., des-mac is + stored as 02 00. */ +enum sgn_alg { + SGN_ALG_DES_MAC_MD5 = 0x0000, + SGN_ALG_MD2_5 = 0x0001, + SGN_ALG_DES_MAC = 0x0002, + SGN_ALG_3 = 0x0003, /* not published */ + SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */ + SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 +}; +enum seal_alg { + SEAL_ALG_NONE = 0xffff, + SEAL_ALG_DES = 0x0000, + SEAL_ALG_1 = 0x0001, /* not published */ + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; no support */ + SEAL_ALG_DES3KD = 0x0002 +}; + +#define KG_USAGE_SEAL 22 +#define KG_USAGE_SIGN 23 +#define KG_USAGE_SEQ 24 + +enum qop { + GSS_KRB5_INTEG_C_QOP_MD5 = 0x0001, /* *partial* MD5 = "MD2.5" */ + GSS_KRB5_INTEG_C_QOP_DES_MD5 = 0x0002, + GSS_KRB5_INTEG_C_QOP_DES_MAC = 0x0003, + GSS_KRB5_INTEG_C_QOP_HMAC_SHA1 = 0x0004, + GSS_KRB5_INTEG_C_QOP_MASK = 0x00ff, + GSS_KRB5_CONF_C_QOP_DES = 0x0100, + GSS_KRB5_CONF_C_QOP_DES3_KD = 0x0200, + GSS_KRB5_CONF_C_QOP_MASK = 0xff00 +}; + /** internal types **/ typedef krb5_principal krb5_gss_name_t; @@ -91,7 +144,6 @@ typedef struct _krb5_gss_cred_id_rec { krb5_principal princ; /* this is not interned as a gss_name_t */ int prerfc_mech; int rfc_mech; - int rfcv2_mech; /* keytab (accept) data */ krb5_keytab keytab; @@ -127,7 +179,6 @@ typedef struct _krb5_gss_ctx_id_rec { int big_endian; krb5_auth_context auth_context; gss_OID_desc *mech_used; - int gsskrb5_version; int nctypes; krb5_cksumtype *ctypes; } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; @@ -192,12 +243,18 @@ int kg_encrypt_size PROTOTYPE((krb5_context context, krb5_keyblock *key, int n)); krb5_error_code kg_encrypt PROTOTYPE((krb5_context context, - krb5_keyblock *key, - krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length)); + krb5_keyblock *key, int usage, + krb5_pointer iv, + krb5_pointer in, + krb5_pointer out, + int length)); krb5_error_code kg_decrypt PROTOTYPE((krb5_context context, - krb5_keyblock *key, - krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length)); + krb5_keyblock *key, int usage, + krb5_pointer iv, + krb5_pointer in, + krb5_pointer out, + int length)); OM_uint32 kg_seal PROTOTYPE((krb5_context context, OM_uint32 *minor_status, diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c index 8baad8c..13a971f 100644 --- a/src/lib/gssapi/krb5/init_sec_context.c +++ b/src/lib/gssapi/krb5/init_sec_context.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -51,10 +75,7 @@ #include <memory.h> #endif #include <stdlib.h> - -/* - * $Id$ - */ +#include <assert.h> /* XXX This is for debugging only!!! Should become a real bitfield at some point */ @@ -65,17 +86,18 @@ int krb5_gss_dbg_client_expcreds = 0; * ccache. */ static krb5_error_code get_credentials(context, cred, server, now, - endtime, enctype, out_creds) + endtime, enctypes, out_creds) krb5_context context; krb5_gss_cred_id_t cred; krb5_principal server; krb5_timestamp now; krb5_timestamp endtime; - krb5_enctype enctype; + const krb5_enctype *enctypes; krb5_creds **out_creds; { krb5_error_code code; krb5_creds in_creds; + int i; memset((char *) &in_creds, 0, sizeof(krb5_creds)); @@ -84,10 +106,21 @@ static krb5_error_code get_credentials(context, cred, server, now, if ((code = krb5_copy_principal(context, server, &in_creds.server))) goto cleanup; in_creds.times.endtime = endtime; - in_creds.keyblock.enctype = enctype; - if ((code = krb5_get_credentials(context, 0, cred->ccache, - &in_creds, out_creds))) + in_creds.keyblock.enctype = 0; + + for (i = 0; enctypes[i]; i++) { + in_creds.keyblock.enctype = enctypes[i]; + code = krb5_get_credentials(context, 0, cred->ccache, + &in_creds, out_creds); + if (code != KRB5_CC_NOT_KTYPE && code != KRB5KDC_ERR_ETYPE_NOSUPP) + break; + } + if (enctypes[i] == 0) { + code = KRB5_CONFIG_ETYPE_NOSUPP; + goto cleanup; + } + if (code) goto cleanup; /* @@ -95,7 +128,8 @@ static krb5_error_code get_credentials(context, cred, server, now, * boundaries) because accept_sec_context code is also similarly * non-forgiving. */ - if (!krb5_gss_dbg_client_expcreds && (*out_creds)->times.endtime < now) { + if (!krb5_gss_dbg_client_expcreds && *out_creds != NULL && + (*out_creds)->times.endtime < now) { code = KRB5KRB_AP_ERR_TKT_EXPIRED; goto cleanup; } @@ -119,196 +153,8 @@ make_ap_req_v2(context, ctx, cred, k_cred, chan_bindings, mech_type, token) gss_OID mech_type; gss_buffer_t token; { - krb5_flags mk_req_flags = 0; - krb5_int32 con_flags; - krb5_error_code code; - krb5_data credmsg, cksumdata, ap_req; - int i, tlen, cblen, nctypes; - krb5_cksumtype *ctypes; - unsigned char *t, *ptr; - - credmsg.data = 0; - cksumdata.data = 0; - ap_req.data = 0; - ctypes = 0; - - /* create the option data if necessary */ - if (ctx->gss_flags & GSS_C_DELEG_FLAG) { - /* first get KRB_CRED message, so we know its length */ - - /* clear the time check flag that was set in krb5_auth_con_init() */ - krb5_auth_con_getflags(context, ctx->auth_context, &con_flags); - krb5_auth_con_setflags(context, ctx->auth_context, - con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME); - - code = krb5_fwd_tgt_creds(context, ctx->auth_context, 0, - cred->princ, ctx->there, cred->ccache, 1, - &credmsg); - - /* turn KRB5_AUTH_CONTEXT_DO_TIME back on */ - krb5_auth_con_setflags(context, ctx->auth_context, con_flags); - - if (code) { - /* don't fail here; just don't accept/do the delegation - request */ - ctx->gss_flags &= ~GSS_C_DELEG_FLAG; - } else { - if (credmsg.length > KRB5_INT16_MAX) { - krb5_free_data_contents(context, &credmsg); - return(KRB5KRB_ERR_FIELD_TOOLONG); - } - } - } else { - credmsg.length = 0; - } - - /* construct the list of compatible cksum types */ - - if ((code = krb5_c_keyed_checksum_types(context, - k_cred->keyblock.enctype, - &nctypes, &ctypes))) - goto cleanup; - - if (nctypes == 0) { - code = KRB5_CRYPTO_INTERNAL; - goto cleanup; - } - - /* construct the checksum fields */ - - cblen = 4*5; - if (chan_bindings) - cblen += (chan_bindings->initiator_address.length+ - chan_bindings->acceptor_address.length+ - chan_bindings->application_data.length); - - cksumdata.length = cblen + 8 + 4*nctypes + 4; - if (credmsg.length) - cksumdata.length += 4 + credmsg.length; - - if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) - goto cleanup; - - /* helper macros. This code currently depends on a long being 32 - bits, and htonl dtrt. */ - - ptr = cksumdata.data; - - if (chan_bindings) { - TWRITE_INT(ptr, chan_bindings->initiator_addrtype, 1); - TWRITE_BUF(ptr, chan_bindings->initiator_address, 1); - TWRITE_INT(ptr, chan_bindings->acceptor_addrtype, 1); - TWRITE_BUF(ptr, chan_bindings->acceptor_address, 1); - TWRITE_BUF(ptr, chan_bindings->application_data, 1); - } else { - memset(ptr, 0, cblen); - ptr += cblen; - } - - /* construct the token fields */ - - ptr[0] = (KG2_TOK_INITIAL >> 8) & 0xff; - ptr[1] = KG2_TOK_INITIAL & 0xff; - - ptr[2] = (ctx->gss_flags >> 24) & 0xff; - ptr[3] = (ctx->gss_flags >> 16) & 0xff; - ptr[4] = (ctx->gss_flags >> 8) & 0xff; - ptr[5] = ctx->gss_flags & 0xff; - - ptr[6] = (nctypes >> 8) & 0xff; - ptr[7] = nctypes & 0xff; - - ptr += 8; - - for (i=0; i<nctypes; i++) { - ptr[0] = (ctypes[i] >> 24) & 0xff; - ptr[1] = (ctypes[i] >> 16) & 0xff; - ptr[2] = (ctypes[i] >> 8) & 0xff; - ptr[3] = ctypes[i] & 0xff; - - ptr += 4; - } - - if (credmsg.length) { - ptr[0] = (KRB5_GSS_FOR_CREDS_OPTION >> 8) & 0xff; - ptr[1] = KRB5_GSS_FOR_CREDS_OPTION & 0xff; - - ptr[2] = (credmsg.length >> 8) & 0xff; - ptr[3] = credmsg.length & 0xff; - - ptr += 4; - - memcpy(ptr, credmsg.data, credmsg.length); - - ptr += credmsg.length; - } - - memset(ptr, 0, 4); - - /* call mk_req. subkey and ap_req need to be used or destroyed */ - - mk_req_flags = AP_OPTS_USE_SUBKEY; - - if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) - mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED; - - if ((code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags, - &cksumdata, k_cred, &ap_req))) - goto cleanup; - - /* store the interesting stuff from creds and authent */ - ctx->endtime = k_cred->times.endtime; - ctx->krb_flags = k_cred->ticket_flags; - - /* build up the token */ - - /* allocate space for the token */ - tlen = g_token_size((gss_OID) mech_type, - (cksumdata.length-(2+cblen))+2+ap_req.length); - - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) { - code = ENOMEM; - goto cleanup; - } - - ptr = t; - - g_make_token_header((gss_OID) mech_type, - (cksumdata.length-(2+cblen))+2+ap_req.length, - &ptr, KG2_TOK_INITIAL); - - /* skip over the channel bindings and the token id */ - memcpy(ptr, cksumdata.data+cblen+2, cksumdata.length-(cblen+2)); - ptr += cksumdata.length-(cblen+2); - ptr[0] = (ap_req.length >> 8) & 0xff; - ptr[1] = ap_req.length & 0xff; - ptr += 2; - memcpy(ptr, ap_req.data, ap_req.length); - - /* pass allocated data back */ - - ctx->nctypes = nctypes; - ctx->ctypes = ctypes; - - token->length = tlen; - token->value = (void *) t; - - code = 0; - -cleanup: - if (code) { - if (ctypes) - krb5_free_cksumtypes(context, ctypes); - } - - if (credmsg.data) - free(credmsg.data); - if (ap_req.data) - free(ap_req.data); - if (cksumdata.data) - free(cksumdata.data); - - return(code); + int krb5_mech2_supported = 0; + assert(krb5_mech2_supported); } static krb5_error_code @@ -482,13 +328,19 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, krb5_context context; krb5_gss_cred_id_t cred; krb5_creds *k_cred = 0; - krb5_enctype enctype = ENCTYPE_DES_CBC_CRC; + static const krb5_enctype wanted_enctypes[] = { +#if 1 + ENCTYPE_DES3_CBC_SHA1, +#endif + ENCTYPE_DES_CBC_CRC, + ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4, + 0 + }; krb5_error_code code; krb5_gss_ctx_id_rec *ctx, *ctx_free; krb5_timestamp now; gss_buffer_desc token; - int gsskrb5_vers = 0; - int i, err; + int i, j, err; int default_mech = 0; krb5_ui_4 resp_flags; OM_uint32 major_status; @@ -530,32 +382,19 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, err = 0; if (mech_type == GSS_C_NULL_OID) { default_mech = 1; - if (cred->rfcv2_mech) { - mech_type = gss_mech_krb5_v2; - gsskrb5_vers = 2000; - } else if (cred->rfc_mech) { + if (cred->rfc_mech) { mech_type = gss_mech_krb5; - gsskrb5_vers = 1000; - enctype = ENCTYPE_DES_CBC_CRC; } else if (cred->prerfc_mech) { mech_type = gss_mech_krb5_old; - gsskrb5_vers = 1000; - enctype = ENCTYPE_DES_CBC_CRC; } else { err = 1; } - } else if (g_OID_equal(mech_type, gss_mech_krb5_v2)) { - if (!cred->rfcv2_mech) - err = 1; - gsskrb5_vers = 2000; } else if (g_OID_equal(mech_type, gss_mech_krb5)) { if (!cred->rfc_mech) err = 1; - gsskrb5_vers = 1000; } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) { if (!cred->prerfc_mech) err = 1; - gsskrb5_vers = 1000; } else { err = 1; } @@ -609,7 +448,6 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, ctx->seed_init = 0; ctx->big_endian = 0; /* all initiators do little-endian, as per spec */ ctx->seqstate = 0; - ctx->gsskrb5_version = gsskrb5_vers; ctx->nctypes = 0; ctx->ctypes = 0; @@ -630,27 +468,12 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, goto fail; if ((code = get_credentials(context, cred, ctx->there, now, - ctx->endtime, enctype, &k_cred))) + ctx->endtime, wanted_enctypes, &k_cred))) goto fail; - /* - * If the default mechanism was requested, and the keytype is - * DES_CBC, force the old mechanism - */ - if (default_mech && - ((k_cred->keyblock.enctype == ENCTYPE_DES_CBC_CRC) || - (k_cred->keyblock.enctype == ENCTYPE_DES_CBC_MD4) || - (k_cred->keyblock.enctype == ENCTYPE_DES_CBC_MD5))) { - ctx->gsskrb5_version = gsskrb5_vers = 1000; + if (default_mech) { mech_type = gss_mech_krb5; - if (k_cred->keyblock.enctype != ENCTYPE_DES_CBC_CRC) { - krb5_free_creds(context, k_cred); - enctype = ENCTYPE_DES_CBC_CRC; - if ((code = get_credentials(context, cred, ctx->there, now, - ctx->endtime, enctype, &k_cred))) - goto fail; - } - } + } if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used) != GSS_S_COMPLETE) { @@ -662,24 +485,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, */ ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used); - if (ctx->gsskrb5_version == 2000) { - /* gsskrb5 v2 */ - if ((code = make_ap_req_v2(context, ctx, - cred, k_cred, input_chan_bindings, - mech_type, &token))) { - if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) || - (code == KG_EMPTY_CCACHE)) - major_status = GSS_S_NO_CRED; - if (code == KRB5KRB_AP_ERR_TKT_EXPIRED) - major_status = GSS_S_CREDENTIALS_EXPIRED; - goto fail; - } - - krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, - &ctx->seq_send); - krb5_auth_con_getlocalsubkey(context, ctx->auth_context, - &ctx->subkey); - } else { + { /* gsskrb5 v1 */ if ((code = make_ap_req_v1(context, ctx, cred, k_cred, input_chan_bindings, @@ -701,11 +507,41 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, switch(ctx->subkey->enctype) { case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_CRC: ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW; - ctx->signalg = 0; + ctx->signalg = SGN_ALG_DES_MAC_MD5; ctx->cksum_size = 8; - ctx->sealalg = 0; + ctx->sealalg = SEAL_ALG_DES; + + /* The encryption key is the session key XOR + 0xf0f0f0f0f0f0f0f0. */ + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) + goto fail; + + for (i=0; i<ctx->enc->length; i++) + /*SUPPRESS 113*/ + ctx->enc->contents[i] ^= 0xf0; + + if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) + goto fail; + + break; + + case ENCTYPE_DES3_CBC_SHA1: + ctx->subkey->enctype = ENCTYPE_DES3_CBC_RAW; + ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; + ctx->cksum_size = 20; + ctx->sealalg = SEAL_ALG_DES3KD; + + code = krb5_copy_keyblock (context, ctx->subkey, &ctx->enc); + if (code) + goto fail; + code = krb5_copy_keyblock (context, ctx->subkey, &ctx->seq); + if (code) { + krb5_free_keyblock (context, ctx->enc); + goto fail; + } break; #if 0 case ENCTYPE_DES3_CBC_MD5: @@ -716,20 +552,10 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, break; #endif default: + *minor_status = KRB5_BAD_ENCTYPE; return GSS_S_FAILURE; } - /* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */ - - if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) - goto fail; - - for (i=0; i<ctx->enc->length; i++) - /*SUPPRESS 113*/ - ctx->enc->contents[i] ^= 0xf0; - - if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) - goto fail; } if (k_cred) { @@ -826,94 +652,38 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, ptr = (unsigned char *) input_token->value; - if (ctx->gsskrb5_version == 2000) { - int token_length; - int nctypes; - krb5_cksumtype *ctypes = 0; - - /* gsskrb5 v2 */ - - if ((code = g_verify_token_header((gss_OID) ctx->mech_used, - &token_length, - &ptr, KG2_TOK_RESPONSE, - input_token->length))) { - major_status = GSS_S_DEFECTIVE_TOKEN; - goto fail; - } - - if (GSS_ERROR(major_status = - kg2_parse_token(minor_status, ptr, token_length, - &resp_flags, &nctypes, &ctypes, - 0, NULL, &ap_rep, &mic))) { - if (ctypes) - free(ctypes); - code = *minor_status; - goto fail; - } - major_status = GSS_S_FAILURE; - - kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes); - - free(ctypes); + if ((err = g_verify_token_header((gss_OID) ctx->mech_used, + &(ap_rep.length), + &ptr, KG_TOK_CTX_AP_REP, + input_token->length))) { + if (g_verify_token_header((gss_OID) ctx->mech_used, + &(ap_rep.length), + &ptr, KG_TOK_CTX_ERROR, + input_token->length) == 0) { - if (ctx->nctypes == 0) { - code = KG_NO_CTYPES; - goto fail; - } + /* Handle a KRB_ERROR message from the server */ - if (resp_flags & KG2_RESP_FLAG_ERROR) { - if ((code = krb5_rd_error(context, &ap_rep, &krb_error))) + sptr = (char *) ptr; /* PC compiler bug */ + TREAD_STR(sptr, ap_rep.data, ap_rep.length); + + code = krb5_rd_error(context, &ap_rep, &krb_error); + if (code) goto fail; - if (krb_error->error) code = krb_error->error + ERROR_TABLE_BASE_krb5; else code = 0; - krb5_free_error(context, krb_error); goto fail; + } else { + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); } - - if (resp_flags & KG2_RESP_FLAG_DELEG_OK) - ctx->gss_flags |= GSS_C_DELEG_FLAG; - - /* drop through to ap_rep handling */ - } else { - /* gsskrb5 v1 */ - - if ((err = g_verify_token_header((gss_OID) ctx->mech_used, - &(ap_rep.length), - &ptr, KG_TOK_CTX_AP_REP, - input_token->length))) { - if (g_verify_token_header((gss_OID) ctx->mech_used, - &(ap_rep.length), - &ptr, KG_TOK_CTX_ERROR, - input_token->length) == 0) { - - /* Handle a KRB_ERROR message from the server */ - - sptr = (char *) ptr; /* PC compiler bug */ - TREAD_STR(sptr, ap_rep.data, ap_rep.length); - - code = krb5_rd_error(context, &ap_rep, &krb_error); - if (code) - goto fail; - if (krb_error->error) - code = krb_error->error + ERROR_TABLE_BASE_krb5; - else - code = 0; - krb5_free_error(context, krb_error); - goto fail; - } else { - *minor_status = 0; - return(GSS_S_DEFECTIVE_TOKEN); - } - } - - sptr = (char *) ptr; /* PC compiler bug */ - TREAD_STR(sptr, ap_rep.data, ap_rep.length); } + sptr = (char *) ptr; /* PC compiler bug */ + TREAD_STR(sptr, ap_rep.data, ap_rep.length); + /* decode the ap_rep */ if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep, &ap_rep_data))) { @@ -940,26 +710,6 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle, /* set established */ ctx->established = 1; - if (ctx->gsskrb5_version == 2000) { - gss_buffer_desc mic_data, mic_token; - - /* start with the token id */ - mic_data.value = ptr-2; - /* end before the ap-rep length */ - mic_data.length = ((char*)(ap_rep.data-2)-(char*)(ptr-2)); - - mic_token.length = mic.length; - mic_token.value = mic.data; - - if (GSS_ERROR(major_status = - krb5_gss_verify_mic(minor_status, *context_handle, - &mic_data, &mic_token, NULL))) { - code = *minor_status; - goto fail; - } - major_status = GSS_S_FAILURE; - } - /* set returns */ if (time_rec) { diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c index c800012..6da0a52 100644 --- a/src/lib/gssapi/krb5/inq_cred.c +++ b/src/lib/gssapi/krb5/inq_cred.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -121,10 +145,6 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret, (cred->rfc_mech && GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, gss_mech_krb5, - &mechs))) || - (cred->rfcv2_mech && - GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, - gss_mech_krb5_v2, &mechs)))) { krb5_free_principal(context, ret_name); /* *minor_status set above */ diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c index ae8cc75..1ca108e 100644 --- a/src/lib/gssapi/krb5/k5seal.c +++ b/src/lib/gssapi/krb5/k5seal.c @@ -1,6 +1,6 @@ /* * Copyright 1993 by OpenVision Technologies, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and @@ -10,7 +10,7 @@ * without specific, written prior permission. OpenVision makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. - * + * * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR @@ -22,14 +22,14 @@ /* * 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 @@ -40,7 +40,7 @@ * 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. @@ -49,196 +49,280 @@ #include "gssapiP_krb5.h" static krb5_error_code -make_priv_token_v2 PROTOTYPE((krb5_context context, - krb5_keyblock *subkey, +make_seal_token_v1 PROTOTYPE((krb5_context context, + krb5_keyblock *enc, + krb5_keyblock *seq, krb5_int32 *seqnum, int direction, gss_buffer_t text, gss_buffer_t token, + int signalg, + int cksum_size, + int sealalg, + int encrypt, + int toktype, + int bigend, gss_OID oid)); static krb5_error_code -make_priv_token_v2(context, subkey, seqnum, direction, text, token, oid) - krb5_context context; - krb5_keyblock *subkey; - krb5_int32 *seqnum; - int direction; - gss_buffer_t text; - gss_buffer_t token; - gss_OID oid; -{ - krb5_data plain; - krb5_enc_data cipher; - krb5_error_code code; - size_t enclen; - int tlen; - unsigned char *t, *ptr; - - plain.data = 0; - cipher.ciphertext.data = 0; - t = 0; - - plain.length = 7+text->length; - if ((plain.data = (void *) malloc(plain.length)) == NULL) { - code = ENOMEM; - goto cleanup; - } - - plain.data[0] = (*seqnum >> 24) & 0xff; - plain.data[1] = (*seqnum >> 16) & 0xff; - plain.data[2] = (*seqnum >> 8) & 0xff; - plain.data[3] = *seqnum & 0xff; - - plain.data[4] = direction?0:0xff; - - plain.data[5] = (text->length >> 8) & 0xff; - plain.data[6] = text->length & 0xff; - - memcpy(plain.data+7, text->value, text->length); - - if (code = krb5_c_encrypt_length(context, subkey->enctype, - plain.length, &enclen)) - goto cleanup; - - tlen = g_token_size((gss_OID) oid, 2+enclen); - - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) - return(ENOMEM); - - ptr = t; - - g_make_token_header((gss_OID) oid, 2+enclen, &ptr, - KG2_TOK_WRAP_PRIV); - - ptr[0] = (enclen >> 8) & 0xff; - ptr[1] = enclen & 0xff; - - cipher.ciphertext.length = enclen; - cipher.ciphertext.data = ptr+2; - - if (code = krb5_c_encrypt(context, subkey, - KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV, - 0, &plain, &cipher)) - goto cleanup; - - /* that's it. return the token */ - - (*seqnum)++; - - token->length = tlen; - token->value = (void *) t; - - code = 0; - -cleanup: - if (plain.data) - free(plain.data); - if (code) { - if (t) - free(t); - } - - return(code); -} - -static krb5_error_code -make_integ_token_v2 PROTOTYPE((krb5_context context, - krb5_keyblock *subkey, - krb5_cksumtype ctype, - krb5_int32 *seqnum, - int direction, - gss_buffer_t text, - gss_buffer_t token, - int toktype, - gss_OID oid)); - -static krb5_error_code -make_integ_token_v2(context, subkey, ctype, seqnum, direction, text, token, - toktype, oid) - krb5_context context; - krb5_keyblock *subkey; - krb5_cksumtype ctype; - krb5_int32 *seqnum; - int direction; - gss_buffer_t text; - gss_buffer_t token; - int toktype; - gss_OID oid; +make_seal_token_v1(context, enc, seq, seqnum, direction, text, token, + signalg, cksum_size, sealalg, encrypt, toktype, + bigend, oid) + krb5_context context; + krb5_keyblock *enc; + krb5_keyblock *seq; + krb5_int32 *seqnum; + int direction; + gss_buffer_t text; + gss_buffer_t token; + int signalg; + int cksum_size; + int sealalg; + int encrypt; + int toktype; + int bigend; + gss_OID oid; { krb5_error_code code; - int tmp, tlen; - unsigned char *t, *ptr; - krb5_data plain; + size_t sumlen; + char *data_ptr; + krb5_data plaind; + krb5_checksum md5cksum; krb5_checksum cksum; + int conflen=0, tmsglen, tlen; + unsigned char *t, *ptr; - plain.data = 0; - t = 0; - cksum.contents = 0; + int encblksize, sumblksize; + + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + case SGN_ALG_HMAC_MD5: + sumblksize = 1; + break; + case SGN_ALG_DES_MAC: + sumblksize = 8; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + sumblksize = 1; + break; + default: + abort (); + return 123; /* find error code */ + } - /* assemble the checksum buffer and compute the checksum */ + switch (sealalg) { + case SEAL_ALG_NONE: + case SEAL_ALG_DES: + case SEAL_ALG_DES3KD: + encblksize = 8; + break; + default: + abort (); + return 12345654321; + } - plain.length = 7+text->length; + /* create the token buffer */ - if ((plain.data = (char *) malloc(plain.length)) == NULL) { - code = errno; - goto cleanup; + if (toktype == KG_TOK_SEAL_MSG) { + if (bigend && !encrypt) { + tmsglen = text->length; + } else { + conflen = kg_confounder_size(context, enc); + /* XXX knows that des block size is 8 */ + tmsglen = (conflen+text->length+8)&(~7); + } + } else { + tmsglen = 0; } - plain.data[0] = (*seqnum >> 24) & 0xff; - plain.data[1] = (*seqnum >> 16) & 0xff; - plain.data[2] = (*seqnum >> 8) & 0xff; - plain.data[3] = *seqnum & 0xff; + tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen); - plain.data[4] = direction?0:0xff; + if ((t = (unsigned char *) xmalloc(tlen)) == NULL) + return(ENOMEM); - plain.data[5] = (text->length >> 8) & 0xff; - plain.data[6] = text->length & 0xff; + /*** fill in the token */ - memcpy(plain.data+7, text->value, text->length); + ptr = t; - if (code = krb5_c_make_checksum(context, ctype, subkey, - (toktype == KG2_TOK_WRAP_INTEG)? - KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG: - KRB5_KEYUSAGE_GSS_TOK_MIC, - &plain, &cksum)) - goto cleanup; + g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype); - /* assemble the token itself */ + /* 0..1 SIGN_ALG */ - if (toktype == KG2_TOK_WRAP_INTEG) - tmp = 4+(7+text->length)+2+cksum.length; - else - tmp = 4+(5)+2+cksum.length; + ptr[0] = signalg & 0xff; + ptr[1] = (signalg >> 8) & 0xff; - tlen = g_token_size((gss_OID) oid, tmp); + /* 2..3 SEAL_ALG or Filler */ - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) - return(ENOMEM); + if ((toktype == KG_TOK_SEAL_MSG) && encrypt) { + ptr[2] = sealalg & 0xff; + ptr[3] = (sealalg >> 8) & 0xff; + } else { + /* No seal */ + ptr[2] = 0xff; + ptr[3] = 0xff; + } - ptr = t; + /* 4..5 Filler */ + + ptr[4] = 0xff; + ptr[5] = 0xff; + + /* pad the plaintext, encrypt if needed, and stick it in the token */ + + /* initialize the the cksum */ + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + case SGN_ALG_HMAC_MD5: + md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + default: + case SGN_ALG_DES_MAC: + abort (); + } - g_make_token_header((gss_OID) oid, tmp, &ptr, toktype); + if (code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen)) + return(code); + md5cksum.length = sumlen; + + if (toktype == KG_TOK_SEAL_MSG) { + unsigned char *plain; + unsigned char pad; + + if (!bigend || encrypt) { + if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { + xfree(t); + return(ENOMEM); + } + + if ((code = kg_make_confounder(context, enc, plain))) { + xfree(plain); + xfree(t); + return(code); + } + + memcpy(plain+conflen, text->value, text->length); + + /* XXX 8 is DES cblock size */ + pad = 8-(text->length%8); + + memset(plain+conflen+text->length, pad, pad); + } else { + /* plain is never used in the bigend && !encrypt case */ + plain = NULL; + } + + if (encrypt) { + if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL, + (krb5_pointer) plain, + (krb5_pointer) (ptr+cksum_size+14), + tmsglen))) { + if (plain) + xfree(plain); + xfree(t); + return(code); + } + } else { + if (bigend) + memcpy(ptr+14+cksum_size, text->value, text->length); + else + memcpy(ptr+14+cksum_size, plain, tmsglen); + } + + /* compute the checksum */ + + /* 8 = head of token body as specified by mech spec */ + if (! (data_ptr = + (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) { + if (plain) + xfree(plain); + xfree(t); + return(ENOMEM); + } + (void) memcpy(data_ptr, ptr-2, 8); + if (bigend) + (void) memcpy(data_ptr+8, text->value, text->length); + else + (void) memcpy(data_ptr+8, plain, tmsglen); + plaind.length = 8 + (bigend ? text->length : tmsglen); + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq, + KG_USAGE_SIGN, &plaind, &md5cksum); + xfree(data_ptr); + + if (code) { + if (plain) + xfree(plain); + xfree(t); + return(code); + } - ptr[0] = (ctype >> 24) & 0xff; - ptr[1] = (ctype >> 16) & 0xff; - ptr[2] = (ctype >> 8) & 0xff; - ptr[3] = ctype & 0xff; + if (plain) + xfree(plain); + } else { + /* Sign only. */ + /* compute the checksum */ - ptr += 4; + if (! (data_ptr = (char *) xmalloc(8 + text->length))) { + xfree(t); + return(ENOMEM); + } + (void) memcpy(data_ptr, ptr-2, 8); + (void) memcpy(data_ptr+8, text->value, text->length); + plaind.length = 8 + text->length; + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq, + KG_USAGE_SIGN, &plaind, &md5cksum); + xfree(data_ptr); + if (code) { + xfree(t); + return(code); + } + } - if (toktype == KG2_TOK_WRAP_INTEG) { - memcpy(ptr, plain.data, 7+text->length); - ptr += 7+text->length; - } else { - memcpy(ptr, plain.data, 5); - ptr += 5; + switch(signalg) { + case SGN_ALG_DES_MAC_MD5: + case 3: + + if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL, + (g_OID_equal(oid, gss_mech_krb5_old) ? + seq->contents : NULL), + md5cksum.contents, md5cksum.contents, 16))) { + xfree(md5cksum.contents); + xfree(t); + return code; + } + + cksum.length = cksum_size; + cksum.contents = md5cksum.contents + 16 - cksum.length; + + memcpy(ptr+14, cksum.contents, cksum.length); + break; + + case SGN_ALG_HMAC_SHA1_DES3_KD: + /* + * Using key derivation, the call to krb5_c_make_checksum + * already dealt with encrypting. + */ + if (md5cksum.length != cksum_size) + abort (); + memcpy (ptr+14, md5cksum.contents, md5cksum.length); + break; } - ptr[0] = (cksum.length >> 8) & 0xff; - ptr[1] = cksum.length & 0xff; - ptr += 2; + xfree(md5cksum.contents); + + /* create the seq_num */ - memcpy(ptr, cksum.contents, cksum.length); + if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum, + ptr+14, ptr+6))) { + xfree(t); + return(code); + } /* that's it. return the token */ @@ -247,372 +331,110 @@ make_integ_token_v2(context, subkey, ctype, seqnum, direction, text, token, token->length = tlen; token->value = (void *) t; - code = 0; - -cleanup: - if (plain.data) - free(plain.data); - if (cksum.contents) - krb5_free_checksum_contents(context, &cksum); - if (code) { - if (t) - free(t); - } - - return(code); + return(0); } -static krb5_error_code -make_seal_token_v1 PROTOTYPE((krb5_context context, - krb5_keyblock *enc, - krb5_keyblock *seq, - krb5_int32 *seqnum, - int direction, - gss_buffer_t text, - gss_buffer_t token, - int signalg, - int cksum_size, - int sealalg, - int encrypt, - int toktype, - int bigend, - gss_OID oid)); +/* if signonly is true, ignore conf_req, conf_state, + and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */ -static krb5_error_code -make_seal_token_v1(context, enc, seq, seqnum, direction, text, token, - signalg, cksum_size, sealalg, encrypt, toktype, - bigend, oid) - krb5_context context; - krb5_keyblock *enc; - krb5_keyblock *seq; - krb5_int32 *seqnum; - int direction; - gss_buffer_t text; - gss_buffer_t token; - int signalg; - int cksum_size; - int sealalg; - int encrypt; - int toktype; - int bigend; - gss_OID oid; +OM_uint32 +kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req, + input_message_buffer, conf_state, output_message_buffer, toktype) + krb5_context context; + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + int conf_req_flag; + int qop_req; + gss_buffer_t input_message_buffer; + int *conf_state; + gss_buffer_t output_message_buffer; + int toktype; { - krb5_error_code code; - size_t sumlen; - char *data_ptr; - krb5_data plaind; - krb5_checksum md5cksum; - krb5_checksum cksum; - int conflen=0, tmsglen, tlen; - unsigned char *t, *ptr; - - /* create the token buffer */ - - if (toktype == KG_TOK_SEAL_MSG) { - if (bigend && !encrypt) { - tmsglen = text->length; - } else { - conflen = kg_confounder_size(context, enc); - /* XXX knows that des block size is 8 */ - tmsglen = (conflen+text->length+8)&(~7); - } - } else { - tmsglen = 0; - } - - tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen); - - if ((t = (unsigned char *) xmalloc(tlen)) == NULL) - return(ENOMEM); - - /*** fill in the token */ - - ptr = t; - - g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype); - - /* 0..1 SIGN_ALG */ - - ptr[0] = signalg; - ptr[1] = 0; - - /* 2..3 SEAL_ALG or Filler */ - - if ((toktype == KG_TOK_SEAL_MSG) && encrypt) { - ptr[2] = sealalg; - ptr[3] = 0; - } else { - /* No seal */ - ptr[2] = 0xff; - ptr[3] = 0xff; - } - - /* 4..5 Filler */ - - ptr[4] = 0xff; - ptr[5] = 0xff; - - /* pad the plaintext, encrypt if needed, and stick it in the token */ - - /* initialize the the cksum */ - if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen)) - return(code); - - md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; - md5cksum.length = sumlen; - if (toktype == KG_TOK_SEAL_MSG) { - unsigned char *plain; - unsigned char pad; - - if (!bigend || encrypt) { - if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { - xfree(t); - return(ENOMEM); - } - - if ((code = kg_make_confounder(context, enc, plain))) { - xfree(plain); - xfree(t); - return(code); - } - - memcpy(plain+conflen, text->value, text->length); - - /* XXX 8 is DES cblock size */ - pad = 8-(text->length%8); - - memset(plain+conflen+text->length, pad, pad); - } else { - /* plain is never used in the bigend && !encrypt case */ - plain = NULL; - } + krb5_gss_ctx_id_rec *ctx; + krb5_error_code code; + krb5_timestamp now; - if (encrypt) { - if ((code = kg_encrypt(context, enc, NULL, (krb5_pointer) plain, - (krb5_pointer) (ptr+cksum_size+14), - tmsglen))) { - if (plain) - xfree(plain); - xfree(t); - return(code); - } - } else { - if (bigend) - memcpy(ptr+14+cksum_size, text->value, text->length); - else - memcpy(ptr+14+cksum_size, plain, tmsglen); - } - - /* compute the checksum */ - - /* 8 = head of token body as specified by mech spec */ - if (! (data_ptr = - (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) { - if (plain) - xfree(plain); - xfree(t); - return(ENOMEM); - } - (void) memcpy(data_ptr, ptr-2, 8); - if (bigend) - (void) memcpy(data_ptr+8, text->value, text->length); - else - (void) memcpy(data_ptr+8, plain, tmsglen); - plaind.length = 8 + (bigend ? text->length : tmsglen); - plaind.data = data_ptr; - code = krb5_c_make_checksum(context, md5cksum.checksum_type, - 0, 0, &plaind, &md5cksum); - xfree(data_ptr); - - if (code) { - if (plain) - xfree(plain); - xfree(t); - return(code); - memcpy(ptr+14+cksum_size, plain, tmsglen); - } - - if (plain) - xfree(plain); - } else { - /* compute the checksum */ - - if (! (data_ptr = (char *) xmalloc(8 + text->length))) { - xfree(t); - return(ENOMEM); - } - (void) memcpy(data_ptr, ptr-2, 8); - (void) memcpy(data_ptr+8, text->value, text->length); - plaind.length = 8 + text->length; - plaind.data = data_ptr; - code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0, - &plaind, &md5cksum); - xfree(data_ptr); - if (code) { - xfree(t); - return(code); - } - } - - switch(signalg) { - case 0: - case 3: + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + /* only default qop or matching established cryptosystem is allowed */ + #if 0 - /* XXX this depends on the key being a single-des key */ - - /* DES CBC doesn't use a zero IV like it should in some - krb5 implementations (beta5+). So we just do the - DES encryption the long way, and keep the last block - as the MAC */ - - /* XXX not converted to new api since it's inside an #if 0 */ - - /* initialize the the cksum and allocate the contents buffer */ - cksum.checksum_type = CKSUMTYPE_DESCBC; - cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC); - if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL) - return(ENOMEM); - - /* XXX not converted to new api since it's inside an #if 0 */ - if (code = krb5_calculate_checksum(context, cksum.checksum_type, - md5cksum.contents, 16, - seq->contents, - seq->length, - &cksum)) { - xfree(cksum.contents); - xfree(md5cksum.contents); - xfree(t); - return(code); - } - - memcpy(ptr+14, cksum.contents, 8); - - xfree(cksum.contents); + switch (qop_req & GSS_KRB5_CONF_C_QOP_MASK) { + case GSS_C_QOP_DEFAULT: + break; + default: + unknown_qop: + *minor_status = (OM_uint32) G_UNKNOWN_QOP; + return GSS_S_FAILURE; + case GSS_KRB5_CONF_C_QOP_DES: + if (ctx->sealalg != SEAL_ALG_DES) { + bad_qop: + *minor_status = (OM_uint32) G_BAD_QOP; + return GSS_S_FAILURE; + } + break; + case GSS_KRB5_CONF_C_QOP_DES3: + if (ctx->sealalg != SEAL_ALG_DES3) + goto bad_qop; + break; + } + switch (qop_req & GSS_KRB5_INTEG_C_QOP_MASK) { + case GSS_C_QOP_DEFAULT: + break; + default: + goto unknown_qop; + case GSS_KRB5_INTEG_C_QOP_MD5: + case GSS_KRB5_INTEG_C_QOP_DES_MD5: + case GSS_KRB5_INTEG_C_QOP_DES_MAC: + if (ctx->sealalg != SEAL_ALG_DES) + goto bad_qop; + break; + case GSS_KRB5_INTEG_C_QOP_HMAC_SHA1: + if (ctx->sealalg != SEAL_ALG_DES3KD) + goto bad_qop; + break; + } #else - if ((code = kg_encrypt(context, seq, - (g_OID_equal(oid, gss_mech_krb5_old) ? - seq->contents : NULL), - md5cksum.contents, md5cksum.contents, 16))) { - xfree(md5cksum.contents); - xfree(t); - return code; - } - - cksum.length = cksum_size; - cksum.contents = md5cksum.contents + 16 - cksum.length; - - memcpy(ptr+14, cksum.contents, cksum.length); + if (qop_req != 0) { + *minor_status = (OM_uint32) G_UNKNOWN_QOP; + return GSS_S_FAILURE; + } #endif - break; - } - - xfree(md5cksum.contents); - - /* create the seq_num */ + /* validate the context handle */ + if (! kg_validate_ctx_id(context_handle)) { + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + return(GSS_S_NO_CONTEXT); + } - if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum, - ptr+14, ptr+6))) { - xfree(t); - return(code); - } + ctx = (krb5_gss_ctx_id_rec *) context_handle; - /* that's it. return the token */ + if (! ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } - (*seqnum)++; + if ((code = krb5_timeofday(context, &now))) { + *minor_status = code; + return(GSS_S_FAILURE); + } - token->length = tlen; - token->value = (void *) t; + code = make_seal_token_v1(context, ctx->enc, ctx->seq, + &ctx->seq_send, ctx->initiate, + input_message_buffer, output_message_buffer, + ctx->signalg, ctx->cksum_size, ctx->sealalg, + conf_req_flag, toktype, ctx->big_endian, + ctx->mech_used); - return(0); -} + if (code) { + *minor_status = code; + return(GSS_S_FAILURE); + } -/* if signonly is true, ignore conf_req, conf_state, - and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */ + if (conf_state) + *conf_state = conf_req_flag; -OM_uint32 -kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req, - input_message_buffer, conf_state, output_message_buffer, toktype) - krb5_context context; - OM_uint32 *minor_status; - gss_ctx_id_t context_handle; - int conf_req_flag; - int qop_req; - gss_buffer_t input_message_buffer; - int *conf_state; - gss_buffer_t output_message_buffer; - int toktype; -{ - krb5_gss_ctx_id_rec *ctx; - krb5_error_code code; - krb5_timestamp now; - - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - - /* only default qop is allowed */ - if (qop_req != GSS_C_QOP_DEFAULT) { - *minor_status = (OM_uint32) G_UNKNOWN_QOP; - return(GSS_S_FAILURE); - } - - /* validate the context handle */ - if (! kg_validate_ctx_id(context_handle)) { - *minor_status = (OM_uint32) G_VALIDATE_FAILED; - return(GSS_S_NO_CONTEXT); - } - - ctx = (krb5_gss_ctx_id_rec *) context_handle; - - if (! ctx->established) { - *minor_status = KG_CTX_INCOMPLETE; - return(GSS_S_NO_CONTEXT); - } - - if ((code = krb5_timeofday(context, &now))) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (ctx->gsskrb5_version == 2000) { - if (toktype == KG_TOK_WRAP_MSG) { - if (conf_req_flag) - toktype = KG2_TOK_WRAP_PRIV; - else - toktype = KG2_TOK_WRAP_INTEG; - } else { - toktype = KG2_TOK_MIC; - } - - if (conf_req_flag) { - code = make_priv_token_v2(context, ctx->subkey, &ctx->seq_send, - ctx->initiate, input_message_buffer, - output_message_buffer, ctx->mech_used); - } else { - code = make_integ_token_v2(context, ctx->subkey, ctx->ctypes[0], - &ctx->seq_send, ctx->initiate, - input_message_buffer, - output_message_buffer, toktype, - ctx->mech_used); - } - } else { - code = make_seal_token_v1(context, ctx->enc, ctx->seq, - &ctx->seq_send, ctx->initiate, - input_message_buffer, output_message_buffer, - ctx->signalg, ctx->cksum_size, ctx->sealalg, - conf_req_flag, toktype, ctx->big_endian, - ctx->mech_used); - } - - if (code) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (conf_state) - *conf_state = conf_req_flag; - - *minor_status = 0; - return((ctx->endtime < now)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE); + *minor_status = 0; + return((ctx->endtime < now)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE); } diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c index da5966f..bc35e70 100644 --- a/src/lib/gssapi/krb5/k5unseal.c +++ b/src/lib/gssapi/krb5/k5unseal.c @@ -1,6 +1,6 @@ /* * Copyright 1993 by OpenVision Technologies, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appears in all copies and @@ -10,7 +10,7 @@ * without specific, written prior permission. OpenVision makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. - * + * * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR @@ -22,14 +22,14 @@ /* * 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 @@ -40,7 +40,7 @@ * 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. @@ -51,838 +51,438 @@ #include <memory.h> #endif -/* - * $Id$ - */ +/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX + conf_state is only valid if SEAL. */ -static OM_uint32 -kg2_verify_mic(context, minor_status, ctx, ptr, bodysize, - text, qop_state) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t text; - gss_qop_t *qop_state; +OM_uint32 +kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, + conf_state, qop_state, toktype) + krb5_context context; + OM_uint32 *minor_status; + krb5_gss_ctx_id_rec *ctx; + unsigned char *ptr; + int bodysize; + gss_buffer_t message_buffer; + int *conf_state; + int *qop_state; + int toktype; { - size_t cksumlen; krb5_error_code code; - krb5_data plain; - krb5_cksumtype tctype; - krb5_ui_4 tseqnum; - int tdirection; + int tmsglen; + int conflen = 0; + int signalg; + int sealalg; + gss_buffer_desc token; krb5_checksum cksum; - krb5_boolean ckvalid; + krb5_checksum md5cksum; + krb5_data plaind; + char *data_ptr; krb5_timestamp now; + unsigned char *plain; + int cksum_len = 0; + int plainlen; + int direction; + krb5_int32 seqnum; OM_uint32 retval; + size_t sumlen; - plain.data = 0; - cksum.contents = 0; - - /* verify the header */ - - if (bodysize < 11) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); + if (toktype == KG_TOK_SEAL_MSG) { + message_buffer->length = 0; + message_buffer->value = NULL; } - /* allocate the checksum buffer */ - - plain.length = 7+text->length; + /* get the sign and seal algorithms */ - if ((plain.data = (char *) malloc(plain.length)) == NULL) { - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } + signalg = ptr[0] + (ptr[1]<<8); + sealalg = ptr[2] + (ptr[3]<<8); - /* suck out the body parts from the token */ + /* Sanity checks */ - tctype = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) | - (ptr[2]<<8) | ptr[3]); - ptr += 4; - - memcpy(plain.data, ptr, 5); - tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]); - ptr += 4; - tdirection = ptr[0]; - ptr += 1; - - cksum.length = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 11; - - if (cksum.length != bodysize) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); + if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; } - cksum.contents = ptr; - cksum.checksum_type = tctype; + if ((toktype != KG_TOK_SEAL_MSG) && + (sealalg != 0xffff)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } - /* finish assembling the checksum buffer and compute the checksum */ + /* in the current spec, there is only one valid seal algorithm per + key type, so a simple comparison is ok */ - plain.data[5] = (text->length >> 8) & 0xff; - plain.data[6] = text->length & 0xff; + if ((toktype == KG_TOK_SEAL_MSG) && + !((sealalg == 0xffff) || + (sealalg == ctx->sealalg))) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } - memcpy(plain.data+7, text->value, text->length); + /* there are several mappings of seal algorithms to sign algorithms, + but few enough that we can try them all. */ - if (code = krb5_c_verify_checksum(context, ctx->subkey, - KRB5_KEYUSAGE_GSS_TOK_MIC, - &plain, &cksum, &ckvalid)) { - free(plain.data); - *minor_status = code; - return(GSS_S_FAILURE); + if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || + (ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) || + (ctx->sealalg == SEAL_ALG_DES3KD && + signalg != SGN_ALG_HMAC_SHA1_DES3_KD)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; } - if (!ckvalid) { - free(plain.data); + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + cksum_len = 8; + break; + case SGN_ALG_3: + cksum_len = 16; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + cksum_len = 20; + break; + default: *minor_status = 0; - return(GSS_S_BAD_SIG); + return GSS_S_DEFECTIVE_TOKEN; } - /* check context expiry */ + if (toktype == KG_TOK_SEAL_MSG) + tmsglen = bodysize-(14+cksum_len); - if ((code = krb5_timeofday(context, &now))) { - free(plain.data); - *minor_status = code; - return(GSS_S_FAILURE); - } + /* get the token parameters */ - if (now > ctx->endtime) { - free(plain.data); - *minor_status = 0; - return(GSS_S_CONTEXT_EXPIRED); - } + /* decode the message, if SEAL */ - /* do sequencing checks */ + if (toktype == KG_TOK_SEAL_MSG) { + if (sealalg != 0xffff) { + if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } - if ((ctx->initiate && tdirection != 0xff) || - (!ctx->initiate && tdirection != 0)) { - free(plain.data); - *minor_status = G_BAD_DIRECTION; - return(GSS_S_BAD_SIG); - } + if ((code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL, + ptr+14+cksum_len, plain, tmsglen))) { + xfree(plain); + *minor_status = code; + return(GSS_S_FAILURE); + } + } else { + plain = ptr+14+cksum_len; + } - retval = g_order_check(&(ctx->seqstate), tseqnum); + plainlen = tmsglen; - free(plain.data); + if ((sealalg == 0xffff) && ctx->big_endian) { + token.length = tmsglen; + } else { + conflen = kg_confounder_size(context, ctx->enc); + token.length = tmsglen - conflen - plain[tmsglen-1]; + } - if (retval) { - *minor_status = 0; - return(retval); - } + if (token.length) { + if ((token.value = (void *) xmalloc(token.length)) == NULL) { + if (sealalg != 0xffff) + xfree(plain); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + memcpy(token.value, plain+conflen, token.length); + } + } else if (toktype == KG_TOK_SIGN_MSG) { + token = *message_buffer; + plain = token.value; + plainlen = token.length; + } else { + token.length = 0; + token.value = NULL; + plain = token.value; + plainlen = token.length; + } - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; + /* compute the checksum of the message */ + + /* initialize the the cksum */ + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_MD2_5: + case SGN_ALG_HMAC_MD5: + case SGN_ALG_DES_MAC: + case SGN_ALG_3: + md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + default: + abort (); + } - *minor_status = 0; - return(GSS_S_COMPLETE); -} + if (code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen)) + return(code); + md5cksum.length = sumlen; -static OM_uint32 -kg2_unwrap_integ(context, minor_status, ctx, ptr, bodysize, output, qop_state) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t output; - gss_qop_t *qop_state; -{ - krb5_error_code code; - OM_uint32 retval; - krb5_ui_4 tseqnum; - int tdirection; - int tmsglen; - unsigned char *tmsg; - krb5_data plain; - krb5_checksum tcksum; - krb5_boolean ckvalid; - krb5_timestamp now; + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + case SGN_ALG_3: + /* compute the checksum of the message */ - output->length = 0; - output->value = NULL; + /* 8 = bytes of token body to be checksummed according to spec */ - /* read the body parts out of the message */ + if (! (data_ptr = (void *) + xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { + if (sealalg != 0xffff) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } - if (bodysize < 11) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } + (void) memcpy(data_ptr, ptr-2, 8); + + if (ctx->big_endian) + (void) memcpy(data_ptr+8, token.value, token.length); + else + (void) memcpy(data_ptr+8, plain, plainlen); - tcksum.checksum_type = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) | - (ptr[2]<<8) | ptr[3]); - ptr += 4; + plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, + ctx->seq, KG_USAGE_SIGN, + &plaind, &md5cksum); + xfree(data_ptr); - plain.data = ptr; + if (code) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return(GSS_S_FAILURE); + } - tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]); - ptr += 4; - tdirection = ptr[0]; - ptr += 1; + if ((code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL, + (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? + ctx->seq->contents : NULL), + md5cksum.contents, md5cksum.contents, 16))) { + xfree(md5cksum.contents); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return GSS_S_FAILURE; + } - tmsglen = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 11; + if (signalg == 0) + cksum.length = 8; + else + cksum.length = 16; + cksum.contents = md5cksum.contents + 16 - cksum.length; - if (bodysize < tmsglen) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } + code = memcmp(cksum.contents, ptr+14, cksum.length); + break; - tmsg = ptr; - ptr += tmsglen; - bodysize -= tmsglen; + case SGN_ALG_MD2_5: + if (!ctx->seed_init && + (code = kg_make_seed(context, ctx->subkey, ctx->seed))) { + xfree(md5cksum.contents); + if (sealalg != 0xffff) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return GSS_S_FAILURE; + } - plain.length = ((char*)ptr) - ((char *)plain.data); + if (! (data_ptr = (void *) + xmalloc(sizeof(ctx->seed) + 8 + + (ctx->big_endian ? token.length : plainlen)))) { + xfree(md5cksum.contents); + if (sealalg == 0) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + (void) memcpy(data_ptr, ptr-2, 8); + (void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed)); + if (ctx->big_endian) + (void) memcpy(data_ptr+8+sizeof(ctx->seed), + token.value, token.length); + else + (void) memcpy(data_ptr+8+sizeof(ctx->seed), + plain, plainlen); + plaind.length = 8 + sizeof(ctx->seed) + + (ctx->big_endian ? token.length : plainlen); + plaind.data = data_ptr; + xfree(md5cksum.contents); + code = krb5_c_make_checksum(context, md5cksum.checksum_type, + ctx->seq, KG_USAGE_SIGN, + &plaind, &md5cksum); + xfree(data_ptr); + + if (code) { + if (sealalg == 0) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return(GSS_S_FAILURE); + } - tcksum.length = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 2; + code = memcmp(md5cksum.contents, ptr+14, 8); + /* Falls through to defective-token?? */ - if (bodysize != tcksum.length) { - *minor_status = G_TOK_TRUNC; + default: + *minor_status = 0; return(GSS_S_DEFECTIVE_TOKEN); - } - tcksum.contents = ptr; + case SGN_ALG_HMAC_SHA1_DES3_KD: + /* compute the checksum of the message */ - /* verify the MIC */ + /* 8 = bytes of token body to be checksummed according to spec */ - if (code = krb5_c_verify_checksum(context, ctx->subkey, - KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG, - &plain, &tcksum, &ckvalid)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (!ckvalid) { - *minor_status = 0; - return(GSS_S_BAD_SIG); - } + if (! (data_ptr = (void *) + xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { + if (sealalg != 0xffff) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } - /* check context expiry */ - - if ((code = krb5_timeofday(context, &now))) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (now > ctx->endtime) { - *minor_status = 0; - return(GSS_S_CONTEXT_EXPIRED); - } - - /* do sequencing checks */ - - if ((ctx->initiate && tdirection != 0xff) || - (!ctx->initiate && tdirection != 0)) { - *minor_status = G_BAD_DIRECTION; - return(GSS_S_BAD_SIG); - } - - if (retval = g_order_check(&(ctx->seqstate), tseqnum)) { - *minor_status = 0; - return(retval); - } - - if (tmsglen) { - if ((output->value = (void *) malloc(tmsglen)) == NULL) { - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - memcpy(output->value, tmsg, tmsglen); - output->length = tmsglen; - } - - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; - - *minor_status = 0; - return(GSS_S_COMPLETE); -} + (void) memcpy(data_ptr, ptr-2, 8); -static OM_uint32 -kg2_unwrap_priv(context, minor_status, ctx, ptr, bodysize, output, qop_state) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t output; - gss_qop_t *qop_state; -{ - krb5_error_code code; - OM_uint32 retval; - krb5_enc_data cipher; - krb5_data plain; - krb5_ui_4 tseqnum; - int tdirection; - int tmsglen; - unsigned char *tmsg; - krb5_timestamp now; + if (ctx->big_endian) + (void) memcpy(data_ptr+8, token.value, token.length); + else + (void) memcpy(data_ptr+8, plain, plainlen); - output->length = 0; - output->value = NULL; + plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); + plaind.data = data_ptr; + code = krb5_c_make_checksum(context, md5cksum.checksum_type, + ctx->seq, KG_USAGE_SIGN, + &plaind, &md5cksum); + xfree(data_ptr); - /* read the body parts out of the message */ + if (code) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; + return(GSS_S_FAILURE); + } - if (bodysize < 2) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); + code = memcmp(md5cksum.contents, ptr+14, md5cksum.length); + break; } - cipher.ciphertext.length = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 2; - - if (bodysize != cipher.ciphertext.length) { - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } + xfree(md5cksum.contents); + if (sealalg != 0xffff) + xfree(plain); - cipher.ciphertext.data = ptr; - cipher.enctype = ENCTYPE_UNKNOWN; + /* compare the computed checksum against the transmitted checksum */ - plain.length = cipher.ciphertext.length; - if ((plain.data = (char *) malloc(plain.length)) == NULL) { + if (code) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); *minor_status = 0; - return(GSS_S_FAILURE); - } - - /* decrypt (and implicitly verify) the encrypted data */ - - if (code = krb5_c_decrypt(context, ctx->subkey, - KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV, - 0, &cipher, &plain)) { - free(plain.data); - *minor_status = code; - return(GSS_S_FAILURE); + return(GSS_S_BAD_SIG); } - /* parse out the encrypted fields */ - ptr = plain.data; - bodysize = plain.length; + /* it got through unscathed. Make sure the context is unexpired */ - if (bodysize < 7) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } - - tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]); - ptr += 4; - tdirection = ptr[0]; - ptr += 1; + if (toktype == KG_TOK_SEAL_MSG) + *message_buffer = token; - tmsglen = (ptr[0]<<8) | ptr[1]; - ptr += 2; - bodysize -= 7; + if (conf_state) + *conf_state = (sealalg != 0xffff); - /* check context expiry */ + if (qop_state) + *qop_state = GSS_C_QOP_DEFAULT; if ((code = krb5_timeofday(context, &now))) { - free(plain.data); *minor_status = code; return(GSS_S_FAILURE); } if (now > ctx->endtime) { - free(plain.data); *minor_status = 0; return(GSS_S_CONTEXT_EXPIRED); } /* do sequencing checks */ - if ((ctx->initiate && tdirection != 0xff) || - (!ctx->initiate && tdirection != 0)) { - free(plain.data); - *minor_status = G_BAD_DIRECTION; + if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction, + &seqnum))) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = code; return(GSS_S_BAD_SIG); } - if (retval = g_order_check(&(ctx->seqstate), tseqnum)) { - free(plain.data); - *minor_status = 0; - return(retval); - } - - /* now copy out the data. can't do a strict equality check here, - since the output could be padded. */ - - if (bodysize < tmsglen) { - free(plain.data); - *minor_status = G_TOK_TRUNC; - return(GSS_S_DEFECTIVE_TOKEN); - } - - tmsg = ptr; - - if (tmsglen) { - if ((output->value = (void *) malloc(tmsglen)) == NULL) { - free(plain.data); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - memcpy(output->value, tmsg, tmsglen); - output->length = tmsglen; + if ((ctx->initiate && direction != 0xff) || + (!ctx->initiate && direction != 0)) { + if (toktype == KG_TOK_SEAL_MSG) + xfree(token.value); + *minor_status = G_BAD_DIRECTION; + return(GSS_S_BAD_SIG); } - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; + retval = g_order_check(&(ctx->seqstate), seqnum); - free(plain.data); + /* success or ordering violation */ *minor_status = 0; - return(GSS_S_COMPLETE); + return(retval); } /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX conf_state is only valid if SEAL. */ OM_uint32 -kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, - conf_state, qop_state, toktype) - krb5_context context; - OM_uint32 *minor_status; - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - gss_buffer_t message_buffer; - int *conf_state; - int *qop_state; - int toktype; +kg_unseal(context, minor_status, context_handle, input_token_buffer, + message_buffer, conf_state, qop_state, toktype) + krb5_context context; + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_buffer_t input_token_buffer; + gss_buffer_t message_buffer; + int *conf_state; + int *qop_state; + int toktype; { - krb5_error_code code; - int tmsglen; - int conflen = 0; - int signalg; - int sealalg; - gss_buffer_desc token; - krb5_checksum cksum; - krb5_checksum desmac; - krb5_checksum md5cksum; - krb5_data plaind; - char *data_ptr; - krb5_timestamp now; - unsigned char *plain; - int cksum_len = 0; - int plainlen; - int err; - int direction; - krb5_int32 seqnum; - OM_uint32 retval; - size_t sumlen; - - if (toktype == KG_TOK_SEAL_MSG) { - message_buffer->length = 0; - message_buffer->value = NULL; - } - - /* get the sign and seal algorithms */ - - signalg = ptr[0] + (ptr[1]<<8); - sealalg = ptr[2] + (ptr[3]<<8); - - /* Sanity checks */ - - if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - if ((toktype != KG_TOK_SEAL_MSG) && - (sealalg != 0xffff)) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - /* in the current spec, there is only one valid seal algorithm per - key type, so a simple comparison is ok */ - - if ((toktype == KG_TOK_SEAL_MSG) && - !((sealalg == 0xffff) || - (sealalg == ctx->sealalg))) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - /* there are several mappings of seal algorithms to sign algorithms, - but few enough that we can try them all. */ - - if (((ctx->sealalg == 0) && - (signalg > 1)) || - ((ctx->sealalg == 1) && - (signalg != 3))) { - *minor_status = 0; - return GSS_S_DEFECTIVE_TOKEN; - } - - switch (signalg) { - case 0: - case 1: - cksum_len = 8; - break; - case 3: - cksum_len = 16; - break; - } - - if (toktype == KG_TOK_SEAL_MSG) - tmsglen = bodysize-(14+cksum_len); - - /* get the token parameters */ - - /* decode the message, if SEAL */ - - if (toktype == KG_TOK_SEAL_MSG) { - if (sealalg != 0xffff) { - if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } + krb5_gss_ctx_id_rec *ctx; + unsigned char *ptr; + int bodysize; + int err; + + /* validate the context handle */ + if (! kg_validate_ctx_id(context_handle)) { + *minor_status = (OM_uint32) G_VALIDATE_FAILED; + return(GSS_S_NO_CONTEXT); + } - if ((code = kg_decrypt(context, ctx->enc, NULL, - ptr+14+cksum_len, plain, tmsglen))) { - xfree(plain); - *minor_status = code; - return(GSS_S_FAILURE); - } - } else { - plain = ptr+14+cksum_len; - } - - plainlen = tmsglen; - - if ((sealalg == 0xffff) && ctx->big_endian) { - token.length = tmsglen; - } else { - conflen = kg_confounder_size(context, ctx->enc); - token.length = tmsglen - conflen - plain[tmsglen-1]; - } - - if (token.length) { - if ((token.value = (void *) xmalloc(token.length)) == NULL) { - if (sealalg != 0xffff) - xfree(plain); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - memcpy(token.value, plain+conflen, token.length); - } - } else if (toktype == KG_TOK_SIGN_MSG) { - token = *message_buffer; - plain = token.value; - plainlen = token.length; - } else { - token.length = 0; - token.value = NULL; - plain = token.value; - plainlen = token.length; - } - - /* compute the checksum of the message */ - - /* initialize the the cksum */ - if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen)) - return(code); - - md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; - md5cksum.length = sumlen; - - switch (signalg) { - case 0: - case 3: - /* compute the checksum of the message */ - - /* 8 = bytes of token body to be checksummed according to spec */ - - if (! (data_ptr = (void *) - xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { - if (sealalg != 0xffff) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - - (void) memcpy(data_ptr, ptr-2, 8); - - if (ctx->big_endian) - (void) memcpy(data_ptr+8, token.value, token.length); - else - (void) memcpy(data_ptr+8, plain, plainlen); - - plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); - plaind.data = data_ptr; - code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0, - &plaind, &md5cksum); - xfree(data_ptr); - - if (code) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_FAILURE); - } - -#if 0 - /* XXX this depends on the key being a single-des key, but that's - all that kerberos supports right now */ - - /* initialize the the cksum and allocate the contents buffer */ - cksum.checksum_type = CKSUMTYPE_DESCBC; - cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC); - if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL) { - xfree(md5cksum.contents); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - - /* XXX not converted to new api since it's inside an #if 0 */ - if (code = krb5_calculate_checksum(context, cksum.checksum_type, - md5cksum.contents, 16, - ctx->seq.key->contents, - ctx->seq.key->length, - &cksum)) { - xfree(cksum.contents); - xfree(md5cksum.contents); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_FAILURE); - } - - code = memcmp(cksum.contents, ptr+14, cksum.length); - - xfree(cksum.contents); -#else - if ((code = kg_encrypt(context, ctx->seq, - (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? - ctx->seq->contents : NULL), - md5cksum.contents, md5cksum.contents, 16))) { - xfree(md5cksum.contents); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return GSS_S_FAILURE; - } + ctx = (krb5_gss_ctx_id_rec *) context_handle; - if (signalg == 0) - cksum.length = 8; - else - cksum.length = 16; - cksum.contents = md5cksum.contents + 16 - cksum.length; + if (! ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } - code = memcmp(cksum.contents, ptr+14, cksum.length); -#endif - break; - - case 1: - if (!ctx->seed_init && - (code = kg_make_seed(context, ctx->subkey, ctx->seed))) { - xfree(md5cksum.contents); - if (sealalg != 0xffff) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return GSS_S_FAILURE; - } - - if (! (data_ptr = (void *) - xmalloc(sizeof(ctx->seed) + 8 + - (ctx->big_endian ? token.length : plainlen)))) { - xfree(md5cksum.contents); - if (sealalg == 0) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = ENOMEM; - return(GSS_S_FAILURE); - } - (void) memcpy(data_ptr, ptr-2, 8); - (void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed)); - if (ctx->big_endian) - (void) memcpy(data_ptr+8+sizeof(ctx->seed), - token.value, token.length); - else - (void) memcpy(data_ptr+8+sizeof(ctx->seed), - plain, plainlen); - plaind.length = 8 + sizeof(ctx->seed) + - (ctx->big_endian ? token.length : plainlen); - plaind.data = data_ptr; - xfree(md5cksum.contents); - code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0, - &plaind, &md5cksum); - xfree(data_ptr); - - if (code) { - if (sealalg == 0) - xfree(plain); - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_FAILURE); - } - - code = memcmp(md5cksum.contents, ptr+14, 8); - - default: - *minor_status = 0; - return(GSS_S_DEFECTIVE_TOKEN); - } - - xfree(md5cksum.contents); - if (sealalg != 0xffff) - xfree(plain); - - /* compare the computed checksum against the transmitted checksum */ - - if (code) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = 0; - return(GSS_S_BAD_SIG); - } - - - /* it got through unscathed. Make sure the context is unexpired */ - - if (toktype == KG_TOK_SEAL_MSG) - *message_buffer = token; - - if (conf_state) - *conf_state = (sealalg != 0xffff); - - if (qop_state) - *qop_state = GSS_C_QOP_DEFAULT; - - if ((code = krb5_timeofday(context, &now))) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - if (now > ctx->endtime) { - *minor_status = 0; - return(GSS_S_CONTEXT_EXPIRED); - } - - /* do sequencing checks */ - - if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction, - &seqnum))) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = code; - return(GSS_S_BAD_SIG); - } - - if ((ctx->initiate && direction != 0xff) || - (!ctx->initiate && direction != 0)) { - if (toktype == KG_TOK_SEAL_MSG) - xfree(token.value); - *minor_status = G_BAD_DIRECTION; - return(GSS_S_BAD_SIG); - } - - retval = g_order_check(&(ctx->seqstate), seqnum); - - /* success or ordering violation */ - - *minor_status = 0; - return(retval); -} + /* parse the token, leave the data in message_buffer, setting conf_state */ -/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX - conf_state is only valid if SEAL. */ + /* verify the header */ -OM_uint32 -kg_unseal(context, minor_status, context_handle, input_token_buffer, - message_buffer, conf_state, qop_state, toktype) - krb5_context context; - OM_uint32 *minor_status; - gss_ctx_id_t context_handle; - gss_buffer_t input_token_buffer; - gss_buffer_t message_buffer; - int *conf_state; - int *qop_state; - int toktype; -{ - krb5_gss_ctx_id_rec *ctx; - unsigned char *ptr; - int bodysize; - int err; - OM_uint32 retval; - - /* validate the context handle */ - if (! kg_validate_ctx_id(context_handle)) { - *minor_status = (OM_uint32) G_VALIDATE_FAILED; - return(GSS_S_NO_CONTEXT); - } - - ctx = (krb5_gss_ctx_id_rec *) context_handle; - - if (! ctx->established) { - *minor_status = KG_CTX_INCOMPLETE; - return(GSS_S_NO_CONTEXT); - } - - /* parse the token, leave the data in message_buffer, setting conf_state */ - - /* verify the header */ - - ptr = (unsigned char *) input_token_buffer->value; - - if (ctx->gsskrb5_version == 2000) { - if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, KG2_TOK_MIC, - input_token_buffer->length))) { - return(kg2_verify_mic(context, minor_status, ctx, ptr, bodysize, - message_buffer, qop_state)); - } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, - KG2_TOK_WRAP_INTEG, - input_token_buffer->length))) { - if (GSS_ERROR(retval = kg2_unwrap_integ(context, minor_status, - ctx, ptr, bodysize, - message_buffer, qop_state))) - return(retval); - - if (conf_state) - *conf_state = 0; - return(GSS_S_COMPLETE); - } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, - KG2_TOK_WRAP_PRIV, - input_token_buffer->length))) { - if (GSS_ERROR(retval = kg2_unwrap_priv(context, minor_status, - ctx, ptr, bodysize, - message_buffer, qop_state))) - return(retval); - - if (conf_state) - *conf_state = 1; - return(GSS_S_COMPLETE); - } - } else { - if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, - &bodysize, &ptr, toktype, - input_token_buffer->length))) { - return(kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, - message_buffer, conf_state, qop_state, - toktype)); - } - } - - *minor_status = err; - return(GSS_S_DEFECTIVE_TOKEN); + ptr = (unsigned char *) input_token_buffer->value; + + if (!(err = g_verify_token_header((gss_OID) ctx->mech_used, + &bodysize, &ptr, toktype, + input_token_buffer->length))) { + return(kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, + message_buffer, conf_state, qop_state, + toktype)); + } + + *minor_status = err; + return(GSS_S_DEFECTIVE_TOKEN); } diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c index 2a6231e..1989a7d 100644 --- a/src/lib/gssapi/krb5/ser_sctx.c +++ b/src/lib/gssapi/krb5/ser_sctx.c @@ -233,7 +233,6 @@ kg_ctx_size(kcontext, arg, sizep) * krb5_int32 for seq_recv. * krb5_int32 for established. * krb5_int32 for big_endian. - * krb5_int32 for gsskrb5_version. * krb5_int32 for nctypes. * krb5_int32 for trailer. */ @@ -349,8 +348,6 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain) &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian, &bp, &remain); - (void) krb5_ser_pack_int32((krb5_int32) ctx->gsskrb5_version, - &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) ctx->nctypes, &bp, &remain); @@ -477,8 +474,6 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain) (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->big_endian = (int) ibuf; (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); - ctx->gsskrb5_version = (int) ibuf; - (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); ctx->nctypes = (int) ibuf; if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp, diff --git a/src/lib/gssapi/krb5/util_cksum.c b/src/lib/gssapi/krb5/util_cksum.c index 61fbc66..77feade 100644 --- a/src/lib/gssapi/krb5/util_cksum.c +++ b/src/lib/gssapi/krb5/util_cksum.c @@ -20,15 +20,12 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* - * $Id$ - */ - #include "gssapiP_krb5.h" #ifdef HAVE_MEMORY_H #include <memory.h> #endif +/* Checksumming the channel bindings always uses plain MD5. */ krb5_error_code kg_checksum_channel_bindings(context, cb, cksum, bigend) krb5_context context; diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c index 8792e5f..3e40236 100644 --- a/src/lib/gssapi/krb5/util_crypt.c +++ b/src/lib/gssapi/krb5/util_crypt.c @@ -52,12 +52,6 @@ #include <memory.h> #endif -/* - * $Id$ - */ - -static unsigned char zeros[8] = {0,0,0,0,0,0,0,0}; - int kg_confounder_size(context, key) krb5_context context; @@ -107,9 +101,10 @@ kg_encrypt_size(context, key, n) } krb5_error_code -kg_encrypt(context, key, iv, in, out, length) +kg_encrypt(context, key, usage, iv, in, out, length) krb5_context context; krb5_keyblock *key; + int usage; krb5_pointer iv; krb5_pointer in; krb5_pointer out; @@ -125,7 +120,10 @@ kg_encrypt(context, key, iv, in, out, length) return(code); ivd.length = blocksize; - ivd.data = iv; + ivd.data = malloc(ivd.length); + if (ivd.data == NULL) + return ENOMEM; + memcpy(ivd.data, iv, ivd.length); pivd = &ivd; } else { pivd = NULL; @@ -137,18 +135,19 @@ kg_encrypt(context, key, iv, in, out, length) outputd.ciphertext.length = length; outputd.ciphertext.data = out; - return(krb5_c_encrypt(context, key, - /* XXX this routine is only used for the old - bare-des stuff which doesn't use the - key usage */ 0, pivd, &inputd, &outputd)); + code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd); + if (pivd != NULL) + krb5_free_data_contents(context, pivd); + return code; } /* length is the length of the cleartext. */ krb5_error_code -kg_decrypt(context, key, iv, in, out, length) +kg_decrypt(context, key, usage, iv, in, out, length) krb5_context context; krb5_keyblock *key; + int usage; krb5_pointer iv; krb5_pointer in; krb5_pointer out; @@ -164,7 +163,10 @@ kg_decrypt(context, key, iv, in, out, length) return(code); ivd.length = blocksize; - ivd.data = iv; + ivd.data = malloc(ivd.length); + if (ivd.data == NULL) + return ENOMEM; + memcpy(ivd.data, iv, ivd.length); pivd = &ivd; } else { pivd = NULL; @@ -177,8 +179,8 @@ kg_decrypt(context, key, iv, in, out, length) outputd.length = length; outputd.data = out; - return(krb5_c_decrypt(context, key, - /* XXX this routine is only used for the old - bare-des stuff which doesn't use the - key usage */ 0, pivd, &inputd, &outputd)); + code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd); + if (pivd != NULL) + krb5_free_data_contents(context, pivd); + return code; } diff --git a/src/lib/gssapi/krb5/util_seed.c b/src/lib/gssapi/krb5/util_seed.c index 24ae7f3..3f6eb47 100644 --- a/src/lib/gssapi/krb5/util_seed.c +++ b/src/lib/gssapi/krb5/util_seed.c @@ -25,10 +25,6 @@ #include <memory.h> #endif -/* - * $Id$ - */ - static unsigned char zeros[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; krb5_error_code @@ -49,7 +45,7 @@ kg_make_seed(context, key, seed) for (i=0; i<tmpkey->length; i++) tmpkey->contents[i] = key->contents[key->length - 1 - i]; - code = kg_encrypt(context, tmpkey, NULL, zeros, seed, 16); + code = kg_encrypt(context, tmpkey, KG_USAGE_SEAL, NULL, zeros, seed, 16); krb5_free_keyblock(context, tmpkey); diff --git a/src/lib/gssapi/krb5/util_seqnum.c b/src/lib/gssapi/krb5/util_seqnum.c index e14b2f3..b8f2b38 100644 --- a/src/lib/gssapi/krb5/util_seqnum.c +++ b/src/lib/gssapi/krb5/util_seqnum.c @@ -47,7 +47,7 @@ kg_make_seq_num(context, key, direction, seqnum, cksum, buf) plain[6] = direction; plain[7] = direction; - return(kg_encrypt(context, key, cksum, plain, buf, 8)); + return(kg_encrypt(context, key, KG_USAGE_SEQ, cksum, plain, buf, 8)); } krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum) @@ -61,7 +61,7 @@ krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum) krb5_error_code code; unsigned char plain[8]; - if (code = kg_decrypt(context, key, cksum, buf, plain, 8)) + if (code = kg_decrypt(context, key, KG_USAGE_SEQ, cksum, buf, plain, 8)) return(code); if ((plain[4] != plain[5]) || diff --git a/src/lib/gssapi/krb5/wrap_size_limit.c b/src/lib/gssapi/krb5/wrap_size_limit.c index d71a3f8..a3c05df4 100644 --- a/src/lib/gssapi/krb5/wrap_size_limit.c +++ b/src/lib/gssapi/krb5/wrap_size_limit.c @@ -1,4 +1,28 @@ /* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* * Copyright 1993 by OpenVision Technologies, Inc. * * Permission to use, copy, modify, distribute, and sell this software @@ -48,10 +72,6 @@ #include "gssapiP_krb5.h" -/* - * $Id$ - */ - /* V2 interface */ OM_uint32 krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, @@ -66,6 +86,9 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, krb5_context context; krb5_gss_ctx_id_rec *ctx; krb5_error_code code; + OM_uint32 data_size, conflen; + OM_uint32 ohlen; + int overhead; if (GSS_ERROR(kg_get_context(minor_status, &context))) return(GSS_S_FAILURE); @@ -88,91 +111,23 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, return(GSS_S_NO_CONTEXT); } - if (ctx->gsskrb5_version == 2000) { - if (conf_req_flag) { - /* this is pretty gross. take the max output, and call - krb5_c_encrypt_length to see how much overhead is added - on. subtract that much, and see if it fits in the - requested space. If not, start subtracting 1 until it - does. This doesn't necessarily give us the optimal - packing, but I think that's ok (I could start adding 1 - until I went over, but that seems like it's not worth - the effort). This is probably O(blocksize), but that's - never going to be large. */ - - OM_uint32 headerlen, plainlen; - size_t enclen; - - headerlen = g_token_size((gss_OID) ctx->mech_used, 2); - plainlen = req_output_size - headerlen; - - if (code = krb5_c_encrypt_length(context, ctx->enc->enctype, - plainlen, &enclen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - plainlen -= plainlen - (enclen - plainlen); - - if (code = krb5_c_encrypt_length(context, ctx->enc->enctype, - plainlen, &enclen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - while (headerlen + enclen > req_output_size) { - plainlen--; - - if (code = krb5_c_encrypt_length(context, ctx->enc->enctype, - plainlen, &enclen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - } - - /* subtract off the fixed size inside the encrypted part */ - - plainlen -= 7; - - *max_input_size = plainlen; - } else { - size_t cksumlen; - OM_uint32 headerlen; - - if (code = krb5_c_checksum_length(context, ctx->ctypes[0], - &cksumlen)) { - *minor_status = code; - return(GSS_S_FAILURE); - } - - headerlen = g_token_size((gss_OID) ctx->mech_used, 13 + cksumlen); - - *max_input_size = req_output_size - headerlen; - } - } else { - OM_uint32 data_size, conflen; - OM_uint32 ohlen; - int overhead; - - /* Calculate the token size and subtract that from the output size */ - overhead = 7 + ctx->mech_used->length; - data_size = req_output_size; - conflen = kg_confounder_size(context, ctx->enc); - data_size = (conflen + data_size + 8) & (~(OM_uint32)7); - ohlen = g_token_size((gss_OID) ctx->mech_used, - (unsigned int) (data_size + ctx->cksum_size + 14)) - - req_output_size; - - if (ohlen+overhead < req_output_size) - /* - * Cannot have trailer length that will cause us to pad over - * our length - */ - *max_input_size = (req_output_size - ohlen - overhead) - & (~(OM_uint32)7); - else - *max_input_size = 0; - } + /* Calculate the token size and subtract that from the output size */ + overhead = 7 + ctx->mech_used->length; + data_size = req_output_size; + conflen = kg_confounder_size(context, ctx->enc); + data_size = (conflen + data_size + 8) & (~(OM_uint32)7); + ohlen = g_token_size((gss_OID) ctx->mech_used, + (unsigned int) (data_size + ctx->cksum_size + 14)) + - req_output_size; + + if (ohlen+overhead < req_output_size) + /* + * Cannot have trailer length that will cause us to pad over our + * length. + */ + *max_input_size = (req_output_size - ohlen - overhead) & (~(OM_uint32)7); + else + *max_input_size = 0; *minor_status = 0; return(GSS_S_COMPLETE); diff --git a/src/lib/kadm5/ChangeLog b/src/lib/kadm5/ChangeLog index b8dedb2..59ea4ae 100644 --- a/src/lib/kadm5/ChangeLog +++ b/src/lib/kadm5/ChangeLog @@ -1,3 +1,23 @@ +2000-06-23 Ken Raeburn <raeburn@mit.edu> + + * alt_prof.c (kadm5_get_config_params): Include des3 in supported + enctypes by default. + + * ovsec_glue.c (ovsec_kadm_chpass_principal_util): Use 1024 for + hard-coded length, to match existing callers. + +2000-06-23 Nalin Dahyabhai <nalin@redhat.com> + + * admin.h: Add a length parameter to kadm5_chpass_principal_util(). + * admin_internal.h: Add a length parameter to + _kadm5_chpass_principal_util(). + * chpass_util.c (_kadm5_chpass_principal_util): Add a length parameter, + and use it to avoid overflowing "msg_ret". + * ovsec_glue.c (ovsec_kadm_chpass_principal_util): Adjust for new + parameter in kadm5_chpass_principal_util(). + + * logger.c (klog_com_err_proc): Don't overflow buffer "outbuf". + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * configure.in, chpass_util.c, server_internal.h: Check for diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h index 159c7fb..2164e1e 100644 --- a/src/lib/kadm5/admin.h +++ b/src/lib/kadm5/admin.h @@ -411,7 +411,8 @@ kadm5_ret_t kadm5_chpass_principal_util(void *server_handle, krb5_principal princ, char *new_pw, char **ret_pw, - char *msg_ret); + char *msg_ret, + int msg_len); kadm5_ret_t kadm5_free_principal_ent(void *server_handle, kadm5_principal_ent_t diff --git a/src/lib/kadm5/admin_internal.h b/src/lib/kadm5/admin_internal.h index d2d1533..97cb5e5 100644 --- a/src/lib/kadm5/admin_internal.h +++ b/src/lib/kadm5/admin_internal.h @@ -62,7 +62,8 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, krb5_principal princ, char *new_pw, char **ret_pw, - char *msg_ret); + char *msg_ret, + int msg_len); /* this is needed by the alt_prof code I stole. The functions maybe shouldn't be named krb5_*, but they are. */ diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c index 5582df0..4d1e769 100644 --- a/src/lib/kadm5/alt_prof.c +++ b/src/lib/kadm5/alt_prof.c @@ -644,8 +644,8 @@ krb5_error_code kadm5_get_config_params(context, kdcprofile, kdcenv, if (aprofile) krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue); if (svalue == NULL) - svalue = strdup("des-cbc-crc:normal"); - + svalue = strdup("des3-hmac-sha1:normal des-cbc-crc:normal"); + params.keysalts = NULL; params.num_keysalts = 0; krb5_string_to_keysalts(svalue, diff --git a/src/lib/kadm5/chpass_util.c b/src/lib/kadm5/chpass_util.c index 367d8f2..a991ca0 100644 --- a/src/lib/kadm5/chpass_util.c +++ b/src/lib/kadm5/chpass_util.c @@ -1,9 +1,5 @@ /* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. - * - * $Header$ - * - * */ @@ -63,7 +59,8 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, krb5_principal princ, char *new_pw, char **ret_pw, - char *msg_ret) + char *msg_ret, + int msg_len) { int code, code2, pwsize; static char buffer[255]; @@ -96,12 +93,18 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, memset(buffer, 0, sizeof(buffer)); #endif if (code == KRB5_LIBOS_BADPWDMATCH) { - strcpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH)); + strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH), + msg_len - 1); + msg_ret[msg_len - 1] = '\0'; return(code); } else { - sprintf(msg_ret, "%s %s\n%s\n", error_message(code), - string_text(CHPASS_UTIL_WHILE_READING_PASSWORD), - string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED)); + strncpy(msg_ret, error_message(code), msg_len - 1); + strncat(msg_ret, " ", msg_len - 1); + strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_READING_PASSWORD), + msg_len - 1); + strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED), + msg_len - 1); + msg_ret[msg_len - 1] = '\0'; return(code); } } @@ -109,7 +112,8 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, #ifdef ZEROPASSWD memset(buffer, 0, sizeof(buffer)); #endif - strcpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ)); + strncpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ), msg_len - 1); + msg_ret[msg_len - 1] = '\0'; return(KRB5_LIBOS_CANTREADPWD); /* could do better */ } } @@ -125,7 +129,8 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, #endif if (code == KADM5_OK) { - strcpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED)); + strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED), msg_len - 1); + msg_ret[msg_len - 1] = '\0'; return(0); } @@ -143,12 +148,15 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, /* Ok, we have a password quality error. Return a good message */ if (code == KADM5_PASS_REUSE) { - strcpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE)); + strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE), msg_len - 1); + msg_ret[msg_len - 1] = '\0'; return(code); } if (code == KADM5_PASS_Q_DICT) { - strcpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY)); + strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY), + msg_len - 1); + msg_ret[msg_len - 1] = '\0'; return(code); } @@ -157,18 +165,32 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, code2 = kadm5_get_principal (lhandle, princ, &princ_ent, KADM5_PRINCIPAL_NORMAL_MASK); if (code2 != 0) { - sprintf(msg_ret, "%s %s\n%s %s\n\n%s\n ", error_message(code2), - string_text(CHPASS_UTIL_GET_PRINC_INFO), - error_message(code), - string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE), - string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED)); + strncpy(msg_ret, error_message(code2), msg_len - 1); + strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, string_text(CHPASS_UTIL_GET_PRINC_INFO), msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, "\n", msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, error_message(code), msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE), + msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, "\n\n", msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED), + msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, "\n", msg_len - 1 - strlen(msg_ret)); + msg_ret[msg_len - 1] = '\0'; return(code); } if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) { - sprintf(msg_ret, "%s %s\n\n%s", error_message(code), - string_text(CHPASS_UTIL_NO_POLICY_YET_Q_ERROR), - string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED)); + strncpy(msg_ret, error_message(code), msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, " ", msg_len - 1 - strlen(msg_ret)); + strncpy(msg_ret, string_text(CHPASS_UTIL_NO_POLICY_YET_Q_ERROR), + msg_len - 1 - strlen(msg_ret)); + strncat(msg_ret, "\n\n", msg_len - 1 - strlen(msg_ret)); + strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED), + msg_len - 1 - strlen(msg_ret)); + msg_ret[msg_len - 1] = '\0'; + (void) kadm5_free_principal_ent(lhandle, &princ_ent); return(code); } diff --git a/src/lib/kadm5/clnt/ChangeLog b/src/lib/kadm5/clnt/ChangeLog index 1672942..0e47993 100644 --- a/src/lib/kadm5/clnt/ChangeLog +++ b/src/lib/kadm5/clnt/ChangeLog @@ -1,3 +1,17 @@ +2000-06-23 Nalin Dahyabhai <nalin@redhat.com> + + * clnt_chpass_util.c (kadm5_chpass_principal_util): Adjust for new + length parameter in both kadm5_chpass_principal_util() and in + _kadm5_chpass_principal_util(). + + * client_init.c (_kadm5_init_any): Fix determination of client + name length for overflow checking. + +2000-06-23 Ken Raeburn <raeburn@mit.edu> + + * client_init.c (enctypes): Add des3 and des-md5 to the list of + permitted enctypes. + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * client_init.c, client_principal.c, client_rpc.c: Check for diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c index 53d6e15..56fbfcd 100644 --- a/src/lib/kadm5/clnt/client_init.c +++ b/src/lib/kadm5/clnt/client_init.c @@ -1,7 +1,5 @@ /* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved - * - * $Header$ */ /* @@ -30,10 +28,6 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#if !defined(lint) && !defined(__CODECENTER__) -static char *rcsid = "$Header$"; -#endif - #include <stdio.h> #include <netdb.h> #ifdef HAVE_MEMORY_H @@ -136,6 +130,8 @@ static int preauth_search_list[] = { }; static krb5_enctype enctypes[] = { + ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC, 0, }; @@ -284,9 +280,15 @@ static kadm5_ret_t _kadm5_init_any(char *client_name, goto error; if (realm) { + if(strlen(service_name) + strlen(realm) + 1 >= sizeof(full_service_name)) { + goto error; + } sprintf(full_service_name, "%s@%s", service_name, realm); } else { /* krb5_princ_realm(creds.client) is not null terminated */ + if(strlen(service_name) + krb5_princ_realm(handle->context, creds.client)->length + 1 >= sizeof(full_service_name)) { + goto error; + } strcpy(full_service_name, service_name); strcat(full_service_name, "@"); strncat(full_service_name, krb5_princ_realm(handle->context, diff --git a/src/lib/kadm5/clnt/clnt_chpass_util.c b/src/lib/kadm5/clnt/clnt_chpass_util.c index d6c7f0b..ae9ced0 100644 --- a/src/lib/kadm5/clnt/clnt_chpass_util.c +++ b/src/lib/kadm5/clnt/clnt_chpass_util.c @@ -5,11 +5,12 @@ kadm5_ret_t kadm5_chpass_principal_util(void *server_handle, krb5_principal princ, char *new_pw, char **ret_pw, - char *msg_ret) + char *msg_ret, + int msg_len) { kadm5_server_handle_t handle = server_handle; CHECK_HANDLE(server_handle); return _kadm5_chpass_principal_util(handle, handle->lhandle, princ, - new_pw, ret_pw, msg_ret); + new_pw, ret_pw, msg_ret, msg_len); } diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c index 4f2ad20..bf6bbfd 100644 --- a/src/lib/kadm5/logger.c +++ b/src/lib/kadm5/logger.c @@ -199,8 +199,9 @@ klog_com_err_proc(whoami, code, format, ap) /* If reporting an error message, separate it. */ if (code) { - strcat(outbuf, error_message(code)); - strcat(outbuf, " - "); + outbuf[sizeof(outbuf) - 1] = '\0'; + strncat(outbuf, error_message(code), sizeof(outbuf) - 1 - strlen(outbuf)); + strncat(outbuf, " - ", sizeof(outbuf) - 1 - strlen(outbuf)); } cp = &outbuf[strlen(outbuf)]; diff --git a/src/lib/kadm5/ovsec_glue.c b/src/lib/kadm5/ovsec_glue.c index 6118282..ce81893 100644 --- a/src/lib/kadm5/ovsec_glue.c +++ b/src/lib/kadm5/ovsec_glue.c @@ -102,8 +102,10 @@ ovsec_kadm_ret_t ovsec_kadm_chpass_principal_util(void *server_handle, char **ret_pw, char *msg_ret) { - return kadm5_chpass_principal_util(server_handle, princ, new_pw, - ret_pw, msg_ret); + /* Oh crap. Can't change the API without bumping the API version... */ + memset(msg_ret, '\0', 1024); + return kadm5_chpass_principal_util(server_handle, princ, new_pw, + ret_pw, msg_ret, 1024); } ovsec_kadm_ret_t ovsec_kadm_randkey_principal(void *server_handle, diff --git a/src/lib/kadm5/srv/ChangeLog b/src/lib/kadm5/srv/ChangeLog index 1864a73..d397604 100644 --- a/src/lib/kadm5/srv/ChangeLog +++ b/src/lib/kadm5/srv/ChangeLog @@ -1,3 +1,11 @@ +2000-06-23 Nalin Dahyabhai <nalin@redhat.com> + + * adb_openclose.c (osa_adb_create_db): Open lock files using O_EXCL + and fdopen() the descriptor instead of using fopen(). + * svr_chpass_util.c (kadm5_chpass_principal_util): Adjust for new + length parameter in both kadm5_chpass_principal_util() and in + _kadm5_chpass_principal_util(). + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * adb_free.c, adb_xdr.c, server_dict.c: Check for existance diff --git a/src/lib/kadm5/srv/adb_openclose.c b/src/lib/kadm5/srv/adb_openclose.c index e776192..2a9bba8 100644 --- a/src/lib/kadm5/srv/adb_openclose.c +++ b/src/lib/kadm5/srv/adb_openclose.c @@ -24,7 +24,7 @@ struct _locklist { osa_adb_ret_t osa_adb_create_db(char *filename, char *lockfilename, int magic) { - FILE *lf; + int lf; DB *db; HASHINFO info; @@ -41,10 +41,10 @@ osa_adb_ret_t osa_adb_create_db(char *filename, char *lockfilename, return errno; /* only create the lock file if we successfully created the db */ - lf = fopen(lockfilename, "w+"); - if (lf == NULL) + lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600); + if (lf == -1) return errno; - (void) fclose(lf); + (void) close(lf); return OSA_ADB_OK; } @@ -333,7 +333,7 @@ osa_adb_ret_t osa_adb_get_lock(osa_adb_db_t db, int mode) osa_adb_ret_t osa_adb_release_lock(osa_adb_db_t db) { - int ret; + int ret, fd; if (!db->lock->lockcnt) /* lock already unlocked */ return OSA_ADB_NOTLOCKED; @@ -341,8 +341,9 @@ osa_adb_ret_t osa_adb_release_lock(osa_adb_db_t db) if (--db->lock->lockcnt == 0) { if (db->lock->lockmode == OSA_ADB_PERMANENT) { /* now we need to create the file since it does not exist */ - if ((db->lock->lockfile = fopen(db->lock->filename, - "w+")) == NULL) + fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL, + 0600); + if ((db->lock->lockfile = fdopen(fd, "w+")) == NULL) return OSA_ADB_NOLOCKFILE; } else if (ret = krb5_lock_file(db->lock->context, fileno(db->lock->lockfile), diff --git a/src/lib/kadm5/srv/svr_chpass_util.c b/src/lib/kadm5/srv/svr_chpass_util.c index df2bf4c..4c4c6bb 100644 --- a/src/lib/kadm5/srv/svr_chpass_util.c +++ b/src/lib/kadm5/srv/svr_chpass_util.c @@ -5,11 +5,12 @@ kadm5_ret_t kadm5_chpass_principal_util(void *server_handle, krb5_principal princ, char *new_pw, char **ret_pw, - char *msg_ret) + char *msg_ret, + int msg_len) { kadm5_server_handle_t handle = server_handle; CHECK_HANDLE(server_handle); return _kadm5_chpass_principal_util(handle, handle->lhandle, princ, - new_pw, ret_pw, msg_ret); + new_pw, ret_pw, msg_ret, msg_len); } diff --git a/src/lib/kadm5/unit-test/ChangeLog b/src/lib/kadm5/unit-test/ChangeLog index 15c4bad..f195831 100644 --- a/src/lib/kadm5/unit-test/ChangeLog +++ b/src/lib/kadm5/unit-test/ChangeLog @@ -1,3 +1,10 @@ +2000-05-09 Ken Raeburn <raeburn@mit.edu> + + * api.2/chpass-principal-v2.exp (test200): Expect an additional + key to be reported, since des3 has been added to the list. + * api.2/get-principal-v2.exp (test101_102): Likewise. + * api.2/randkey-principal-v2.exp (test100): Likewise. + 2000-02-08 Tom Yu <tlyu@mit.edu> * api.1/lock.exp: Since a "wait" directive to the command list of diff --git a/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp b/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp index 40a78c9..ef45510 100644 --- a/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp +++ b/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp @@ -53,10 +53,10 @@ proc test200 {} { } # XXX Perhaps I should actually check the key type returned. - if {$num_keys == 2} { + if {$num_keys == 3} { pass "$test" } else { - fail "$test: $num_keys keys, should be 2" + fail "$test: $num_keys keys, should be 3" } if { ! [cmd {kadm5_destroy $server_handle}]} { error "$test: unexpected failure in destroy" diff --git a/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp b/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp index 0e3e1b5..d2eb85a 100644 --- a/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp +++ b/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp @@ -143,8 +143,8 @@ proc test101_102 {rpc} { } set failed 0 - if {$num_keys != 2} { - fail "$test: num_keys $num_keys should be 2" + if {$num_keys != 3} { + fail "$test: num_keys $num_keys should be 3" set failed 1 } for {set i 0} {$i < $num_keys} {incr i} { diff --git a/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp b/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp index 5c8fdc5..d9cc971 100644 --- a/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp +++ b/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp @@ -47,10 +47,10 @@ proc test100 {} { } # XXX Perhaps I should actually check the key type returned. - if {$num_keys == 1} { + if {$num_keys == 2} { pass "$test" } else { - fail "$test: $num_keys keys, should be 1" + fail "$test: $num_keys keys, should be 2" } if { ! [cmd {kadm5_destroy $server_handle}]} { error "$test: unexpected failure in destroy" diff --git a/src/lib/kdb/ChangeLog b/src/lib/kdb/ChangeLog index 7d7368c..b72e642 100644 --- a/src/lib/kdb/ChangeLog +++ b/src/lib/kdb/ChangeLog @@ -1,3 +1,26 @@ +2000-05-11 Nalin Dahyabhai <nalin@redhat.com> + + * t_kdb.c (gen_principal): Don't overflow "pnamebuf" if bad data was + passed in. + +2000-05-03 Nalin Dahyabhai <nalin@redhat.com> + + * setup_mkey.c (krb5_db_setup_mkey_name): Use REALM_SEP_STRING + when computing size of buffer that is to include it. + + * fetch_mkey.c (krb5_db_fetch_mkey): Make sure "defkeyfile" is + null terminated after construction. + * store_mkey.c (krb5_db_store_mkey): Likewise. + +2000-04-27 Ken Raeburn <raeburn@mit.edu> + Ezra Peisach <epeisach@mit.edu> + + * t_kdb.c (gen_principal): Force argument to isalnum to be in + range 0..255. + (do_testing): Cast pid_t to long before passing to fprintf, and + use %ld format. Fix argument lists to find_principal and + delete_principal. + 2000-03-16 Ezra Peisach <epeisach@mit.edu> * kdb_xdr.c (krb5_dbe_lookup_mod_princ_data): Get rid of diff --git a/src/lib/kdb/fetch_mkey.c b/src/lib/kdb/fetch_mkey.c index 2ff5c29..7ae26bb 100644 --- a/src/lib/kdb/fetch_mkey.c +++ b/src/lib/kdb/fetch_mkey.c @@ -133,7 +133,7 @@ krb5_db_fetch_mkey(context, mname, etype, fromkeyboard, twice, keyfile, (void) strncat(defkeyfile, realm->data, min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1, realm->length)); - (void) strcat(defkeyfile, ""); + defkeyfile[sizeof(defkeyfile) - 1] = '\0'; #ifdef ANSI_STDIO if (!(kf = fopen((keyfile) ? keyfile : defkeyfile, "rb"))) diff --git a/src/lib/kdb/setup_mkey.c b/src/lib/kdb/setup_mkey.c index 0898a63..1788ecd 100644 --- a/src/lib/kdb/setup_mkey.c +++ b/src/lib/kdb/setup_mkey.c @@ -56,7 +56,7 @@ krb5_db_setup_mkey_name(context, keyname, realm, fullname, principal) keylen = strlen(keyname); - fname = malloc(keylen+rlen+2); + fname = malloc(keylen+rlen+strlen(REALM_SEP_STRING)+1); if (!fname) return ENOMEM; diff --git a/src/lib/kdb/store_mkey.c b/src/lib/kdb/store_mkey.c index d18630a..47e0bc9 100644 --- a/src/lib/kdb/store_mkey.c +++ b/src/lib/kdb/store_mkey.c @@ -68,7 +68,7 @@ krb5_db_store_mkey(context, keyfile, mname, key) (void) strncat(defkeyfile, realm->data, min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1, realm->length)); - (void) strcat(defkeyfile, ""); + defkeyfile[sizeof(defkeyfile) - 1] = '\0'; keyfile = defkeyfile; } diff --git a/src/lib/kdb/t_kdb.c b/src/lib/kdb/t_kdb.c index 8358088..10e6163 100644 --- a/src/lib/kdb/t_kdb.c +++ b/src/lib/kdb/t_kdb.c @@ -363,15 +363,23 @@ gen_principal(kcontext, realm, do_rand, n, princp, namep) complen = RANDOM(1,MAX_COMP_SIZE); for (j=0; j<complen; j++) { *cp = (char) RANDOM(0,256); - while (!isalnum(*cp)) + while (!isalnum(*cp & 0xff)) *cp = (char) RANDOM(0,256); cp++; + if(cp + strlen(realm) >= pnamebuf + sizeof(pnamebuf)) + break; } + if(cp + strlen(realm) >= pnamebuf + sizeof(pnamebuf)) + break; *cp = '/'; cp++; } - cp[-1] = '@'; - strcpy(cp, realm); + if(cp + strlen(realm) < pnamebuf + sizeof(pnamebuf)) { + cp[-1] = '@'; + strcpy(cp, realm); + } else { + strcpy(cp , ""); + } } else { instname = instnames[n % (sizeof(instnames)/sizeof(instnames[0]))]; @@ -894,45 +902,40 @@ do_testing(db, passes, verbose, timing, rcases, check, save_db, dontclean, &stat_kb, rseed))) { fprintf(stderr, - "%d: (%d,%d) Failed add of %s with %s\n", - getpid(), i, j, playback_name(base+j), + "%ld: (%d,%d) Failed add of %s with %s\n", + (long) getpid(), i, j, playback_name(base+j), error_message(kret)); break; } if (verbose > 4) - fprintf(stderr, "*A[%d](%s)\n", getpid(), + fprintf(stderr, "*A[%ld](%s)\n", (long) getpid(), playback_name(base+j)); } for (j=0; (j<nper) && (!kret); j++) { if ((kret = find_principal(ccontext, playback_principal(base+j), - &master_encblock, - &stat_kb, - rseed))) { + check))) { fprintf(stderr, - "%d: (%d,%d) Failed lookup of %s with %s\n", - getpid(), i, j, playback_name(base+j), + "%ld: (%d,%d) Failed lookup of %s with %s\n", + (long) getpid(), i, j, playback_name(base+j), error_message(kret)); break; } if (verbose > 4) - fprintf(stderr, "-S[%d](%s)\n", getpid(), + fprintf(stderr, "-S[%ld](%s)\n", (long) getpid(), playback_name(base+j)); } for (j=0; (j<nper) && (!kret); j++) { if ((kret = delete_principal(ccontext, - playback_principal(base+j), - &master_encblock, - &stat_kb, - rseed))) { + playback_principal(base+j)))) { fprintf(stderr, - "%d: (%d,%d) Failed delete of %s with %s\n", - getpid(), i, j, playback_name(base+j), + "%ld: (%d,%d) Failed delete of %s with %s\n", + (long) getpid(), i, j, playback_name(base+j), error_message(kret)); break; } if (verbose > 4) - fprintf(stderr, "XD[%d](%s)\n", getpid(), + fprintf(stderr, "XD[%ld](%s)\n", (long) getpid(), playback_name(base+j)); } krb5_db_fini(ccontext); @@ -949,13 +952,13 @@ do_testing(db, passes, verbose, timing, rcases, check, save_db, dontclean, for (i=0; i<nprocs; i++) { if (waitpid(children[i], &existat, 0) == children[i]) { if (verbose) - fprintf(stderr, "%d finished with %d\n", children[i], - existat); + fprintf(stderr, "%ld finished with %d\n", + (long) children[i], existat); if (existat) kret = KRB5KRB_ERR_GENERIC; } else - fprintf(stderr, "Wait for %d failed\n", children[i]); + fprintf(stderr, "Wait for %ld failed\n", (long) children[i]); } } diff --git a/src/lib/krb4/ChangeLog b/src/lib/krb4/ChangeLog index 29d985f..c1d81d3 100644 --- a/src/lib/krb4/ChangeLog +++ b/src/lib/krb4/ChangeLog @@ -1,3 +1,86 @@ +2000-06-09 Tom Yu <tlyu@mit.edu> + + * configure.in: Check for strdup(). + + * kparse.c: Remove strsave() and replace with an inlined static + version of strdup() if HAVE_STRDUP is not defined. + + * g_ad_tkt.c (get_ad_tkt): ptr may be signed; cast while + assigning to larger types. [from Charles Hannum by way of + ghudson] + +2000-05-23 Ken Raeburn <raeburn@mit.edu> + + * decomp_tkt.c (dcmp_tkt_int): Add a couple more length checks. + Reject names that are exactly ANAME_SZ (etc) bytes long without + the trailing nul, because krb.h says the *_SZ macros are "maximum + sizes ... +1". + * mk_auth.c (krb_mk_auth): Force nul termination of inst. + * sendauth.c (krb_sendauth): Force nul termination of srv_inst. + +2000-05-11 Nalin Dahyabhai <nalin@redhat.com> + + * Password.c (GetUserInfo): Truncate user name if it's too long + to fit. + * cr_auth_repl.c (cr_auth_reply): Bail if the reply packet won't + fit into its buffer. + * cr_ciph.c (create_ciph): Ditto. + * cr_death_pkt.c (krb_create_death_packet): Truncate "aname" to + make it fit into the packet's data buffer. + * cr_err_repl.c (cr_err_reply): Bail if the reply packet won't + fit into its buffer. + * cr_tkt.c (krb_create_ticket): Ditto. + * g_ad_tkt.c (get_ad_tkt): Stop if data being added to buffer + would overflow it. Add more sanity checks when decomposing the + credential received. + * g_in_tkt.c (krb_mk_in_tkt_preauth): Bail if the request packet + won't fit into its buffer. + * g_krbhst.c (get_krbhst_default): Truncate the guessed KDC's + hostname if it is too long. + * g_pw_in_tkt.c: Remove useless strcpy() prototype. + * kntoln.c (krb_kntoln): Don't overflow buffer "lname". + * mk_err.c (krb_mk_err): Return the needed buffer length if the + pointer passed in is NULL. + * mk_req.c (krb_mk_req): Bail if the reply packet won't + fit into its buffer. + * rd_req.c (krb_rd_req): Sanity check the realm name being read, + and truncate the service name, nstance, and realm from credential + read from keytab. + * realmofhost.c (krb_realmofhost): Truncate realm names read + from file if they are too long. + * send_to_kdc.c (send_to_kdc): Truncate passed-in realm name. + +2000-05-08 Ken Raeburn <raeburn@mit.edu> + + * rd_req.c (krb_rd_req): Mask length byte with 0xff in case the + length is over 127 and char is signed. + + * recvauth.c (krb_recvauth): If the number of bytes to be read + from the net is not positive, just return an error. + +2000-05-03 Tom Yu <tlyu@mit.edu> + + * cr_tkt.c: Delete prototype for krb_cr_tkt_int(), since the + definition is K&R style and contains narrow types. Thank you + HP/UX for having a compiler that actually makes this a fatal + error. + +2000-04-28 Ken Raeburn <raeburn@mit.edu> + Nalin Dahyabhai <nalin@redhat.com> + + * dest_tkt.c (dest_tkt): Don't overflow buffer "shmidname". + * in_tkt.c (in_tkt): Don't overflow buffer "shmidname". + * kuserok.c (kuserok): Don't overflow buffer "pbuf". + * tf_util.c (tf_init): Don't overflow buffer "shmidname". + * win_store.c (krb__get_cnffile): Don't overflow buffers "defname" + and "cnfname". + (krb__get_realmsfile): Don't overflow buffers "defname" and + "realmsname". + +2000-04-28 Tom Yu <tlyu@mit.edu> + + * rd_req.c (krb_rd_req): Fix some uses of strcpy(). + 2000-03-12 Ezra Peisach <epeisach@mit.edu> * cr_tkt.c (krb_cr_tkt_int): Add static prototype. diff --git a/src/lib/krb4/Password.c b/src/lib/krb4/Password.c index b296630..5862e0e 100644 --- a/src/lib/krb4/Password.c +++ b/src/lib/krb4/Password.c @@ -177,7 +177,8 @@ OSErr GetUserInfo( char *password ) // already got a password, just get the initial ticket ////////////////////////////////////////////////////// if (*gPassword) { - strcpy (UserName, krb_get_default_user( )); + strncpy (UserName, krb_get_default_user( ), sizeof(UserName)-1); + UserName[sizeof(UserName) - 1] = '\0'; /* FIXME jcm - if we have a password then no dialog comes up for setting the uinstance. */ rc = kname_parse(uname, uinst, realm, UserName); @@ -201,7 +202,8 @@ OSErr GetUserInfo( char *password ) } // Insert user's name in dialog - strcpy (UserName, krb_get_default_user( )); + strncpy (UserName, krb_get_default_user( ), sizeof(UserName) - 1); + UserName[sizeof(UserName) - 1] = '\0'; if (*UserName) { tempStr[0] = strlen(UserName); memcpy( &(tempStr[1]), UserName, tempStr[0]); @@ -417,7 +419,8 @@ CacheInitialTicket( serviceName ) if (!serviceName || (serviceName[0] == '\0')) return err; - strcpy (UserName, krb_get_default_user()); + strncpy (UserName, krb_get_default_user(), sizeof(UserName) - 1); + UserName[sizeof(UserName) - 1] = '\0'; err = kname_parse(uname, uinst, urealm, UserName); if (err) return err; diff --git a/src/lib/krb4/configure.in b/src/lib/krb4/configure.in index 0434c7d..59937e1 100644 --- a/src/lib/krb4/configure.in +++ b/src/lib/krb4/configure.in @@ -38,7 +38,7 @@ else AC_DEFINE(BITS32) fi AC_DEFINE(KRB4_USE_KEYTAB) -AC_HAVE_FUNCS(strsave seteuid setreuid setresuid) +AC_HAVE_FUNCS(strdup seteuid setreuid setresuid) AC_PROG_AWK KRB5_BUILD_LIBOBJS KRB5_BUILD_LIBRARY_WITH_DEPS diff --git a/src/lib/krb4/cr_auth_repl.c b/src/lib/krb4/cr_auth_repl.c index 5203506..a0562d9 100644 --- a/src/lib/krb4/cr_auth_repl.c +++ b/src/lib/krb4/cr_auth_repl.c @@ -83,6 +83,16 @@ create_auth_reply(pname,pinst,prealm,time_ws,n,x_date,kvno,cipher) if (n != 0) *v = 3; + /* Make sure the response will actually fit into its buffer. */ + if(sizeof(pkt->dat) < 3 + strlen(pname) + + 1 + strlen(pinst) + + 1 + strlen(prealm) + + 4 + 1 + 4 + + 1 + 2 + cipher->length) { + pkt->length = 0; + return NULL; + } + /* Add the basic info */ (void) strcpy((char *) (pkt->dat+2), pname); pkt->length = 3 + strlen(pname); diff --git a/src/lib/krb4/cr_ciph.c b/src/lib/krb4/cr_ciph.c index d15a4e0..d9c7512 100644 --- a/src/lib/krb4/cr_ciph.c +++ b/src/lib/krb4/cr_ciph.c @@ -71,6 +71,17 @@ create_ciph(c, session, service, instance, realm, life, kvno, tkt, ptr = (char *) c->dat; + if(sizeof(c->dat) / 8 < (8 + + strlen(service) + 1 + + strlen(instance) + 1 + + strlen(realm) + 1 + + 1 + 1 + 1 + + tkt->length + 4 + + 7) / 8) { + c->length = 0; + return(KFAILURE); + } + memcpy(ptr, (char *) session, 8); ptr += 8; diff --git a/src/lib/krb4/cr_death_pkt.c b/src/lib/krb4/cr_death_pkt.c index 8daa2d6..c356267 100644 --- a/src/lib/krb4/cr_death_pkt.c +++ b/src/lib/krb4/cr_death_pkt.c @@ -52,8 +52,9 @@ krb_create_death_packet(a_name) *v = (unsigned char) KRB_PROT_VERSION; *t = (unsigned char) AUTH_MSG_DIE; *t |= HOST_BYTE_ORDER; - (void) strcpy((char *) (pkt->dat+2),a_name); - pkt->length = 3 + strlen(a_name); + (void) strncpy((char *) (pkt->dat+2),a_name,sizeof(pkt->dat) - 3); + pkt->dat[sizeof(pkt->dat) - 1] = '\0'; + pkt->length = 3 + strlen(pkt->dat+2); return pkt; } #endif /* DEBUG */ diff --git a/src/lib/krb4/cr_err_repl.c b/src/lib/krb4/cr_err_repl.c index 7f68bda..54e87d8 100644 --- a/src/lib/krb4/cr_err_repl.c +++ b/src/lib/krb4/cr_err_repl.c @@ -78,6 +78,15 @@ cr_err_reply(pkt,pname,pinst,prealm,time_ws,e,e_string) *t = (unsigned char) AUTH_MSG_ERR_REPLY; *t |= HOST_BYTE_ORDER; + /* Make sure the reply will fit into the buffer. */ + if(sizeof(pkt->dat) < 3 + strlen(pname) + + 1 + strlen(pinst) + + 1 + strlen(prealm) + + 4 + 4 + + 1 + strlen(e_string)) { + pkt->length = 0; + return; + } /* Add the basic info */ (void) strcpy((char *) (pkt->dat+2),pname); pkt->length = 3 + strlen(pname); diff --git a/src/lib/krb4/cr_tkt.c b/src/lib/krb4/cr_tkt.c index 0293e10..34bec48 100644 --- a/src/lib/krb4/cr_tkt.c +++ b/src/lib/krb4/cr_tkt.c @@ -15,12 +15,6 @@ #include <string.h> #include <krb5.h> -static int krb_cr_tkt_int PROTOTYPE((KTEXT tkt, unsigned char flags, - char *pname, char *pinstance, - char *prealm, long paddress, - char *session, short life, long time_sec, - char *sname, char *sinstance, - C_Block key, krb5_keyblock *k5key)); /* * Create ticket takes as arguments information that should be in a * ticket, and the KTEXT object in which the ticket should be @@ -141,6 +135,23 @@ krb_cr_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, register char *data; /* running index into ticket */ tkt->length = 0; /* Clear previous data */ + + /* Check length of ticket */ + if (sizeof(tkt->dat) < (sizeof(flags) + + 1 + strlen(pname) + + 1 + strlen(pinstance) + + 1 + strlen(prealm) + + 4 + /* address */ + 8 + /* session */ + 1 + /* life */ + 4 + /* issue time */ + 1 + strlen(sname) + + 1 + strlen(sinstance) + + 7) / 8) { /* roundoff */ + memset(tkt->dat, 0, sizeof(tkt->dat)); + return KFAILURE /* XXX */; + } + flags |= HOST_BYTE_ORDER; /* ticket byte order */ memcpy((char *) (tkt->dat), (char *) &flags, sizeof(flags)); data = ((char *)tkt->dat) + sizeof(flags); diff --git a/src/lib/krb4/decomp_tkt.c b/src/lib/krb4/decomp_tkt.c index 04d3298..06e9e31 100644 --- a/src/lib/krb4/decomp_tkt.c +++ b/src/lib/krb4/decomp_tkt.c @@ -192,17 +192,17 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1)) tkt_swap_bytes++; - if (strlen(ptr) > ANAME_SZ) + if (strlen(ptr) >= ANAME_SZ) return(KFAILURE); (void) strcpy(pname,ptr); /* pname */ ptr += strlen(pname) + 1; - if (strlen(ptr) > INST_SZ) + if (strlen(ptr) >= INST_SZ) return(KFAILURE); (void) strcpy(pinstance,ptr); /* instance */ ptr += strlen(pinstance) + 1; - if (strlen(ptr) > REALM_SZ) + if (strlen(ptr) >= REALM_SZ) return(KFAILURE); (void) strcpy(prealm,ptr); /* realm */ ptr += strlen(prealm) + 1; @@ -229,9 +229,13 @@ dcmp_tkt_int(tkt, flags, pname, pinstance, prealm, paddress, session, if (tkt_swap_bytes) *time_sec = krb4_swab32(*time_sec); + if (strlen(ptr) >= ANAME_SZ) + return KFAILURE; (void) strcpy(sname,ptr); /* service name */ ptr += 1 + strlen(sname); + if (strlen (ptr) >= INST_SZ) + return KFAILURE; (void) strcpy(sinstance,ptr); /* instance */ ptr += 1 + strlen(sinstance); diff --git a/src/lib/krb4/dest_tkt.c b/src/lib/krb4/dest_tkt.c index 7057818..50c1352 100644 --- a/src/lib/krb4/dest_tkt.c +++ b/src/lib/krb4/dest_tkt.c @@ -87,8 +87,9 @@ out: /* * handle the shared memory case */ - (void) strcpy(shmidname, file); - (void) strcat(shmidname, ".shm"); + (void) strncpy(shmidname, file, sizeof(shmidname) - 1); + shmidname[sizeof(shmidname) - 1] = '\0'; + (void) strcat(shmidname, ".shm", sizeof(shmidname) - 1 - strlen(shmidname)); if ((i = krb_shm_dest(shmidname)) != KSUCCESS) return(i); #endif /* TKT_SHMEM */ diff --git a/src/lib/krb4/g_ad_tkt.c b/src/lib/krb4/g_ad_tkt.c index b3abb2d..afcd0c6 100644 --- a/src/lib/krb4/g_ad_tkt.c +++ b/src/lib/krb4/g_ad_tkt.c @@ -19,6 +19,19 @@ extern int krb_debug; extern int swap_bytes; +/* Return the length of the string if a NUL is found within the first + * max_len bytes, otherwise, -1. */ +static int krb_strnlen(const char *str, int max_len) +{ + int i; + for(i = 0; i < max_len; i++) { + if(str[i] == '\0') { + return i; + } + } + return -1; +} + /* * get_ad_tkt obtains a new service ticket from Kerberos, using * the ticket-granting ticket which must be in the ticket file. @@ -136,11 +149,22 @@ get_ad_tkt(service,sinstance,realm,lifetime) return(AD_NOTGT); /* timestamp */ /* FIXME -- always 0 now, should we fill it in??? */ + if(pkt->length + 4 > sizeof(pkt->dat)) + return(INTK_ERR); memcpy((char *) (pkt->dat+pkt->length), (char *) &time_ws, 4); pkt->length += 4; + + if(pkt->length + 1 > sizeof(pkt->dat)) + return(INTK_ERR); *(pkt->dat+(pkt->length)++) = (char) lifetime; + + if(pkt->length + 1 + strlen(service) > sizeof(pkt->dat)) + return(INTK_ERR); (void) strcpy((char *) (pkt->dat+pkt->length),service); pkt->length += 1 + strlen(service); + + if(pkt->length + 1 + strlen(sinstance) > sizeof(pkt->dat)) + return(INTK_ERR); (void) strcpy((char *)(pkt->dat+pkt->length),sinstance); pkt->length += 1 + strlen(sinstance); @@ -199,18 +223,27 @@ get_ad_tkt(service,sinstance,realm,lifetime) memcpy((char *)ses, ptr, 8); ptr += 8; - (void) strcpy(s_name,ptr); + if(krb_strnlen(ptr, sizeof(s_name)) < 0) + return RD_AP_MODIFIED; + (void) strncpy(s_name,ptr,sizeof(s_name) - 1); + s_name[sizeof(s_name) - 1] = '\0'; ptr += strlen(s_name) + 1; - (void) strcpy(s_instance,ptr); + if(krb_strnlen(ptr, sizeof(s_instance)) < 0) + return RD_AP_MODIFIED; + (void) strncpy(s_instance,ptr,sizeof(s_instance)-1); + s_instance[sizeof(s_instance)-1] = '\0'; ptr += strlen(s_instance) + 1; - (void) strcpy(rlm,ptr); + if(krb_strnlen(ptr, sizeof(rlm)) < 0) + return RD_AP_MODIFIED; + (void) strncpy(rlm,ptr,sizeof(rlm) - 1); + rlm[sizeof(rlm)-1]; ptr += strlen(rlm) + 1; - lifetime = (unsigned long) ptr[0]; - kvno = (unsigned long) ptr[1]; - tkt->length = (int) ptr[2]; + lifetime = (unsigned char) ptr[0]; + kvno = (unsigned char) ptr[1]; + tkt->length = (unsigned char) ptr[2]; ptr += 3; memcpy((char *)(tkt->dat), ptr, tkt->length); ptr += tkt->length; diff --git a/src/lib/krb4/g_in_tkt.c b/src/lib/krb4/g_in_tkt.c index c9d6183..361273c 100644 --- a/src/lib/krb4/g_in_tkt.c +++ b/src/lib/krb4/g_in_tkt.c @@ -152,6 +152,20 @@ krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life, *t = (unsigned char) AUTH_MSG_KDC_REQUEST; *t |= HOST_BYTE_ORDER; + /* Make sure the ticket data will fit into the buffer. */ + if(sizeof(pkt->dat) < 2 + /* protocol version + flags */ + 3 + strlen(user) + + 1 + strlen(instance) + + 1 + strlen(realm) + + 4 + /* timestamp */ + 1 + /* lifetime */ + 1 + strlen(service) + + 1 + strlen(sinstance) + + preauth_len) { + pkt->length = 0; + return INTK_ERR; + } + /* Now for the variable info */ (void) strcpy((char *)(pkt->dat+2),user); /* aname */ pkt->length = 3 + strlen(user); diff --git a/src/lib/krb4/g_krbhst.c b/src/lib/krb4/g_krbhst.c index 529ac07..4e0fd6d 100644 --- a/src/lib/krb4/g_krbhst.c +++ b/src/lib/krb4/g_krbhst.c @@ -52,9 +52,11 @@ get_krbhst_default(h, r, n) int n; { if (n==1) { - (void) strcpy(h,KRB_HOST); - (void) strcat(h,"."); - (void) strcat(h,r); /* KRB_HOST.REALM (ie. kerberos.CYGNUS.COM) */ + (void) strncpy(h,KRB_HOST,MAXHOSTNAMELEN-1); + h[MAXHOSTNAMELEN-1] = '\0'; + (void) strncat(h,".",MAXHOSTNAMELEN-1-strlen(h)); + (void) strncat(h,r,MAXHOSTNAMELEN-1-strlen(h)); + /* KRB_HOST.REALM (ie. kerberos.CYGNUS.COM) */ return(KSUCCESS); } else diff --git a/src/lib/krb4/g_krbrlm.c b/src/lib/krb4/g_krbrlm.c index 983150c..c750231 100644 --- a/src/lib/krb4/g_krbrlm.c +++ b/src/lib/krb4/g_krbrlm.c @@ -44,7 +44,8 @@ krb_get_lrealm(r,n) cnffile = krb__get_cnffile(); if (!cnffile) { if (n == 1) { - (void) strcpy(r, KRB_REALM); + (void) strncpy(r, KRB_REALM, REALM_SZ); + r[REALM_SZ - 1] = '\0'; return(KSUCCESS); } else diff --git a/src/lib/krb4/g_pw_in_tkt.c b/src/lib/krb4/g_pw_in_tkt.c index 6723df8..13f762b 100644 --- a/src/lib/krb4/g_pw_in_tkt.c +++ b/src/lib/krb4/g_pw_in_tkt.c @@ -176,7 +176,6 @@ krb_get_pw_in_tkt_preauth(user,instance,realm,service,sinstance,life,password) #include <signal.h> #include <setjmp.h> #else -char *strcpy(); int strcmp(); #endif #if defined(__svr4__) || defined(__SVR4) diff --git a/src/lib/krb4/in_tkt.c b/src/lib/krb4/in_tkt.c index ea17be8..4e220f9 100644 --- a/src/lib/krb4/in_tkt.c +++ b/src/lib/krb4/in_tkt.c @@ -159,8 +159,9 @@ in_tkt(pname,pinst) } (void) close(tktfile); #ifdef TKT_SHMEM - (void) strcpy(shmidname, file); - (void) strcat(shmidname, ".shm"); + (void) strncpy(shmidname, file, sizeof(shmidname) - 1); + shmidname[sizeof(shmidname) - 1] = '\0'; + (void) strncat(shmidname, ".shm", sizeof(shmidname) - 1 - strlen(shmidname)); return(krb_shm_create(shmidname)); #else /* !TKT_SHMEM */ return(KSUCCESS); diff --git a/src/lib/krb4/kntoln.c b/src/lib/krb4/kntoln.c index 8b6cdfe..f86599c 100644 --- a/src/lib/krb4/kntoln.c +++ b/src/lib/krb4/kntoln.c @@ -38,6 +38,10 @@ * KSUCCESS if all goes well, otherwise KFAILURE. */ +/* The definition of MAX_USERNAME here MUST agree with kuserok.c, or bad + * things will happen. */ +#define MAX_USERNAME 10 + krb_kntoln(ad,lname) AUTH_DAT *ad; char *lname; @@ -51,6 +55,7 @@ krb_kntoln(ad,lname) return(KFAILURE); if (strcmp(ad->prealm,lrealm)) return(KFAILURE); - (void) strcpy(lname,ad->pname); + (void) strncpy(lname,ad->pname,MAX_USERNAME-1); + lname[MAX_USERNAME - 1] = '\0'; return(KSUCCESS); } diff --git a/src/lib/krb4/kparse.c b/src/lib/krb4/kparse.c index 98e48fb..e72295c 100644 --- a/src/lib/krb4/kparse.c +++ b/src/lib/krb4/kparse.c @@ -54,8 +54,8 @@ static char *strutol(); -#ifndef HAVE_STRSAVE -static char *strsave(); +#ifndef HAVE_STRDUP +static char *strdup(); #endif #ifndef HAVE_STDLIB_H extern char *malloc(); @@ -104,7 +104,7 @@ int fGetParameterSet( fp,parm,parmcount ) keyword); return(PS_BAD_KEYWORD); } - parm[i].value = strsave( value ); + parm[i].value = strdup(value); break; } } @@ -552,34 +552,6 @@ int fGetChar(fp) return(ch); } - -/* - * Routine Name: strsave - * - * Function: return a pointer to a saved copy of the - * input string. the copy will be allocated - * as large as necessary. - * - * Explicit Parameters: pointer to string to save - * - * Implicit Parameters: None - * - * External Procedures: malloc,strcpy,strlen - * - * Side Effects: None - * - * Return Value: pointer to copied string - * - */ -#ifndef HAVE_STRSAVE -static char * strsave(p) - char *p; -{ - return(strcpy(malloc(strlen(p)+1),p)); -} -#endif - - /* * strutol changes all characters in a string to lower case, in place. * the pointer to the beginning of the string is returned. @@ -770,3 +742,42 @@ main(argc,argv) exit(0); } #endif + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* based on @(#)strdup.c 5.3 (Berkeley) 6/1/90 */ + +#ifndef HAVE_STRDUP +static char * +strdup(str) + const char *str; +{ + int len; + char *copy; + + if (!str) + return((char *)0); + len = strlen(str) + 1; + if (!(copy = malloc((u_int)len))) + return((char *)0); + memcpy(copy, str, len); + return(copy); +} +#endif diff --git a/src/lib/krb4/kuserok.c b/src/lib/krb4/kuserok.c index 0aee893..20587cb 100644 --- a/src/lib/krb4/kuserok.c +++ b/src/lib/krb4/kuserok.c @@ -118,8 +118,11 @@ kuserok(kdata, luser) if ((pwd = getpwnam(luser)) == NULL) { return(NOTOK); } - (void) strcpy(pbuf, pwd->pw_dir); - (void) strcat(pbuf, "/.klogin"); + if (strlen (pwd->pw_dir) + sizeof ("/.klogin") >= sizeof (pbuf)) + return NOTOK; + (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1); + pbuf[sizeof(pbuf) - 1] = '\0'; + (void) strncat(pbuf, "/.klogin", sizeof(pbuf) - 1 - strlen(pbuf)); if (access(pbuf, F_OK)) { /* not accessible */ /* diff --git a/src/lib/krb4/mk_auth.c b/src/lib/krb4/mk_auth.c index 39a2e2f..a94a25d 100644 --- a/src/lib/krb4/mk_auth.c +++ b/src/lib/krb4/mk_auth.c @@ -124,8 +124,10 @@ krb_mk_auth(options, ticket, service, inst, realm, checksum, version, buf) realm = krb_realm; } - if (!(options & KOPT_DONT_CANON)) - (void) strncpy(inst, krb_get_phost(inst), INST_SZ); + if (!(options & KOPT_DONT_CANON)) { + (void) strncpy(inst, krb_get_phost(inst), INST_SZ - 1); + inst[INST_SZ-1] = 0; + } /* get the ticket if desired */ if (!(options & KOPT_DONT_MK_REQ)) { diff --git a/src/lib/krb4/mk_err.c b/src/lib/krb4/mk_err.c index e30e299..029aa9f 100644 --- a/src/lib/krb4/mk_err.c +++ b/src/lib/krb4/mk_err.c @@ -41,6 +41,14 @@ krb_mk_err(p,e,e_string) { u_char *start; + /* Just return the buffer length if p is NULL, because writing to the + * buffer would be a bad idea. Note that this feature is a change from + * previous versions, and can therefore only be used safely in this + * source tree, where we know this function supports it. */ + if(p == NULL) { + return 2 + sizeof(e) + strlen(e_string); + } + start = p; /* Create fixed part of packet */ diff --git a/src/lib/krb4/mk_req.c b/src/lib/krb4/mk_req.c index 1936cb2..468dccd 100644 --- a/src/lib/krb4/mk_req.c +++ b/src/lib/krb4/mk_req.c @@ -130,6 +130,19 @@ krb_mk_req(authent,service,instance,realm,checksum) if (retval != KSUCCESS) return (retval); + if(sizeof(authent->dat) / 8 < (3 + + strlen(realm) + 1 + 2 + + 3 + ticket->length + + strlen(cr.pname) + 1 + + strlen(cr.pinst) + 1 + + strlen(myrealm) + 1 + + 4 + /* checksum */ + 4 + /* timestamp */ + 7) / 8) { /* round-up */ + authent->length = 0; + return KFAILURE; + } + if (krb_ap_req_debug) DEB (("%s %s %s %s %s\n", service, instance, realm, cr.pname, cr.pinst)); diff --git a/src/lib/krb4/rd_req.c b/src/lib/krb4/rd_req.c index c9b6ac7..09f914d 100644 --- a/src/lib/krb4/rd_req.c +++ b/src/lib/krb4/rd_req.c @@ -108,6 +108,19 @@ krb_clear_key_krb5(ctx) krb5_key = 0; } +/* A helper function to let us see if a buffer is properly terminated. */ +static int +krb_strnlen(const char *str, size_t max_len) +{ + int i = 0; + for(i = 0; i < max_len; i++) { + if(str[i] == '\0') { + return i; + } + } + return -1; +} + /* * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(), @@ -184,6 +197,8 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) krb5_keyblock keyblock; int status; + tkt->mbz = req_id->mbz = 0; + if (authent->length <= 0) return(RD_AP_MODIFIED); @@ -219,8 +234,13 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) mutual = 0; #endif /* lint */ s_kvno = *ptr++; /* get server key version */ - (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */ - ptr += strlen(ptr) + 1; /* skip the realm "hint" */ + if(krb_strnlen(ptr, sizeof(realm)) < 0) { + return RD_AP_MODIFIED; /* must have been modified, the client wouldn't + try to trick us with wacky data */ + } + (void) strncpy(realm,ptr,REALM_SZ); /* And the realm of the issuing KDC */ + realm[REALM_SZ-1] = '\0'; + ptr += strlen(realm) + 1; /* skip the realm "hint" */ /* * If "fn" is NULL, key info should already be set; don't @@ -249,13 +269,16 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) return(RD_AP_UNDEC); #endif /* !NOENCRYPTION */ - (void) strcpy(st_rlm,realm); - (void) strcpy(st_nam,service); - (void) strcpy(st_inst,instance); + (void) strncpy(st_rlm,realm, sizeof(st_rlm) - 1); + st_rlm[sizeof(st_rlm) - 1] = '\0'; + (void) strncpy(st_nam,service, sizeof(st_nam) - 1); + st_nam[sizeof(st_nam) - 1] = '\0'; + (void) strncpy(st_inst,instance, sizeof(st_inst) - 1); + st_inst[sizeof(st_inst) - 1] = '\0'; } /* Get ticket from authenticator */ - tkt->length = (int) *ptr++; + tkt->length = (int) *ptr++ & 0xff; if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length) return(RD_AP_MODIFIED); memcpy((char *)(tkt->dat), ptr+1, tkt->length); @@ -324,13 +347,16 @@ krb_rd_req(authent,service,instance,from_addr,ad,fn) #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED); ptr = (char *) req_id->dat; - (void) strcpy(r_aname,ptr); /* Authentication name */ + (void) strncpy(r_aname,ptr,ANAME_SZ); /* Authentication name */ + r_aname[ANAME_SZ-1] = '\0'; ptr += strlen(r_aname)+1; check_ptr(); - (void) strcpy(r_inst,ptr); /* Authentication instance */ + (void) strncpy(r_inst,ptr,INST_SZ); /* Authentication instance */ + r_inst[INST_SZ-1] = '\0'; ptr += strlen(r_inst)+1; check_ptr(); - (void) strcpy(r_realm,ptr); /* Authentication name */ + (void) strncpy(r_realm,ptr,REALM_SZ); /* Authentication name */ + r_realm[REALM_SZ-1] = '\0'; ptr += strlen(r_realm)+1; check_ptr(); memcpy((char *)&ad->checksum, ptr, 4); /* Checksum */ diff --git a/src/lib/krb4/realmofhost.c b/src/lib/krb4/realmofhost.c index 90e01bb..1e4b786 100644 --- a/src/lib/krb4/realmofhost.c +++ b/src/lib/krb4/realmofhost.c @@ -131,14 +131,18 @@ krb_realmofhost(host) if (domain && (strlen(trans_host) == strlen(domain)) && !strcasecmp (trans_host, domain)) { /* got domain match, save for later */ - (void) strcpy (ret_realm, trans_realm); + (void) strncpy (ret_realm, trans_realm, + sizeof(ret_realm) - 1); + ret_realm[sizeof(ret_realm) - 1] = '\0'; continue; } } else { /* want exact match of hostname */ if ((strlen(lhost) == strlen(trans_host)) && !strcasecmp (trans_host, lhost)) { - (void) strcpy (ret_realm, trans_realm); + (void) strncpy (ret_realm, trans_realm, + sizeof(ret_realm) - 1); + ret_realm[sizeof(ret_realm) - 1] = '\0'; break; } } diff --git a/src/lib/krb4/recvauth.c b/src/lib/krb4/recvauth.c index e62e3f9..2a66656 100644 --- a/src/lib/krb4/recvauth.c +++ b/src/lib/krb4/recvauth.c @@ -188,9 +188,12 @@ krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata, if (i < KRB_SENDAUTH_VLEN) { /* since we already got the space, and part of the ticket, we read fewer bytes to get the rest of the ticket */ + int len_to_read = tkt_len - KRB_SENDAUTH_VLEN + 1 + i; + if (len_to_read <= 0) + return KFAILURE; if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN), - (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i)) - != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i)) + len_to_read) + != len_to_read) return(errno); } else { if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) != diff --git a/src/lib/krb4/send_to_kdc.c b/src/lib/krb4/send_to_kdc.c index c7e0fb3..f93b9d0 100644 --- a/src/lib/krb4/send_to_kdc.c +++ b/src/lib/krb4/send_to_kdc.c @@ -94,12 +94,13 @@ send_to_kdc(pkt,rpkt,realm) * local realm. */ if (realm) - (void) strcpy(lrealm, realm); + (void) strncpy(lrealm, realm, sizeof(lrealm) - 1); else if (krb_get_lrealm(lrealm,1)) { DEB (("%s: can't get local realm\n", prog)); return(SKDC_CANT); } + lrealm[sizeof(lrealm) - 1] = '\0'; DEB (("lrealm is %s\n", lrealm)); if (SOCKET_INITIALIZE()) { diff --git a/src/lib/krb4/sendauth.c b/src/lib/krb4/sendauth.c index 9b8fb39..76c470c 100644 --- a/src/lib/krb4/sendauth.c +++ b/src/lib/krb4/sendauth.c @@ -208,7 +208,8 @@ krb_sendauth(options, fd, ticket, service, inst, realm, checksum, } /* copy instance into local storage, so mk_auth can canonicalize */ - (void) strncpy(srv_inst, inst, INST_SZ); + (void) strncpy(srv_inst, inst, INST_SZ-1); + srv_inst[INST_SZ-1] = 0; rem = krb_mk_auth (options, ticket, service, srv_inst, realm, checksum, version, packet); if (rem != KSUCCESS) diff --git a/src/lib/krb4/tf_util.c b/src/lib/krb4/tf_util.c index ebf500b..0d69719 100644 --- a/src/lib/krb4/tf_util.c +++ b/src/lib/krb4/tf_util.c @@ -181,8 +181,9 @@ int tf_init(tf_name, rw) tf_name = tkt_string(); #ifdef TKT_SHMEM - (void) strcpy(shmidname, tf_name); - (void) strcat(shmidname, ".shm"); + (void) strncpy(shmidname, tf_name, sizeof(shmidname) - 1); + shmidname[sizeof(shmidname) - 1] = '\0'; + (void) strncat(shmidname, ".shm", sizeof(shmidname) - 1 - strlen(shmidname)); #endif /* TKT_SHMEM */ /* diff --git a/src/lib/krb4/win_store.c b/src/lib/krb4/win_store.c index 50507aa..28d11bd 100644 --- a/src/lib/krb4/win_store.c +++ b/src/lib/krb4/win_store.c @@ -62,15 +62,17 @@ krb__get_cnffile() char defname[FILENAME_MAX]; UINT rc; - rc = GetWindowsDirectory(defname, sizeof(defname)); + defname[sizeof(defname) - 1] = '\0'; + rc = GetWindowsDirectory(defname, sizeof(defname) - 1); assert(rc > 0); - strcat(defname, "\\"); + strncat(defname, "\\", sizeof(defname) - 1 - strlen(defname)); - strcat(defname, DEF_KRB_CONF); + strncat(defname, DEF_KRB_CONF, sizeof(defname) - 1 - strlen(defname)); + cnfname[sizeof(cnfname) - 1] = '\0'; GetPrivateProfileString(INI_FILES, INI_KRB_CONF, defname, - cnfname, sizeof(cnfname), KERBEROS_INI); + cnfname, sizeof(cnfname) - 1, KERBEROS_INI); cnffile = fopen(cnfname, "r"); @@ -94,15 +96,17 @@ krb__get_realmsfile() char defname[FILENAME_MAX]; UINT rc; - rc = GetWindowsDirectory(defname, sizeof(defname)); + defname[sizeof(defname) - 1] = '\0'; + rc = GetWindowsDirectory(defname, sizeof(defname) - 1); assert(rc > 0); - strcat(defname, "\\"); + strncat(defname, "\\", sizeof(defname) - 1 - strlen(defname)); - strcat(defname, DEF_KRB_REALMS); + strncat(defname, DEF_KRB_REALMS, sizeof(defname) - 1 - strlen(defname)); + defname[sizeof(defname) - 1] = '\0'; GetPrivateProfileString(INI_FILES, INI_KRB_REALMS, defname, - realmsname, sizeof(realmsname), KERBEROS_INI); + realmsname, sizeof(realmsname) - 1, KERBEROS_INI); realmsfile = fopen(realmsname, "r"); diff --git a/src/lib/krb5/ChangeLog b/src/lib/krb5/ChangeLog index 89f7f2e..0610803 100644 --- a/src/lib/krb5/ChangeLog +++ b/src/lib/krb5/ChangeLog @@ -1,3 +1,11 @@ +2000-06-23 Tom Yu <tlyu@mit.edu> + + * Makefile.in (LIBMAJOR, LIBMINOR): Bump version. + +2000-06-23 Ken Raeburn <raeburn@mit.edu> + + * Makefile.in (SHLIB_EXPLIBS): Add @RESOLV_LIB@. + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * configure.in: Check for existance of <memory.h>. diff --git a/src/lib/krb5/Makefile.in b/src/lib/krb5/Makefile.in index 0dab1f3..68e354c 100644 --- a/src/lib/krb5/Makefile.in +++ b/src/lib/krb5/Makefile.in @@ -32,8 +32,8 @@ LIBDONE= error_tables/DONE asn.1/DONE ccache/DONE ccache/stdio/DONE \ STLIBOBJS=krb5_libinit.o LIB=krb5 -LIBMAJOR=2 -LIBMINOR=2 +LIBMAJOR=3 +LIBMINOR=0 STOBJLISTS= \ OBJS.ST \ @@ -58,7 +58,7 @@ RELDIR=krb5 SHLIB_EXPDEPS = \ $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ $(TOPLIBD)/libcom_err$(SHLIBEXT) -SHLIB_EXPLIBS=-lk5crypto -lcom_err @GEN_LIB@ +SHLIB_EXPLIBS=-lk5crypto -lcom_err @GEN_LIB@ @RESOLV_LIB@ SHLIB_DIRS=-L$(TOPLIBD) SHLIB_RDIRS=$(KRB5_LIBDIR) diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog index 14fa9c3..80f24eb 100644 --- a/src/lib/krb5/krb/ChangeLog +++ b/src/lib/krb5/krb/ChangeLog @@ -1,3 +1,102 @@ +2000-06-23 Miro Jurisic <meeroh@mit.edu> + + * conv_princ.c (krb5_425_conv_principal): Fixed v4->v5 realm + name conversion + + * conv_princ.c (krb5_425_conv_principal): Honor v4/v5 realm name + differences when convertion from v4 principals to v5. + +2000-06-23 Tom Yu <tlyu@mit.edu> + + * get_creds.c (krb5_get_credentials): Translate KRB5_CC_NOTFOUND + returned from krb5_get_cred_from_kdc() if a prior call to + krb5_cc_retrieve_cred() returned KRB5_CC_NOT_KTYPE. + + * rd_priv.c (krb5_rd_priv_basic): Delete code that was incorrectly + doing explicit ivec chaining; c_decrypt() does it now. + + * mk_priv.c (krb5_mk_priv_basic): Delete code that was incorrectly + doing explicit ivec chaining; c_encrypt() does it now. + + * conv_princ.c (krb5_524_conv_principal): Make a copy of the krb5 + realm that is nul-terminated to avoid falling off the end of the + krb5 realm, which is not necessarily nul-terminated. + +2000-06-23 Danilo Almeida <dalmeida@mit.edu> + + * init_ctx.c (krb5_get_tgs_ktypes, krb5_free_ktypes): Fix linkage to + be KRB5_CALLCONV. + +2000-06-23 Ken Raeburn <raeburn@mit.edu> + + * get_in_tkt.c (krb5_get_in_tkt): If enctypes are specified, send + the server the intersection of that list and the supported types, + in the order requested. + + * recvauth.c (krb5_recvauth_version): New routine, takes a + krb5_data in which to store the client's application version + string. + (recvauth_common): Renamed from krb5_recvauth, added above + functionality depending on extra argument values. + (krb5_recvauth): New stub, calls above routine with extra dummy + values. + + * kfree.c: Remove unneeded "return" statements at the end of many + functions. + (krb5_free_*_content, krb5_free_*_contents, + krb5_free_cred_enc_part, krb5_free_pwd_sequences): Set freed + pointer members to null when containing structure isn't being + freed. + + * t_kerb.c (test_524_conv_principal): New test code, to exercise + bbense's code addition. + (main, usage): Updated. + * t_krb5.conf: Added stanford.edu->IR.STANFORD.EDU mapping, and a + test case for improperly long v4 realm names. + * Makefile.in (check-unix): Run 524 conversion test for some test + Athena and Stanford names. + * t_ref_kerb.out: Updated. + + * init_ctx.c (init_common): Feed current-microsecond time and + process-id into PRNG, instead of just current-second time. + * mk_req_ext.c (krb5_mk_req_extended): Feed current time into + PRNG if a subkey will be generated. + * sendauth.c (krb5_sendauth): Feed local and remote addresses of + socket, if they can be determined, into the PRNG if a subkey will + be used. + + * init_ctx.c (krb5_free_ktypes): New routine, to free values + returned by krb5_get_tgs_ktypes, krb5_get_permitted_enctypes, and + krb5_get_default_in_tkt_ktypes. + (krb5_set_default_tgs_ktypes, krb5_is_permitted_enctype): Use it. + (get_profile_etype_list): Use passed-in enctype list if the + passed-in count is non-zero, instead of checking the + in_tkt_ktype_count value in the context. + +2000-06-23 Ken Raeburn <raeburn@mit.edu> + Nalin Dahyabhai <nalin@redhat.com> + + * conv_princ.c (krb5_524_conv_principal): Return an error if name + is too long. Use memcpy for character data since we already know + the length. + +2000-06-23 Nalin Dahyabhai <nalin@redhat.com> + + * kfree.c (krb5_free_keyblock_contents): Set contents pointer to + null after freeing. + + * chk_trans.c (krb5_check_transited_list): Don't overflow buffers + "prev" and "next". + * conv_princ.c (krb5_425_conv_principal): Don't overflow buffer + "buf". + +2000-06-23 Ken Raeburn <raeburn@mit.edu> + Booker C. Bense <bbense@networking.stanford.edu> + + * conv_princ.c (krb5_524_conv_principal): Look up v4_realm in + config file, in case site's krb4 realm name isn't the same as the + krb5 realm name. + 2000-05-31 Wilfredo Sanchez <tritan@mit.edu> * fwd_tgt.c: Check for existance of <memory.h>. @@ -22,8 +121,9 @@ 2000-04-28 Alexandra Ellwood <lxs@mit.edu> - * gic_pwd.c (krb5_init_creds_password) added code to return to login library if - the password is expired (login library handles this error appropriately). + * gic_pwd.c (krb5_init_creds_password) added code to return to + login library if the password is expired (login library handles + this error appropriately). 2000-04-08 Tom Yu <tlyu@mit.edu> @@ -32,11 +132,12 @@ 2000-04-07 Jeffrey Altman <jaltman@columbia.edu> - * gic_pwd.c (krb5_get_init_creds_keytab), gic_pwd.c (krb5_get_init_creds_password) - when determining whether or not to retry with a "master kdc" do not retry if - the return value from the first attempt was KRB5_REALM_CANT_RESOLV. Also, do - not overwrite the return code if the return value from the access to the "master - kdc" was KRB5_REALM_CANT_RESOLV. + * gic_pwd.c (krb5_get_init_creds_keytab), gic_pwd.c + (krb5_get_init_creds_password) when determining whether or not to + retry with a "master kdc" do not retry if the return value from + the first attempt was KRB5_REALM_CANT_RESOLV. Also, do not + overwrite the return code if the return value from the access to + the "master kdc" was KRB5_REALM_CANT_RESOLV. 2000-03-15 Danilo Almeida <dalmeida@mit.edu> diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 8aeb398..19c1da4 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -327,6 +327,8 @@ check-unix:: $(TEST_PROGS) 425_conv_principal rcmd uunet UU.NET \ 425_conv_principal zephyr zephyr ATHENA.MIT.EDU \ 425_conv_principal kadmin ATHENA.MIT.EDU ATHENA.MIT.EDU \ + 524_conv_principal host/e40-po.mit.edu@ATHENA.MIT.EDU \ + 524_conv_principal host/foobar.stanford.edu@stanford.edu \ set_realm marc@MIT.EDU CYGNUS.COM \ > test.out cmp test.out $(srcdir)/t_ref_kerb.out diff --git a/src/lib/krb5/krb/chk_trans.c b/src/lib/krb5/krb/chk_trans.c index c2ac716..eee55c8 100644 --- a/src/lib/krb5/krb/chk_trans.c +++ b/src/lib/krb5/krb/chk_trans.c @@ -56,13 +56,13 @@ krb5_data *realm2; return(retval); } - memset(prev, 0, MAX_REALM_LN + 1); - memset(next, 0, MAX_REALM_LN + 1), nextp = next; + memset(prev, 0, sizeof(prev)); + memset(next, 0, sizeof(next)), nextp = next; for (i = 0; i < trans_length; i++) { if (i < trans_length-1 && trans->data[i] == '\\') { i++; *nextp++ = trans->data[i]; - if (nextp - next > MAX_REALM_LN) { + if (nextp - next >= sizeof(next)) { retval = KRB5KRB_AP_ERR_ILL_CR_TKT; goto finish; } @@ -70,16 +70,17 @@ krb5_data *realm2; } if (i < trans_length && trans->data[i] != ',') { *nextp++ = trans->data[i]; - if (nextp - next > MAX_REALM_LN) { + if (nextp - next >= sizeof(next)) { retval = KRB5KRB_AP_ERR_ILL_CR_TKT; goto finish; } continue; } + next[sizeof(next) - 1] = '\0'; if (strlen(next) > 0) { if (next[0] != '/') { if (*(nextp-1) == '.' && strlen(next) + strlen(prev) <= MAX_REALM_LN) - strcat(next, prev); + strncat(next, prev, sizeof(next) - 1 - strlen(next)); retval = KRB5KRB_AP_ERR_ILL_CR_TKT; for (j = 0; tgs_list[j]; j++) { if (strlen(next) == (size_t) krb5_princ_realm(context, tgs_list[j])->length && @@ -93,12 +94,12 @@ krb5_data *realm2; } if (i+1 < trans_length && trans->data[i+1] == ' ') { i++; - memset(next, 0, MAX_REALM_LN + 1), nextp = next; + memset(next, 0, sizeof(next)), nextp = next; continue; } if (i+1 < trans_length && trans->data[i+1] != '/') { - strcpy(prev, next); - memset(next, 0, MAX_REALM_LN + 1), nextp = next; + strncpy(prev, next, sizeof(prev) - 1); + memset(next, 0, sizeof(next)), nextp = next; continue; } } diff --git a/src/lib/krb5/krb/conv_princ.c b/src/lib/krb5/krb/conv_princ.c index b90289a..36e2bbd 100644 --- a/src/lib/krb5/krb/conv_princ.c +++ b/src/lib/krb5/krb/conv_princ.c @@ -137,7 +137,8 @@ krb5_524_conv_principal(context, princ, name, inst, realm) { const struct krb_convert *p; krb5_data *compo; - char *c; + char *c, *tmp_realm, *tmp_prealm; + int tmp_realm_len, retval; *name = *inst = '\0'; switch (krb5_princ_size(context, princ)) { @@ -147,18 +148,22 @@ krb5_524_conv_principal(context, princ, name, inst, realm) p = sconv_list; while (p->v4_str) { if (strncmp(p->v5_str, compo->data, compo->length) == 0) { - /* It is, so set the new name now, and chop off */ - /* instance's domain name if requested */ - strcpy(name, p->v4_str); - if (p->flags & DO_REALM_CONVERSION) { - compo = krb5_princ_component(context, princ, 1); - c = strnchr(compo->data, '.', compo->length); - if (!c || (c - compo->data) > INST_SZ - 1) - return KRB5_INVALID_PRINCIPAL; - strncpy(inst, compo->data, c - compo->data); - inst[c - compo->data] = '\0'; - } - break; + /* + * It is, so set the new name now, and chop off + * instance's domain name if requested. + */ + if (strlen (p->v4_str) > ANAME_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + strcpy(name, p->v4_str); + if (p->flags & DO_REALM_CONVERSION) { + compo = krb5_princ_component(context, princ, 1); + c = strnchr(compo->data, '.', compo->length); + if (!c || (c - compo->data) >= INST_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + memcpy(inst, compo->data, c - compo->data); + inst[c - compo->data] = '\0'; + } + break; } p++; } @@ -168,7 +173,7 @@ krb5_524_conv_principal(context, princ, name, inst, realm) compo = krb5_princ_component(context, princ, 1); if (compo->length >= INST_SZ - 1) return KRB5_INVALID_PRINCIPAL; - strncpy(inst, compo->data, compo->length); + memcpy(inst, compo->data, compo->length); inst[compo->length] = '\0'; } /* fall through */ @@ -178,7 +183,7 @@ krb5_524_conv_principal(context, princ, name, inst, realm) compo = krb5_princ_component(context, princ, 0); if (compo->length >= ANAME_SZ) return KRB5_INVALID_PRINCIPAL; - strncpy(name, compo->data, compo->length); + memcpy(name, compo->data, compo->length); name[compo->length] = '\0'; } break; @@ -187,11 +192,39 @@ krb5_524_conv_principal(context, princ, name, inst, realm) } compo = krb5_princ_realm(context, princ); - if (compo->length > REALM_SZ - 1) - return KRB5_INVALID_PRINCIPAL; - strncpy(realm, compo->data, compo->length); - realm[compo->length] = '\0'; + tmp_prealm = malloc(compo->length + 1); + if (tmp_prealm == NULL) + return ENOMEM; + strncpy(tmp_prealm, compo->data, compo->length); + tmp_prealm[compo->length] = '\0'; + + /* Ask for v4_realm corresponding to + krb5 principal realm from krb5.conf realms stanza */ + + if (context->profile == 0) + return KRB5_CONFIG_CANTOPEN; + retval = profile_get_string(context->profile, "realms", + tmp_prealm, "v4_realm", 0, + &tmp_realm); + free(tmp_prealm); + if (retval) { + return retval; + } else { + if (tmp_realm == 0) { + if (compo->length > REALM_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + strncpy(realm, compo->data, compo->length); + realm[compo->length] = '\0'; + } else { + tmp_realm_len = strlen(tmp_realm); + if (tmp_realm_len > REALM_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + strncpy(realm, tmp_realm, tmp_realm_len); + realm[tmp_realm_len] = '\0'; + profile_release_string(tmp_realm); + } + } return 0; } @@ -209,6 +242,37 @@ krb5_425_conv_principal(context, name, instance, realm, princ) char *domain, *cp; char **full_name = 0, **cpp; const char *names[5]; + void* iterator = NULL; + char** v4realms = NULL; + char* realm_name = NULL; + char* dummy_value = NULL; + + /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm + To do that, iterate over all the realms in the config file, looking for a matching + v4_realm line */ + names [0] = "realms"; + names [1] = NULL; + retval = profile_iterator_create (context -> profile, names, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator); + while (retval == 0) { + retval = profile_iterator (&iterator, &realm_name, &dummy_value); + if ((retval == 0) && (realm_name != NULL)) { + names [0] = "realms"; + names [1] = realm_name; + names [2] = "v4_realm"; + names [3] = NULL; + + retval = profile_get_values (context -> profile, names, &v4realms); + if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) { + realm = realm_name; + break; + } else if (retval == PROF_NO_RELATION) { + /* If it's not found, just keep going */ + retval = 0; + } + } else if ((retval == 0) && (realm_name == NULL)) { + break; + } + } if (instance) { if (instance[0] == '\0') { @@ -234,7 +298,8 @@ krb5_425_conv_principal(context, name, instance, realm, princ) if (retval == 0 && full_name && full_name[0]) { instance = full_name[0]; } else { - strcpy(buf, instance); + strncpy(buf, instance, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; retval = krb5_get_realm_domain(context, realm, &domain); if (retval) return retval; @@ -242,8 +307,8 @@ krb5_425_conv_principal(context, name, instance, realm, princ) for (cp = domain; *cp; cp++) if (isupper(*cp)) *cp = tolower(*cp); - strcat(buf, "."); - strcat(buf, domain); + strncat(buf, ".", sizeof(buf) - 1 - strlen(buf)); + strncat(buf, domain, sizeof(buf) - 1 - strlen(buf)); krb5_xfree(domain); } instance = buf; @@ -254,6 +319,10 @@ krb5_425_conv_principal(context, name, instance, realm, princ) not_service: retval = krb5_build_principal(context, princ, strlen(realm), realm, name, instance, 0); + profile_iterator_free (&iterator); profile_free_list(full_name); + profile_free_list(v4realms); + profile_release_string (realm_name); + profile_release_string (dummy_value); return retval; } diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c index 3bcaa0b..6d764d3 100644 --- a/src/lib/krb5/krb/get_creds.c +++ b/src/lib/krb5/krb/get_creds.c @@ -102,6 +102,7 @@ krb5_get_credentials(context, options, ccache, in_creds, out_creds) krb5_creds *ncreds; krb5_creds **tgts; krb5_flags fields; + int not_ktype; retval = krb5_get_credentials_core(context, options, ccache, in_creds, out_creds, @@ -128,6 +129,11 @@ krb5_get_credentials(context, options, ccache, in_creds, out_creds) || options & KRB5_GC_CACHED) return retval; + if (retval == KRB5_CC_NOT_KTYPE) + not_ktype = 1; + else + not_ktype = 0; + retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts); if (tgts) { register int i = 0; @@ -141,6 +147,21 @@ krb5_get_credentials(context, options, ccache, in_creds, out_creds) } krb5_free_tgt_creds(context, tgts); } + /* + * Translate KRB5_CC_NOTFOUND if we previously got + * KRB5_CC_NOT_KTYPE from krb5_cc_retrieve_cred(), in order to + * handle the case where there is no TGT in the ccache and the + * input enctype didn't match. This handling is necessary because + * some callers, such as GSSAPI, iterate through enctypes and + * KRB5_CC_NOTFOUND passed through from the + * krb5_get_cred_from_kdc() is semantically incorrect, since the + * actual failure was the non-existence of a ticket of the correct + * enctype rather than the missing TGT. + */ + if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE) + && not_ktype) + retval = KRB5_CC_NOT_KTYPE; + if (!retval) retval = krb5_cc_store_cred(context, ccache, *out_creds); return retval; diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 9686f57..298f152 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -457,12 +457,35 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed, request.from = creds->times.starttime; request.till = creds->times.endtime; request.rtime = creds->times.renew_till; - if (ktypes) - request.ktype = ktypes; - else - if ((retval = krb5_get_default_in_tkt_ktypes(context, &request.ktype))) - goto cleanup; + if ((retval = krb5_get_default_in_tkt_ktypes(context, &request.ktype))) + goto cleanup; for (request.nktypes = 0;request.ktype[request.nktypes];request.nktypes++); + if (ktypes) { + int i, req, next = 0; + for (req = 0; ktypes[req]; req++) { + if (ktypes[req] == request.ktype[next]) { + next++; + continue; + } + for (i = next + 1; i < request.nktypes; i++) + if (ktypes[req] == request.ktype[i]) { + /* Found the enctype we want, but not in the + position we want. Move it, but keep the old + one from the desired slot around in case it's + later in our requested-ktypes list. */ + krb5_enctype t; + t = request.ktype[next]; + request.ktype[next] = request.ktype[i]; + request.ktype[i] = t; + next++; + break; + } + /* If we didn't find it, don't do anything special, just + drop it. */ + } + request.ktype[next] = 0; + request.nktypes = next; + } request.authorization_data.ciphertext.length = 0; request.authorization_data.ciphertext.data = 0; request.unenc_authdata = 0; @@ -538,7 +561,7 @@ krb5_get_in_tkt(context, options, addrs, ktypes, ptypes, key_proc, keyseed, goto cleanup; cleanup: - if (!ktypes && request.ktype) + if (request.ktype) free(request.ktype); if (!addrs && request.addresses) krb5_free_addresses(context, request.addresses); diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c index e2eccc4..c10c6f7 100644 --- a/src/lib/krb5/krb/init_ctx.c +++ b/src/lib/krb5/krb/init_ctx.c @@ -1,7 +1,7 @@ /* * lib/krb5/krb/init_ctx.c * - * Copyright 1994 by the Massachusetts Institute of Technology. + * Copyright 1994,1999,2000 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -84,7 +84,10 @@ init_common (context, secure) { krb5_context ctx = 0; krb5_error_code retval; - krb5_timestamp now; + struct { + krb5_int32 now, now_usec; + long pid; + } seed_data; krb5_data seed; int tmp; @@ -129,10 +132,11 @@ init_common (context, secure) goto cleanup; /* initialize the prng (not well, but passable) */ - if ((retval = krb5_timeofday(ctx, &now))) + if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec))) goto cleanup; - seed.length = sizeof(now); - seed.data = (char *) &now; + seed_data.pid = getpid (); + seed.length = sizeof(seed_data); + seed.data = (char *) &seed_data; if ((retval = krb5_c_random_seed(ctx, &seed))) goto cleanup; @@ -281,7 +285,7 @@ get_profile_etype_list(context, ktypes, profstr, ctx_count, ctx_list) { krb5_enctype *old_ktypes; - if (context->in_tkt_ktype_count) { + if (ctx_count) { /* application-set defaults */ if ((old_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * @@ -396,13 +400,23 @@ krb5_set_default_tgs_ktypes(context, ktypes) } if (context->tgs_ktypes) - free(context->tgs_ktypes); + krb5_free_ktypes(context, context->tgs_ktypes); context->tgs_ktypes = new_ktypes; context->tgs_ktype_count = i; return 0; } +void +KRB5_CALLCONV +krb5_free_ktypes (context, val) + krb5_context context; + krb5_enctype FAR *val; +{ + free (val); +} + krb5_error_code +KRB5_CALLCONV krb5_get_tgs_ktypes(context, princ, ktypes) krb5_context context; krb5_const_principal princ; @@ -441,7 +455,7 @@ krb5_is_permitted_enctype(context, etype) if (*ptr == etype) ret = 1; - krb5_xfree(list); + krb5_free_ktypes (context, list); return(ret); } diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index 24d8aaf..8e57f83 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -36,7 +36,6 @@ krb5_free_address(context, val) if (val->contents) krb5_xfree(val->contents); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -52,7 +51,6 @@ krb5_free_addresses(context, val) krb5_xfree(*temp); } krb5_xfree(val); - return; } @@ -64,7 +62,6 @@ krb5_free_ap_rep(context, val) if (val->enc_part.ciphertext.data) krb5_xfree(val->enc_part.ciphertext.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -77,7 +74,6 @@ krb5_free_ap_req(context, val) if (val->authenticator.ciphertext.data) krb5_xfree(val->authenticator.ciphertext.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -88,7 +84,6 @@ krb5_free_ap_rep_enc_part(context, val) if (val->subkey) krb5_free_keyblock(context, val->subkey); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -96,15 +91,22 @@ krb5_free_authenticator_contents(context, val) krb5_context context; krb5_authenticator FAR *val; { - if (val->checksum) + if (val->checksum) { krb5_free_checksum(context, val->checksum); - if (val->client) + val->checksum = 0; + } + if (val->client) { krb5_free_principal(context, val->client); - if (val->subkey) + val->client = 0; + } + if (val->subkey) { krb5_free_keyblock(context, val->subkey); - if (val->authorization_data) - krb5_free_authdata(context, val->authorization_data); - return; + val->subkey = 0; + } + if (val->authorization_data) { + krb5_free_authdata(context, val->authorization_data); + val->authorization_data = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -120,7 +122,6 @@ krb5_free_authdata(context, val) krb5_xfree(*temp); } krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -128,16 +129,8 @@ krb5_free_authenticator(context, val) krb5_context context; krb5_authenticator FAR *val; { - if (val->checksum) - krb5_free_checksum(context, val->checksum); - if (val->client) - krb5_free_principal(context, val->client); - if (val->subkey) - krb5_free_keyblock(context, val->subkey); - if (val->authorization_data) - krb5_free_authdata(context, val->authorization_data); + krb5_free_authenticator_contents(context, val); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -145,10 +138,8 @@ krb5_free_checksum(context, val) krb5_context context; register krb5_checksum *val; { - if (val->contents) - krb5_xfree(val->contents); + krb5_free_checksum_contents(context, val); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -156,9 +147,10 @@ krb5_free_checksum_contents(context, val) krb5_context context; register krb5_checksum *val; { - if (val->contents) + if (val->contents) { krb5_xfree(val->contents); - return; + val->contents = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -171,7 +163,6 @@ krb5_free_cred(context, val) if (val->enc_part.ciphertext.data) krb5_xfree(val->enc_part.ciphertext.data); krb5_xfree(val); - return; } /* @@ -184,23 +175,35 @@ krb5_free_cred_contents(context, val) krb5_context context; krb5_creds FAR *val; { - if (val->client) + if (val->client) { krb5_free_principal(context, val->client); - if (val->server) + val->client = 0; + } + if (val->server) { krb5_free_principal(context, val->server); + val->server = 0; + } if (val->keyblock.contents) { memset((char *)val->keyblock.contents, 0, val->keyblock.length); krb5_xfree(val->keyblock.contents); + val->keyblock.contents = 0; } - if (val->ticket.data) + if (val->ticket.data) { krb5_xfree(val->ticket.data); - if (val->second_ticket.data) + val->ticket.data = 0; + } + if (val->second_ticket.data) { krb5_xfree(val->second_ticket.data); - if (val->addresses) + val->second_ticket.data = 0; + } + if (val->addresses) { krb5_free_addresses(context, val->addresses); - if (val->authdata) + val->addresses = 0; + } + if (val->authdata) { krb5_free_authdata(context, val->authdata); - return; + val->authdata = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -210,10 +213,14 @@ krb5_free_cred_enc_part(context, val) { register krb5_cred_info **temp; - if (val->r_address) - krb5_free_address(context, val->r_address); - if (val->s_address) - krb5_free_address(context, val->s_address); + if (val->r_address) { + krb5_free_address(context, val->r_address); + val->r_address = 0; + } + if (val->s_address) { + krb5_free_address(context, val->s_address); + val->s_address = 0; + } if (val->ticket_info) { for (temp = val->ticket_info; *temp; temp++) { @@ -228,8 +235,8 @@ krb5_free_cred_enc_part(context, val) krb5_xfree((*temp)); } krb5_xfree(val->ticket_info); + val->ticket_info = 0; } - return; } @@ -240,7 +247,6 @@ krb5_free_creds(context, val) { krb5_free_cred_contents(context, val); krb5_xfree(val); - return; } @@ -252,7 +258,6 @@ krb5_free_data(context, val) if (val->data) krb5_xfree(val->data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -260,9 +265,10 @@ krb5_free_data_contents(context, val) krb5_context context; krb5_data FAR * val; { - if (val->data) + if (val->data) { krb5_xfree(val->data); - return; + val->data = 0; + } } void krb5_free_etype_info(context, info) @@ -294,7 +300,6 @@ krb5_free_enc_kdc_rep_part(context, val) if (val->caddrs) krb5_free_addresses(context, val->caddrs); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -313,7 +318,6 @@ krb5_free_enc_tkt_part(context, val) if (val->authorization_data) krb5_free_authdata(context, val->authorization_data); krb5_xfree(val); - return; } @@ -331,7 +335,6 @@ krb5_free_error(context, val) if (val->e_data.data) krb5_xfree(val->e_data.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -350,7 +353,6 @@ krb5_free_kdc_rep(context, val) if (val->enc_part2) krb5_free_enc_kdc_rep_part(context, val->enc_part2); krb5_xfree(val); - return; } @@ -376,7 +378,6 @@ krb5_free_kdc_req(context, val) if (val->second_ticket) krb5_free_tickets(context, val->second_ticket); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -387,8 +388,8 @@ krb5_free_keyblock_contents(context, key) if (key->contents) { memset(key->contents, 0, key->length); krb5_xfree(key->contents); + key->contents = 0; } - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -398,7 +399,6 @@ krb5_free_keyblock(context, val) { krb5_free_keyblock_contents(context, val); krb5_xfree(val); - return; } @@ -413,7 +413,6 @@ krb5_free_last_req(context, val) for (temp = val; *temp; temp++) krb5_xfree(*temp); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -429,7 +428,6 @@ krb5_free_pa_data(context, val) krb5_xfree(*temp); } krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -451,7 +449,6 @@ krb5_free_principal(context, val) if (val->realm.data) krb5_xfree(val->realm.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -462,7 +459,6 @@ krb5_free_priv(context, val) if (val->enc_part.ciphertext.data) krb5_xfree(val->enc_part.ciphertext.data); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -477,7 +473,6 @@ krb5_free_priv_enc_part(context, val) if (val->s_address) krb5_free_address(context, val->s_address); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -488,7 +483,6 @@ krb5_free_pwd_data(context, val) if (val->element) krb5_free_pwd_sequences(context, val->element); krb5_xfree(val); - return; } @@ -497,11 +491,14 @@ krb5_free_pwd_sequences(context, val) krb5_context context; passwd_phrase_element FAR * FAR *val; { - if ((*val)->passwd) + if ((*val)->passwd) { krb5_xfree((*val)->passwd); - if ((*val)->phrase) + (*val)->passwd = 0; + } + if ((*val)->phrase) { krb5_xfree((*val)->phrase); - return; + (*val)->phrase = 0; + } } @@ -519,7 +516,6 @@ krb5_free_safe(context, val) if (val->checksum) krb5_free_checksum(context, val->checksum); krb5_xfree(val); - return; } @@ -535,7 +531,6 @@ krb5_free_ticket(context, val) if (val->enc_part2) krb5_free_enc_tkt_part(context, val->enc_part2); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -548,7 +543,6 @@ krb5_free_tickets(context, val) for (temp = val; *temp; temp++) krb5_free_ticket(context, *temp); krb5_xfree(val); - return; } @@ -573,7 +567,6 @@ krb5_free_tkt_authent(context, val) if (val->authenticator) krb5_free_authenticator(context, val->authenticator); krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -583,7 +576,6 @@ krb5_free_unparsed_name(context, val) { if (val) krb5_xfree(val); - return; } KRB5_DLLIMP void KRB5_CALLCONV @@ -612,8 +604,10 @@ krb5_free_sam_challenge_contents(krb5_context ctx, krb5_sam_challenge FAR *sc) krb5_free_data_contents(ctx, &sc->sam_response_prompt); if (sc->sam_pk_for_sad.data) krb5_free_data_contents(ctx, &sc->sam_pk_for_sad); - if (sc->sam_cksum.contents) + if (sc->sam_cksum.contents) { krb5_xfree(sc->sam_cksum.contents); + sc->sam_cksum.contents = 0; + } } KRB5_DLLIMP void KRB5_CALLCONV @@ -656,8 +650,10 @@ krb5_free_predicted_sam_response_contents(krb5_context ctx, return; if (psr->sam_key.contents) krb5_free_keyblock_contents(ctx, &psr->sam_key); - if (psr->client) + if (psr->client) { krb5_free_principal(ctx, psr->client); + psr->client = 0; + } if (psr->msd.data) krb5_free_data_contents(ctx, &psr->msd); } @@ -689,4 +685,3 @@ krb5_free_pa_enc_ts(krb5_context ctx, krb5_pa_enc_ts FAR *pa_enc_ts) return; krb5_xfree(pa_enc_ts); } - diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c index 7685817..d72f6b2 100644 --- a/src/lib/krb5/krb/mk_priv.c +++ b/src/lib/krb5/krb/mk_priv.c @@ -93,14 +93,6 @@ krb5_mk_priv_basic(context, userdata, keyblock, replaydata, local_addr, 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 - blocksize), - blocksize); - if ((retval = encode_krb5_priv(&privmsg, &scratch2))) goto clean_encpart; diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index a8b20eb..88daab5 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -126,10 +126,24 @@ krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, in_creds, /* generate subkey if needed */ - if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->local_subkey)) + if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->local_subkey)) { + /* Provide some more fodder for random number code. + This isn't strong cryptographically; the point here is not + to guarantee randomness, but to make it less likely that multiple + sessions could pick the same subkey. */ + struct { + krb5_int32 sec, usec; + } rnd_data; + krb5_data d; + krb5_crypto_us_timeofday (&rnd_data.sec, &rnd_data.usec); + d.length = sizeof (rnd_data); + d.data = (char *) &rnd_data; + (void) krb5_c_random_seed (context, &d); + if ((retval = krb5_generate_subkey(context, &(in_creds)->keyblock, &(*auth_context)->local_subkey))) goto cleanup; + } if (in_data) { if ((*auth_context)->req_cksumtype == 0x8003) { diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index 9629b0c..ab6a531 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -101,13 +101,6 @@ krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr, &privmsg->enc_part, &scratch))) 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 - blocksize), - blocksize); - /* now decode the decrypted stuff */ if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part))) goto cleanup_scratch; diff --git a/src/lib/krb5/krb/recvauth.c b/src/lib/krb5/krb/recvauth.c index 3d5bce4..f74041c 100644 --- a/src/lib/krb5/krb/recvauth.c +++ b/src/lib/krb5/krb/recvauth.c @@ -37,20 +37,18 @@ static char *sendauth_version = "KRB5_SENDAUTH_V1.0"; -KRB5_DLLIMP krb5_error_code KRB5_CALLCONV -krb5_recvauth(context, auth_context, - /* IN */ - fd, appl_version, server, flags, keytab, - /* OUT */ - ticket) - krb5_context context; - krb5_auth_context FAR * auth_context; - krb5_pointer fd; - char FAR * appl_version; - krb5_principal server; - krb5_int32 flags; - krb5_keytab keytab; - krb5_ticket FAR * FAR * ticket; +krb5_error_code +recvauth_common(krb5_context context, + krb5_auth_context FAR * auth_context, + /* IN */ + krb5_pointer fd, + char FAR *appl_version, + krb5_principal server, + krb5_int32 flags, + krb5_keytab keytab, + /* OUT */ + krb5_ticket FAR * FAR * ticket, + krb5_data FAR *version) { krb5_auth_context new_auth_context; krb5_flags ap_option; @@ -91,12 +89,15 @@ krb5_recvauth(context, auth_context, */ if ((retval = krb5_read_message(context, fd, &inbuf))) return(retval); - if (strcmp(inbuf.data, appl_version)) { + if (appl_version && strcmp(inbuf.data, appl_version)) { krb5_xfree(inbuf.data); if (!problem) problem = KRB5_SENDAUTH_BADAPPLVERS; } - krb5_xfree(inbuf.data); + if (version && !problem) + *version = inbuf; + else + krb5_xfree(inbuf.data); /* * OK, now check the problem variable. If it's zero, we're * fine and we can continue. Otherwise, we have to signal an @@ -243,3 +244,38 @@ cleanup:; } return retval; } + +KRB5_DLLIMP krb5_error_code KRB5_CALLCONV +krb5_recvauth(context, auth_context, + /* IN */ + fd, appl_version, server, flags, keytab, + /* OUT */ + ticket) + krb5_context context; + krb5_auth_context FAR * auth_context; + krb5_pointer fd; + char FAR * appl_version; + krb5_principal server; + krb5_int32 flags; + krb5_keytab keytab; + krb5_ticket FAR * FAR * ticket; +{ + return recvauth_common (context, auth_context, fd, appl_version, + server, flags, keytab, ticket, 0); +} + +KRB5_DLLIMP krb5_error_code KRB5_CALLCONV +krb5_recvauth_version(krb5_context context, + krb5_auth_context FAR *auth_context, + /* IN */ + krb5_pointer fd, + krb5_principal server, + krb5_int32 flags, + krb5_keytab keytab, + /* OUT */ + krb5_ticket FAR * FAR *ticket, + krb5_data FAR *version) +{ + return recvauth_common (context, auth_context, fd, 0, + server, flags, keytab, ticket, version); +} diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c index 1e6b726..b19afdb 100644 --- a/src/lib/krb5/krb/sendauth.c +++ b/src/lib/krb5/krb/sendauth.c @@ -152,9 +152,32 @@ krb5_sendauth(context, auth_context, credsp = in_creds; } - if ((retval = krb5_mk_req_extended(context, auth_context, ap_req_options, - in_data, credsp, &outbuf))) - goto error_return; + if (ap_req_options & AP_OPTS_USE_SUBKEY) { + /* Provide some more fodder for random number code. + This isn't strong cryptographically; the point here is + not to guarantee randomness, but to make it less likely + that multiple sessions could pick the same subkey. */ + char rnd_data[1024]; + size_t len; + krb5_data d; + d.length = sizeof (rnd_data); + d.data = rnd_data; + len = sizeof (rnd_data); + if (getpeername (*(int*)fd, (struct sockaddr *) rnd_data, &len) == 0) { + d.length = len; + (void) krb5_c_random_seed (context, &d); + } + len = sizeof (rnd_data); + if (getsockname (*(int*)fd, (struct sockaddr *) rnd_data, &len) == 0) { + d.length = len; + (void) krb5_c_random_seed (context, &d); + } + } + + if ((retval = krb5_mk_req_extended(context, auth_context, + ap_req_options, in_data, credsp, + &outbuf))) + goto error_return; /* * First write the length of the AP_REQ message, then write diff --git a/src/lib/krb5/krb/t_kerb.c b/src/lib/krb5/krb/t_kerb.c index 2feef39..458015d 100644 --- a/src/lib/krb5/krb/t_kerb.c +++ b/src/lib/krb5/krb/t_kerb.c @@ -4,6 +4,7 @@ */ #include "krb5.h" +#include "kerberosIV/krb.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -56,6 +57,32 @@ void test_425_conv_principal(ctx, name, inst, realm) krb5_free_principal(ctx, princ); } +void test_524_conv_principal(ctx, name) + krb5_context ctx; + char *name; +{ + krb5_principal princ = 0; + krb5_error_code retval; + char aname[ANAME_SZ+1], inst[INST_SZ+1], realm[REALM_SZ+1]; + + aname[ANAME_SZ] = inst[INST_SZ] = realm[REALM_SZ] = 0; + retval = krb5_parse_name(ctx, name, &princ); + if (retval) { + com_err("krb5_parse_name", retval, 0); + goto fail; + } + retval = krb5_524_conv_principal(ctx, princ, aname, inst, realm); + if (retval) { + com_err("krb5_524_conv_principal", retval, 0); + goto fail; + } + printf("524_converted_principal(%s): '%s' '%s' '%s'\n", + name, aname, inst, realm); + fail: + if (princ) + krb5_free_principal (ctx, princ); +} + void test_parse_name(ctx, name) krb5_context ctx; const char *name; @@ -131,6 +158,7 @@ void usage(progname) { fprintf(stderr, "%s: Usage: %s 425_conv_principal <name> <inst> <realm\n", progname, progname); + fprintf(stderr, "\t%s 524_conv_principal <name>\n", progname); fprintf(stderr, "\t%s parse_name <name>\n", progname); fprintf(stderr, "\t%s set_realm <name> <realm>\n", progname); fprintf(stderr, "\t%s string_to_timestamp <time>\n", progname); @@ -186,6 +214,10 @@ main(argc, argv) argc--; argv++; if (!argc) usage(progname); test_string_to_timestamp(ctx, *argv); + } else if (strcmp(*argv, "524_conv_principal") == 0) { + argc--; argv++; + if (!argc) usage(progname); + test_524_conv_principal(ctx, *argv); } else usage(progname); diff --git a/src/lib/krb5/krb/t_krb5.conf b/src/lib/krb5/krb/t_krb5.conf index 5882d97..8d7a4d9 100644 --- a/src/lib/krb5/krb/t_krb5.conf +++ b/src/lib/krb5/krb/t_krb5.conf @@ -19,6 +19,12 @@ kdc = KERBEROS.CYGNUS.COM admin_server = KERBEROS.MIT.EDU } + stanford.edu = { + v4_realm = IR.STANFORD.EDU + } + LONGNAMES.COM = { + v4_realm = SOME-REALLY-LONG-REALM-NAME-V4-CANNOT-HANDLE.COM + } [domain_realm] .mit.edu = ATHENA.MIT.EDU diff --git a/src/lib/krb5/krb/t_ref_kerb.out b/src/lib/krb5/krb/t_ref_kerb.out index 9423944..08a5334 100644 --- a/src/lib/krb5/krb/t_ref_kerb.out +++ b/src/lib/krb5/krb/t_ref_kerb.out @@ -14,4 +14,6 @@ parsed (and unparsed) principal(\/slash/\@atsign/octa\/thorpe@\/slash\@at\/sign) 425_converted principal(rcmd, uunet, UU.NET): 'host/uunet.uu.net@UU.NET' 425_converted principal(zephyr, zephyr, ATHENA.MIT.EDU): 'zephyr/zephyr@ATHENA.MIT.EDU' 425_converted principal(kadmin, ATHENA.MIT.EDU, ATHENA.MIT.EDU): 'kadmin/ATHENA.MIT.EDU@ATHENA.MIT.EDU' +524_converted_principal(host/e40-po.mit.edu@ATHENA.MIT.EDU): 'rcmd' 'e40-po' 'ATHENA.MIT.EDU' +524_converted_principal(host/foobar.stanford.edu@stanford.edu): 'rcmd' 'foobar' 'IR.STANFORD.EDU' old principal: marc@MIT.EDU, modified principal: marc@CYGNUS.COM diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog index adf1c5d..33f8018 100644 --- a/src/lib/krb5/os/ChangeLog +++ b/src/lib/krb5/os/ChangeLog @@ -1,3 +1,50 @@ +2000-06-23 Miro Jurisic <meeroh@mit.edu> + + * init_os_ctx.c (os_get_default_config_files): Return ENOENT when + file is not found on MacOS (not ENFILE). Use Kerberos Preferences + library to locate the config files on Mac OS. Eliminated some + dead code. + +2000-06-23 Nalin Dahyabhai <nalin@redhat.com> + + * an_to_ln.c (do_replacement): Don't overflow buffers "in" or "out". + * hst_realm.c (krb5_try_realm_txt_rr): Don't overfill "host" when + malformed DNS responses are received. + + * ccdefname.c (get_from_os): Don't overflow buffer "name_buf". + * kuserok.c (krb5_kuserok): Don't overflow buffer "pbuf". + +2000-06-23 Ken Raeburn <raeburn@mit.edu> + + * localaddr.c: Include stddef.h. + (foreach_localaddr): Check each address against previously used + addresses, and skip duplicates, in case multiple interfaces have + the same address. If called functions fail, drop out of loop and + return nonzero. Use SIOCGSIZIFCONF ioctl if available to get the + buffer size needed for SIOCGIFCONF, and skip the silly heuristics + if it returns a reasonable value. + (krb5_os_localaddr): Increment count of addresses to include null + pointer terminator. Delete check for zero count. + + * locate_kdc.c (maybe_use_dns): Renamed from _krb5_use_dns. Now + takes an arg to indicate a key to look up in krb5.conf, falling + back to "dns_fallback", and an arg indicating the default value if + no config file entries match. + (_krb5_use_dns_realm): New routine; use "dns_lookup_realm" and + KRB5_DNS_LOOKUP_REALM setting. + (_krb5_use_dns_kdc): New routine; use "dns_lookup_kdc" and + KRB5_DNS_LOOKUP_KDC. + (krb5_locate_kdc): Call _krb5_use_dns_kdc. + * changepw.c (krb5_locate_kpasswd): Call _krb5_use_dns_kdc. + * def_realm.c (krb5_get_default_realm): Call _krb5_use_dns_realm. + * hst_realm.c (krb5_get_host_realm): Call _krb5_use_dns_realm. + +2000-06-23 Alexandra Ellwood <lxs@mit.edu> + + * ccdefname.c: Added support to store a krb5_principal in the os_context + along with the default ccache name (if known, this principal is the same + as the last time we looked at the ccache. + 2000-05-09 Alexandra Ellwood <lxs@mit.edu> *localaddr.c: Fixed the local_addr_fallback_kludge so that it actually does something. diff --git a/src/lib/krb5/os/an_to_ln.c b/src/lib/krb5/os/an_to_ln.c index 3c721fb..02e68fb 100644 --- a/src/lib/krb5/os/an_to_ln.c +++ b/src/lib/krb5/os/an_to_ln.c @@ -298,15 +298,15 @@ do_replacement(regexp, repl, doall, in, out) strncpy(op, cp, match_match.rm_so); op += match_match.rm_so; } - strcpy(op, repl); - op += strlen(repl); + strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out)); + op += strlen(op); cp += match_match.rm_eo; if (!doall) - strcpy(op, cp); + strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out)); matched = 1; } else { - strcpy(op, cp); + strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out)); matched = 0; } } while (doall && matched); @@ -333,20 +333,20 @@ do_replacement(regexp, repl, doall, in, out) strncpy(op, cp, sdispl); op += sdispl; } - strcpy(op, repl); + strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out)); op += strlen(repl); cp += edispl; if (!doall) - strcpy(op, cp); + strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out)); matched = 1; } else { - strcpy(op, cp); + strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out)); matched = 0; } } while (doall && matched); #else /* HAVE_REGEXP_H */ - strcpy(out, in); + memcpy(out, in, MAX_FORMAT_BUFFER); #endif /* HAVE_REGCOMP */ } @@ -379,7 +379,8 @@ aname_replacer(string, contextp, result) * Prime the buffers. Copy input string to "out" to simulate it * being the result of an initial iteration. */ - strcpy(out, string); + strncpy(out, string, MAX_FORMAT_BUFFER - 1); + out[MAX_FORMAT_BUFFER - 1] = '\0'; in[0] = '\0'; kret = 0; /* @@ -421,6 +422,7 @@ aname_replacer(string, contextp, result) out = ep; /* Do the replacemenbt */ + memset(out, '\0', MAX_FORMAT_BUFFER); do_replacement(rule, repl, doglobal, in, out); free(rule); free(repl); diff --git a/src/lib/krb5/os/ccdefname.c b/src/lib/krb5/os/ccdefname.c index 3bc2546..6b00e52 100644 --- a/src/lib/krb5/os/ccdefname.c +++ b/src/lib/krb5/os/ccdefname.c @@ -160,7 +160,7 @@ static krb5_error_code get_from_os(char *name_buf, int name_size) if (get_from_registry_indirect(name_buf, name_size) != 0) return 0; - strncpy(name_buf, prefix, name_size); + strncpy(name_buf, prefix, name_size - 1); name_buf[name_size - 1] = 0; size = name_size - strlen(prefix); if (size > 0) diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c index 5973516..575866e 100644 --- a/src/lib/krb5/os/changepw.c +++ b/src/lib/krb5/os/changepw.c @@ -66,10 +66,10 @@ krb5_locate_kpasswd(context, realm, addr_pp, naddrs) * We always try the local file first */ - code = krb5_locate_srv_conf( context, realm, "kpasswd_server", + code = krb5_locate_srv_conf(context, realm, "kpasswd_server", addr_pp, naddrs, 0); if (code) { - code = krb5_locate_srv_conf( context, realm, "admin_server", + code = krb5_locate_srv_conf(context, realm, "admin_server", addr_pp, naddrs, 0); if ( !code ) { /* success with admin_server but now we need to change the port */ @@ -83,7 +83,7 @@ krb5_locate_kpasswd(context, realm, addr_pp, naddrs) #ifdef KRB5_DNS_LOOKUP if (code) { - int use_dns = _krb5_use_dns(context); + int use_dns = _krb5_use_dns_kdc(context); if ( use_dns ) { code = krb5_locate_srv_dns(realm, "_kpasswd", "_udp", addr_pp, naddrs); diff --git a/src/lib/krb5/os/def_realm.c b/src/lib/krb5/os/def_realm.c index d3c031f..d9bd017 100644 --- a/src/lib/krb5/os/def_realm.c +++ b/src/lib/krb5/os/def_realm.c @@ -104,7 +104,7 @@ krb5_get_default_realm(context, lrealm) #ifdef KRB5_DNS_LOOKUP if (context->default_realm == 0) { - int use_dns = _krb5_use_dns(context); + int use_dns = _krb5_use_dns_realm(context); if ( use_dns ) { /* * Since this didn't appear in our config file, try looking diff --git a/src/lib/krb5/os/hst_realm.c b/src/lib/krb5/os/hst_realm.c index 1e8923f..965a991 100644 --- a/src/lib/krb5/os/hst_realm.c +++ b/src/lib/krb5/os/hst_realm.c @@ -117,6 +117,8 @@ krb5_try_realm_txt_rr(prefix, name, realm) */ if (name == NULL || name[0] == '\0') { + if (strlen (prefix) >= sizeof(host)-1) + return KRB5_ERR_HOST_REALM_UNKNOWN; strcpy(host,prefix); } else { if ( strlen(prefix) + strlen(name) + 3 > MAX_DNS_NAMELEN ) @@ -134,7 +136,7 @@ krb5_try_realm_txt_rr(prefix, name, realm) */ h = host + strlen (host); - if (h > host && h[-1] != '.') + if ((h > host) && (h[-1] != '.') && ((h - host + 1) < sizeof(host))) strcpy (h, "."); } size = res_search(host, C_IN, T_TXT, answer.bytes, sizeof(answer.bytes)); @@ -312,7 +314,7 @@ krb5_get_host_realm(context, host, realmsp) #ifdef KRB5_DNS_LOOKUP if (realm == (char *)NULL) { - int use_dns = _krb5_use_dns(context); + int use_dns = _krb5_use_dns_realm(context); if ( use_dns ) { /* * Since this didn't appear in our config file, try looking diff --git a/src/lib/krb5/os/init_os_ctx.c b/src/lib/krb5/os/init_os_ctx.c index 5222e6a..f599697 100644 --- a/src/lib/krb5/os/init_os_ctx.c +++ b/src/lib/krb5/os/init_os_ctx.c @@ -30,22 +30,7 @@ #include "k5-int.h" #ifdef macintosh -OSErr -GetMacProfileFileSpec (FSSpec* outFileSpec, StringPtr inName, UInt32 whichFolder) -{ - OSErr err; - - - - err = FindFolder (kOnSystemDisk, whichFolder, kCreateFolder, - &(outFileSpec -> vRefNum) , &(outFileSpec -> parID)); - - if (err == noErr) { - BlockMoveData (inName, &(outFileSpec -> name), strlen (inName) + 1); - } - - return err; -} +#include <PreferencesLib.h> #endif /* macintosh */ #if defined(_MSDOS) || defined(_WIN32) @@ -204,42 +189,94 @@ os_get_default_config_files(pfiles, secure) { profile_filespec_t* files; #ifdef macintosh - files = malloc(7 * sizeof(FSSpec)); - - if (files != 0) { - OSErr err = GetMacProfileFileSpec(&(files [3]), "\pKerberos Preferences", kApplicationSupportFolderType); - if (err == noErr) { - err = GetMacProfileFileSpec( &(files [4]), "\pkrb5.ini", kApplicationSupportFolderType); - } - if (err == noErr) { - err = GetMacProfileFileSpec( &(files [5]), "\pKerberos5 Configuration", kApplicationSupportFolderType); - } - - if (err == noErr) { - files[6].vRefNum = 0; - files[6].parID = 0; - files[6].name[0] = '\0'; - } else { - files[3].vRefNum = 0; - files[3].parID = 0; - files[3].name[0] = '\0'; + FSSpec* preferencesFiles = nil; + UInt32 numPreferencesFiles; + FSSpec* preferencesFilesToInit = nil; + UInt32 numPreferencesFilesToInit; + UInt32 i; + Boolean foundPreferences = false; + Boolean writtenPreferences = false; + SInt16 refNum = -1; + SInt32 length = 0; + + OSErr err = KPGetListOfPreferencesFiles ( + secure ? kpSystemPreferences : kpUserPreferences | kpSystemPreferences, + &preferencesFiles, + &numPreferencesFiles); + + if (err == noErr) { + /* After we get the list of files, check whether any of them contain any useful information */ + for (i = 0; i < numPreferencesFiles; i++) { + if (KPPreferencesFileIsReadable (&preferencesFiles [i]) == noErr) { + /* It's readable, check if it has anything in the data fork */ + err = FSpOpenDF (&preferencesFiles [i], fsRdPerm, &refNum); + if (err == noErr) { + err = GetEOF (refNum, &length); + } + + if (refNum != -1) { + FSClose (refNum); + } + + if (length != 0) { + foundPreferences = true; + break; + } + } } - err = GetMacProfileFileSpec(&(files [0]), "\pKerberos Preferences", kPreferencesFolderType); - if (err == noErr) { - err = GetMacProfileFileSpec( &(files [1]), "\pkrb5.ini", kPreferencesFolderType); - } - if (err == noErr) { - err = GetMacProfileFileSpec( &(files [2]), "\pKerberos5 Configuration", kPreferencesFolderType); + if (!foundPreferences) { + /* We found no profile data in any of those files; try to initialize one */ + /* If we are running "secure" do not try to initialize preferences */ + if (!secure) { + err = KPGetListOfPreferencesFiles (kpUserPreferences, &preferencesFilesToInit, &numPreferencesFilesToInit); + if (err == noErr) { + for (i = 0; i < numPreferencesFilesToInit; i++) { + if (KPPreferencesFileIsWritable (&preferencesFilesToInit [i]) == noErr) { + err = noErr; + /* If not readable, create it */ + if (KPPreferencesFileIsReadable (&preferencesFilesToInit [i]) != noErr) { + err = KPCreatePreferencesFile (&preferencesFilesToInit [i]); + } + /* Initialize it */ + if (err == noErr) { + err = KPInitializeWithDefaultKerberosLibraryPreferences (&preferencesFilesToInit [i]); + } + break; + } + } + } + } } + } + + if (err == noErr) { + files = malloc ((numPreferencesFiles + 1) * sizeof (FSSpec)); + if (files == NULL) + err = memFullErr; + } + + if (err == noErr) { + for (i = 0; i < numPreferencesFiles; i++) { + files [i] = preferencesFiles [i]; + } + + files [numPreferencesFiles].vRefNum = 0; + files [numPreferencesFiles].parID = 0; + files [numPreferencesFiles].name[0] = '\0'; + } + + if (preferencesFiles != nil) + KPFreeListOfPreferencesFiles (preferencesFiles); + + if (preferencesFilesToInit != nil) + KPFreeListOfPreferencesFiles (preferencesFilesToInit); - if (err != noErr) { - free (files); - return ENFILE; - } - } else { + if (err == memFullErr) return ENOMEM; - } + else if (err != noErr) + return ENOENT; + #else /* !macintosh */ #if defined(_MSDOS) || defined(_WIN32) krb5_error_code retval = 0; @@ -405,7 +442,7 @@ krb5_os_init_context(ctx) os_ctx->os_flags = 0; os_ctx->default_ccname = 0; os_ctx->default_ccprincipal = 0; - + krb5_cc_set_default_name(ctx, NULL); retval = os_init_paths(ctx); @@ -522,8 +559,8 @@ krb5_os_free_context(ctx) if (os_ctx->default_ccname) { free(os_ctx->default_ccname); - os_ctx->default_ccname = 0; - } + os_ctx->default_ccname = 0; + } if (os_ctx->default_ccprincipal) { krb5_free_principal (ctx, os_ctx->default_ccprincipal); diff --git a/src/lib/krb5/os/kuserok.c b/src/lib/krb5/os/kuserok.c index ef08037..6d2adb1 100644 --- a/src/lib/krb5/os/kuserok.c +++ b/src/lib/krb5/os/kuserok.c @@ -80,8 +80,9 @@ krb5_kuserok(context, principal, luser) if ((pwd = getpwnam(luser)) == NULL) { return(FALSE); } - (void) strcpy(pbuf, pwd->pw_dir); - (void) strcat(pbuf, "/.k5login"); + (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1); + pbuf[sizeof(pbuf) - 1] = '\0'; + (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf)); if (access(pbuf, F_OK)) { /* not accessible */ /* diff --git a/src/lib/krb5/os/localaddr.c b/src/lib/krb5/os/localaddr.c index f0f1a29..d5b46b6 100644 --- a/src/lib/krb5/os/localaddr.c +++ b/src/lib/krb5/os/localaddr.c @@ -1,7 +1,7 @@ /* * lib/krb5/os/localaddr.c * - * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2000 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -39,6 +39,7 @@ #include <sys/ioctl.h> #include <sys/time.h> #include <errno.h> +#include <stddef.h> /* * The SIOCGIF* ioctls require a socket. @@ -255,13 +256,17 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) int (*betweenfn) (void *); int (*pass2fn) (void *, struct sockaddr *); { - struct ifreq *ifr, ifreq; + struct ifreq *ifr, ifreq, *ifr2; struct ifconf ifc; - int s, code, n, i; + int s, code, n, i, j; int est_if_count = 8, est_ifreq_size; char *buf = 0; size_t current_buf_size = 0; - + int fail = 0; +#ifdef SIOCGSIZIFCONF + int ifconfsize = -1; +#endif + s = socket (USE_AF, USE_TYPE, USE_PROTO); if (s < 0) return SOCKET_ERRNO; @@ -270,7 +275,15 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) isn't big enough for an IPv6 or ethernet address. So add a little more space. */ est_ifreq_size = sizeof (struct ifreq) + 8; - current_buf_size = est_ifreq_size * est_if_count; +#ifdef SIOCGSIZIFCONF + code = ioctl (s, SIOCGSIZIFCONF, &ifconfsize); + if (!code) { + current_buf_size = ifconfsize; + est_if_count = ifconfsize / est_ifreq_size; + } +#endif + if (current_buf_size == 0) + current_buf_size = est_ifreq_size * est_if_count; buf = malloc (current_buf_size); ask_again: @@ -289,7 +302,11 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) the only indication we get, complicated by the fact that the associated address may make the required storage a little bigger than the size of an ifreq. */ - if (current_buf_size - ifc.ifc_len < sizeof (struct ifreq) + 40) { + if (current_buf_size - ifc.ifc_len < sizeof (struct ifreq) + 40 +#ifdef SIOCGSIZIFCONF + && ifconfsize <= 0 +#endif + ) { int new_size; char *newbuf; @@ -312,26 +329,49 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) 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 -#ifdef IFF_LOOPBACK - /* None of the current callers want loopback addresses. */ - || (ifreq.ifr_flags & IFF_LOOPBACK) -#endif - /* Ignore interfaces that are down. */ - || !(ifreq.ifr_flags & IFF_UP)) { + if (ioctl (s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { + skip: /* mark for next pass */ ifr->ifr_name[0] = 0; continue; } +#ifdef IFF_LOOPBACK + /* None of the current callers want loopback addresses. */ + if (ifreq.ifr_flags & IFF_LOOPBACK) + goto skip; +#endif + /* Ignore interfaces that are down. */ + if (!(ifreq.ifr_flags & IFF_UP)) + goto skip; + + /* Make sure we didn't process this address already. */ + for (j = 0; j < i; j += ifreq_size(*ifr2)) { + ifr2 = (struct ifreq *)((caddr_t) ifc.ifc_buf+j); + if (ifr2->ifr_name[0] == 0) + continue; + if (ifr2->ifr_addr.sa_family == ifr->ifr_addr.sa_family + && ifreq_size (*ifr) == ifreq_size (*ifr2) + /* Compare address info. If this isn't good enough -- + i.e., if random padding bytes turn out to differ + when the addresses are the same -- then we'll have + to do it on a per address family basis. */ + && !memcmp (&ifr2->ifr_addr.sa_data, &ifr->ifr_addr.sa_data, + (ifreq_size (*ifr) + - offsetof (struct ifreq, ifr_addr.sa_data)))) + goto skip; + } + if ((*pass1fn) (data, &ifr->ifr_addr)) { - abort (); + fail = 1; + goto punt; } } if (betweenfn && (*betweenfn)(data)) { - abort (); + fail = 1; + goto punt; } if (pass2fn) @@ -343,13 +383,15 @@ foreach_localaddr (data, pass1fn, betweenfn, pass2fn) continue; if ((*pass2fn) (data, &ifr->ifr_addr)) { - abort (); + fail = 1; + goto punt; } } + punt: closesocket(s); free (buf); - return 0; + return fail; } @@ -376,10 +418,9 @@ krb5_os_localaddr(context, addr) return r; } + data.cur_idx++; /* null termination */ if (data.mem_err) return ENOMEM; - else if (data.cur_idx == 0) - abort (); else if (data.cur_idx == data.count) *addr = data.addr_temp; else { diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c index 1139fb3..53f36d8 100644 --- a/src/lib/krb5/os/locate_kdc.c +++ b/src/lib/krb5/os/locate_kdc.c @@ -53,29 +53,57 @@ #define KPASSWD_PORTNAME "kpasswd" #endif -int -_krb5_use_dns(context) - krb5_context context; +#if KRB5_DNS_LOOKUP_KDC +#define DEFAULT_LOOKUP_KDC 1 +#else +#define DEFAULT_LOOKUP_KDC 0 +#endif +#if KRB5_DNS_LOOKUP_REALM +#define DEFAULT_LOOKUP_REALM 1 +#else +#define DEFAULT_LOOKUP_REALM 0 +#endif + +static int +maybe_use_dns (context, name, defalt) + krb5_context context; + const char *name; + int defalt; { krb5_error_code code; char * value = NULL; int use_dns = 0; code = profile_get_string(context->profile, "libdefaults", - "dns_fallback", 0, - context->profile_in_memory?"1":"0", - &value); + name, 0, 0, &value); + if (value == 0 && code == 0) + code = profile_get_string(context->profile, "libdefaults", + "dns_fallback", 0, 0, &value); if (code) - return(code); + return defalt; - if (value) { - use_dns = _krb5_conf_boolean(value); - profile_release_string(value); - } + if (value == 0) + return defalt; + use_dns = _krb5_conf_boolean(value); + profile_release_string(value); return use_dns; } +int +_krb5_use_dns_kdc(context) + krb5_context context; +{ + return maybe_use_dns (context, "dns_lookup_kdc", DEFAULT_LOOKUP_KDC); +} + +int +_krb5_use_dns_realm(context) + krb5_context context; +{ + return maybe_use_dns (context, "dns_lookup_realm", DEFAULT_LOOKUP_REALM); +} + #endif /* KRB5_DNS_LOOKUP */ /* @@ -205,9 +233,9 @@ krb5_locate_srv_conf(context, realm, name, addr_pp, naddrs, get_masters) addr_p = (struct sockaddr *)malloc (sizeof (struct sockaddr) * count); if (addr_p == NULL) { - if ( hostlist ) + if (hostlist) profile_free_list(hostlist); - if ( masterlist ) + if (masterlist) profile_free_list(masterlist); return ENOMEM; } @@ -281,9 +309,9 @@ krb5_locate_srv_conf(context, realm, name, addr_pp, naddrs, get_masters) } } - if ( hostlist ) + if (hostlist) profile_free_list(hostlist); - if ( masterlist ) + if (masterlist) profile_free_list(masterlist); if (out == 0) { /* Couldn't resolve any KDC names */ @@ -582,11 +610,11 @@ krb5_locate_kdc(context, realm, addr_pp, naddrs, get_masters) #ifdef KRB5_DNS_LOOKUP if (code) { - int use_dns = _krb5_use_dns(context); + int use_dns = _krb5_use_dns_kdc(context); if ( use_dns ) { code = krb5_locate_srv_dns(realm, - get_masters ? "_kerberos-master" : "_kerberos", - "_udp", addr_pp, naddrs); + get_masters ? "_kerberos-master" : "_kerberos", + "_udp", addr_pp, naddrs); } } #endif /* KRB5_DNS_LOOKUP */ diff --git a/src/lib/krb5/posix/ChangeLog b/src/lib/krb5/posix/ChangeLog index 813ec31..118c028 100644 --- a/src/lib/krb5/posix/ChangeLog +++ b/src/lib/krb5/posix/ChangeLog @@ -1,3 +1,10 @@ +2000-04-28 Ken Raeburn <raeburn@mit.edu> + Nalin Dahyabhai <nalin@redhat.com> + + * syslog.c (vsyslog): Use strncpy and strncat instead of strcpy + and strcat when adding to buffer "tbuf". If calling vsprintf, + abort if it appears to have overrun the buffer. + 1999-10-26 Wilfredo Sanchez <tritan@mit.edu> * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES, diff --git a/src/lib/krb5/posix/syslog.c b/src/lib/krb5/posix/syslog.c index 31e7874..f7ddbff 100644 --- a/src/lib/krb5/posix/syslog.c +++ b/src/lib/krb5/posix/syslog.c @@ -115,7 +115,7 @@ vsyslog(pri, fmt, ap) (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); for (p = tbuf; *p; ++p); if (LogTag) { - (void)strcpy(p, LogTag); + (void)strncpy(p, LogTag, sizeof(tbuf) - 1 - (p - tbuf)); for (; *p; ++p); } if (LogStat & LOG_PID) { @@ -146,6 +146,11 @@ vsyslog(pri, fmt, ap) } (void)vsprintf(p, fmt_cpy, ap); + /* Bounds checking?? If a system doesn't have syslog, we + probably can't rely on it having vsnprintf either. Try not + to let a buffer overrun be exploited. */ + if (strlen (tbuf) >= sizeof (tbuf)) + abort (); /* output the message to the local logger */ if (send(LogFile, tbuf, cnt = strlen(tbuf), 0) >= 0 || @@ -169,7 +174,8 @@ vsyslog(pri, fmt, ap) if ((fd = open(CONSOLE, O_WRONLY, 0)) < 0) return; (void)alarm((u_int)0); - (void)strcat(tbuf, "\r"); + tbuf[sizeof(tbuf) - 1] = '\0'; + (void)strncat(tbuf, "\r", sizeof(tbuf) - 1 - strlen(tbuf)); p = strchr(tbuf, '>') + 1; (void)write(fd, p, cnt + 1 - (p - tbuf)); (void)close(fd); diff --git a/src/lib/krb5/rcache/ChangeLog b/src/lib/krb5/rcache/ChangeLog index 52f9db9..f58e877 100644 --- a/src/lib/krb5/rcache/ChangeLog +++ b/src/lib/krb5/rcache/ChangeLog @@ -1,3 +1,8 @@ +2000-04-28 Nalin Dahyabhai <nalin@redhat.com> + + * rc_io.c (getdir): Don't check dirlen again, the call sites + always do. Fix dirlen calculation. + 1999-10-26 Wilfredo Sanchez <tritan@mit.edu> * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES, diff --git a/src/lib/krb5/rcache/rc_io.c b/src/lib/krb5/rcache/rc_io.c index d45c7a1..b4291bc 100644 --- a/src/lib/krb5/rcache/rc_io.c +++ b/src/lib/krb5/rcache/rc_io.c @@ -57,8 +57,6 @@ static char *dir; static void getdir() { - if (!dirlen) - { if (!(dir = getenv("KRB5RCACHEDIR"))) #if defined(_MSDOS) || defined(_WIN32) if (!(dir = getenv("TEMP"))) @@ -72,8 +70,7 @@ static void getdir() dir = "/tmp"; #endif #endif - dirlen = strlen(dir) + 1; - } + dirlen = strlen(dir) + sizeof(PATH_SEPARATOR); } krb5_error_code krb5_rc_io_creat (context, d, fn) diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def index 6604060..5506c42 100644 --- a/src/lib/krb5_32.def +++ b/src/lib/krb5_32.def @@ -13,10 +13,6 @@ ; !CALLCONV - entrypoint that should have used KRB5_CALLCONV, but did not due ; developer error -;LIBRARY KRB5 -DESCRIPTION 'DLL for Kerberos 5' -HEAPSIZE 8192 - EXPORTS ; Kerberos 5 krb5_build_principal @@ -42,7 +38,7 @@ EXPORTS krb5_free_authenticator krb5_free_authenticator_contents krb5_free_checksum - krb5_free_config_files + krb5_free_config_files krb5_free_context krb5_free_cred krb5_free_cred_contents @@ -76,7 +72,7 @@ EXPORTS krb5_get_credentials krb5_get_credentials_renew krb5_get_credentials_validate - krb5_get_default_config_files + krb5_get_default_config_files krb5_get_default_realm krb5_get_host_realm krb5_get_realm_domain @@ -208,18 +204,18 @@ EXPORTS krb5_change_password ; - krb5_write_message - krb5_read_message - krb5_net_write - krb5_net_read - krb5_encrypt - krb5_decrypt - krb5_encrypt_size + krb5_write_message + krb5_read_message + krb5_net_write + krb5_net_read + krb5_encrypt + krb5_decrypt + krb5_encrypt_size ; ; Added for Kermit 95 - krb5_address_search ; !CALLCONV - krb5_auth_con_getrcache ; !CALLCONV - krb5_c_enctype_compare + krb5_address_search ; !CALLCONV + krb5_auth_con_getrcache ; !CALLCONV + krb5_c_enctype_compare ; krb5_kuserok ; @@ -227,29 +223,30 @@ EXPORTS krb5_decode_ticket krb5_appdefault_string krb5_appdefault_boolean - +; ; Temporary exports (DO NOT USE) -; decode_krb5_ticket -- no longer in library des_ecb_encrypt des_new_random_key des_key_sched des_pcbc_encrypt des_quad_cksum des_string_to_key -; des_set_random_generator_seed -- no longer in library des_init_random_number_generator krb5_random_confounder - krb5_size_opaque - krb5_internalize_opaque - krb5_externalize_opaque - krb5_ser_pack_int32 - krb5_ser_unpack_int32 - krb5_ser_pack_bytes - krb5_ser_unpack_bytes - krb5_ser_auth_context_init - krb5_ser_context_init - krb5_ser_ccache_init - krb5_ser_keytab_init - krb5_ser_rcache_init + krb5_size_opaque ; gssapi + krb5_internalize_opaque ; gssapi + krb5_externalize_opaque ; gssapi + krb5_ser_pack_int32 ; gssapi + krb5_ser_unpack_int32 ; gssapi + krb5_ser_pack_bytes ; gssapi + krb5_ser_unpack_bytes ; gssapi + krb5_ser_auth_context_init ; gssapi + krb5_ser_context_init ; gssapi + krb5_ser_ccache_init ; gssapi + krb5_ser_keytab_init ; gssapi + krb5_ser_rcache_init ; gssapi decode_krb5_ap_req ; gssapi - krb5_mcc_ops + krb5_mcc_ops ; gssapi + krb5_get_tgs_ktypes ; gssapi + krb5_free_ktypes ; gssapi + krb5int_cc_default ; gssapi diff --git a/src/lib/krb5util/ChangeLog b/src/lib/krb5util/ChangeLog index cde0c8a..d00bc48 100644 --- a/src/lib/krb5util/ChangeLog +++ b/src/lib/krb5util/ChangeLog @@ -1,3 +1,8 @@ +2000-05-31 Ken Raeburn <raeburn@mit.edu> + + * compat_recv.c (krb5_compat_recvauth_version): Variant of + krb5_compat_recvauth, similar to krb5_recvauth_version. + 1999-10-26 Wilfredo Sanchez <tritan@mit.edu> * Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES, diff --git a/src/lib/krb5util/compat_recv.c b/src/lib/krb5util/compat_recv.c index ec6b151..ee7df24 100644 --- a/src/lib/krb5util/compat_recv.c +++ b/src/lib/krb5util/compat_recv.c @@ -193,6 +193,151 @@ krb5_compat_recvauth(context, auth_context, return retval; } +krb5_error_code +krb5_compat_recvauth_version(context, auth_context, + /* IN */ + fdp, server, flags, keytab, + v4_options, v4_service, v4_instance, v4_faddr, + v4_laddr, + v4_filename, + /* OUT */ + ticket, + auth_sys, v4_kdata, v4_schedule, + version) + krb5_context context; + krb5_auth_context *auth_context; + krb5_pointer fdp; + krb5_principal server; + krb5_int32 flags; + krb5_keytab keytab; + krb5_ticket ** ticket; + krb5_int32 *auth_sys; + + /* + * Version 4 arguments + */ + krb5_int32 v4_options; /* bit-pattern of options */ + char *v4_service; /* service expected */ + char *v4_instance; /* inst expected (may be filled in) */ + struct sockaddr_in *v4_faddr; /* foreign address */ + struct sockaddr_in *v4_laddr; /* local address */ + AUTH_DAT **v4_kdata; /* kerberos data (returned) */ + char *v4_filename; /* name of file with service keys */ + Key_schedule v4_schedule; /* key schedule (return) */ + krb5_data *version; /* application version filled in */ +{ + union verslen { + krb5_int32 len; + char vers[4]; + } vers; + char *buf; + int len, length; + krb5_int32 retval; + int fd = *( (int *) fdp); +#ifdef KRB5_KRB4_COMPAT + KTEXT v4_ticket; /* storage for client's ticket */ +#endif + + if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4) + return((retval < 0) ? errno : ECONNABORTED); + +#ifdef KRB5_KRB4_COMPAT + if (!strncmp(vers.vers, KRB_V4_SENDAUTH_VERS, 4)) { + /* + * We must be talking to a V4 sendauth; read in the + * rest of the version string and make sure. + */ + if ((retval = krb5_net_read(context, fd, vers.vers, 4)) != 4) + return((retval < 0) ? errno : ECONNABORTED); + + if (strncmp(vers.vers, KRB_V4_SENDAUTH_VERS+4, 4)) + return KRB5_SENDAUTH_BADAUTHVERS; + + *auth_sys = KRB5_RECVAUTH_V4; + + *v4_kdata = (AUTH_DAT *) malloc( sizeof(AUTH_DAT) ); + v4_ticket = (KTEXT) malloc(sizeof(KTEXT_ST)); + + version->length = KRB_SENDAUTH_VLEN; /* no trailing \0! */ + version->data = malloc (KRB_SENDAUTH_VLEN + 1); + version->data[KRB_SENDAUTH_VLEN] = 0; + if (version->data == 0) + return errno; + retval = krb_v4_recvauth(v4_options, fd, v4_ticket, + v4_service, v4_instance, v4_faddr, + v4_laddr, *v4_kdata, v4_filename, + v4_schedule, version->data); + krb5_xfree(v4_ticket); + /* + * XXX error code translation? + */ + switch (retval) { + case RD_AP_OK: + return 0; + case RD_AP_TIME: + return KRB5KRB_AP_ERR_SKEW; + case RD_AP_EXP: + return KRB5KRB_AP_ERR_TKT_EXPIRED; + case RD_AP_NYV: + return KRB5KRB_AP_ERR_TKT_NYV; + case RD_AP_NOT_US: + return KRB5KRB_AP_ERR_NOT_US; + case RD_AP_UNDEC: + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + case RD_AP_REPEAT: + return KRB5KRB_AP_ERR_REPEAT; + case RD_AP_MSG_TYPE: + return KRB5KRB_AP_ERR_MSG_TYPE; + case RD_AP_MODIFIED: + return KRB5KRB_AP_ERR_MODIFIED; + case RD_AP_ORDER: + return KRB5KRB_AP_ERR_BADORDER; + case RD_AP_BADD: + return KRB5KRB_AP_ERR_BADADDR; + default: + return KRB5_SENDAUTH_BADRESPONSE; + } + } +#endif + + /* + * Assume that we're talking to a V5 recvauth; read in the + * the version string, and make sure it matches. + */ + + len = (int) ntohl(vers.len); + + if (len < 0 || len > 255) + return KRB5_SENDAUTH_BADAUTHVERS; + + buf = malloc(len); + if (!buf) + return ENOMEM; + + length = krb5_net_read(context, fd, buf, len); + if (len != length) { + krb5_xfree(buf); + if (len < 0) + return errno; + else + return ECONNABORTED; + } + + if (strcmp(buf, KRB_V5_SENDAUTH_VERS)) { + krb5_xfree(buf); + return KRB5_SENDAUTH_BADAUTHVERS; + } + krb5_xfree(buf); + + *auth_sys = KRB5_RECVAUTH_V5; + + retval = krb5_recvauth_version(context, auth_context, fdp, server, + flags | KRB5_RECVAUTH_SKIP_VERSION, + keytab, ticket, version); + + return retval; +} + #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) diff --git a/src/lib/rpc/ChangeLog b/src/lib/rpc/ChangeLog index 392e7d9..7d0aa31 100644 --- a/src/lib/rpc/ChangeLog +++ b/src/lib/rpc/ChangeLog @@ -1,3 +1,36 @@ +2000-05-31 Ken Raeburn <raeburn@mit.edu> + + * pmap_rmt.c (GIFCONF_BUFSIZE): New macro. + (getbroadcastnets): Use it for buffer size. + (clnt_broadcast): Make buffer at least that big. + + * get_myaddress.c (get_myaddress): Increase buffer size. + +2000-05-18 Ken Raeburn <raeburn@mit.edu> + + * auth_gssapi_misc.c (auth_gssapi_display_status_1): Don't pass a + gss_buffer_desc to fprintf. + + * clnt_tcp.c (clnttcp_create): Initialize "ct". + * clnt_udp.c (clntudp_bufcreate): Initialize "cu". + + * svc_auth_gssapi.c (_svcauth_gssapi, create_client, + destroy_client, dump_db, clean_client): Use %p format for + displaying pointers. Remove unused variables. + +2000-05-17 Ken Raeburn <raeburn@mit.edu> + Nalin Dahyabhai <nalin@redhat.com> + + * clnt_perror.c (clnt_sperror): Don't overflow buffer "str" beyond + known allocation size. + * clnt_simple.c (gssrpc_callrpc): Don't overfill buffer "crp->oldhost". + +2000-05-03 Nalin Dahyabhai <nalin@redhat.com> + + * clnt_perror.c (_buf): Use bigger buffer. + (clnt_spcreateerror): Don't overflow buffer "buf" beyond known + allocation size. + 2000-02-22 Donn Cave <donn@u.washington.edu> * Makefile.in (includes): Extract basename of header file to be diff --git a/src/lib/rpc/auth_gssapi_misc.c b/src/lib/rpc/auth_gssapi_misc.c index fd9393c..e7c38a8 100644 --- a/src/lib/rpc/auth_gssapi_misc.c +++ b/src/lib/rpc/auth_gssapi_misc.c @@ -162,15 +162,17 @@ static void auth_gssapi_display_status_1(m, code, type, rec) auth_gssapi_display_status_1(m,gssstat,GSS_C_GSS_CODE,1); auth_gssapi_display_status_1(m, minor_stat, GSS_C_MECH_CODE, 1); - } else - fprintf(stderr, - "GSS-API authentication error %s: recursive failure!\n", - msg); + } else { + fputs ("GSS-API authentication error ", stderr); + fwrite (msg.value, msg.length, 1, stderr); + fputs (": recursive failure!\n", stderr); + } return; } - - fprintf(stderr, "GSS-API authentication error %s: %s\n", m, - (char *)msg.value); + + fprintf (stderr, "GSS-API authentication error %s: ", m); + fwrite (msg.value, msg.length, 1, stderr); + putc ('\n', stderr); (void) gss_release_buffer(&minor_stat, &msg); if (!msg_ctx) diff --git a/src/lib/rpc/clnt_perror.c b/src/lib/rpc/clnt_perror.c index 560cb27..06dd22e 100644 --- a/src/lib/rpc/clnt_perror.c +++ b/src/lib/rpc/clnt_perror.c @@ -57,9 +57,8 @@ static char *buf; static char * _buf() { - - if (buf == 0) - buf = (char *)malloc(256); + if (buf == NULL) + buf = (char *)malloc(BUFSIZ); return (buf); } @@ -74,17 +73,20 @@ clnt_sperror(rpch, s) struct rpc_err e; void clnt_perrno(); char *err; - char *str = _buf(); + char *bufstart = _buf(); + char *str = bufstart; char *strstart = str; if (str == 0) return (0); CLNT_GETERR(rpch, &e); - (void) sprintf(str, "%s: ", s); + strncpy (str, s, BUFSIZ - 1); + str[BUFSIZ - 1] = 0; + strncat (str, ": ", BUFSIZ - 1 - strlen (bufstart)); str += strlen(str); - - (void) strcpy(str, clnt_sperrno(e.re_status)); + strncat (str, clnt_sperrno(e.re_status), BUFSIZ - 1 - strlen (bufstart)); + str[BUFSIZ - 1] = '\0'; str += strlen(str); switch (e.re_status) { @@ -105,47 +107,64 @@ clnt_sperror(rpch, s) case RPC_CANTSEND: case RPC_CANTRECV: - (void) sprintf(str, "; errno = %s", - sys_errlist[e.re_errno]); + /* 10 for the string */ + if(str - bufstart + 10 + strlen(sys_errlist[e.re_errno]) < BUFSIZ) + (void) sprintf(str, "; errno = %s", + sys_errlist[e.re_errno]); str += strlen(str); break; case RPC_VERSMISMATCH: - (void) sprintf(str, - "; low version = %lu, high version = %lu", - e.re_vers.low, e.re_vers.high); + /* 33 for the string, 22 for the numbers */ + if(str - bufstart + 33 + 22 < BUFSIZ) + (void) sprintf(str, + "; low version = %lu, high version = %lu", + (unsigned long) e.re_vers.low, + (unsigned long) e.re_vers.high); str += strlen(str); break; case RPC_AUTHERROR: err = auth_errmsg(e.re_why); - (void) sprintf(str,"; why = "); + /* 8 for the string */ + if(str - bufstart + 8 < BUFSIZ) + (void) sprintf(str,"; why = "); str += strlen(str); if (err != NULL) { - (void) sprintf(str, "%s",err); + if(str - bufstart + strlen(err) < BUFSIZ) + (void) sprintf(str, "%s",err); } else { + /* 33 for the string, 11 for the number */ + if(str - bufstart + 33 + 11 < BUFSIZ) (void) sprintf(str, - "(unknown authentication error - %d)", - (int) e.re_why); + "(unknown authentication error - %d)", + (int) e.re_why); } str += strlen(str); break; case RPC_PROGVERSMISMATCH: - (void) sprintf(str, - "; low version = %lu, high version = %lu", - e.re_vers.low, e.re_vers.high); + /* 33 for the string, 22 for the numbers */ + if(str - bufstart + 33 + 22 < BUFSIZ) + (void) sprintf(str, + "; low version = %lu, high version = %lu", + (unsigned long) e.re_vers.low, + (unsigned long) e.re_vers.high); str += strlen(str); break; default: /* unknown */ - (void) sprintf(str, - "; s1 = %lu, s2 = %lu", - e.re_lb.s1, e.re_lb.s2); + /* 14 for the string, 22 for the numbers */ + if(str - bufstart + 14 + 22 < BUFSIZ) + (void) sprintf(str, + "; s1 = %lu, s2 = %lu", + (unsigned long) e.re_lb.s1, + (unsigned long) e.re_lb.s2); str += strlen(str); break; } - (void) sprintf(str, "\n"); + if(str - bufstart + 1 < BUFSIZ) + (void) sprintf(str, "\n"); return(strstart) ; } @@ -238,26 +257,29 @@ clnt_spcreateerror(s) if (str == 0) return(0); (void) sprintf(str, "%s: ", s); - (void) strcat(str, clnt_sperrno(rpc_createerr.cf_stat)); + str[BUFSIZ - 1] = '\0'; + (void) strncat(str, clnt_sperrno(rpc_createerr.cf_stat), BUFSIZ - 1); switch (rpc_createerr.cf_stat) { case RPC_PMAPFAILURE: - (void) strcat(str, " - "); - (void) strcat(str, - clnt_sperrno(rpc_createerr.cf_error.re_status)); + (void) strncat(str, " - ", BUFSIZ - 1 - strlen(str)); + (void) strncat(str, + clnt_sperrno(rpc_createerr.cf_error.re_status), + BUFSIZ - 1 - strlen(str)); break; case RPC_SYSTEMERROR: - (void) strcat(str, " - "); + (void) strncat(str, " - ", BUFSIZ - 1 - strlen(str)); if (rpc_createerr.cf_error.re_errno > 0 && rpc_createerr.cf_error.re_errno < sys_nerr) - (void) strcat(str, - sys_errlist[rpc_createerr.cf_error.re_errno]); + (void) strncat(str, + sys_errlist[rpc_createerr.cf_error.re_errno], + BUFSIZ - 1 - strlen(str)); else (void) sprintf(&str[strlen(str)], "Error %d", rpc_createerr.cf_error.re_errno); break; } - (void) strcat(str, "\n"); + (void) strncat(str, "\n", BUFSIZ - 1 - strlen(str)); return (str); } diff --git a/src/lib/rpc/clnt_simple.c b/src/lib/rpc/clnt_simple.c index b3d2eb3..2f203d7 100644 --- a/src/lib/rpc/clnt_simple.c +++ b/src/lib/rpc/clnt_simple.c @@ -70,6 +70,8 @@ gssrpc_callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) } if (crp->oldhost == NULL) { crp->oldhost = mem_alloc(256); + if (crp->oldhost == 0) + return 0; crp->oldhost[0] = 0; crp->socket = RPC_ANYSOCK; } @@ -98,7 +100,8 @@ gssrpc_callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) crp->valid = 1; crp->oldprognum = prognum; crp->oldversnum = versnum; - (void) strcpy(crp->oldhost, host); + (void) strncpy(crp->oldhost, host, 255); + crp->oldhost[255] = '\0'; } tottimeout.tv_sec = 25; tottimeout.tv_usec = 0; diff --git a/src/lib/rpc/clnt_tcp.c b/src/lib/rpc/clnt_tcp.c index 4e10a48..f87da78 100644 --- a/src/lib/rpc/clnt_tcp.c +++ b/src/lib/rpc/clnt_tcp.c @@ -116,7 +116,7 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) unsigned int recvsz; { CLIENT *h; - register struct ct_data *ct; + register struct ct_data *ct = 0; struct timeval now; struct rpc_msg call_msg; diff --git a/src/lib/rpc/clnt_udp.c b/src/lib/rpc/clnt_udp.c index 6046942..df3945a 100644 --- a/src/lib/rpc/clnt_udp.c +++ b/src/lib/rpc/clnt_udp.c @@ -117,7 +117,7 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) unsigned int recvsz; { CLIENT *cl; - register struct cu_data *cu; + register struct cu_data *cu = 0; struct timeval now; struct rpc_msg call_msg; diff --git a/src/lib/rpc/get_myaddress.c b/src/lib/rpc/get_myaddress.c index 4c9bf29..13bafa0 100644 --- a/src/lib/rpc/get_myaddress.c +++ b/src/lib/rpc/get_myaddress.c @@ -81,7 +81,7 @@ get_myaddress(addr) struct sockaddr_in *addr; { int s; - char buf[BUFSIZ]; + char buf[256 * sizeof (struct ifconf)]; struct ifconf ifc; struct ifreq ifreq, *ifr; int len; diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c index 7cafe6e..dc9735d 100644 --- a/src/lib/rpc/pmap_rmt.c +++ b/src/lib/rpc/pmap_rmt.c @@ -165,6 +165,8 @@ xdr_rmtcallres(xdrs, crp) * routines which only support udp/ip . */ +#define GIFCONF_BUFSIZE (256 * sizeof (struct ifconf)) + static int getbroadcastnets(addrs, sock, buf) struct in_addr *addrs; @@ -176,8 +178,9 @@ getbroadcastnets(addrs, sock, buf) struct sockaddr_in *sin; int n, i; - ifc.ifc_len = UDPMSGSIZE; + ifc.ifc_len = GIFCONF_BUFSIZE; ifc.ifc_buf = buf; + memset (buf, 0, GIFCONF_BUFSIZE); if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { perror("broadcast: ioctl (get interface configuration)"); return (0); @@ -255,7 +258,11 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) struct rmtcallres r; struct rpc_msg msg; struct timeval t; - char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; + char outbuf[MAX_BROADCAST_SIZE]; +#ifndef MAX +#define MAX(A,B) ((A)<(B)?(B):(A)) +#endif + char inbuf[MAX (UDPMSGSIZE, GIFCONF_BUFSIZE)]; /* * initialization: create a socket, a broadcast address, and diff --git a/src/lib/rpc/svc_auth_gssapi.c b/src/lib/rpc/svc_auth_gssapi.c index 827596a..34ee0ef 100644 --- a/src/lib/rpc/svc_auth_gssapi.c +++ b/src/lib/rpc/svc_auth_gssapi.c @@ -134,7 +134,6 @@ enum auth_stat _svcauth_gssapi(rqst, msg, no_dispatch) svc_auth_gssapi_data *client_data; int ret_flags, ret, i; rpc_u_int32 seq_num; - int flag; PRINTF(("svcauth_gssapi: starting\n")); @@ -307,8 +306,6 @@ enum auth_stat _svcauth_gssapi(rqst, msg, no_dispatch) #endif if (call_arg.version >= 3) { - int len; - memset(&bindings, 0, sizeof(bindings)); bindings.application_data.length = 0; bindings.initiator_addrtype = GSS_C_AF_INET; @@ -657,7 +654,6 @@ static svc_auth_gssapi_data *create_client() client_list *c; svc_auth_gssapi_data *client_data; static int client_key = 1; - int ret; PRINTF(("svcauth_gssapi: empty creds, creating\n")); @@ -665,7 +661,7 @@ static svc_auth_gssapi_data *create_client() if (client_data == NULL) return NULL; memset((char *) client_data, 0, sizeof(*client_data)); - L_PRINTF(2, ("create_client: new client_data = %#x\n", client_data)); + L_PRINTF(2, ("create_client: new client_data = %p\n", client_data)); /* set up client data structure */ client_data->established = 0; @@ -783,10 +779,9 @@ static void destroy_client(client_data) OM_uint32 gssstat, minor_stat; gss_buffer_desc out_buf; client_list *c, *c2; - int ret; PRINTF(("destroy_client: destroying client_data\n")); - L_PRINTF(2, ("destroy_client: client_data = %#x\n", client_data)); + L_PRINTF(2, ("destroy_client: client_data = %p\n", client_data)); #ifdef DEBUG_GSSAPI if (svc_debug_gssapi >= 3) @@ -852,7 +847,7 @@ static void dump_db(msg) c = clients; while (c) { client_data = c->client; - L_PRINTF(3, ("\tclient_data = %#x, exp = %d\n", + L_PRINTF(3, ("\tclient_data = %p, exp = %d\n", client_data, client_data->expiration)); c = c->next; } @@ -871,7 +866,7 @@ static void clean_client() while (c) { client_data = c->client; - L_PRINTF(2, ("clean_client: client_data = %#x\n", + L_PRINTF(2, ("clean_client: client_data = %p\n", client_data)); if (client_data->expiration < time(0)) { @@ -884,7 +879,6 @@ static void clean_client() } } -done: PRINTF(("clean_client: done\n")); } diff --git a/src/lib/rpc/unit-test/ChangeLog b/src/lib/rpc/unit-test/ChangeLog index aa14bfc..0a21776 100644 --- a/src/lib/rpc/unit-test/ChangeLog +++ b/src/lib/rpc/unit-test/ChangeLog @@ -1,3 +1,9 @@ +2000-06-08 Tom Yu <tlyu@mit.edu> + + * lib/helpers.exp (kinit): Move "expect eof" into the commands + that send the prompt. Don't "expect eof" outside of the main + expect, as the main expect may have already read eof. + 2000-02-15 Tom Yu <tlyu@mit.edu> * server.c: Add code to set a signal handler for SIGHUP and a few diff --git a/src/lib/rpc/unit-test/lib/helpers.exp b/src/lib/rpc/unit-test/lib/helpers.exp index 3d7b167..c4b76aa 100644 --- a/src/lib/rpc/unit-test/lib/helpers.exp +++ b/src/lib/rpc/unit-test/lib/helpers.exp @@ -23,10 +23,10 @@ proc kinit {princ pass lifetime} { spawn -noecho $kinit -5 -l $lifetime $princ expect { - -re "Password for $princ.*: " { send "$pass\n" } + -re "Password for $princ.*: " { send "$pass\n"; expect eof } timeout { perror "Timeout waiting for kinit"; close } + eof } - expect { eof {} } set ret [wait] if {[lindex $ret $wait_error_index] == -1} { @@ -117,7 +117,7 @@ proc wait_client {testname ccname id status} { set env(KRB5CCNAME) FILE:/tmp/krb5cc_rpc_test_$ccname if {[catch "exec $kdestroy -5"] != 0} { - error "$testname: cannot destroy client $ccname ccache" + perror "$testname: cannot destroy client $ccname ccache" } unset env(KRB5CCNAME) diff --git a/src/lib/win_glue.c b/src/lib/win_glue.c index ab3e1a1..6dc9e10 100644 --- a/src/lib/win_glue.c +++ b/src/lib/win_glue.c @@ -90,8 +90,13 @@ extern void krb5_stdcc_shutdown(); * arbitrary third party applications. If there is an error, or we * decide that we should not version check the calling application * then VSflag will be FALSE when the function returns. + * + * The buffers passed into this function must be at least + * APPVERINFO_SIZE bytes long. */ - + +#define APPVERINFO_SIZE 256 + void GetCallingAppVerInfo( char *AppTitle, char *AppVer, char *AppIni, BOOL *VSflag) { @@ -187,11 +192,15 @@ void GetCallingAppVerInfo( char *AppTitle, char *AppVer, char *AppIni, * We don't have a way to determine that INI file of the * application at the moment so let's just use krb5.ini */ - strcpy( locAppIni, KERBEROS_INI ); + strncpy( locAppIni, KERBEROS_INI, sizeof(locAppIni) - 1 ); + locAppIni[ sizeof(locAppIni) - 1 ] = '\0'; - strcpy( AppTitle, locAppTitle); - strcpy( AppVer, locAppVer); - strcpy( AppIni, locAppIni); + strncpy( AppTitle, locAppTitle, APPVERINFO_SIZE); + AppTitle[APPVERINFO_SIZE - 1] = '\0'; + strncpy( AppVer, locAppVer, APPVERINFO_SIZE); + AppVer[APPVERINFO_SIZE - 1] = '\0'; + strncpy( AppIni, locAppIni, APPVERINFO_SIZE); + AppIni[APPVERINFO_SIZE - 1] = '\0'; /* * We also need to determine if we want to suppress version @@ -271,9 +280,10 @@ static krb5_error_code do_timebomb() if (first_time) { sprintf(buf, "Your version of %s has expired.\n", TIMEBOMB_PRODUCT); - strcat(buf, "Please upgrade it."); + buf[sizeof(buf) - 1] = '\0'; + strncat(buf, "Please upgrade it.", sizeof(buf) - 1 - strlen(buf)); #ifdef TIMEBOMB_INFO - strcat(buf, TIMEBOMB_INFO); + strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf)); #endif MessageBox(NULL, buf, "", MB_OK); first_time = 0; @@ -285,9 +295,9 @@ static krb5_error_code do_timebomb() if (first_time) { sprintf(buf, "Your version of %s will expire in %ld days.\n", TIMEBOMB_PRODUCT, timeleft); - strcat(buf, "Please upgrade it soon."); + strncat(buf, "Please upgrade it soon.", sizeof(buf) - 1 - strlen(buf)); #ifdef TIMEBOMB_INFO - strcat(buf, TIMEBOMB_INFO); + strncat(buf, TIMEBOMB_INFO, sizeof(buf) - 1 - strlen(buf)); #endif MessageBox(NULL, buf, "", MB_OK); first_time = 0; @@ -323,9 +333,9 @@ krb5_error_code krb5_vercheck() if (CallVersionServer(APP_TITLE, APP_VER, APP_INI, NULL)) return VERSERV_ERROR; #else - char AppTitle[256]; - char AppVer[256]; - char AppIni[256]; + char AppTitle[APPVERINFO_SIZE]; + char AppVer[APPVERINFO_SIZE]; + char AppIni[APPVERINFO_SIZE]; BOOL VSflag=TRUE; GetCallingAppVerInfo( AppTitle, AppVer, AppIni, &VSflag); |