Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,6 +1,18 @@ 2000-08-15 Jeff Hobbs + + * README.txt: added notes about need to use 8.2.0+. + + * tlsInt.h: + * tls.c: + * tlsIO.c: corrected structure initialization to work when + compiling with 8.2. Now compiles with 8.2+ and tested to work + with 8.2+ and dynamically adjust to the version of Tcl it was + loaded into. TLS will fail the test suite with Tcl 8.2-8.3.1. + + * tests/all.tcl: added catch around ::tcltest::normalizePath + because it doesn't exist in pre-8.3 tcltest. * tests/simpleClient.tcl: * tests/simpleServer.tcl: added simple client/server test scripts that use test certs and can do simple stress tests. Index: tls.c ================================================================== --- tls.c +++ tls.c @@ -1,9 +1,10 @@ /* * Copyright (C) 1997-1999 Matt Newman + * Copyright (C) 2000 Ajuba Solutions * - * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tls.c,v 1.9 2000/08/15 00:02:08 hobbs Exp $ + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tls.c,v 1.10 2000/08/15 18:49:30 hobbs Exp $ * * TLS (aka SSL) Channel - can be layered on any bi-directional * Tcl_Channel (Note: Requires Trf Core Patch) * * This was built (almost) from scratch based upon observation of Index: tlsIO.c ================================================================== --- tlsIO.c +++ tlsIO.c @@ -1,9 +1,10 @@ /* * Copyright (C) 1997-2000 Matt Newman + * Copyright (C) 2000 Ajuba Solutions * - * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.9 2000/08/15 00:02:08 hobbs Exp $ + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.10 2000/08/15 18:49:30 hobbs Exp $ * * TLS (aka SSL) Channel - can be layered on any bi-directional * Tcl_Channel (Note: Requires Trf Core Patch) * * This was built from scratch based upon observation of OpenSSL 0.9.2B @@ -18,18 +19,10 @@ * */ #include "tlsInt.h" -/* - * External functions - */ - -/* - * Local Defines - */ - /* * Forward declarations */ static int TlsBlockModeProc _ANSI_ARGS_((ClientData instanceData, @@ -52,20 +45,17 @@ int mask)); static void TlsChannelHandlerTimer _ANSI_ARGS_ ((ClientData clientData)); /* * This structure describes the channel type structure for TCP socket - * based IO: + * based IO. These are what the structures should look like, but we + * have to build them up at runtime to be correct depending on whether + * we are loaded into an 8.2.0-8.3.1 or 8.3.2+ Tcl interpreter. */ +#ifdef TLS_STATIC_STRUCTURES_NOT_USED static Tcl_ChannelType tlsChannelType2 = { "tls", /* Type name. */ -#ifndef TCL_CHANNEL_VERSION_2 - /* - * Avoids warning in Windows compiler when compiling with 8.3.1-. - */ - (Tcl_DriverBlockModeProc *) -#endif TCL_CHANNEL_VERSION_2, /* A v2 channel (8.3.2+) */ TlsCloseProc, /* Close proc. */ TlsInputProc, /* Input proc. */ TlsOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -79,16 +69,10 @@ TlsNotifyProc, /* handlerProc. */ }; static Tcl_ChannelType tlsChannelType1 = { "tls", /* Type name. */ -#ifdef TCL_CHANNEL_VERSION_2 - /* - * Avoids warning in Windows compiler when compiling with 8.3.2+. - */ - (Tcl_ChannelTypeVersion) -#endif TlsBlockModeProc, /* Set blocking/nonblocking mode.*/ TlsCloseProc, /* Close proc. */ TlsInputProc, /* Input proc. */ TlsOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -95,18 +79,150 @@ NULL, /* Set option proc. */ TlsGetOptionProc, /* Get option proc. */ TlsWatchProc, /* Initialize notifier. */ TlsGetHandleProc, /* Get file handle out of channel. */ }; +#else +static Tcl_ChannelType *tlsChannelType = NULL; +#endif +/* + *------------------------------------------------------------------- + * + * Tls_ChannelType -- + * + * Return the correct TLS channel driver info + * + * Results: + * The correct channel driver for the current version of Tcl. + * + * Side effects: + * None. + * + *------------------------------------------------------------------- + */ Tcl_ChannelType *Tls_ChannelType() { - if (channelTypeVersion == TLS_CHANNEL_VERSION_2) { - return &tlsChannelType2; - } else { - return &tlsChannelType1; + /* + * Initialize the channel type if necessary + */ + if (tlsChannelType == NULL) { + /* + * Allocation of a new channeltype structure is not easy, because of + * the various verson of the core and subsequent changes to the + * structure. The main challenge is to allocate enough memory for + * odern versions even if this extyension is compiled against one + * of the older variant! + * + * (1) Versions before stubs (8.0.x) are simple, because they are + * supported only if the extension is compiled against exactly + * that version of the core. + * + * (2) With stubs we just determine the difference between the older + * and modern variant and overallocate accordingly if compiled + * against an older variant. + */ + + int size = sizeof(Tcl_ChannelType); /* Base size */ + + /* + * Size of a procedure pointer. We assume that all procedure + * pointers are of the same size, regardless of exact type + * (arguments and return values). + * + * 8.2. First version containing close2proc. Baseline. + * 8.3.2 Three additional vectors. Moved blockMode, new flush- and + * handlerProc's. + * + * => Compilation against earlier version has to overallocate three + * procedure pointers. + */ + +#ifdef EMULATE_CHANNEL_VERSION_2 + size += 3 * procPtrSize; +#endif + + tlsChannelType = (Tcl_ChannelType *) ckalloc(size); + memset((VOID *) tlsChannelType, 0, size); + + /* + * Common elements of the structure (no changes in location or name) + * close2Proc, seekProc, setOptionProc stay NULL. + */ + + tlsChannelType->closeProc = TlsCloseProc; + tlsChannelType->inputProc = TlsInputProc; + tlsChannelType->outputProc = TlsOutputProc; + tlsChannelType->getOptionProc = TlsGetOptionProc; + tlsChannelType->watchProc = TlsWatchProc; + tlsChannelType->getHandleProc = TlsGetHandleProc; + + /* + * blockModeProc is a twister. We have to make some runtime-choices, + * depending on the version we compiled against. + */ + +#ifdef EMULATE_CHANNEL_VERSION_2 + /* + * We are compiling against an 8.3.1- core. We have to create some + * definitions for the new elements as the compiler does not know them + * by name. + */ + + if (channelTypeVersion == TLS_CHANNEL_VERSION_1) { + /* + * The 'version' element of 8.3.2 is in the the place of the + * blockModeProc. For 8.2.0-8.3.1 we have to set our blockModeProc + * into this place. + */ + tlsChannelType->blockModeProc = TlsBlockModeProc; + } else /* channelTypeVersion == TLS_CHANNEL_VERSION_2 */ { + /* + * For the 8.3.2 core we present ourselves as a version 2 + * driver. This means a special value in version (ex + * blockModeProc), blockModeProc in a different place and of + * course usage of the handlerProc. The last two have to + * referenced with pointer magic because they aren't defined + * otherwise. + */ + + tlsChannelType->blockModeProc = + (Tcl_DriverBlockModeProc*) TLS_CHANNEL_VERSION_2; + (*((Tcl_DriverBlockModeProc**)(&(tlsChannelType->close2Proc)+1))) + = TlsBlockModeProc; + (*((TlsDriverHandlerProc**)(&(tlsChannelType->close2Proc)+3))) + = TlsNotifyProc; + } +#else + /* + * Compiled against 8.3.2+. Direct access to all elements possible. Use + * channelTypeVersion information to select the values to use. + */ + + if (channelTypeVersion == TLS_CHANNEL_VERSION_1) { + /* + * The 'version' element of 8.3.2 is in the the place of the + * blockModeProc. For the original patch in 8.1.x and the firstly + * included (8.2) we have to set our blockModeProc into this + * place. + */ + tlsChannelType->version = (Tcl_ChannelTypeVersion)TlsBlockModeProc; + } else /* channelTypeVersion == TLS_CHANNEL_VERSION_2 */ { + /* + * For the 8.3.2 core we present ourselves as a version 2 + * driver. This means a special value in version (ex + * blockModeProc), blockModeProc in a different place and of + * course usage of the handlerProc. + */ + + tlsChannelType->version = TCL_CHANNEL_VERSION_2; + tlsChannelType->blockModeProc = TlsBlockModeProc; + tlsChannelType->handlerProc = TlsNotifyProc; + } +#endif } + return tlsChannelType; } /* *------------------------------------------------------------------- * Index: tlsInt.h ================================================================== --- tlsInt.h +++ tlsInt.h @@ -1,9 +1,9 @@ /* * Copyright (C) 1997-2000 Matt Newman * - * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsInt.h,v 1.6 2000/08/15 00:02:08 hobbs Exp $ + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsInt.h,v 1.7 2000/08/15 18:49:31 hobbs Exp $ * * TLS (aka SSL) Channel - can be layered on any bi-directional * Tcl_Channel (Note: Requires Trf Core Patch) * * This was built from scratch based upon observation of OpenSSL 0.9.2B @@ -102,12 +102,12 @@ char *err; } State; /* - * The following definitions have to be usable for 8.0.x, 8.1.x, 8.2.x, - * 8.3.[01], 8.3.2 and beyond. The differences between these versions: + * The following definitions have to be usable for 8.2.0-8.3.1 and 8.3.2+. + * The differences between these versions: * * 8.0-8.1: There is no support for these in TLS 1.4 (get 1.3). This * was the version with the original patch. * * 8.2.0- Changed semantics for Tcl_StackChannel (Tcl_ReplaceChannel). @@ -115,11 +115,11 @@ * of the core from now on. * * 8.3.2+: Stacked channels rewritten for better behaviour in some * situations (closing). Some new API's, semantic changes. * - * The following magic was taken from Trf 2.1 (Kupries). + * The following magic was adapted from Trf 2.1 (Kupries). */ #define TLS_CHANNEL_VERSION_1 0x1 #define TLS_CHANNEL_VERSION_2 0x2 extern int channelTypeVersion; @@ -162,16 +162,22 @@ #define Tcl_GetStackedChannel ((tls_GetStackedChannel*) tclStubsPtr->reserved283) #endif /* Tcl_GetStackedChannel */ -#ifndef Tcl_WriteRaw +#ifndef TCL_CHANNEL_VERSION_2 /* * Core is older than 8.3.2. Supply the missing definitions for * the new API's in 8.3.2. */ +#define EMULATE_CHANNEL_VERSION_2 + +typedef struct TlsChannelTypeVersion_* TlsChannelTypeVersion; +#define TCL_CHANNEL_VERSION_2 ((TlsChannelTypeVersion) 0x2) +typedef int (TlsDriverHandlerProc) _ANSI_ARGS_((ClientData instanceData, + int interestMask)); /* 394 */ typedef int (tls_ReadRaw) _ANSI_ARGS_((Tcl_Channel chan, char *dst, int bytesToRead)); /* 395 */ typedef int (tls_WriteRaw) _ANSI_ARGS_((Tcl_Channel chan, char *src, @@ -195,19 +201,16 @@ #define Tcl_ReadRaw (*((tls_ReadRaw**) (SLOT(394)))) #define Tcl_WriteRaw (*((tls_WriteRaw**) (SLOT(395)))) #define Tcl_GetTopChannel (*((tls_GetTopChannel**)(SLOT(396)))) -typedef struct TlsChannelTypeVersion_* TlsChannelTypeVersion; -#define TCL_CHANNEL_VERSION_2 ((TlsChannelTypeVersion) 0x2) - /* * Required, easy emulation. */ #define Tcl_ChannelGetOptionProc(chanDriver) ((chanDriver)->getOptionProc) -#endif /* Tcl_WriteRaw */ +#endif /* TCL_CHANNEL_VERSION_2 */ #endif /* USE_TCL_STUBS */ /* * Forward declarations