Check-in [53bd8f71ad]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merged in trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tls-1-7
Files: files | file ages | folders
SHA1:53bd8f71ad69f48553185cf6a9777193c909ca4a
User & Date: rkeene 2016-12-13 16:05:35
Context
2016-12-13
16:05
TclTLS 1.7.6 check-in: ba6e2a082f user: rkeene tags: tls-1-7, tls-1-7-6
16:05
Merged in trunk check-in: 53bd8f71ad user: rkeene tags: tls-1-7
16:00
Updated to return soft errors on during SSL negotiation retries on reads and hard errors on SSL negotiation during writes or handshake commands check-in: b9557ba691 user: rkeene tags: trunk
05:17
TclTLS 1.7.5 check-in: 1303418e93 user: rkeene tags: tls-1-7, tls-1-7-5
Changes

Changes to .fossil-settings/ignore-glob.

    12     12   tcltls.a
    13     13   tcltls.a.linkadd
    14     14   tls.o
    15     15   tlsBIO.o
    16     16   tlsIO.o
    17     17   tlsX509.o
    18     18   tls.tcl.h
           19  +tls.tcl.h.new.1
           20  +tls.tcl.h.new.2
    19     21   build/work
    20     22   dh_params.h

Changes to Makefile.in.

     6      6   LDFLAGS = @LDFLAGS@ @SHOBJLDFLAGS@
     7      7   LIBS = @LIBS@
     8      8   INSTALL = @INSTALL@
     9      9   PACKAGE_VERSION = @PACKAGE_VERSION@
    10     10   TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@
    11     11   PACKAGE_INSTALL_DIR = $(TCL_PACKAGE_PATH)/tcltls$(PACKAGE_VERSION)
    12     12   VPATH = @srcdir@
           13  +srcdir = @srcdir@
    13     14   
    14     15   all: @EXTENSION_TARGET@
    15     16   
    16     17   # The shared object target
    17     18   tcltls.@SHOBJEXT@: tls.o tlsBIO.o tlsIO.o tlsX509.o Makefile
    18     19   	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o tcltls.@SHOBJEXT@ tls.o tlsBIO.o tlsIO.o tlsX509.o $(LIBS)
    19     20   
................................................................................
    20     21   # The static target
    21     22   tcltls.@AREXT@: tls.o tlsBIO.o tlsIO.o tlsX509.o Makefile
    22     23   	$(AR) rcu tcltls.a.new tls.o tlsBIO.o tlsIO.o tlsX509.o
    23     24   	$(RANLIB) tcltls.a.new
    24     25   	mv tcltls.a.new tcltls.a
    25     26   
    26     27   # Dependencies for all our targets
    27         -tls.o: @srcdir@/tls.c @srcdir@/tlsInt.h @srcdir@/tclOpts.h @srcdir@/tls.tcl.h dh_params.h Makefile
           28  +tls.o: @srcdir@/tls.c @srcdir@/tlsInt.h @srcdir@/tclOpts.h tls.tcl.h dh_params.h Makefile
    28     29   tlsBIO.o: @srcdir@/tlsBIO.c @srcdir@/tlsInt.h Makefile
    29     30   tlsIO.o: @srcdir@/tlsIO.c @srcdir@/tlsInt.h Makefile
    30     31   tlsX509.o: @srcdir@/tlsX509.c @srcdir@/tlsInt.h Makefile
    31     32   
    32     33   # Create a C-source-ified version of the script resources
    33     34   # for TclTLS so that we only need a single file to enable
    34     35   # this extension
    35         -@srcdir@/tls.tcl.h: @srcdir@/tls.tcl
    36         -	@XXD@ -i < '@srcdir@/tls.tcl' > '@srcdir@/tls.tcl.h.new'
    37         -	mv '@srcdir@/tls.tcl.h.new' '@srcdir@/tls.tcl.h'
           36  +tls.tcl.h: $(srcdir)/tls.tcl
           37  +	od -A n -v -t xC < '$(srcdir)/tls.tcl' > tls.tcl.h.new.1
           38  +	sed 's@  *@@g;s@..@0x&, @g' < tls.tcl.h.new.1 > tls.tcl.h.new.2
           39  +	rm -f tls.tcl.h.new.1
           40  +	mv tls.tcl.h.new.2 tls.tcl.h
    38     41   
    39     42   # Create default DH parameters
    40     43   dh_params.h: @srcdir@/gen_dh_params Makefile
    41     44   	@srcdir@/gen_dh_params @GEN_DH_PARAMS_ARGS@ > dh_params.h.new
    42     45   	mv dh_params.h.new dh_params.h
    43     46   
    44     47   # Generic target for building files from the "srcdir"
................................................................................
    46     49   .c.o:
    47     50   	$(CC) $(CPPFLAGS) $(CFLAGS) -o "$@" -c "$<"
    48     51   
    49     52   # Install the extension
    50     53   install: @EXTENSION_TARGET@ pkgIndex.tcl
    51     54   	$(INSTALL) -d '$(DESTDIR)$(PACKAGE_INSTALL_DIR)'
    52     55   	$(INSTALL) -t '$(DESTDIR)$(PACKAGE_INSTALL_DIR)' @EXTENSION_TARGET@ pkgIndex.tcl
           56  +
           57  +# Test target, run the automated test suite
           58  +test: @EXTENSION_TARGET@
           59  +	cd tests && @TCLSH_PROG@ all.tcl
    53     60   
    54     61   # Clean the local build directory for rebuild against the same configuration
    55     62   clean:
    56     63   	rm -f tls.o tlsBIO.o tlsIO.o tlsX509.o
    57     64   	rm -f tcltls.@SHOBJEXT@
    58     65   	rm -f tcltls.a.new tcltls.a
           66  +	rm -f tls.tcl.h tls.tcl.h.new.1 tls.tcl.h.new.2
    59     67   
    60     68   # Clean the local build directory back to what it was after unpacking the
    61     69   # distribution tarball
    62     70   distclean: clean
    63     71   	rm -f config.log config.status
    64     72   	rm -f dh_params.h.new dh_params.h
    65     73   	rm -f Makefile pkgIndex.tcl
    66     74   	rm -f tcltls.a.linkadd
    67     75   
    68     76   # Clean the local build directory back to only thing things that exist in
    69     77   # version control system
    70     78   mrproper: distclean
    71         -	rm -f @srcdir@/tls.tcl.h
    72     79   	rm -f @srcdir@/configure @srcdir@/config.sub @srcdir@/config.guess @srcdir@/install-sh
    73     80   	rm -f @srcdir@/aclocal.m4
    74     81   	rm -rf @srcdir@/autom4te.cache
    75     82   
    76         -.PHONY: all install clean distclean mrproper
           83  +.PHONY: all install clean distclean mrproper test

Added aclocal/ax_check_compile_flag.m4.

            1  +# ===========================================================================
            2  +#   http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
            3  +# ===========================================================================
            4  +#
            5  +# SYNOPSIS
            6  +#
            7  +#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
            8  +#
            9  +# DESCRIPTION
           10  +#
           11  +#   Check whether the given FLAG works with the current language's compiler
           12  +#   or gives an error.  (Warnings, however, are ignored)
           13  +#
           14  +#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
           15  +#   success/failure.
           16  +#
           17  +#   If EXTRA-FLAGS is defined, it is added to the current language's default
           18  +#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
           19  +#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
           20  +#   force the compiler to issue an error when a bad flag is given.
           21  +#
           22  +#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
           23  +#
           24  +#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
           25  +#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
           26  +#
           27  +# LICENSE
           28  +#
           29  +#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
           30  +#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
           31  +#
           32  +#   This program is free software: you can redistribute it and/or modify it
           33  +#   under the terms of the GNU General Public License as published by the
           34  +#   Free Software Foundation, either version 3 of the License, or (at your
           35  +#   option) any later version.
           36  +#
           37  +#   This program is distributed in the hope that it will be useful, but
           38  +#   WITHOUT ANY WARRANTY; without even the implied warranty of
           39  +#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
           40  +#   Public License for more details.
           41  +#
           42  +#   You should have received a copy of the GNU General Public License along
           43  +#   with this program. If not, see <http://www.gnu.org/licenses/>.
           44  +#
           45  +#   As a special exception, the respective Autoconf Macro's copyright owner
           46  +#   gives unlimited permission to copy, distribute and modify the configure
           47  +#   scripts that are the output of Autoconf when processing the Macro. You
           48  +#   need not follow the terms of the GNU General Public License when using
           49  +#   or distributing such scripts, even though portions of the text of the
           50  +#   Macro appear in them. The GNU General Public License (GPL) does govern
           51  +#   all other use of the material that constitutes the Autoconf Macro.
           52  +#
           53  +#   This special exception to the GPL applies to versions of the Autoconf
           54  +#   Macro released by the Autoconf Archive. When you make and distribute a
           55  +#   modified version of the Autoconf Macro, you may extend this special
           56  +#   exception to the GPL to apply to your modified version as well.
           57  +
           58  +#serial 4
           59  +
           60  +AC_DEFUN([AX_CHECK_COMPILE_FLAG],
           61  +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
           62  +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
           63  +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
           64  +  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
           65  +  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
           66  +  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
           67  +    [AS_VAR_SET(CACHEVAR,[yes])],
           68  +    [AS_VAR_SET(CACHEVAR,[no])])
           69  +  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
           70  +AS_VAR_IF(CACHEVAR,yes,
           71  +  [m4_default([$2], :)],
           72  +  [m4_default([$3], :)])
           73  +AS_VAR_POPDEF([CACHEVAR])dnl
           74  +])dnl AX_CHECK_COMPILE_FLAGS

Changes to build/post.sh.

     1      1   #! /usr/bin/env bash
            2  +
            3  +set -e
     2      4   
     3      5   rm -rf build
     4      6   rm -f autogen.sh
            7  +make -f Makefile.in srcdir=. tls.tcl.h
     5      8   
     6      9   exit 0

Changes to configure.in.

    55     55   	GEN_DH_PARAMS_ARGS='fallback'
    56     56   else
    57     57   	GEN_DH_PARAMS_ARGS=''
    58     58   fi
    59     59   AC_SUBST(GEN_DH_PARAMS_ARGS)
    60     60   
    61     61   dnl Allow the user to manually disable protocols
    62         -dnl ## SSLv2: Disabled by default
    63         -tcltls_ssl_ssl2='false'
    64         -AC_ARG_ENABLE([sslv2], AS_HELP_STRING([--enable-sslv2], [enable SSLv2 protocol]), [
           62  +dnl ## SSLv2: Enabled by default
           63  +tcltls_ssl_ssl2='true'
           64  +AC_ARG_ENABLE([sslv2], AS_HELP_STRING([--disable-sslv2], [disable SSLv2 protocol]), [
    65     65   	if test "$enableval" = "yes"; then
    66     66   		tcltls_ssl_ssl2='force'
           67  +	else
           68  +		tcltls_ssl_ssl2='false'
    67     69   	fi
    68     70   ])
    69     71   
    70         -dnl ## SSLv3: Disabled by default
    71         -tcltls_ssl_ssl3='false'
    72         -AC_ARG_ENABLE([sslv3], AS_HELP_STRING([--enable-sslv3], [enable SSLv3 protocol]), [
           72  +dnl ## SSLv3: Enabled by default
           73  +tcltls_ssl_ssl3='true'
           74  +AC_ARG_ENABLE([sslv3], AS_HELP_STRING([--disable-sslv3], [disable SSLv3 protocol]), [
    73     75   	if test "$enableval" = "yes"; then
    74     76   		tcltls_ssl_ssl3='force'
           77  +	else
           78  +		tcltls_ssl_ssl3='false'
    75     79   	fi
    76     80   ])
    77     81   
    78     82   dnl ## TLSv1.0: Enabled by default
    79     83   tcltls_ssl_tls1_0='true'
    80     84   AC_ARG_ENABLE([tlsv1.0], AS_HELP_STRING([--disable-tlsv1.0], [disable TLSv1.0 protocol]), [
    81         -	if test "$enableval" = "no"; then
           85  +	if test "$enableval" = "yes"; then
           86  +		tcltls_ssl_tls1_0='force'
           87  +	else
    82     88   		tcltls_ssl_tls1_0='false'
    83     89   	fi
    84     90   ])
    85     91   
    86     92   dnl ## TLSv1.1: Enabled by default
    87     93   tcltls_ssl_tls1_1='true'
    88     94   AC_ARG_ENABLE([tlsv1.1], AS_HELP_STRING([--disable-tlsv1.1], [disable TLSv1.1 protocol]), [
    89         -	if test "$enableval" = "no"; then
           95  +	if test "$enableval" = "yes"; then
           96  +		tcltls_ssl_tls1_1='force'
           97  +	else
    90     98   		tcltls_ssl_tls1_1='false'
    91     99   	fi
    92    100   ])
    93    101   
    94    102   dnl ## TLSv1.1: Enabled by default
    95    103   tcltls_ssl_tls1_2='true'
    96    104   AC_ARG_ENABLE([tlsv1.2], AS_HELP_STRING([--disable-tlsv1.2], [disable TLSv1.2 protocol]), [
    97         -	if test "$enableval" = "no"; then
          105  +	if test "$enableval" = "yes"; then
          106  +		tcltls_ssl_tls1_2='force'
          107  +	else
    98    108   		tcltls_ssl_tls1_2='false'
    99    109   	fi
   100    110   ])
   101    111   
   102    112   dnl Enable support for a debugging build
   103    113   tcltls_debug='false'
   104    114   AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [enable debugging parameters]), [
................................................................................
   105    115   	if test "$enableval" = "yes"; then
   106    116   		tcltls_debug='true'
   107    117   	fi
   108    118   ])
   109    119   if test "$tcltls_debug" = 'true'; then
   110    120   	AC_DEFINE(TCLEXT_TCLTLS_DEBUG, [1], [Enable debugging build])
   111    121   	AX_CHECK_COMPILE_FLAG([-fcheck-pointer-bounds], [CFLAGS="$CFLAGS -fcheck-pointer-bounds"])
   112         -	AX_CHECK_COMPILE_FLAG([-fsanitize=address], [CFLAGS="$CFLAGS -fsanitize=address"])
   113         -	AX_CHECK_COMPILE_FLAG([-fsanitize=undefined], [CFLAGS="$CFLAGS -fsanitize=undefined"])
   114    122   else
   115    123   	dnl If we are not doing debugging disable some of the more annoying warnings
   116    124   	AX_CHECK_COMPILE_FLAG([-Wno-unused-value], [CFLAGS="$CFLAGS -Wno-unused-value"])
   117    125   	AX_CHECK_COMPILE_FLAG([-Wno-unused-parameter], [CFLAGS="$CFLAGS -Wno-unused-parameter"])
   118    126   	AX_CHECK_COMPILE_FLAG([-Wno-deprecated-declarations], [CFLAGS="$CFLAGS -Wno-deprecated-declarations"])
   119    127   fi
   120    128   
   121         -dnl Find "xxd" so we can build the tls.tcl.h file
   122         -AC_CHECK_PROG([XXD], [xxd], [xxd], [__xxd__not__found])
   123         -
   124    129   dnl Find "pkg-config" since we need to use it
   125    130   AC_CHECK_TOOL([PKGCONFIG], [pkg-config], [false])
   126    131   
   127    132   dnl Determine if we have been asked to use a fast path if possible
   128    133   tcltls_ssl_fastpath='yes'
   129         -AC_ARG_ENABLE([ssl-fastpath], AS_HELP_STRING([--disable-ssl-fast-path], [disable using the underlying file descriptor for talking directly to the SSL library]), [
          134  +AC_ARG_ENABLE([ssl-fastpath], AS_HELP_STRING([--disable-ssl-fastpath], [disable using the underlying file descriptor for talking directly to the SSL library]), [
   130    135   	if test "$enableval" = 'no'; then
   131    136   		tcltls_ssl_fastpath='no'
   132    137   	fi
   133    138   ])
   134    139   
   135    140   if test "$tcltls_ssl_fastpath" = 'yes'; then
   136    141   	AC_DEFINE(TCLTLS_SSL_USE_FASTPATH, [1], [Define this to enable using the underlying file descriptor for talking directly to the SSL library])

Changes to tls.c.

   128    128   		/* dprintf("Called to lock (n=%i of %i)", n, locksCount); */
   129    129   		Tcl_MutexLock(&locks[n]);
   130    130   	} else {
   131    131   		/* dprintf("Called to unlock (n=%i of %i)", n, locksCount); */
   132    132   		Tcl_MutexUnlock(&locks[n]);
   133    133   	}
   134    134   
   135         -	dprintf("Returning");
          135  +	/* dprintf("Returning"); */
   136    136   
   137    137   	return;
   138    138   	file = file;
   139    139   	line = line;
   140    140   }
   141    141   
   142    142   unsigned long CryptoThreadIdCallback(void) {
................................................................................
   632    632       Tcl_Interp *interp;
   633    633       int objc;
   634    634       Tcl_Obj *CONST objv[];
   635    635   {
   636    636       Tcl_Channel chan;		/* The channel to set a mode on. */
   637    637       State *statePtr;		/* client state for ssl socket */
   638    638       int ret = 1;
          639  +    int err = 0;
   639    640   
   640    641       dprintf("Called");
   641    642   
   642    643       if (objc != 2) {
   643    644   	Tcl_WrongNumArgs(interp, 1, objv, "channel");
   644    645   	return TCL_ERROR;
   645    646       }
................................................................................
   656    657       if (Tcl_GetChannelType(chan) != Tls_ChannelType()) {
   657    658   	Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan),
   658    659   		"\": not a TLS channel", NULL);
   659    660   	return TCL_ERROR;
   660    661       }
   661    662       statePtr = (State *)Tcl_GetChannelInstanceData(chan);
   662    663   
   663         -    if (!SSL_is_init_finished(statePtr->ssl)) {
   664         -	int err = 0;
   665    664           dprintf("Calling Tls_WaitForConnect");
   666         -	ret = Tls_WaitForConnect(statePtr, &err);
          665  +	ret = Tls_WaitForConnect(statePtr, &err, 1);
   667    666           dprintf("Tls_WaitForConnect returned: %i", ret);
   668    667   
          668  +     if (ret < 0) {
   669    669   	if ((statePtr->flags & TLS_TCL_ASYNC) && err == EAGAIN) {
   670    670               dprintf("Async set and err = EAGAIN");
   671    671   	    ret = 0;
   672    672   	}
          673  +     }
   673    674   
   674    675   	if (ret < 0) {
   675    676   	    CONST char *errStr = statePtr->err;
   676    677   	    Tcl_ResetResult(interp);
   677    678   	    Tcl_SetErrno(err);
   678    679   
   679    680   	    if (!errStr || *errStr == 0) {
   680    681   		errStr = Tcl_PosixError(interp);
   681    682   	    }
   682    683   
   683    684   	    Tcl_AppendResult(interp, "handshake failed: ", errStr, (char *) NULL);
   684    685               dprintf("Returning TCL_ERROR with handshake failed: %s", errStr);
   685    686   	    return TCL_ERROR;
   686         -	}
   687         -    }
          687  +	} else {
          688  +          ret = 1;
          689  +        }
   688    690   
          691  +    dprintf("Returning TCL_OK with data \"%i\"", ret);
   689    692       Tcl_SetObjResult(interp, Tcl_NewIntObj(ret));
   690    693       return TCL_OK;
   691    694       	clientData = clientData;
   692    695   }
   693    696   
   694    697   /*
   695    698    *-------------------------------------------------------------------
................................................................................
   730    733       char *CAfile	= NULL;
   731    734       char *CAdir		= NULL;
   732    735       char *DHparams	= NULL;
   733    736       char *model		= NULL;
   734    737   #ifndef OPENSSL_NO_TLSEXT
   735    738       char *servername	= NULL;	/* hostname for Server Name Indication */
   736    739   #endif
   737         -#if defined(NO_SSL2)
   738         -    int ssl2 = 0;
   739         -#else
   740         -    int ssl2 = 1;
   741         -#endif
   742         -#if defined(NO_SSL3)
   743         -    int ssl3 = 0;
   744         -#else
   745         -    int ssl3 = 1;
   746         -#endif
   747         -#if defined(NO_TLS1)
   748         -    int tls1 = 0;
   749         -#else
   750         -    int tls1 = 1;
   751         -#endif
   752         -#if defined(NO_TLS1_1)
   753         -    int tls1_1 = 0;
   754         -#else
   755         -    int tls1_1 = 1;
   756         -#endif
   757         -#if defined(NO_TLS1_2)
   758         -    int tls1_2 = 0;
   759         -#else
   760         -    int tls1_2 = 1;
   761         -#endif
          740  +    int ssl2 = 0, ssl3 = 0;
          741  +    int tls1 = 1, tls1_1 = 1, tls1_2 = 1;
   762    742       int proto = 0;
   763    743       int verify = 0, require = 0, request = 1;
   764    744   
   765    745       dprintf("Called");
          746  +
          747  +#if defined(NO_TLS1) && defined(NO_TLS1_1) && defined(NO_TLS1_2) && defined(NO_SSL3) && !defined(NO_SSL2)
          748  +    ssl2 = 1;
          749  +#endif
          750  +#if defined(NO_TLS1) && defined(NO_TLS1_1) && defined(NO_TLS1_2) && defined(NO_SSL2) && !defined(NO_SSL3)
          751  +    ssl3 = 1;
          752  +#endif
          753  +#if defined(NO_TLS1)
          754  +    tls1 = 0;
          755  +#endif
          756  +#if defined(NO_TLS1_1)
          757  +    tls1_1 = 0;
          758  +#endif
          759  +#if defined(NO_TLS1_2)
          760  +    tls1_2 = 0;
          761  +#endif
   766    762   
   767    763       if (objc < 2) {
   768    764   	Tcl_WrongNumArgs(interp, 1, objv, "channel ?options?");
   769    765   	return TCL_ERROR;
   770    766       }
   771    767   
   772    768       chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL);
................................................................................
  1658   1654    *
  1659   1655    *-------------------------------------------------------------------
  1660   1656    */
  1661   1657   
  1662   1658   int Tls_Init(Tcl_Interp *interp) {
  1663   1659   	const char tlsTclInitScript[] = {
  1664   1660   #include "tls.tcl.h"
  1665         -            , 0x00
         1661  +            0x00
  1666   1662   	};
  1667   1663   
  1668   1664           dprintf("Called");
  1669   1665   
  1670   1666   	/*
  1671   1667   	 * We only support Tcl 8.4 or newer
  1672   1668   	 */

Changes to tlsIO.c.

   171    171   	dprintf("Returning TCL_OK");
   172    172   
   173    173   	return(TCL_OK);
   174    174   
   175    175   	/* Interp is unused. */
   176    176   	interp = interp;
   177    177   }
          178  +
          179  +/*
          180  + *------------------------------------------------------*
          181  + *
          182  + *	Tls_WaitForConnect --
          183  + *
          184  + *	Sideeffects:
          185  + *		Issues SSL_accept or SSL_connect
          186  + *
          187  + *	Result:
          188  + *		None.
          189  + *
          190  + *------------------------------------------------------*
          191  + */
          192  +int Tls_WaitForConnect(State *statePtr, int *errorCodePtr, int handshakeFailureIsPermanent) {
          193  +	unsigned long backingError;
          194  +	int err, rc;
          195  +	int bioShouldRetry;
          196  +
          197  +	dprintf("WaitForConnect(%p)", (void *) statePtr);
          198  +	dprintFlags(statePtr);
          199  +
          200  +	if (!(statePtr->flags & TLS_TCL_INIT)) {
          201  +		dprintf("Tls_WaitForConnect called on already initialized channel -- returning with immediate success");
          202  +		*errorCodePtr = 0;
          203  +		return(0);
          204  +	}
          205  +
          206  +	if (statePtr->flags & TLS_TCL_HANDSHAKE_FAILED) {
          207  +		/*
          208  +		 * Different types of operations have different requirements
          209  +		 * SSL being established
          210  +		 */
          211  +		if (handshakeFailureIsPermanent) {
          212  +			dprintf("Asked to wait for a TLS handshake that has already failed.  Returning fatal error");
          213  +			*errorCodePtr = ECONNABORTED;
          214  +		} else {
          215  +			dprintf("Asked to wait for a TLS handshake that has already failed.  Returning soft error");
          216  +			*errorCodePtr = ECONNRESET;
          217  +		}
          218  +		return(-1);
          219  +	}
          220  +
          221  +	for (;;) {
          222  +		/* Not initialized yet! */
          223  +		if (statePtr->flags & TLS_TCL_SERVER) {
          224  +			dprintf("Calling SSL_accept()");
          225  +
          226  +			err = SSL_accept(statePtr->ssl);
          227  +		} else {
          228  +			dprintf("Calling SSL_connect()");
          229  +
          230  +			err = SSL_connect(statePtr->ssl);
          231  +		}
          232  +
          233  +		if (err > 0) {
          234  +			dprintf("That seems to have gone okay");
          235  +
          236  +			err = BIO_flush(statePtr->bio);
          237  +
          238  +			if (err <= 0) {
          239  +				dprintf("Flushing the lower layers failed, this will probably terminate this session");
          240  +			}
          241  +		}
          242  +
          243  +		rc = SSL_get_error(statePtr->ssl, err);
          244  +
          245  +		dprintf("Got error: %i (rc = %i)", err, rc);
          246  +
          247  +		bioShouldRetry = 0;
          248  +		if (err <= 0) {
          249  +			if (rc == SSL_ERROR_WANT_CONNECT || rc == SSL_ERROR_WANT_ACCEPT || rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) {
          250  +				bioShouldRetry = 1;
          251  +			} else if (BIO_should_retry(statePtr->bio)) {
          252  +				bioShouldRetry = 1;
          253  +			} else if (rc == SSL_ERROR_SYSCALL && Tcl_GetErrno() == EAGAIN) {
          254  +				bioShouldRetry = 1;
          255  +			}
          256  +		} else {
          257  +			if (!SSL_is_init_finished(statePtr->ssl)) {
          258  +				bioShouldRetry = 1;
          259  +			}
          260  +		}
          261  +
          262  +		if (bioShouldRetry) {
          263  +			dprintf("The I/O did not complete -- but we should try it again");
          264  +
          265  +			if (statePtr->flags & TLS_TCL_ASYNC) {
          266  +				dprintf("Returning EAGAIN so that it can be retried later");
          267  +
          268  +				*errorCodePtr = EAGAIN;
          269  +
          270  +				return(-1);
          271  +			} else {
          272  +				dprintf("Doing so now");
          273  +
          274  +				continue;
          275  +			}
          276  +		}
          277  +
          278  +		dprintf("We have either completely established the session or completely failed it -- there is no more need to ever retry it though");
          279  +		break;
          280  +	}
          281  +
          282  +
          283  +	*errorCodePtr = EINVAL;
          284  +
          285  +	switch (rc) {
          286  +		case SSL_ERROR_NONE:
          287  +			/* The connection is up, we are done here */
          288  +			dprintf("The connection is up");
          289  +			break;
          290  +		case SSL_ERROR_ZERO_RETURN:
          291  +			dprintf("SSL_ERROR_ZERO_RETURN: Connect returned an invalid value...")
          292  +			return(-1);
          293  +		case SSL_ERROR_SYSCALL:
          294  +			backingError = ERR_get_error();
          295  +
          296  +			if (backingError == 0 && err == 0) {
          297  +				dprintf("EOF reached")
          298  +				*errorCodePtr = ECONNRESET;
          299  +			} else if (backingError == 0 && err == -1) {
          300  +				dprintf("I/O error occured (errno = %lu)", (unsigned long) Tcl_GetErrno());
          301  +				*errorCodePtr = Tcl_GetErrno();
          302  +				if (*errorCodePtr == ECONNRESET) {
          303  +					*errorCodePtr = ECONNABORTED;
          304  +				}
          305  +			} else {
          306  +				dprintf("I/O error occured (backingError = %lu)", backingError);
          307  +				*errorCodePtr = backingError;
          308  +				if (*errorCodePtr == ECONNRESET) {
          309  +					*errorCodePtr = ECONNABORTED;
          310  +				}
          311  +			}
          312  +
          313  +			statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED;
          314  +
          315  +			return(-1);
          316  +		case SSL_ERROR_SSL:
          317  +			dprintf("Got permanent fatal SSL error, aborting immediately");
          318  +			Tls_Error(statePtr, (char *)ERR_reason_error_string(ERR_get_error()));
          319  +			statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED;
          320  +			*errorCodePtr = ECONNABORTED;
          321  +			return(-1);
          322  +		case SSL_ERROR_WANT_CONNECT:
          323  +		case SSL_ERROR_WANT_ACCEPT:
          324  +		case SSL_ERROR_WANT_X509_LOOKUP:
          325  +		default:
          326  +			dprintf("We got a confusing reply: %i", rc);
          327  +			*errorCodePtr = Tcl_GetErrno();
          328  +			dprintf("ERR(%d, %d) ", rc, *errorCodePtr);
          329  +			return(-1);
          330  +	}
          331  +
          332  +#if 0
          333  +	if (statePtr->flags & TLS_TCL_SERVER) {
          334  +		dprintf("This is an TLS server, checking the certificate for the peer");
          335  +
          336  +		err = SSL_get_verify_result(statePtr->ssl);
          337  +		if (err != X509_V_OK) {
          338  +			dprintf("Invalid certificate, returning in failure");
          339  +
          340  +			Tls_Error(statePtr, (char *)X509_verify_cert_error_string(err));
          341  +			statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED;
          342  +			*errorCodePtr = ECONNABORTED;
          343  +			return(-1);
          344  +		}
          345  +	}
          346  +#endif
          347  +
          348  +	dprintf("Removing the \"TLS_TCL_INIT\" flag since we have completed the handshake");
          349  +	statePtr->flags &= ~TLS_TCL_INIT;
          350  +
          351  +	dprintf("Returning in success");
          352  +	*errorCodePtr = 0;
          353  +
          354  +	return(0);
          355  +}
   178    356   
   179    357   /*
   180    358    *-------------------------------------------------------------------
   181    359    *
   182    360    * TlsInputProc --
   183    361    *
   184    362    *	This procedure is invoked by the generic IO level
................................................................................
   192    370    * Side effects:
   193    371    *	Reads input from the input device of the channel.
   194    372    *
   195    373    *-------------------------------------------------------------------
   196    374    */
   197    375   
   198    376   static int TlsInputProc(ClientData instanceData, char *buf, int bufSize, int *errorCodePtr) {
          377  +	unsigned long backingError;
   199    378   	State *statePtr = (State *) instanceData;
   200    379   	int bytesRead;
   201    380   	int tlsConnect;
   202    381   	int err;
   203    382   
   204    383   	*errorCodePtr = 0;
   205    384   
................................................................................
   208    387   	if (statePtr->flags & TLS_TCL_CALLBACK) {
   209    388   		/* don't process any bytes while verify callback is running */
   210    389   		dprintf("Callback is running, reading 0 bytes");
   211    390   		return(0);
   212    391   	}
   213    392   
   214    393   	dprintf("Calling Tls_WaitForConnect");
   215         -	tlsConnect = Tls_WaitForConnect(statePtr, errorCodePtr);
          394  +	tlsConnect = Tls_WaitForConnect(statePtr, errorCodePtr, 0);
   216    395   	if (tlsConnect < 0) {
   217         -		dprintf("Got an error (bytesRead = %i)", bytesRead);
          396  +		dprintf("Got an error waiting to connect (tlsConnect = %i, *errorCodePtr = %i)", tlsConnect, *errorCodePtr);
   218    397   
          398  +		bytesRead = -1;
   219    399   		if (*errorCodePtr == ECONNRESET) {
   220    400   			dprintf("Got connection reset");
   221    401   			/* Soft EOF */
   222    402   			*errorCodePtr = 0;
   223    403   			bytesRead = 0;
   224    404   		}
   225    405   
   226         -		return(0);
   227         -	}
   228         -
   229         -	if (statePtr->flags & TLS_TCL_INIT) {
   230         -		statePtr->flags &= ~(TLS_TCL_INIT);
          406  +		return(bytesRead);
   231    407   	}
   232    408   
   233    409   	/*
   234    410   	 * We need to clear the SSL error stack now because we sometimes reach
   235    411   	 * this function with leftover errors in the stack.  If BIO_read
   236    412   	 * returns -1 and intends EAGAIN, there is a leftover error, it will be
   237    413   	 * misconstrued as an error, not EAGAIN.
................................................................................
   243    419   	 */
   244    420   	ERR_clear_error();
   245    421   	bytesRead = BIO_read(statePtr->bio, buf, bufSize);
   246    422   	dprintf("BIO_read -> %d", bytesRead);
   247    423   
   248    424   	err = SSL_get_error(statePtr->ssl, bytesRead);
   249    425   
   250         -	if (BIO_should_retry(statePtr->bio)) {
   251         -		dprintf("I/O failed, will retry based on EAGAIN");
   252         -		*errorCodePtr = EAGAIN;
          426  +#if 0
          427  +	if (bytesRead <= 0) {
          428  +		if (BIO_should_retry(statePtr->bio)) {
          429  +			dprintf("I/O failed, will retry based on EAGAIN");
          430  +			*errorCodePtr = EAGAIN;
          431  +		}
   253    432   	}
          433  +#endif
   254    434   
   255    435   	switch (err) {
   256    436   		case SSL_ERROR_NONE:
   257    437   			dprintBuffer(buf, bytesRead);
   258    438   			break;
   259    439   		case SSL_ERROR_SSL:
          440  +			dprintf("SSL negotiation error, indicating that the connection has been aborted");
          441  +
   260    442   			Tls_Error(statePtr, TCLTLS_SSL_ERROR(statePtr->ssl, bytesRead));
   261    443   			*errorCodePtr = ECONNABORTED;
          444  +			bytesRead = -1;
          445  +
   262    446   			break;
   263    447   		case SSL_ERROR_SYSCALL:
   264         -			dprintf("I/O error reading, treating it as EOF");
          448  +			backingError = ERR_get_error();
          449  +
          450  +			if (backingError == 0 && bytesRead == 0) {
          451  +				dprintf("EOF reached")
          452  +				*errorCodePtr = 0;
          453  +				bytesRead = 0;
          454  +			} else if (backingError == 0 && bytesRead == -1) {
          455  +				dprintf("I/O error occured (errno = %lu)", (unsigned long) Tcl_GetErrno());
          456  +				*errorCodePtr = Tcl_GetErrno();
          457  +				bytesRead = -1;
          458  +			} else {
          459  +				dprintf("I/O error occured (backingError = %lu)", backingError);
          460  +				*errorCodePtr = backingError;
          461  +				bytesRead = -1;
          462  +			}
          463  +
          464  +			break;
          465  +		case SSL_ERROR_ZERO_RETURN:
          466  +			dprintf("Got SSL_ERROR_ZERO_RETURN, this means an EOF has been reached");
          467  +			bytesRead = 0;
          468  +			*errorCodePtr = 0;
          469  +			break;
          470  +		default:
          471  +			dprintf("Unknown error (err = %i), mapping to EOF", err);
   265    472   			*errorCodePtr = 0;
   266    473   			bytesRead = 0;
   267    474   			break;
   268    475   	}
   269    476   
   270    477   	dprintf("Input(%d) -> %d [%d]", bufSize, bytesRead, *errorCodePtr);
   271    478   	return(bytesRead);
................................................................................
   286    493    * Side effects:
   287    494    *	Writes output on the output device of the channel.
   288    495    *
   289    496    *-------------------------------------------------------------------
   290    497    */
   291    498   
   292    499   static int TlsOutputProc(ClientData instanceData, CONST char *buf, int toWrite, int *errorCodePtr) {
          500  +	unsigned long backingError;
   293    501   	State *statePtr = (State *) instanceData;
   294    502   	int written, err;
          503  +	int tlsConnect;
   295    504   
   296    505   	*errorCodePtr = 0;
   297    506   
   298    507   	dprintf("BIO_write(%p, %d)", (void *) statePtr, toWrite);
   299    508   	dprintBuffer(buf, toWrite);
   300    509   
   301    510   	if (statePtr->flags & TLS_TCL_CALLBACK) {
................................................................................
   302    511   		dprintf("Don't process output while callbacks are running")
   303    512   		written = -1;
   304    513   		*errorCodePtr = EAGAIN;
   305    514   		return(-1);
   306    515   	}
   307    516   
   308    517   	dprintf("Calling Tls_WaitForConnect");
   309         -	written = Tls_WaitForConnect(statePtr, errorCodePtr);
   310         -	if (written < 0) {
   311         -		dprintf("Tls_WaitForConnect returned %i (err = %i)", written, *errorCodePtr);
          518  +	tlsConnect = Tls_WaitForConnect(statePtr, errorCodePtr, 1);
          519  +	if (tlsConnect < 0) {
          520  +		dprintf("Got an error waiting to connect (tlsConnect = %i, *errorCodePtr = %i)", tlsConnect, *errorCodePtr);
   312    521   
   313         -		return(-1);
          522  +		written = -1;
          523  +		if (*errorCodePtr == ECONNRESET) {
          524  +			dprintf("Got connection reset");
          525  +			/* Soft EOF */
          526  +			*errorCodePtr = 0;
          527  +			written = 0;
          528  +		}
          529  +
          530  +		return(written);
   314    531   	}
   315    532   
   316    533   	if (toWrite == 0) {
   317    534   		dprintf("zero-write");
   318    535   		err = BIO_flush(statePtr->bio);
   319    536   
   320    537   		if (err <= 0) {
................................................................................
   360    577   			break;
   361    578   		case SSL_ERROR_WANT_X509_LOOKUP:
   362    579   			dprintf(" write X BLOCK");
   363    580   			break;
   364    581   		case SSL_ERROR_ZERO_RETURN:
   365    582   			dprintf(" closed");
   366    583   			written = 0;
          584  +			*errorCodePtr = 0;
   367    585   			break;
   368    586   		case SSL_ERROR_SYSCALL:
   369         -			*errorCodePtr = Tcl_GetErrno();
   370         -			dprintf(" [%d] syscall errr: %d", written, *errorCodePtr);
   371         -			written = -1;
          587  +			backingError = ERR_get_error();
          588  +
          589  +			if (backingError == 0 && written == 0) {
          590  +				dprintf("EOF reached")
          591  +				*errorCodePtr = 0;
          592  +				written = 0;
          593  +			} else if (backingError == 0 && written == -1) {
          594  +				dprintf("I/O error occured (errno = %lu)", (unsigned long) Tcl_GetErrno());
          595  +				*errorCodePtr = Tcl_GetErrno();
          596  +				written = -1;
          597  +			} else {
          598  +				dprintf("I/O error occured (backingError = %lu)", backingError);
          599  +				*errorCodePtr = backingError;
          600  +				written = -1;
          601  +			}
          602  +
   372    603   			break;
   373    604   		case SSL_ERROR_SSL:
   374    605   			Tls_Error(statePtr, TCLTLS_SSL_ERROR(statePtr->ssl, written));
   375    606   			*errorCodePtr = ECONNABORTED;
   376    607   			written = -1;
   377    608   			break;
   378    609   		default:
................................................................................
   581    812   	if (statePtr->flags & TLS_TCL_CALLBACK) {
   582    813   		dprintf("Returning 0 due to callback");
   583    814   		return 0;
   584    815   	}
   585    816   
   586    817   	dprintf("Calling Tls_WaitForConnect");
   587    818   	errorCode = 0;
   588         -	if (Tls_WaitForConnect(statePtr, &errorCode) < 0) {
          819  +	if (Tls_WaitForConnect(statePtr, &errorCode, 1) < 0) {
   589    820   		if (errorCode == EAGAIN) {
   590    821   			dprintf("Async flag could be set (didn't check) and errorCode == EAGAIN:  Returning 0");
   591    822   
   592    823   			return 0;
   593    824   		}
   594    825   
   595    826   		dprintf("Tls_WaitForConnect returned an error");
................................................................................
   725    956   	Tcl_NotifyChannel(statePtr->self, mask);
   726    957   
   727    958   	dprintf("Returning");
   728    959   
   729    960   	return;
   730    961   }
   731    962   
   732         -/*
   733         - *------------------------------------------------------*
   734         - *
   735         - *	Tls_WaitForConnect --
   736         - *
   737         - *	Sideeffects:
   738         - *		Issues SSL_accept or SSL_connect
   739         - *
   740         - *	Result:
   741         - *		None.
   742         - *
   743         - *------------------------------------------------------*
   744         - */
   745         -int Tls_WaitForConnect(State *statePtr, int *errorCodePtr) {
   746         -	unsigned long backingError;
   747         -	int err, rc;
   748         -	int bioShouldRetry;
   749         -
   750         -	dprintf("WaitForConnect(%p)", (void *) statePtr);
   751         -	dprintFlags(statePtr);
   752         -
   753         -	if (!(statePtr->flags & TLS_TCL_INIT)) {
   754         -		dprintf("Tls_WaitForConnect called on already initialized channel -- returning with immediate success");
   755         -		*errorCodePtr = 0;
   756         -		return(0);
   757         -	}
   758         -
   759         -	if (statePtr->flags & TLS_TCL_HANDSHAKE_FAILED) {
   760         -		/*
   761         -		 * We choose ECONNRESET over ECONNABORTED here because some server
   762         -		 * side code, on the wiki for example, sets up a read handler that
   763         -		 * does a read and if eof closes the channel. There is no catch/try
   764         -		 * around the reads so exceptions will result in potentially many
   765         -		 * dangling channels hanging around that should have been closed.
   766         -		 * (Backgroun: ECONNABORTED maps to a Tcl exception and 
   767         -		 * ECONNRESET maps to graceful EOF).
   768         -		 */
   769         -		*errorCodePtr = ECONNRESET;
   770         -		return(-1);
   771         -	}
   772         -
   773         -	for (;;) {
   774         -		/* Not initialized yet! */
   775         -		if (statePtr->flags & TLS_TCL_SERVER) {
   776         -			dprintf("Calling SSL_accept()");
   777         -
   778         -			err = SSL_accept(statePtr->ssl);
   779         -		} else {
   780         -			dprintf("Calling SSL_connect()");
   781         -
   782         -			err = SSL_connect(statePtr->ssl);
   783         -		}
   784         -
   785         -		if (err > 0) {
   786         -			dprintf("That seems to have gone okay");
   787         -
   788         -			err = BIO_flush(statePtr->bio);
   789         -
   790         -			if (err <= 0) {
   791         -				dprintf("Flushing the lower layers failed, this will probably terminate this session");
   792         -			}
   793         -		}
   794         -
   795         -		rc = SSL_get_error(statePtr->ssl, err);
   796         -
   797         -		dprintf("Got error: %i (rc = %i)", err, rc);
   798         -
   799         -		bioShouldRetry = 0;
   800         -		if (err <= 0) {
   801         -			if (rc == SSL_ERROR_WANT_CONNECT || rc == SSL_ERROR_WANT_ACCEPT || rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) {
   802         -				bioShouldRetry = 1;
   803         -			} else if (BIO_should_retry(statePtr->bio)) {
   804         -				bioShouldRetry = 1;
   805         -			} else if (rc == SSL_ERROR_SYSCALL && Tcl_GetErrno() == EAGAIN) {
   806         -				bioShouldRetry = 1;
   807         -			}
   808         -		} else {
   809         -			if (!SSL_is_init_finished(statePtr->ssl)) {
   810         -				bioShouldRetry = 1;
   811         -			}
   812         -		}
   813         -
   814         -		if (bioShouldRetry) {
   815         -			dprintf("The I/O did not complete -- but we should try it again");
   816         -
   817         -			if (statePtr->flags & TLS_TCL_ASYNC) {
   818         -				dprintf("Returning EAGAIN so that it can be retried later");
   819         -
   820         -				*errorCodePtr = EAGAIN;
   821         -
   822         -				return(-1);
   823         -			} else {
   824         -				dprintf("Doing so now");
   825         -
   826         -				continue;
   827         -			}
   828         -		}
   829         -
   830         -		dprintf("We have either completely established the session or completely failed it -- there is no more need to ever retry it though");
   831         -		break;
   832         -	}
   833         -
   834         -
   835         -	*errorCodePtr = EINVAL;
   836         -
   837         -	switch (rc) {
   838         -		case SSL_ERROR_NONE:
   839         -			/* The connection is up, we are done here */
   840         -			dprintf("The connection is up");
   841         -			break;
   842         -		case SSL_ERROR_ZERO_RETURN:
   843         -			dprintf("SSL_ERROR_ZERO_RETURN: Connect returned an invalid value...")
   844         -			return(-1);
   845         -		case SSL_ERROR_SYSCALL:
   846         -			backingError = ERR_get_error();
   847         -			dprintf("I/O error occured");
   848         -
   849         -			if (backingError == 0 && err == 0) {
   850         -				dprintf("EOF reached")
   851         -			}
   852         -
   853         -			statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED;
   854         -			*errorCodePtr = ECONNRESET;
   855         -			return(-1);
   856         -		case SSL_ERROR_SSL:
   857         -			dprintf("Got permanent fatal SSL error, aborting immediately");
   858         -			Tls_Error(statePtr, (char *)ERR_reason_error_string(ERR_get_error()));
   859         -			statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED;
   860         -			*errorCodePtr = ECONNABORTED;
   861         -			return(-1);
   862         -		case SSL_ERROR_WANT_CONNECT:
   863         -		case SSL_ERROR_WANT_ACCEPT:
   864         -		case SSL_ERROR_WANT_X509_LOOKUP:
   865         -		default:
   866         -			dprintf("We got a confusing reply: %i", rc);
   867         -			*errorCodePtr = Tcl_GetErrno();
   868         -			dprintf("ERR(%d, %d) ", rc, *errorCodePtr);
   869         -			return(-1);
   870         -	}
   871         -
   872         -#if 0
   873         -	if (statePtr->flags & TLS_TCL_SERVER) {
   874         -		dprintf("This is an TLS server, checking the certificate for the peer");
   875         -
   876         -		err = SSL_get_verify_result(statePtr->ssl);
   877         -		if (err != X509_V_OK) {
   878         -			dprintf("Invalid certificate, returning in failure");
   879         -
   880         -			Tls_Error(statePtr, (char *)X509_verify_cert_error_string(err));
   881         -			statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED;
   882         -			*errorCodePtr = ECONNABORTED;
   883         -			return(-1);
   884         -		}
   885         -	}
   886         -#endif
   887         -
   888         -	dprintf("Removing the \"TLS_TCL_INIT\" flag since we have completed the handshake");
   889         -	statePtr->flags &= ~TLS_TCL_INIT;
   890         -
   891         -	dprintf("Returning in success");
   892         -	*errorCodePtr = 0;
   893         -
   894         -	return(0);
   895         -}
   896         -
   897    963   Tcl_Channel Tls_GetParent(State *statePtr, int maskFlags) {
   898    964   	dprintf("Requested to get parent of channel %p", statePtr->self);
   899    965   
   900    966   	if ((statePtr->flags & ~maskFlags) & TLS_TCL_FASTPATH) {
   901    967   		dprintf("Asked to get the parent channel while we are using FastPath -- returning NULL");
   902    968   		return(NULL);
   903    969   	}
   904    970   
   905    971   	return(Tcl_GetStackedChannel(statePtr->self));
   906    972   }

Changes to tlsInt.h.

   167    167   Tcl_ChannelType *Tls_ChannelType(void);
   168    168   Tcl_Channel     Tls_GetParent(State *statePtr, int maskFlags);
   169    169   
   170    170   Tcl_Obj         *Tls_NewX509Obj(Tcl_Interp *interp, X509 *cert);
   171    171   void            Tls_Error(State *statePtr, char *msg);
   172    172   void            Tls_Free(char *blockPtr);
   173    173   void            Tls_Clean(State *statePtr);
   174         -int             Tls_WaitForConnect(State *statePtr, int *errorCodePtr);
          174  +int             Tls_WaitForConnect(State *statePtr, int *errorCodePtr, int handshakeFailureIsPermanent);
   175    175   
   176    176   BIO             *BIO_new_tcl(State* statePtr, int flags);
   177    177   
   178    178   #define PTR2INT(x) ((int) ((intptr_t) (x)))
   179    179   
   180    180   #endif /* _TLSINT_H */