Index: aclocal/tcltls_openssl.m4 ================================================================== --- aclocal/tcltls_openssl.m4 +++ aclocal/tcltls_openssl.m4 @@ -117,17 +117,17 @@ dnl Verify that basic functionality is there AC_LANG_PUSH(C) AC_MSG_CHECKING([if a basic OpenSSL program works]) AC_LINK_IFELSE([AC_LANG_PROGRAM([ #include +#include #if (SSLEAY_VERSION_NUMBER >= 0x0907000L) # include #endif ], [ - (void)SSL_library_init(); + SSL_library_init(); SSL_load_error_strings(); - OPENSSL_config(NULL); ])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([Unable to compile a basic program using OpenSSL]) Index: gen_dh_params ================================================================== --- gen_dh_params +++ gen_dh_params @@ -35,13 +35,12 @@ return 1 } gen_dh_params_fallback() { cat << \_EOF_ -DH *get_dh2048() - { - static unsigned char dh2048_p[]={ +DH *get_dh2048(void) { + static unsigned char dhp_2048[] = { 0xC1,0x51,0x58,0x69,0xFB,0xE8,0x6C,0x47,0x2B,0x86,0x61,0x4F, 0x20,0x2E,0xD3,0xFC,0x19,0xEE,0xB8,0xF3,0x35,0x7D,0xBA,0x86, 0x2A,0xC3,0xC8,0x6E,0xF4,0x99,0x75,0x65,0xD3,0x7A,0x9E,0xDF, 0xD4,0x1F,0x88,0xE3,0x17,0xFC,0xA1,0xED,0xA2,0xB6,0x77,0x84, 0xAA,0x08,0xF2,0x97,0x59,0x7A,0xA0,0x03,0x0D,0x3E,0x7E,0x6D, @@ -60,23 +59,41 @@ 0x09,0x8F,0xBB,0x8E,0xA0,0xD0,0x96,0xAC,0x30,0x20,0x39,0x3B, 0x8C,0x92,0x65,0x37,0x0A,0x8F,0xEC,0x72,0x8B,0x61,0x7D,0x62, 0x24,0x54,0xE9,0x1D,0x01,0x68,0x89,0xC4,0x7B,0x3C,0x48,0x62, 0x9B,0x83,0x11,0x3A,0x0B,0x0D,0xEF,0x5A,0xE4,0x7A,0xA0,0x69, 0xF4,0x54,0xB5,0x5B, - }; - static unsigned char dh2048_g[]={ + }; + static unsigned char dhg_2048[] = { 0x02, - }; - DH *dh; - - if ((dh=DH_new()) == NULL) return(NULL); - dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL); - dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL); - if ((dh->p == NULL) || (dh->g == NULL)) - { DH_free(dh); return(NULL); } - return(dh); - } + }; + + DH *dh = DH_new();; + BIGNUM *dhp_bn, *dhg_bn; + + if (dh == NULL) { + return NULL; + } + + dhp_bn = BN_bin2bn(dhp_2048, sizeof (dhp_2048), NULL); + dhg_bn = BN_bin2bn(dhg_2048, sizeof (dhg_2048), NULL); + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + dh->p = dhp_bn; + dh->g = dhg_bn; + + if (dhp_bn == NULL || dhg_bn == NULL) { +#else + if (dhp_bn == NULL || dhg_bn == NULL || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn)) { +#endif + DH_free(dh); + BN_free(dhp_bn); + BN_free(dhg_bn); + return(NULL); + } + + return(dh); +} _EOF_ } # Enable support for giving the same DH params each time if [ "$1" = 'fallback' ]; then Index: tls.c ================================================================== --- tls.c +++ tls.c @@ -121,10 +121,13 @@ /* * Threaded operation requires locking callbacks * Based from /crypto/cryptlib.c of OpenSSL and NSOpenSSL. */ +#ifndef CRYPTO_NUM_LOCKS +#define CRYPTO_NUM_LOCKS 128 +#endif static Tcl_Mutex locks[CRYPTO_NUM_LOCKS]; static Tcl_Mutex init_mx; static void CryptoThreadLockCallback (int mode, int n, const char *file, int line); static unsigned long CryptoThreadIdCallback (void); @@ -262,11 +265,11 @@ VerifyCallback(int ok, X509_STORE_CTX *ctx) { Tcl_Obj *cmdPtr, *result; char *errStr, *string; int length; - SSL *ssl = (SSL*)X509_STORE_CTX_get_app_data(ctx); + SSL *ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); X509 *cert = X509_STORE_CTX_get_current_cert(ctx); State *statePtr = (State*)SSL_get_app_data(ssl); int depth = X509_STORE_CTX_get_error_depth(ctx); int err = X509_STORE_CTX_get_error(ctx); @@ -1744,67 +1747,62 @@ */ static int TlsLibInit (void) { static int initialized = 0; int i; char rnd_seed[16] = "GrzSlplKqUdnnzP!"; /* 16 bytes */ - int status=TCL_OK; + int status = TCL_OK; if (initialized) { - return status; + return(status); } initialized = 1; #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) size_t num_locks; Tcl_MutexLock(&init_mx); #endif - if (CRYPTO_set_mem_functions((void *(*)(size_t))Tcl_Alloc, - (void *(*)(void *, size_t))Tcl_Realloc, - (void(*)(void *))Tcl_Free) == 0) { - /* Not using Tcl's mem functions ... not critical */ - } - -#if defined(OPENSSL_THREADS) && defined(TCL_THREADS) - /* should we consider allocating mutexes? */ - num_locks = CRYPTO_num_locks(); - if (num_locks > CRYPTO_NUM_LOCKS) { - status=TCL_ERROR; - goto done; - } - - CRYPTO_set_locking_callback(CryptoThreadLockCallback); - CRYPTO_set_id_callback(CryptoThreadIdCallback); +#if defined(OPENSSL_THREADS) && defined(TCL_THREADS) + /* should we consider allocating mutexes? */ + num_locks = CRYPTO_num_locks(); + if (num_locks > CRYPTO_NUM_LOCKS) { + status = TCL_ERROR; + goto done; + } + + CRYPTO_set_locking_callback(CryptoThreadLockCallback); + CRYPTO_set_id_callback(CryptoThreadIdCallback); #endif - if (SSL_library_init() != 1) { - status=TCL_ERROR; - goto done; - } - SSL_load_error_strings(); - ERR_load_crypto_strings(); - - /* - * Seed the random number generator in the SSL library, - * using the do/while construct because of the bug note in the - * OpenSSL FAQ at http://www.openssl.org/support/faq.html#USER1 - * - * The crux of the problem is that Solaris 7 does not have a - * /dev/random or /dev/urandom device so it cannot gather enough - * entropy from the RAND_seed() when TLS initializes and refuses - * to go further. Earlier versions of OpenSSL carried on regardless. - */ - srand((unsigned int) time((time_t *) NULL)); - do { - for (i = 0; i < 16; i++) { - rnd_seed[i] = 1 + (char) (255.0 * rand()/(RAND_MAX+1.0)); - } - RAND_seed(rnd_seed, sizeof(rnd_seed)); - } while (RAND_status() != 1); + if (SSL_library_init() != 1) { + status = TCL_ERROR; + goto done; + } + SSL_load_error_strings(); + ERR_load_crypto_strings(); + + /* + * Seed the random number generator in the SSL library, + * using the do/while construct because of the bug note in the + * OpenSSL FAQ at http://www.openssl.org/support/faq.html#USER1 + * + * The crux of the problem is that Solaris 7 does not have a + * /dev/random or /dev/urandom device so it cannot gather enough + * entropy from the RAND_seed() when TLS initializes and refuses + * to go further. Earlier versions of OpenSSL carried on regardless. + */ + srand((unsigned int) time((time_t *) NULL)); + do { + for (i = 0; i < 16; i++) { + rnd_seed[i] = 1 + (char) (255.0 * rand()/(RAND_MAX+1.0)); + } + RAND_seed(rnd_seed, sizeof(rnd_seed)); + } while (RAND_status() != 1); done: #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) - Tcl_MutexUnlock(&init_mx); + Tcl_MutexUnlock(&init_mx); #endif + return status; } Index: tlsBIO.c ================================================================== --- tlsBIO.c +++ tlsBIO.c @@ -21,25 +21,27 @@ BIO_new_tcl(statePtr, flags) State *statePtr; int flags; { BIO *bio; - static BIO_METHOD BioMethods = { - .type = BIO_TYPE_TCL, - .name = "tcl", - .bwrite = BioWrite, - .bread = BioRead, - .bputs = BioPuts, - .ctrl = BioCtrl, - .create = BioNew, - .destroy = BioFree, - }; - - bio = BIO_new(&BioMethods); - bio->ptr = (char*)statePtr; - bio->init = 1; - bio->shutdown = flags; + static BIO_METHOD *BioMethods = NULL; + + if (BioMethods == NULL) { + BioMethods = BIO_meth_new(BIO_TYPE_TCL, "tcl"); + BIO_meth_set_write(BioMethods, BioWrite); + BIO_meth_set_read(BioMethods, BioRead); + BIO_meth_set_puts(BioMethods, BioPuts); + BIO_meth_set_ctrl(BioMethods, BioCtrl); + BIO_meth_set_create(BioMethods, BioNew); + BIO_meth_set_destroy(BioMethods, BioFree); + } + + bio = BIO_new(BioMethods); + + BIO_set_data(bio, statePtr); + BIO_set_init(bio, 1); + BIO_set_shutdown(bio, flags); return bio; } static int @@ -46,11 +48,11 @@ BioWrite (bio, buf, bufLen) BIO *bio; CONST char *buf; int bufLen; { - Tcl_Channel chan = Tls_GetParent((State*)(bio->ptr)); + Tcl_Channel chan = Tls_GetParent((State*)BIO_get_data(bio)); int ret; dprintf("BioWrite(%p, , %d) [%p]", (void *) bio, bufLen, (void *) chan); @@ -81,11 +83,11 @@ BioRead (bio, buf, bufLen) BIO *bio; char *buf; int bufLen; { - Tcl_Channel chan = Tls_GetParent((State*)bio->ptr); + Tcl_Channel chan = Tls_GetParent((State*)BIO_get_data(bio)); int ret = 0; int tclEofChan; dprintf("BioRead(%p, , %d) [%p]", (void *) bio, bufLen, (void *) chan); @@ -137,13 +139,12 @@ BIO *bio; int cmd; long num; void *ptr; { - Tcl_Channel chan = Tls_GetParent((State*)bio->ptr); + Tcl_Channel chan = Tls_GetParent((State*)BIO_get_data(bio)); long ret = 1; - int *ip; dprintf("BioCtrl(%p, 0x%x, 0x%x, %p)", (void *) bio, (unsigned int) cmd, (unsigned int) num, (void *) ptr); @@ -156,32 +157,22 @@ break; case BIO_CTRL_INFO: ret = 1; break; case BIO_C_SET_FD: - BioFree(bio); - /* Sets State* */ - bio->ptr = *((char **)ptr); - bio->shutdown = (int)num; - bio->init = 1; - break; + dprintf("Unsupported call: BIO_C_SET_FD"); + ret = -1; + break; case BIO_C_GET_FD: - if (bio->init) { - ip = (int *)ptr; - if (ip != NULL) { - *ip = bio->num; - } - ret = bio->num; - } else { - ret = -1; - } - break; + dprintf("Unsupported call: BIO_C_GET_FD"); + ret = -1; + break; case BIO_CTRL_GET_CLOSE: - ret = bio->shutdown; + ret = BIO_get_shutdown(bio); break; case BIO_CTRL_SET_CLOSE: - bio->shutdown = (int)num; + BIO_set_shutdown(bio, num); break; case BIO_CTRL_EOF: dprintf("BIO_CTRL_EOF"); ret = Tcl_Eof(chan); break; @@ -211,14 +202,13 @@ static int BioNew (bio) BIO *bio; { - bio->init = 0; - bio->num = 0; - bio->ptr = NULL; - bio->flags = 0; + BIO_set_init(bio, 0); + BIO_set_data(bio, NULL); + BIO_clear_flags(bio, -1); return 1; } static int @@ -226,17 +216,15 @@ BIO *bio; { if (bio == NULL) { return 0; } - - if (bio->shutdown) { - if (bio->init) { + if (BIO_get_shutdown(bio)) { + if (BIO_get_init(bio)) { /*shutdown(bio->num, 2) */ /*closesocket(bio->num) */ } - bio->init = 0; - bio->flags = 0; - bio->num = 0; + BIO_set_init(bio, 0); + BIO_clear_flags(bio, -1); } return 1; } Index: tlsInt.h ================================================================== --- tlsInt.h +++ tlsInt.h @@ -259,7 +259,28 @@ void Tls_Clean _ANSI_ARGS_ ((State *statePtr)); int Tls_WaitForConnect _ANSI_ARGS_(( State *statePtr, int *errorCodePtr)); BIO * BIO_new_tcl _ANSI_ARGS_((State* statePtr, int flags)); + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define BIO_get_data(bio) ((bio)->ptr) +#define BIO_get_init(bio) ((bio)->init) +#define BIO_get_shutdown(bio) ((bio)->shutdown) +#define BIO_set_data(bio, val) (bio)->ptr = (val) +#define BIO_set_init(bio, val) (bio)->init = (val) +#define BIO_set_shutdown(bio, val) (bio)->shutdown = (val) + +/* XXX: This assumes the variable being assigned to is BioMethods */ +#define BIO_meth_new(type_, name_) (BIO_METHOD *)Tcl_Alloc(sizeof(BIO_METHOD)); \ + memset(BioMethods, 0, sizeof(BIO_METHOD)); \ + BioMethods->type = type_; \ + BioMethods->name = name_; +#define BIO_meth_set_write(bio, val) (bio)->bwrite = val; +#define BIO_meth_set_read(bio, val) (bio)->bread = val; +#define BIO_meth_set_puts(bio, val) (bio)->bputs = val; +#define BIO_meth_set_ctrl(bio, val) (bio)->ctrl = val; +#define BIO_meth_set_create(bio, val) (bio)->create = val; +#define BIO_meth_set_destroy(bio, val) (bio)->destroy = val; +#endif #endif /* _TLSINT_H */ Index: tlsX509.c ================================================================== --- tlsX509.c +++ tlsX509.c @@ -99,12 +99,15 @@ char notBefore[BUFSIZ]; char notAfter[BUFSIZ]; char certStr[BUFSIZ]; #ifndef NO_SSL_SHA int shai; - char sha_hash[SHA_DIGEST_LENGTH*2]; + char sha_hash_ascii[SHA_DIGEST_LENGTH * 2 + 1]; + unsigned char sha_hash_binary[SHA_DIGEST_LENGTH]; const char *shachars="0123456789ABCDEF"; + + sha_hash_ascii[SHA_DIGEST_LENGTH * 2] = '\0'; #endif certStr[0] = 0; if ((bio = BIO_new(BIO_s_mem())) == NULL) { subject[0] = 0; @@ -144,19 +147,17 @@ strcpy( notBefore, ASN1_UTCTIME_tostr( X509_get_notBefore(cert) )); strcpy( notAfter, ASN1_UTCTIME_tostr( X509_get_notAfter(cert) )); #ifndef NO_SSL_SHA - for (shai=0;shaisha1_hash[shai] & 0xF0) >> 4]; - sha_hash[shai * 2 + 1]=shachars[(cert->sha1_hash[shai] & 0x0F)]; - } - Tcl_ListObjAppendElement( interp, certPtr, - Tcl_NewStringObj( "sha1_hash", -1) ); - Tcl_ListObjAppendElement( interp, certPtr, - Tcl_NewStringObj( sha_hash, SHA_DIGEST_LENGTH*2) ); + X509_digest(cert, EVP_sha1(), sha_hash_binary, NULL); + for (shai = 0; shai < SHA_DIGEST_LENGTH; shai++) { + sha_hash_ascii[shai * 2] = shachars[(sha_hash_binary[shai] & 0xF0) >> 4]; + sha_hash_ascii[shai * 2 + 1] = shachars[(sha_hash_binary[shai] & 0x0F)]; + } + Tcl_ListObjAppendElement( interp, certPtr, Tcl_NewStringObj("sha1_hash", -1) ); + Tcl_ListObjAppendElement( interp, certPtr, Tcl_NewStringObj(sha_hash_ascii, SHA_DIGEST_LENGTH * 2) ); #endif Tcl_ListObjAppendElement( interp, certPtr, Tcl_NewStringObj( "subject", -1) ); Tcl_ListObjAppendElement( interp, certPtr,