ADDED Makefile.in Index: Makefile.in ================================================================== --- /dev/null +++ Makefile.in @@ -0,0 +1,391 @@ +# Makefile.in -- +# +# This file is a Makefile for the tsl Tcl extension. If it has the name +# "Makefile.in" then it is a template for a Makefile; to generate the +# actual Makefile, run "./configure", which is a configuration script +# generated by the "autoconf" program (constructs like "@foo@" will get +# replaced in the actual Makefile. +# +# Copyright (c) 1999-2000 Scriptics Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: Makefile.in,v 1.1.1.1 2000/01/19 22:10:58 aborr Exp $ + + +lib_BINARIES=$(tls_LIB_FILE) +BINARIES=$(lib_BINARIES) + +#======================================================================== +# Enumerate the names of the source files included in this package. +# This will be used when a dist target is added to the Makefile. +#======================================================================== + +tls_SOURCES = tls.c tlsIO.c tlsBIO.c \ + tlsX509.c fixstrtod.c strncasecmp.c +SOURCES = $(tls_SOURCES) + +#======================================================================== +# Enumerate the names of the object files included in this package. +# These objects are created and linked into the final library. +#======================================================================== + +tls_OBJECTS = tls.$(OBJEXT) tlsIO.$(OBJEXT) tlsBIO.$(OBJEXT) \ + tlsX509.$(OBJEXT) fixstrtod.$(OBJEXT) strncasecmp.$(OBJEXT) +OBJECTS = $(tls_OBJECTS) + +#======================================================================== +# The substitution of "tls_LIB_FILE" into the variable name below +# allows us to refer to the objects for the library without knowing the name +# of the library in advance. It also lets us use the "$@" variable in +# the rule for building the library, so we can refer to both the list of +# objects and the library itself in a platform-independent manner. +#======================================================================== + +tls_LIB_FILE = @tls_LIB_FILE@ +$(tls_LIB_FILE)_OBJECTS = $(tls_OBJECTS) + +#======================================================================== +# This is a list of header files to be installed +#======================================================================== + +GENERIC_HDRS= \ + $(srcdir)/tls.h + +#======================================================================== +# Variables and AC_SUBST cases added for tls. +#======================================================================== + +SSL_DIR = @SSL_DIR@ +SSL_LIB_DIR = @SSL_LIB_DIR@ +SSL_INCLUDE_DIR = @SSL_INCLUDE_DIR@ +SSL_INCLUDE_DIR_NATIVE = @SSL_INCLUDE_DIR_NATIVE@ +SSL_INCLUDES = -I$(SSL_INCLUDE_DIR_NATIVE) +SSL_CFLAGS = -DNO_PATENTS -DPRE_OPENSSL_0_9_4 + + +#======================================================================== +# This is boilerplate from the sample tcl extension Makefile.in: +# Nothing of the variables below this line need to be changed. Please +# check the TARGETS section below to make sure the make targets are +# correct. +#======================================================================== + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@@VERSION@ +pkglibdir = $(libdir)/@PACKAGE@@VERSION@ +pkgincludedir = $(includedir)/@PACKAGE@@VERSION@ + +top_builddir = . + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_FLAG = +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +CC = @CC@ +CFLAGS_DEBUG = @CFLAGS_DEBUG@ +CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ +CFLAGS_OPTIMIZE = @CFLAGS_OPTIMIZE@ +CLEANFILES = @CLEANFILES@ +EXEEXT = @EXEEXT@ +LDFLAGS_DEBUG = @LDFLAGS_DEBUG@ +LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ +LDFLAGS_OPTIMIZE = @LDFLAGS_OPTIMIZE@ +MAKE_LIB = @MAKE_LIB@ +MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ +MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ +OBJEXT = @OBJEXT@ +RANLIB = @RANLIB@ +SHLIB_CFLAGS = @SHLIB_CFLAGS@ +SHLIB_LD = @SHLIB_LD@ +SHLIB_LDFLAGS = @SHLIB_LDFLAGS@ +SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ +STLIB_LD = @STLIB_LD@ +TCL_BIN_DIR = @TCL_BIN_DIR@ +TCL_DEFS = @TCL_DEFS@ +TCL_EXTRA_CFLAGS = @TCL_EXTRA_CFLAGS@ +TCL_LD_FLAGS = @TCL_LD_FLAGS@ +TCL_LIBS = @TCL_LIBS@ +TCL_SHLIB_LD_LIBS = @TCL_SHLIB_LD_LIBS@ +TCL_SRC_DIR = @TCL_SRC_DIR@ +TCL_DBGX = @TCL_DBGX@ +TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ +TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ +TCL_TOOL_DIR_NATIVE = @TCL_TOOL_DIR_NATIVE@ +TCL_TOP_DIR_NATIVE = @TCL_TOP_DIR_NATIVE@ +TCL_UNIX_DIR_NATIVE = @TCL_UNIX_DIR_NATIVE@ +TCL_WIN_DIR_NATIVE = @TCL_WIN_DIR_NATIVE@ +INCLUDE_DIR_NATIVE = @INCLUDE_DIR_NATIVE@ +TCL_BMAP_DIR_NATIVE = @TCL_BMAP_DIR_NATIVE@ +TCL_PLATFORM_DIR_NATIVE = @TCL_PLATFORM_DIR_NATIVE@ +TCL_GENERIC_DIR_NATIVE = @TCL_GENERIC_DIR_NATIVE@ +TCLSH_PROG = @TCLSH_PROG@ + +AUTOCONF = autoconf + +LDFLAGS = $(LDFLAGS_DEFAULT) + +INCLUDES = @TCL_INCLUDES@ $(SSL_INCLUDES) + +EXTRA_CFLAGS = $(TCL_DEFS) $(PROTO_FLAGS) $(SECURITY_FLAGS) $(MEM_DEBUG_FLAGS) $(KEYSYM_FLAGS) $(NO_DEPRECATED_FLAGS) $(SSL_CFLAGS) + +DEFS = @DEFS@ $(EXTRA_CFLAGS) + +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = + +CPPFLAGS = @CPPFLAGS@ +LIBS = @LIBS@ +AR = ar +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ + +#======================================================================== +# Start of user-definable TARGETS section +#======================================================================== + +#======================================================================== +# TEA TARGETS. Please note that the "libraries:" target refers to platform +# independent files, and the "binaries:" target inclues executable programs and +# platform-dependent libraries. Modify these targets so that they install +# the various pieces of your package. The make and install rules +# for the BINARIES that you specified above have already been done. +#======================================================================== + +all: binaries libraries doc + +#======================================================================== +# The binaries target builds executable programs, Windows .dll's, unix +# shared/static libraries, and any other platform-dependent files. +# The list of targets to build for "binaries:" is specified at the top +# of the Makefile, in the "BINARIES" variable. +#======================================================================== + +binaries: $(BINARIES) + +libraries: + +doc: + +install: all install-binaries install-libraries install-doc + +install-binaries: binaries install-lib-binaries install-bin-binaries + $(INSTALL_DATA) pkgIndex.tcl $(pkglibdir) + +#======================================================================== +# This rule installs platform-independent files, such as header files. +#======================================================================== + +install-libraries: libraries + $(mkinstalldirs) $(includedir) + @echo "Installing header files in $(includedir)" + @for i in $(GENERIC_HDRS) ; do \ + echo "Installing $$i" ; \ + $(INSTALL_DATA) $$i $(includedir) ; \ + done; + $(INSTALL_DATA) $(srcdir)/tls.tcl $(pkglibdir) + +#======================================================================== +# Install documentation. Unix manpages should go in the $(mandir) +# directory. +#======================================================================== + +install-doc: doc + # $(mkinstalldirs) $(mandir)/man1 + # $(mkinstalldirs) $(mandir)/man3 + # $(mkinstalldirs) $(mandir)/mann + # @echo "Installing documentation in $(mandir)" + # @for i in $(srcdir)/*.n; \ + # do \ + # echo "Installing $$i"; \ + # rm -f $(mandir)/mann/$$i; \ + # $(INSTALL_DATA) $$i $(mandir)/mann ; \ + # done + +test: + +depend: + +#======================================================================== +# Enumerate the names of the object files included in this package. +# These objects are created and linked into the final library. In +# most cases these object files will correspond to the source files +# above. +# +# $(exampleA_LIB_FILE) should be listed as part of the BINARIES variable +# at the top of the Makefile. That will ensure that this target is built +# when you run "make binaries". +# +# You shouldn't need to modify this target, except to change the package +# name from "exampleA" to your package's name. +#======================================================================== + +$(tls_LIB_FILE): $(tls_OBJECTS) + -rm -f $(tls_LIB_FILE) + @MAKE_LIB@ + $(RANLIB) $(tls_LIB_FILE) + +#======================================================================== +# We need to enumerate the list of .c to .o lines here. +# Unfortunately, there does not seem to be any other way to do this +# in a Makefile-independent way. We can't use VPATH because it picks up +# object files that may be located in the source directory. +# +# In the following lines, $(srcdir) refers to the toplevel directory +# containing your extension. If your sources are in a subdirectory, +# you will have to modify the paths to reflect this: +# +# exampleA.$(OBJEXT): $(srcdir)/src/win/exampleA.c +# $(COMPILE) -c `@CYGPATH@ $(srcdir)/src/win/exampleA.c` -o $@ +#======================================================================== + +tls.$(OBJEXT): $(srcdir)/tls.c + $(COMPILE) -c `@CYGPATH@ $(srcdir)/tls.c` -o $@ + +tlsIO.$(OBJEXT): $(srcdir)/tlsIO.c + $(COMPILE) -c `@CYGPATH@ $(srcdir)/tlsIO.c` -o $@ + +tlsBIO.$(OBJEXT): $(srcdir)/tlsBIO.c + $(COMPILE) -c `@CYGPATH@ $(srcdir)/tlsBIO.c` -o $@ + +tlsX509.$(OBJEXT): $(srcdir)/tlsX509.c + $(COMPILE) -c `@CYGPATH@ $(srcdir)/tlsX509.c` -o $@ + +fixstrtod.$(OBJEXT): $(srcdir)/fixstrtod.c + $(COMPILE) -c `@CYGPATH@ $(srcdir)/fixstrtod.c` -o $@ + +strncasecmp.$(OBJEXT): $(srcdir)/strncasecmp.c + $(COMPILE) -c `@CYGPATH@ $(srcdir)/strncasecmp.c` -o $@ + +#======================================================================== +# End of user-definable section +#======================================================================== + +#======================================================================== +# Don't modify the file to clean here. Instead, set the "CLEANFILES" +# variable in configure.in +#======================================================================== + +clean: + -test -z "$(BINARIES)" || rm -f $(BINARIES) + -rm -f *.o core *.core + -rm -f *.$(OBJEXT) + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean: clean + -rm -f *.tab.c + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -rm -f config.status + +#======================================================================== +# Install binary object libraries. On Windows this includes both .dll and +# .lib files. Because the .lib files are not explicitly listed anywhere, +# we need to deduce their existence from the .dll file of the same name. +# Additionally, the .dll files go into the bin directory, but the .lib +# files go into the lib directory. On Unix platforms, all library files +# go into the lib directory. In addition, this will generate the pkgIndex.tcl +# file in the install location (assuming it can find a usable tclsh8.2 shell) +# +# You should not have to modify this target. +#======================================================================== + +install-lib-binaries: installdirs + @list='$(lib_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + ext=`echo $$p|sed -e "s/.*\.//"`; \ + if test "x$$ext" = "xdll"; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(bindir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(bindir)/$$p; \ + lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ + if test -f $$lib; then \ + echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(libdir)/$$lib"; \ + $(INSTALL_DATA) $$lib $(DESTDIR)$(libdir)/$$lib; \ + fi; \ + else \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \ + fi; \ + else :; fi; \ + done + @list='$(lib_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(RANLIB) $(DESTDIR)$(bindir)/$$p"; \ + $(RANLIB) $(DESTDIR)$(bindir)/$$p; \ + else :; fi; \ + done + +#======================================================================== +# Install binary executables (e.g. .exe files) +# +# You should not have to modify this target. +#======================================================================== + +install-bin-binaries: installdirs + @list='$(bin_BINARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(bindir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(bindir)/$$p; \ + else :; fi; \ + done + +.SUFFIXES: .c .o .obj + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +uninstall-binaries: + @$(NORMAL_UNINSTALL) + list='$(BINARIES)'; for p in $$list; do \ + rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(mkinstalldirs) $(DESTDIR)$(bindir) + $(mkinstalldirs) $(DESTDIR)$(pkglibdir) + +.PHONY: all binaries clean depend distclean doc install installdirs \ +libraries test + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: ADDED README.txt Index: README.txt ================================================================== --- /dev/null +++ README.txt @@ -0,0 +1,35 @@ +Copyright (C) 1997-2000 Matt Newman + +$Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/README.txt,v 1.1.1.1 2000/01/19 22:10:58 aborr Exp $ + +TLS (aka SSL) Channel - can be layered on any bi-directional +Tcl_Channel (Note: Requires Trf Core Patch) + +Both client and server-side sockets are possible, and this code +should work on any platform as it uses a generic mechanism for +layering on SSL and Tcl. + +Full filevent sematics should also be intact - see tests directory for +blocking and non-blocking examples. + +This was built (almost) from scratch based upon observation of OpenSSL 0.9.2B + +Addition credit is due for Andreas Kupries (a.kupries@westend.com), for +providing the Tcl_ReplaceChannel mechanism and working closely with me +to enhance it to support full fileevent semantics. + +Also work done by the follow people provided the impetus to do this "right":- +tclSSL (Colin McCormack, Shared Technology) +SSLtcl (Peter Antman) + +This code is licensed until the same terms as the Tcl Core. + +I would also like to acknowledge the input of Marshall Rose, who convinced +me that people need to be able to switch-to-encrypted mode part way +through a conversation. + +Also I would like to acknowledge the kind support of Novadigm Inc, my +current employer, which made this possible. + + +Matt Newman ADDED aclocal.m4 Index: aclocal.m4 ================================================================== --- /dev/null +++ aclocal.m4 @@ -0,0 +1,1 @@ +builtin(include,tcl.m4) ADDED configure.in Index: configure.in ================================================================== --- /dev/null +++ configure.in @@ -0,0 +1,283 @@ + +dnl "configure.in" for the "tls" Tcl extension. +dnl +dnl This file is an input file used by the GNU "autoconf" program to +dnl generate the file "configure", which is run during Tcl +dnl installation to configure the system for the local environment. + + +#-------------------------------------------------------------------- +# macro used to verify that the configure script can find the sources +#-------------------------------------------------------------------- + +AC_INIT(tls.h) + + +#-------------------------------------------------------------------- +# Set package name and version numbers here. The NODOT_VERSION is +# required for constructing the library name on systems that don't +# like dots in # library names (Windows). The VERSION variable is +# used on the other systems. +#-------------------------------------------------------------------- + +PACKAGE=tls + +MAJOR_VERSION=1 +MINOR_VERSION=3 +PATCHLEVEL= + +VERSION=${MAJOR_VERSION}.${MINOR_VERSION}${PATCHLEVEL} +NODOT_VERSION=${MAJOR_VERSION}${MINOR_VERSION} + +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) + + +#-------------------------------------------------------------------- +# We put this here so that you can compile with -DVERSION="1.2" to +# encode the package version directly into the source files. +#-------------------------------------------------------------------- + +eval AC_DEFINE_UNQUOTED(VERSION, "${VERSION}") +eval AC_DEFINE_UNQUOTED(PACKAGE, "${PACKAGE}") + + +#-------------------------------------------------------------------- +# Establish the location of the root directory for OpenSSL. +#-------------------------------------------------------------------- + +SSL_DIR='/usr/local/openssl' + +AC_ARG_WITH(ssl-dir, [ --with-ssl-dir=DIR SSL root directory], SSL_DIR=$withval) + +if test -z "${SSL_DIR}"; then + AC_ERROR(must specify SSL directory) +fi +if test ! -f "${SSL_DIR}/include/openssl/opensslv.h"; then + AC_ERROR(bad ssl-dir: cant find opensslv.h under ${SSL_DIR}) +fi + +SSL_LIB_DIR=${SSL_DIR}/lib +SSL_INCLUDE_DIR=${SSL_DIR}/include + +AC_SUBST(SSL_DIR) +AC_SUBST(SSL_LIB_DIR) +AC_SUBST(SSL_INCLUDE_DIR) + + +#-------------------------------------------------------------------- +# Check whether --enable-gcc or --disable-gcc was given. Do this +# before AC_CYGWIN is called so the compiler can be fully tested by +# built-in autoconf tools. This macro also calls AC_PROG_CC to set +# the compiler if --enable-gcc was not used. +#-------------------------------------------------------------------- + +SC_ENABLE_GCC +AC_PROG_INSTALL + + +#-------------------------------------------------------------------- +# Checks to see if the make program sets the $MAKE variable. +#-------------------------------------------------------------------- + +AC_PROG_MAKE_SET + +#-------------------------------------------------------------------- +# Find ranlib +#-------------------------------------------------------------------- + +AC_PROG_RANLIB + +#-------------------------------------------------------------------- +# This macro performs additional compiler tests. +#-------------------------------------------------------------------- + +AC_CYGWIN + +#-------------------------------------------------------------------- +# Determines the correct binary file extension (.o, .obj, .exe etc.) +#-------------------------------------------------------------------- + +AC_OBJEXT +AC_EXEEXT + +#-------------------------------------------------------------------- +# "cygpath" is used on windows to generate native path names for +# include files. These variables should only be used with the +# compiler and linker since # they generate native path names. +# +# Unix tclConfig.sh points SRC_DIR at the top-level directory of +# the Tcl sources, while the Windows tclConfig.sh points SRC_DIR at +# the win subdirectory. Hence the different usages of SRC_DIR below. +# +# This must be done before calling SC_PUBLIC_TCL_HEADERS or +# SC_PRIVATE_TCL_HEADERS. +#-------------------------------------------------------------------- + +case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + CYGPATH="cygpath -w" + ;; + *) + CYGPATH=echo + ;; +esac + +AC_SUBST(CYGPATH) + +SSL_INCLUDE_DIR_NATIVE=\"`${CYGPATH} ${SSL_INCLUDE_DIR}`\" +AC_SUBST(SSL_INCLUDE_DIR_NATIVE) + + +#-------------------------------------------------------------------- +# Load the tclConfig.sh file +#-------------------------------------------------------------------- + +SC_PATH_TCLCONFIG +SC_LOAD_TCLCONFIG + +SC_PRIVATE_TCL_HEADERS + +#-------------------------------------------------------------------- +# A few miscellaneous platform-specific items: +# +# Define a special symbol for Windows (BUILD_tls in this case) so +# that we create the export library with the dll. +# +# Clean up any extra files that Windows creates. +# +# Define any extra compiler flags in the PACKAGE_CFLAGS variable. +# These will be appended to the current set of compiler flags for +# your system. +#-------------------------------------------------------------------- + +case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + AC_DEFINE_UNQUOTED(BUILD_${PACKAGE}) + CLEANFILES="*.lib *.dll *.exp *.ilk *.pdb vc50.pch" + AC_SUBST(CLEANFILES) + ;; + *) + CLEANFILES= + ;; +esac + +#-------------------------------------------------------------------- +# Check whether --enable-threads or --disable-threads was given. +# So far only Tcl responds to this one. +#-------------------------------------------------------------------- + +SC_ENABLE_THREADS + +#-------------------------------------------------------------------- +# The statement below defines a collection of symbols related to +# building as a shared library instead of a static library. +#-------------------------------------------------------------------- + +SC_ENABLE_SHARED + +#-------------------------------------------------------------------- +# This macro figures out what flags to use with the compiler/linker +# when building shared/static debug/optimized objects. This information +# is all taken from the tclConfig.sh file. +#-------------------------------------------------------------------- + +CFLAGS_DEBUG=${TCL_CFLAGS_DEBUG} +CFLAGS_OPTIMIZE=${TCL_CFLAGS_OPTIMIZE} +LDFLAGS_DEBUG=${TCL_LDFLAGS_DEBUG} +LDFLAGS_OPTIMIZE=${TCL_LDFLAGS_OPTIMIZE} +SHLIB_LD=${TCL_SHLIB_LD} +STLIB_LD=${TCL_STLIB_LD} +SHLIB_CFLAGS=${TCL_SHLIB_CFLAGS} + +AC_SUBST(CFLAGS_DEBUG) +AC_SUBST(CFLAGS_OPTIMIZE) +AC_SUBST(STLIB_LD) +AC_SUBST(SHLIB_LD) +AC_SUBST(SHLIB_CFLAGS) +AC_SUBST(SHLIB_LDFLAGS) + +#-------------------------------------------------------------------- +# Set the default compiler switches based on the --enable-symbols +# option. +#-------------------------------------------------------------------- + +SC_ENABLE_SYMBOLS + +if test "${SHARED_BUILD}" = "1" ; then + CFLAGS='${CFLAGS_DEFAULT} ${CFLAGS_WARNING} ${SHLIB_CFLAGS}' +else + CFLAGS='${CFLAGS_DEFAULT} ${CFLAGS_WARNING}' +fi + +#-------------------------------------------------------------------- +# Everyone should be linking against the Tcl stub library. If you +# can't for some reason, remove this definition. If you aren't using +# stubs, you also need to modify the SHLIB_LD_LIBS setting below to +# link against the non-stubbed Tcl library. +#-------------------------------------------------------------------- + +AC_DEFINE(USE_TCL_STUBS) + +#-------------------------------------------------------------------- +# This macro generates a line to use when building a library. It +# depends on values set by the SC_ENABLE_SHARED, SC_ENABLE_SYMBOLS, +# and SC_LOAD_TCLCONFIG macros above. +#-------------------------------------------------------------------- + +SC_MAKE_LIB + +#-------------------------------------------------------------------- +# eval these two values to dereference the ${DBGX} variable. +#-------------------------------------------------------------------- + +eval "SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}" +eval "UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_SUFFIX}" + +#-------------------------------------------------------------------- +# Shared libraries and static libraries have different names. +# Also, windows libraries and unix libraries have different names. +# (I chose to use the names that OpenSSL uses as its default names.) +#-------------------------------------------------------------------- + +case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="\"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\" ${TCL_SHLIB_LD_LIBS} \"`${CYGPATH} ${SSL_LIB_DIR}/ssleay32.lib`\" \"`${CYGPATH} ${SSL_LIB_DIR}/libeay32.lib`\"" + eval "${PACKAGE}_LIB_FILE=${PACKAGE}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval "${PACKAGE}_LIB_FILE=${PACKAGE}${UNSHARED_LIB_SUFFIX}" + fi + ;; + *) + if test "${SHARED_BUILD}" = "1" ; then + SHLIB_LD_LIBS="${TCL_STUB_LIB_SPEC} -L${SSL_LIB_DIR} -lssl -L${SSL_LIB_DIR} -lcrypto" + eval "${PACKAGE}_LIB_FILE=lib${PACKAGE}${SHARED_LIB_SUFFIX}" + RANLIB=: + else + eval "${PACKAGE}_LIB_FILE=lib${PACKAGE}${UNSHARED_LIB_SUFFIX}" + fi + ;; +esac + + +AC_SUBST(tls_LIB_FILE) +AC_SUBST(SHLIB_LD_LIBS) + +#-------------------------------------------------------------------- +# Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl +# file during the install process. Don't run the TCLSH_PROG through +# ${CYGPATH} because it's being used directly by make. +# Require that we use a tclsh shell version 8.2 or later since earlier +# versions have bugs in the pkg_mkIndex routine. +#-------------------------------------------------------------------- + +SC_PROG_TCLSH + +#-------------------------------------------------------------------- +# Finally, substitute all of the various values into the Makefile. +#-------------------------------------------------------------------- + +AC_OUTPUT([Makefile \ + pkgIndex.tcl]) ADDED fixstrtod.c Index: fixstrtod.c ================================================================== --- /dev/null +++ fixstrtod.c @@ -0,0 +1,38 @@ +/* + * fixstrtod.c -- + * + * Source code for the "fixstrtod" procedure. This procedure is + * used in place of strtod under Solaris 2.4, in order to fix + * a bug where the "end" pointer gets set incorrectly. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) fixstrtod.c 1.5 96/02/15 12:08:21 + */ + +#include + +#undef strtod + +/* + * Declare strtod explicitly rather than including stdlib.h, since in + * somes systems (e.g. SunOS 4.1.4) stdlib.h doesn't declare strtod. + */ + +extern double strtod(); + +double +fixstrtod(string, endPtr) + char *string; + char **endPtr; +{ + double d; + d = strtod(string, endPtr); + if ((endPtr != NULL) && (*endPtr != string) && ((*endPtr)[-1] == 0)) { + *endPtr -= 1; + } + return d; +} ADDED install-sh Index: install-sh ================================================================== --- /dev/null +++ install-sh @@ -0,0 +1,119 @@ +#!/bin/sh + +# +# install - install a program, script, or datafile +# This comes from X11R5; it is not part of GNU. +# +# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" + +instcmd="$mvprog" +chmodcmd="" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +fi + +if [ x"$dst" = x ] +then + echo "install: no destination specified" + exit 1 +fi + + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + +if [ -d $dst ] +then + dst="$dst"/`basename $src` +fi + +# Make a temp file name in the proper directory. + +dstdir=`dirname $dst` +dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + +$doit $instcmd $src $dsttmp + +# and set any options; do chmod last to preserve setuid bits + +if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi +if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi +if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi +if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi + +# Now rename the file to the real destination. + +$doit $rmcmd $dst +$doit $mvcmd $dsttmp $dst + + +exit 0 ADDED license.terms Index: license.terms ================================================================== --- /dev/null +++ license.terms @@ -0,0 +1,38 @@ +This software is copyrighted by Matt Newman and other parties. +The following terms apply to all files associated with the software +unless explicitly disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. ADDED mkinstalldirs Index: mkinstalldirs ================================================================== --- /dev/null +++ mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.1.1.1 2000/01/19 22:10:58 aborr Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here ADDED pkgIndex.tcl.in Index: pkgIndex.tcl.in ================================================================== --- /dev/null +++ pkgIndex.tcl.in @@ -0,0 +1,9 @@ + +# pkgIndex.tcl - +# A new manually generated "pkgIndex.tcl" file for tls to replace the original +# which didn't include the commands from "tls.tcl". +# +# Al Borr 12/99, last revised Jan 11/00. + +package ifneeded tls 1.3 "[list load [file join $dir @tls_LIB_FILE@] ] ; [list source [file join $dir tls.tcl] ]" + ADDED strncasecmp.c Index: strncasecmp.c ================================================================== --- /dev/null +++ strncasecmp.c @@ -0,0 +1,142 @@ +/* + * strncasecmp.c -- + * + * Source code for the "strncasecmp" library routine. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) strncasecmp.c 1.7 96/10/24 15:23:36 + */ + +#include "tclPort.h" + +/* + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ASCII character sequences. + */ + +static unsigned char charmap[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xc5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + +/* + * Here are the prototypes just in case they are not included + * in tclPort.h. + */ +int strncasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2, size_t n)); + +int strcasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2)); + +/* + *---------------------------------------------------------------------- + * + * strcasecmp -- + * + * Compares two strings, ignoring case differences. + * + * Results: + * Compares two null-terminated strings s1 and s2, returning -1, 0, + * or 1 if s1 is lexicographically less than, equal to, or greater + * than s2. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +strcasecmp(s1, s2) + CONST char *s1; /* First string. */ + CONST char *s2; /* Second string. */ +{ + unsigned char u1, u2; + + for ( ; ; s1++, s2++) { + u1 = (unsigned char) *s1; + u2 = (unsigned char) *s2; + if ((u1 == '\0') || (charmap[u1] != charmap[u2])) { + break; + } + } + return charmap[u1] - charmap[u2]; +} + +/* + *---------------------------------------------------------------------- + * + * strncasecmp -- + * + * Compares two strings, ignoring case differences. + * + * Results: + * Compares up to length chars of s1 and s2, returning -1, 0, or 1 + * if s1 is lexicographically less than, equal to, or greater + * than s2 over those characters. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +strncasecmp(s1, s2, length) + CONST char *s1; /* First string. */ + CONST char *s2; /* Second string. */ + size_t length; /* Maximum number of characters to compare + * (stop earlier if the end of either string + * is reached). */ +{ + unsigned char u1, u2; + + for (; length != 0; length--, s1++, s2++) { + u1 = (unsigned char) *s1; + u2 = (unsigned char) *s2; + if (charmap[u1] != charmap[u2]) { + return charmap[u1] - charmap[u2]; + } + if (u1 == '\0') { + return 0; + } + } + return 0; +} ADDED tcl.m4 Index: tcl.m4 ================================================================== --- /dev/null +++ tcl.m4 @@ -0,0 +1,2272 @@ +# tcl.m4 -- +# +# This file provides a set of autoconf macros to help TEA-enable +# a Tcl extension. +# +# Copyright (c) 1999 Scriptics Corporation. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +#------------------------------------------------------------------------ +# SC_PATH_TCLCONFIG -- +# +# Locate the tclConfig.sh file and perform a sanity check on +# the Tcl compile flags +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tcl=... +# +# Defines the following vars: +# TCL_BIN_DIR Full path to the directory containing +# the tclConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PATH_TCLCONFIG, [ + # + # Ok, lets find the tcl configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tcl + # + + if test x"${no_tcl}" = x ; then + # we reset no_tcl in case something fails here + no_tcl=true + AC_ARG_WITH(tcl, [ --with-tcl directory containing tcl configuration (tclConfig.sh)], with_tclconfig=${withval}) + AC_MSG_CHECKING([for Tcl configuration]) + AC_CACHE_VAL(ac_cv_c_tclconfig,[ + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` + else + AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) + fi + fi + + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i; pwd)` + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + AC_MSG_WARN(Can't find Tcl configuration definitions) + exit 0 + else + no_tcl= + TCL_BIN_DIR=${ac_cv_c_tclconfig} + AC_MSG_RESULT(found $TCL_BIN_DIR/tclConfig.sh) + fi + fi +]) + +#------------------------------------------------------------------------ +# SC_PATH_TKCONFIG -- +# +# Locate the tkConfig.sh file +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --with-tk=... +# +# Defines the following vars: +# TK_BIN_DIR Full path to the directory containing +# the tkConfig.sh file +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PATH_TKCONFIG, [ + # + # Ok, lets find the tk configuration + # First, look for one uninstalled. + # the alternative search directory is invoked by --with-tk + # + + if test x"${no_tk}" = x ; then + # we reset no_tk in case something fails here + no_tk=true + AC_ARG_WITH(tk, [ --with-tk directory containing tk configuration (tkConfig.sh)], with_tkconfig=${withval}) + AC_MSG_CHECKING([for Tk configuration]) + AC_CACHE_VAL(ac_cv_c_tkconfig,[ + + # First check to see if --with-tkconfig was specified. + if test x"${with_tkconfig}" != x ; then + if test -f "${with_tkconfig}/tkConfig.sh" ; then + ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)` + else + AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) + fi + fi + + # then check for a private Tk library + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ../tk \ + `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tk \ + `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tk \ + `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + # check in a few common install locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in `ls -d ${prefix}/lib 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` ; do + if test -f "$i/tkConfig.sh" ; then + ac_cv_c_tkconfig=`(cd $i; pwd)` + break + fi + done + fi + # check in a few other private locations + if test x"${ac_cv_c_tkconfig}" = x ; then + for i in \ + ${srcdir}/../tk \ + `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do + if test -f "$i/unix/tkConfig.sh" ; then + ac_cv_c_tkconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + ]) + if test x"${ac_cv_c_tkconfig}" = x ; then + TK_BIN_DIR="# no Tk configs found" + AC_MSG_WARN(Can't find Tk configuration definitions) + exit 0 + else + no_tk= + TK_BIN_DIR=${ac_cv_c_tkconfig} + AC_MSG_RESULT(found $TK_BIN_DIR/tkConfig.sh) + fi + fi + +]) + +#------------------------------------------------------------------------ +# SC_LOAD_TCLCONFIG -- +# +# Load the tclConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TCL_BIN_DIR +# +# Results: +# +# Subst the following vars: +# TCL_BIN_DIR +# TCL_SRC_DIR +# TCL_LIB_FILE +# +#------------------------------------------------------------------------ + +AC_DEFUN(SC_LOAD_TCLCONFIG, [ + AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh]) + + if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then + AC_MSG_RESULT([loading]) + . $TCL_BIN_DIR/tclConfig.sh + else + AC_MSG_RESULT([file not found]) + fi + + # + # The eval is required to do the TCL_DBGX substitution in the + # TCL_LIB_FILE variable + # + + eval TCL_LIB_FILE=${TCL_LIB_FILE} + eval TCL_LIB_FLAG=${TCL_LIB_FLAG} + + AC_SUBST(TCL_DBGX) + AC_SUBST(TCL_BIN_DIR) + AC_SUBST(TCL_SRC_DIR) + AC_SUBST(TCL_LIB_FILE) + AC_SUBST(TCL_LIBS) + AC_SUBST(TCL_DEFS) + AC_SUBST(TCL_SHLIB_LD_LIBS) + AC_SUBST(TCL_EXTRA_CFLAGS) + AC_SUBST(TCL_LD_FLAGS) + AC_SUBST(TCL_LIB_FILE) + AC_SUBST(TCL_STUB_LIB_FILE) + AC_SUBST(TCL_LIB_SPEC) + AC_SUBST(TCL_BUILD_LIB_SPEC) + AC_SUBST(TCL_STUB_LIB_SPEC) + AC_SUBST(TCL_BUILD_STUB_LIB_SPEC) +]) + +#------------------------------------------------------------------------ +# SC_LOAD_TKCONFIG -- +# +# Load the tkConfig.sh file +# +# Arguments: +# +# Requires the following vars to be set: +# TK_BIN_DIR +# +# Results: +# +# Sets the following vars that should be in tkConfig.sh: +# TK_BIN_DIR +#------------------------------------------------------------------------ + +AC_DEFUN(SC_LOAD_TKCONFIG, [ + AC_MSG_CHECKING([for existence of $TK_BIN_DIR/tkConfig.sh]) + + if test -f "$TK_BIN_DIR/tkConfig.sh" ; then + AC_MSG_RESULT([loading]) + . $TK_BIN_DIR/tkConfig.sh + else + AC_MSG_RESULT([could not find $TK_BIN_DIR/tkConfig.sh]) + fi + + AC_SUBST(TK_BIN_DIR) + AC_SUBST(TK_SRC_DIR) + AC_SUBST(TK_LIB_FILE) + AC_SUBST(TK_XINCLUDES) +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_GCC -- +# +# Allows the use of GCC if available +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-gcc +# +# Sets the following vars: +# CC Command to use for the compiler +#------------------------------------------------------------------------ + +AC_DEFUN(SC_ENABLE_GCC, [ + AC_ARG_ENABLE(gcc, [ --enable-gcc allow use of gcc if available [--disable-gcc]], + [ok=$enableval], [ok=no]) + if test "$ok" = "yes"; then + CC=gcc + else + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + CC=cl + ;; + *) + CC=${CC-cc} + ;; + esac + fi + AC_PROG_CC +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_SHARED -- +# +# Allows the building of shared libraries +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-shared=yes|no +# +# Defines the following vars: +# STATIC_BUILD Used for building import/export libraries +# on Windows. +# +# Sets the following vars: +# SHARED_BUILD Value of 1 or 0 +#------------------------------------------------------------------------ + +AC_DEFUN(SC_ENABLE_SHARED, [ + AC_MSG_CHECKING([how to build libraries]) + AC_ARG_ENABLE(shared, + [ --enable-shared build and link with shared libraries [--enable-shared]], + [tcl_ok=$enableval], [tcl_ok=yes]) + + if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + tcl_ok=$enableval + else + tcl_ok=yes + fi + + if test "$tcl_ok" = "yes" ; then + AC_MSG_RESULT([shared]) + SHARED_BUILD=1 + else + AC_MSG_RESULT([static]) + SHARED_BUILD=0 + AC_DEFINE(STATIC_BUILD) + fi +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_THREADS -- +# +# Specify if thread support should be enabled +# +# Arguments: +# none +# +# Results: +# +# Adds the following arguments to configure: +# --enable-threads +# +# Sets the following vars: +# THREADS_LIBS Thread library(s) +# +# Defines the following vars: +# TCL_THREADS +# _REENTRANT +# +#------------------------------------------------------------------------ + +AC_DEFUN(SC_ENABLE_THREADS, [ + AC_MSG_CHECKING(for building with threads) + AC_ARG_ENABLE(threads, [ --enable-threads build with threads], + [tcl_ok=$enableval], [tcl_ok=no]) + + if test "$tcl_ok" = "yes"; then + TCL_THREADS=1 + AC_DEFINE(TCL_THREADS) + AC_DEFINE(_REENTRANT) + + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + AC_MSG_RESULT(yes) + ;; + *) + AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) + if test "$tcl_ok" = "yes"; then + # The space is needed + THREADS_LIBS=" -lpthread" + AC_MSG_RESULT(yes) + else + TCL_THREADS=0 + AC_MSG_RESULT(no) + AC_MSG_WARN("Don t know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...") + fi + ;; + esac + else + TCL_THREADS=0 + AC_MSG_RESULT(no (default)) + fi + +]) + +#------------------------------------------------------------------------ +# SC_ENABLE_SYMBOLS -- +# +# Specify if debugging symbols should be used +# +# Arguments: +# none +# +# Requires the following vars to be set: +# CFLAGS_DEBUG +# CFLAGS_OPTIMIZE +# LDFLAGS_DEBUG +# LDFLAGS_OPTIMIZE +# +# Results: +# +# Adds the following arguments to configure: +# --enable-symbols +# +# Defines the following vars: +# CFLAGS_DEFAULT Sets to CFLAGS_DEBUG if true +# Sets to CFLAGS_OPTIMIZE if false +# LDFLAGS_DEFAULT Sets to LDFLAGS_DEBUG if true +# Sets to LDFLAGS_OPTIMIZE if false +# DBGX Debug library extension +# +#------------------------------------------------------------------------ + +AC_DEFUN(SC_ENABLE_SYMBOLS, [ + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + tcl_dbgx=d + ;; + *) + tcl_dbgx=g + ;; + esac + + AC_MSG_CHECKING([for build with symbols]) + AC_ARG_ENABLE(symbols, [ --enable-symbols build with debugging symbols [--disable-symbols]], [tcl_ok=$enableval], [tcl_ok=no]) + if test "$tcl_ok" = "yes"; then + CFLAGS_DEFAULT="${CFLAGS_DEBUG}" + LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" + DBGX=${tcl_dbgx} + TCL_DBGX=${tcl_dbgx} + AC_MSG_RESULT([yes]) + else + CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE}" + LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" + DBGX="" + TCL_DBGX="" + AC_MSG_RESULT([no]) + fi + + AC_SUBST(TCL_DBGX) + AC_SUBST(CFLAGS_DEFAULT) + AC_SUBST(LDFLAGS_DEFAULT) +]) + +#-------------------------------------------------------------------- +# SC_CONFIG_CFLAGS +# +# Try to determine the proper flags to pass to the compiler +# for building shared libraries and other such nonsense. +# +# Arguments: +# none +# +# Results: +# +# Defines the following vars: +# +# DL_OBJS - Name of the object file that implements dynamic +# loading for Tcl on this system. +# DL_LIBS - Library file(s) to include in tclsh and other base +# applications in order for the "load" command to work. +# LDFLAGS - Flags to pass to the compiler when linking object +# files into an executable application binary such +# as tclsh. +# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", +# that tell the run-time dynamic linker where to look +# for shared libraries such as libtcl.so. Depends on +# the variable LIB_RUNTIME_DIR in the Makefile. +# MAKE_LIB - Command to execute to build the Tcl library; +# differs depending on whether or not Tcl is being +# compiled as a shared library. +# SHLIB_CFLAGS - Flags to pass to cc when compiling the components +# of a shared library (may request position-independent +# code, among other things). +# SHLIB_LD - Base command to use for combining object files +# into a shared library. +# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when +# creating shared libraries. This symbol typically +# goes at the end of the "ld" commands that build +# shared libraries. The value of the symbol is +# "${LIBS}" if all of the dependent libraries should +# be specified when creating a shared library. If +# dependent libraries should not be specified (as on +# SunOS 4.x, where they cause the link to fail, or in +# general if Tcl and Tk aren't themselves shared +# libraries), then this symbol has an empty string +# as its value. +# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable +# extensions. An empty string means we don't know how +# to use shared libraries on this platform. +# TCL_LIB_FILE - Name of the file that contains the Tcl library, such +# as libtcl7.8.so or libtcl7.8.a. +# TCL_LIB_SUFFIX -Specifies everything that comes after the "libtcl" +# in the shared library name, using the $VERSION variable +# to put the version in the right place. This is used +# by platforms that need non-standard library names. +# Examples: ${VERSION}.so.1.1 on NetBSD, since it needs +# to have a version after the .so, and ${VERSION}.a +# on AIX, since the Tcl shared library needs to have +# a .a extension whereas shared objects for loadable +# extensions have a .so extension. Defaults to +# ${VERSION}${SHLIB_SUFFIX}. +# TCL_NEEDS_EXP_FILE - +# 1 means that an export file is needed to link to a +# shared library. +# TCL_EXP_FILE - The name of the installed export / import file which +# should be used to link to the Tcl shared library. +# Empty if Tcl is unshared. +# TCL_BUILD_EXP_FILE - +# The name of the built export / import file which +# should be used to link to the Tcl shared library. +# Empty if Tcl is unshared. +# CFLAGS_DEBUG - +# Flags used when running the compiler in debug mode +# CFLAGS_OPTIMIZE - +# Flags used when running the compiler in optimize mode +# +# EXTRA_CFLAGS +# +# Subst's the following vars: +# DL_LIBS +# CFLAGS_DEBUG +# CFLAGS_OPTIMIZE +#-------------------------------------------------------------------- + +AC_DEFUN(SC_CONFIG_CFLAGS, [ + + # Step 0: Enable 64 bit support? + + AC_MSG_CHECKING([if 64bit support is enabled]) + AC_ARG_ENABLE(64bit,[ --enable-64bit enable 64bit support],,enableval="no") + + if test "$enableval" = "yes"; then + AC_MSG_RESULT(Will compile with 64bit support) + do64bit=yes + else + do64bit=no + fi + AC_MSG_RESULT($do64bit) + + # Step 1: set the variable "system" to hold the name and version number + # for the system. This can usually be done via the "uname" command, but + # there are a few systems, like Next, where this doesn't work. + + AC_MSG_CHECKING([system version (for dynamic loading)]) + if test -f /usr/lib/NextStep/software_version; then + system=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` + else + system=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + AC_MSG_RESULT([unknown (can't find uname command)]) + system=unknown + else + # Special check for weird MP-RAS system (uname returns weird + # results, and the version is kept in special file). + + if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then + system=MP-RAS-`awk '{print $3}' /etc/.relid'` + fi + if test "`uname -s`" = "AIX" ; then + system=AIX-`uname -v`.`uname -r` + fi + AC_MSG_RESULT($system) + fi + fi + + # Step 2: check for existence of -ldl library. This is needed because + # Linux can use either -ldl or -ldld for dynamic loading. + + AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no) + + # Step 3: set configuration options based on system name and version. + + do64bit_ok=no + fullSrcDir=`cd $srcdir; pwd` + EXTRA_CFLAGS="" + TCL_EXPORT_FILE_SUFFIX="" + UNSHARED_LIB_SUFFIX="" + TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`' + ECHO_VERSION='`echo ${VERSION}`' + TCL_LIB_VERSIONS_OK=ok + CFLAGS_DEBUG=-g + CFLAGS_OPTIMIZE=-O + TCL_NEEDS_EXP_FILE=0 + TCL_BUILD_EXP_FILE="" + TCL_EXP_FILE="" + STLIB_LD="ar cr" + case $system in + AIX-4.[[2-9]]) + SHLIB_CFLAGS="" + SHLIB_LD="$fullSrcDir/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512 -bnoentry" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="" + LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + TCL_NEEDS_EXP_FILE=1 + TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.exp' + ;; + AIX-*) + SHLIB_CFLAGS="" + SHLIB_LD="$fullSrcDir/ldAix /bin/ld -bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + LIBOBJS="$LIBOBJS tclLoadAix.o" + DL_LIBS="-lld" + LDFLAGS="" + LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + TCL_NEEDS_EXP_FILE=1 + TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.exp' + ;; + BSD/OS-2.1*|BSD/OS-3*) + SHLIB_CFLAGS="" + SHLIB_LD="shlicc -r" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + BSD/OS-4.*) + SHLIB_CFLAGS="-export-dynamic -fPIC" + SHLIB_LD="cc -shared" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="-export-dynamic" + LD_SEARCH_FLAGS="" + ;; + *win32*|*WIN32*|CYGWIN_NT*|cygwin_nt*) + CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d" + CFLAGS_OPTIMIZE="-nologo -Oti -Gs -GD ${runtime}" + LDFLAGS_CONSOLE="-subsystem:console" + LDFLAGS_WINDOW="-subsystem:windows" + LDFLAGS_DEBUG="-debug:full -debugtype:cv" + LDFLAGS_OPTIMIZE="-release" + EXTRA_CFLAGS="-YX" + PATHTYPE=-w + STLIB_LD="lib -nologo" + SHLIB_LD="link -dll -nologo" + SHLIB_LD_LIBS="user32.lib advapi32.lib" + RC="rc" + ;; + dgux*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD="cc -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*|HP-UX-*.11.*) + SHLIB_SUFFIX=".sl" + AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) + if test "$tcl_ok" = yes; then + SHLIB_CFLAGS="+z" + SHLIB_LD="ld -b" + SHLIB_LD_LIBS="" + DL_OBJS="tclLoadShl.o" + DL_LIBS="-ldld" + LDFLAGS="-Wl,-E" + LD_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' + fi + ;; + IRIX-4.*) + SHLIB_CFLAGS="-G 0" + SHLIB_SUFFIX=".a" + SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0" + SHLIB_LD_LIBS='${LIBS}' + DL_OBJS="tclLoadAout.o" + DL_LIBS="" + LDFLAGS="-Wl,-D,08000000" + LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + SHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}.a' + ;; + IRIX-5.*|IRIX-6.*|IRIX64-6.5*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -n32 -shared -rdata_shared" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then + EXTRA_CFLAGS="-mabi=n32" + LDFLAGS="-mabi=n32" + else + case $system in + IRIX-6.3) + # Use to build 6.2 compatible binaries on 6.3. + EXTRA_CFLAGS="-n32 -D_OLD_TERMIOS" + ;; + *) + EXTRA_CFLAGS="-n32" + ;; + esac + LDFLAGS="-n32" + fi + ;; + IRIX64-6.*) + SHLIB_CFLAGS="" + SHLIB_LD="ld -32 -shared -rdata_shared" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + ;; + Linux*) + SHLIB_CFLAGS="-fPIC" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + + # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings + # when you inline the string and math operations. Turn this off to + # get rid of the warnings. + + CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" + + if test "$have_dl" = yes; then + SHLIB_LD="${CC} -shared" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="-rdynamic" + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + else + AC_CHECK_HEADER(dld.h, [ + SHLIB_LD="ld -shared" + DL_OBJS="tclLoadDld.o" + DL_LIBS="-ldld" + LDFLAGS="" + LD_SEARCH_FLAGS=""]) + fi + if test "`uname -m`" = "alpha" ; then + EXTRA_CFLAGS="-mieee" + fi + ;; + MP-RAS-02*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD="cc -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + MP-RAS-*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD="cc -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="-Wl,-Bexport" + LD_SEARCH_FLAGS="" + ;; + NetBSD-*|FreeBSD-[[12]].*|OpenBSD-*) + # Not available on all versions: check for include file. + AC_CHECK_HEADER(dlfcn.h, [ + SHLIB_CFLAGS="-fpic" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS="" + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0' + ], [ + SHLIB_CFLAGS="" + SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".a" + DL_OBJS="tclLoadAout.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a' + ]) + + # FreeBSD doesn't handle version numbers with dots. + + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + FreeBSD-*) + # FreeBSD 3.* and greater have ELF. + SHLIB_CFLAGS="-fpic" + SHLIB_LD="ld -Bshareable -x" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + NEXTSTEP-*) + SHLIB_CFLAGS="" + SHLIB_LD="cc -nostdlib -r" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadNext.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + OS/390-*) + CFLAGS_OPTIMIZE="" # Optimizer is buggy + AC_DEFINE(_OE_SOCKETS) # needed in sys/socket.h + ;; + OSF1-1.0|OSF1-1.1|OSF1-1.2) + # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 + SHLIB_CFLAGS="" + # Hack: make package name same as library name + SHLIB_LD='ld -R -export $@:' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadOSF.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + OSF1-1.*) + # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 + SHLIB_CFLAGS="-fpic" + SHLIB_LD="ld -shared" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + OSF1-V*) + # Digital OSF/1 + SHLIB_CFLAGS="" + SHLIB_LD='ld -shared -expect_unresolved "*"' + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' + ;; + RISCos-*) + SHLIB_CFLAGS="-G 0" + SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0" + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".a" + DL_OBJS="tclLoadAout.o" + DL_LIBS="" + LDFLAGS="-Wl,-D,08000000" + LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + ;; + SCO_SV-3.2*) + # Note, dlopen is available only on SCO 3.2.5 and greater. However, + # this test works, since "uname -s" was non-standard in 3.2.4 and + # below. + SHLIB_CFLAGS="-Kpic -belf" + SHLIB_LD="ld -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="" + LDFLAGS="-belf -Wl,-Bexport" + LD_SEARCH_FLAGS="" + ;; + SINIX*5.4*) + SHLIB_CFLAGS="-K PIC" + SHLIB_LD="cc -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="" + LD_SEARCH_FLAGS="" + ;; + SunOS-4*) + SHLIB_CFLAGS="-PIC" + SHLIB_LD="ld" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="" + LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + + # SunOS can't handle version numbers with dots in them in library + # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it + # requires an extra version number at the end of .so file names. + # So, the library has to have a name like libtcl75.so.1.0 + + SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1.0' + UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.a' + TCL_LIB_VERSIONS_OK=nodots + ;; + SunOS-5.[[0-6]]*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + + # Note: need the LIBS below, otherwise Tk won't find Tcl's + # symbols when dynamically loaded into tclsh. + + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + LDFLAGS="" + LD_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + ;; + SunOS-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD="/usr/ccs/bin/ld -G -z text" + LDFLAGS="" + + do64bit_ok=no + if test "$do64bit" = "yes" ; then + arch=`isainfo` + if test "$arch" = "sparcv9 sparc" ; then + if test "$CC" != "gcc" -a `$CC -v 2>&1 | grep -c gcc` = "0" ; then + do64bit_ok=yes + EXTRA_CFLAGS="-xarch=v9" + LDFLAGS="-xarch=v9" + else + AC_MSG_WARN("64bit mode not supported using GCC on $system") + fi + else + AC_MSG_WARN("64bit mode only supported sparcv9 system") + fi + fi + + # Note: need the LIBS below, otherwise Tk won't find Tcl's + # symbols when dynamically loaded into tclsh. + + SHLIB_LD_LIBS='${LIBS}' + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then + LD_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' + else + LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' + fi + ;; + ULTRIX-4.*) + SHLIB_CFLAGS="-G 0" + SHLIB_SUFFIX=".a" + SHLIB_LD="echo tclLdAout $CC \{$SHLIB_CFLAGS\} | `pwd`/tclsh -r -G 0" + SHLIB_LD_LIBS='${LIBS}' + DL_OBJS="tclLoadAout.o" + DL_LIBS="" + LDFLAGS="-Wl,-D,08000000" + LD_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' + ;; + UNIX_SV* | UnixWare-5*) + SHLIB_CFLAGS="-KPIC" + SHLIB_LD="cc -G" + SHLIB_LD_LIBS="" + SHLIB_SUFFIX=".so" + DL_OBJS="tclLoadDl.o" + DL_LIBS="-ldl" + # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers + # that don't grok the -Bexport option. Test that it does. + hold_ldflags=$LDFLAGS + AC_MSG_CHECKING(for ld accepts -Bexport flag) + LDFLAGS="${LDFLAGS} -Wl,-Bexport" + AC_TRY_LINK(, [int i;], found=yes, found=no) + LDFLAGS=$hold_ldflags + AC_MSG_RESULT($found) + if test $found = yes; then + LDFLAGS="-Wl,-Bexport" + else + LDFLAGS="" + fi + LD_SEARCH_FLAGS="" + ;; + esac + + if test "$do64bit" = "yes" -a "$do64bit_ok" = "no" ; then + AC_MSG_WARN("64bit support being disabled -- not supported on this platform") + fi + + # Step 4: If pseudo-static linking is in use (see K. B. Kenny, "Dynamic + # Loading for Tcl -- What Became of It?". Proc. 2nd Tcl/Tk Workshop, + # New Orleans, LA, Computerized Processes Unlimited, 1994), then we need + # to determine which of several header files defines the a.out file + # format (a.out.h, sys/exec.h, or sys/exec_aout.h). At present, we + # support only a file format that is more or less version-7-compatible. + # In particular, + # - a.out files must begin with `struct exec'. + # - the N_TXTOFF on the `struct exec' must compute the seek address + # of the text segment + # - The `struct exec' must contain a_magic, a_text, a_data, a_bss + # and a_entry fields. + # The following compilation should succeed if and only if either sys/exec.h + # or a.out.h is usable for the purpose. + # + # Note that the modified COFF format used on MIPS Ultrix 4.x is usable; the + # `struct exec' includes a second header that contains information that + # duplicates the v7 fields that are needed. + + if test "x$DL_OBJS" = "xtclLoadAout.o" ; then + AC_MSG_CHECKING(sys/exec.h) + AC_TRY_COMPILE([#include ],[ + struct exec foo; + unsigned long seek; + int flag; +#if defined(__mips) || defined(mips) + seek = N_TXTOFF (foo.ex_f, foo.ex_o); +#else + seek = N_TXTOFF (foo); +#endif + flag = (foo.a_magic == OMAGIC); + return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry; + ], tcl_ok=usable, tcl_ok=unusable) + AC_MSG_RESULT($tcl_ok) + if test $tcl_ok = usable; then + AC_DEFINE(USE_SYS_EXEC_H) + else + AC_MSG_CHECKING(a.out.h) + AC_TRY_COMPILE([#include ],[ + struct exec foo; + unsigned long seek; + int flag; +#if defined(__mips) || defined(mips) + seek = N_TXTOFF (foo.ex_f, foo.ex_o); +#else + seek = N_TXTOFF (foo); +#endif + flag = (foo.a_magic == OMAGIC); + return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry; + ], tcl_ok=usable, tcl_ok=unusable) + AC_MSG_RESULT($tcl_ok) + if test $tcl_ok = usable; then + AC_DEFINE(USE_A_OUT_H) + else + AC_MSG_CHECKING(sys/exec_aout.h) + AC_TRY_COMPILE([#include ],[ + struct exec foo; + unsigned long seek; + int flag; +#if defined(__mips) || defined(mips) + seek = N_TXTOFF (foo.ex_f, foo.ex_o); +#else + seek = N_TXTOFF (foo); +#endif + flag = (foo.a_midmag == OMAGIC); + return foo.a_text + foo.a_data + foo.a_bss + foo.a_entry; + ], tcl_ok=usable, tcl_ok=unusable) + AC_MSG_RESULT($tcl_ok) + if test $tcl_ok = usable; then + AC_DEFINE(USE_SYS_EXEC_AOUT_H) + else + DL_OBJS="" + fi + fi + fi + fi + + # Step 5: disable dynamic loading if requested via a command-line switch. + + AC_ARG_ENABLE(load, [ --disable-load disallow dynamic loading and "load" command], + [tcl_ok=$enableval], [tcl_ok=yes]) + if test "$tcl_ok" = "no"; then + DL_OBJS="" + fi + + if test "x$DL_OBJS" != "x" ; then + BUILD_DLTEST="\$(DLTEST_TARGETS)" + else + echo "Can't figure out how to do dynamic loading or shared libraries" + echo "on this system." + SHLIB_CFLAGS="" + SHLIB_LD="" + SHLIB_SUFFIX="" + DL_OBJS="tclLoadNone.o" + DL_LIBS="" + LDFLAGS="" + LD_SEARCH_FLAGS="" + BUILD_DLTEST="" + fi + + # If we're running gcc, then change the C flags for compiling shared + # libraries to the right flags for gcc, instead of those for the + # standard manufacturer compiler. + + if test "$DL_OBJS" != "tclLoadNone.o" ; then + if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then + case $system in + AIX-*) + ;; + BSD/OS*) + ;; + IRIX*) + ;; + NetBSD-*|FreeBSD-*|OpenBSD-*) + ;; + RISCos-*) + ;; + ULTRIX-4.*) + ;; + *) + SHLIB_CFLAGS="-fPIC" + ;; + esac + fi + fi + + if test "$SHARED_LIB_SUFFIX" = "" ; then + SHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}${SHLIB_SUFFIX}' + fi + if test "$UNSHARED_LIB_SUFFIX" = "" ; then + UNSHARED_LIB_SUFFIX='${VERSION}\$\{DBGX\}.a' + fi + + AC_SUBST(STLIB_LD) + AC_SUBST(SHLIB_LD) + AC_SUBST(SHLIB_CFLAGS) + AC_SUBST(SHLIB_LDFLAGS) + AC_SUBST(DL_LIBS) + AC_SUBST(CFLAGS_DEBUG) + AC_SUBST(CFLAGS_OPTIMIZE) + AC_SUBST(LDFLAGS_DEBUG) + AC_SUBST(LDFLAGS_OPTIMIZE) +]) + +#-------------------------------------------------------------------- +# SC_SERIAL_PORT +# +# Determine which interface to use to talk to the serial port. +# Note that #include lines must begin in leftmost column for +# some compilers to recognize them as preprocessor directives. +# +# Arguments: +# none +# +# Results: +# +# Defines only one of the following vars: +# USE_TERMIOS +# USE_TERMIO +# USE_SGTTY +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_SERIAL_PORT, [ + AC_MSG_CHECKING([termios vs. termio vs. sgtty]) + + AC_TRY_RUN([ +#include + +main() +{ + struct termios t; + if (tcgetattr(0, &t) == 0) { + cfsetospeed(&t, 0); + t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; +}], tk_ok=termios, tk_ok=no, tk_ok=no) + + if test $tk_ok = termios; then + AC_DEFINE(USE_TERMIOS) + else + AC_TRY_RUN([ +#include + +main() +{ + struct termio t; + if (ioctl(0, TCGETA, &t) == 0) { + t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; + return 0; + } + return 1; + }], tk_ok=termio, tk_ok=no, tk_ok=no) + + if test $tk_ok = termio; then + AC_DEFINE(USE_TERMIO) + else + AC_TRY_RUN([ +#include + +main() +{ + struct sgttyb t; + if (ioctl(0, TIOCGETP, &t) == 0) { + t.sg_ospeed = 0; + t.sg_flags |= ODDP | EVENP | RAW; + return 0; + } + return 1; +}], tk_ok=sgtty, tk_ok=none, tk_ok=none) + if test $tk_ok = sgtty; then + AC_DEFINE(USE_SGTTY) + fi + fi + fi + AC_MSG_RESULT($tk_ok) +]) + +#-------------------------------------------------------------------- +# SC_MISSING_POSIX_HEADERS +# +# Supply substitutes for missing POSIX header files. Special +# notes: +# - stdlib.h doesn't define strtol, strtoul, or +# strtod insome versions of SunOS +# - some versions of string.h don't declare procedures such +# as strstr +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# NO_DIRENT_H +# NO_ERRNO_H +# NO_VALUES_H +# NO_LIMITS_H +# NO_STDLIB_H +# NO_STRING_H +# NO_SYS_WAIT_H +# NO_DLFCN_H +# HAVE_UNISTD_H +# HAVE_SYS_PARAM_H +# +# HAVE_STRING_H ? +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_MISSING_POSIX_HEADERS, [ + + AC_MSG_CHECKING(dirent.h) + AC_TRY_LINK([#include +#include ], [ +#ifndef _POSIX_SOURCE +# ifdef __Lynx__ + /* + * Generate compilation error to make the test fail: Lynx headers + * are only valid if really in the POSIX environment. + */ + + missing_procedure(); +# endif +#endif +DIR *d; +struct dirent *entryPtr; +char *p; +d = opendir("foobar"); +entryPtr = readdir(d); +p = entryPtr->d_name; +closedir(d); +], tcl_ok=yes, tcl_ok=no) + + if test $tcl_ok = no; then + AC_DEFINE(NO_DIRENT_H) + fi + + AC_MSG_RESULT($tcl_ok) + AC_CHECK_HEADER(errno.h, , AC_DEFINE(NO_ERRNO_H)) + AC_CHECK_HEADER(float.h, , AC_DEFINE(NO_FLOAT_H)) + AC_CHECK_HEADER(values.h, , AC_DEFINE(NO_VALUES_H)) + AC_CHECK_HEADER(limits.h, , AC_DEFINE(NO_LIMITS_H)) + AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) + AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) + if test $tcl_ok = 0; then + AC_DEFINE(NO_STDLIB_H) + fi + AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) + AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) + AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) + + # See also memmove check below for a place where NO_STRING_H can be + # set and why. + + if test $tcl_ok = 0; then + AC_DEFINE(NO_STRING_H) + fi + + AC_CHECK_HEADER(sys/wait.h, , AC_DEFINE(NO_SYS_WAIT_H)) + AC_CHECK_HEADER(dlfcn.h, , AC_DEFINE(NO_DLFCN_H)) + + # OS/390 lacks sys/param.h (and doesn't need it, by chance). + + AC_HAVE_HEADERS(unistd.h sys/param.h) + +]) + +#-------------------------------------------------------------------- +# SC_PATH_X +# +# Locate the X11 header files and the X11 library archive. Try +# the ac_path_x macro first, but if it doesn't find the X stuff +# (e.g. because there's no xmkmf program) then check through +# a list of possible directories. Under some conditions the +# autoconf macro will return an include directory that contains +# no include files, so double-check its result just to be safe. +# +# Arguments: +# none +# +# Results: +# +# Sets the the following vars: +# XINCLUDES +# XLIBSW +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_PATH_X, [ + AC_PATH_X + not_really_there="" + if test "$no_x" = ""; then + if test "$x_includes" = ""; then + AC_TRY_CPP([#include ], , not_really_there="yes") + else + if test ! -r $x_includes/X11/Intrinsic.h; then + not_really_there="yes" + fi + fi + fi + if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then + AC_MSG_CHECKING(for X11 header files) + XINCLUDES="# no special path needed" + AC_TRY_CPP([#include ], , XINCLUDES="nope") + if test "$XINCLUDES" = nope; then + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" + for i in $dirs ; do + if test -r $i/X11/Intrinsic.h; then + AC_MSG_RESULT($i) + XINCLUDES=" -I$i" + break + fi + done + fi + else + if test "$x_includes" != ""; then + XINCLUDES=-I$x_includes + else + XINCLUDES="# no special path needed" + fi + fi + if test "$XINCLUDES" = nope; then + AC_MSG_RESULT(couldn't find any!) + XINCLUDES="# no include files found" + fi + + if test "$no_x" = yes; then + AC_MSG_CHECKING(for X11 libraries) + XLIBSW=nope + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" + for i in $dirs ; do + if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl; then + AC_MSG_RESULT($i) + XLIBSW="-L$i -lX11" + x_libraries="$i" + break + fi + done + else + if test "$x_libraries" = ""; then + XLIBSW=-lX11 + else + XLIBSW="-L$x_libraries -lX11" + fi + fi + if test "$XLIBSW" = nope ; then + AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) + fi + if test "$XLIBSW" = nope ; then + AC_MSG_RESULT(couldn't find any! Using -lX11.) + XLIBSW=-lX11 + fi +]) +#-------------------------------------------------------------------- +# SC_BLOCKING_STYLE +# +# The statements below check for systems where POSIX-style +# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. +# On these systems (mostly older ones), use the old BSD-style +# FIONBIO approach instead. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# HAVE_SYS_IOCTL_H +# HAVE_SYS_FILIO_H +# USE_FIONBIO +# O_NONBLOCK +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_BLOCKING_STYLE, [ + AC_CHECK_HEADERS(sys/ioctl.h) + AC_CHECK_HEADERS(sys/filio.h) + AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) + if test -f /usr/lib/NextStep/software_version; then + system=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` + else + system=`uname -s`-`uname -r` + if test "$?" -ne 0 ; then + system=unknown + else + # Special check for weird MP-RAS system (uname returns weird + # results, and the version is kept in special file). + + if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then + system=MP-RAS-`awk '{print $3}' /etc/.relid'` + fi + if test "`uname -s`" = "AIX" ; then + system=AIX-`uname -v`.`uname -r` + fi + fi + fi + case $system in + # There used to be code here to use FIONBIO under AIX. However, it + # was reported that FIONBIO doesn't work under AIX 3.2.5. Since + # using O_NONBLOCK seems fine under AIX 4.*, I removed the FIONBIO + # code (JO, 5/31/97). + + OSF*) + AC_DEFINE(USE_FIONBIO) + AC_MSG_RESULT(FIONBIO) + ;; + SunOS-4*) + AC_DEFINE(USE_FIONBIO) + AC_MSG_RESULT(FIONBIO) + ;; + ULTRIX-4.*) + AC_DEFINE(USE_FIONBIO) + AC_MSG_RESULT(FIONBIO) + ;; + *) + AC_MSG_RESULT(O_NONBLOCK) + ;; + esac +]) + +#-------------------------------------------------------------------- +# SC_HAVE_VFORK +# +# Check to see whether the system provides a vfork kernel call. +# If not, then use fork instead. Also, check for a problem with +# vforks and signals that can cause core dumps if a vforked child +# resets a signal handler. If the problem exists, then use fork +# instead of vfork. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# vfork (=fork) +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_HAVE_VFORK, [ + AC_TYPE_SIGNAL() + AC_CHECK_FUNC(vfork, tcl_ok=1, tcl_ok=0) + if test "$tcl_ok" = 1; then + AC_MSG_CHECKING([vfork/signal bug]); + AC_TRY_RUN([ +#include +#include +#include +int gotSignal = 0; +sigProc(sig) + int sig; +{ + gotSignal = 1; +} +main() +{ + int pid, sts; + (void) signal(SIGCHLD, sigProc); + pid = vfork(); + if (pid < 0) { + exit(1); + } else if (pid == 0) { + (void) signal(SIGCHLD, SIG_DFL); + _exit(0); + } else { + (void) wait(&sts); + } + exit((gotSignal) ? 0 : 1); +}], tcl_ok=1, tcl_ok=0, tcl_ok=0) + + if test "$tcl_ok" = 1; then + AC_MSG_RESULT(ok) + else + AC_MSG_RESULT([buggy, using fork instead]) + fi + fi + rm -f core + if test "$tcl_ok" = 0; then + AC_DEFINE(vfork, fork) + fi +]) + +#-------------------------------------------------------------------- +# SC_TIME_HANLDER +# +# Checks how the system deals with time.h, what time structures +# are used on the system, and what fields the structures have. +# +# Arguments: +# none +# +# Results: +# +# Defines some of the following vars: +# USE_DELTA_FOR_TZ +# HAVE_TM_GMTOFF +# HAVE_TM_TZADJ +# HAVE_TIMEZONE_VAR +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_TIME_HANDLER, [ + AC_CHECK_HEADERS(sys/time.h) + AC_HEADER_TIME + AC_STRUCT_TIMEZONE + + AC_MSG_CHECKING([tm_tzadj in struct tm]) + AC_TRY_COMPILE([#include ], [struct tm tm; tm.tm_tzadj;], + [AC_DEFINE(HAVE_TM_TZADJ) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no)) + + AC_MSG_CHECKING([tm_gmtoff in struct tm]) + AC_TRY_COMPILE([#include ], [struct tm tm; tm.tm_gmtoff;], + [AC_DEFINE(HAVE_TM_GMTOFF) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no)) + + # + # Its important to include time.h in this check, as some systems + # (like convex) have timezone functions, etc. + # + have_timezone=no + AC_MSG_CHECKING([long timezone variable]) + AC_TRY_COMPILE([#include ], + [extern long timezone; + timezone += 1; + exit (0);], + [have_timezone=yes + AC_DEFINE(HAVE_TIMEZONE_VAR) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no)) + + # + # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. + # + if test "$have_timezone" = no; then + AC_MSG_CHECKING([time_t timezone variable]) + AC_TRY_COMPILE([#include ], + [extern time_t timezone; + timezone += 1; + exit (0);], + [AC_DEFINE(HAVE_TIMEZONE_VAR) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no)) + fi + + # + # AIX does not have a timezone field in struct tm. When the AIX bsd + # library is used, the timezone global and the gettimeofday methods are + # to be avoided for timezone deduction instead, we deduce the timezone + # by comparing the localtime result on a known GMT value. + # + + if test "`uname -s`" = "AIX" ; then + AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes) + if test $libbsd = yes; then + AC_DEFINE(USE_DELTA_FOR_TZ) + fi + fi +]) + +#-------------------------------------------------------------------- +# SC_BUGGY_STRTOD +# +# Under Solaris 2.4, strtod returns the wrong value for the +# terminating character under some conditions. Check for this +# and if the problem exists use a substitute procedure +# "fixstrtod" (provided by Tcl) that corrects the error. +# +# Arguments: +# none +# +# Results: +# +# Might defines some of the following vars: +# strtod (=fixstrtod) +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_BUGGY_STRTOD, [ + AC_CHECK_FUNC(strtod, tk_strtod=1, tk_strtod=0) + if test "$tk_strtod" = 1; then + AC_MSG_CHECKING([for Solaris 2.4 strtod bug]) + AC_TRY_RUN([ + extern double strtod(); + int main() + { + char *string = "NaN"; + char *term; + strtod(string, &term); + if ((term != string) && (term[-1] == 0)) { + exit(1); + } + exit(0); + }], tk_ok=1, tk_ok=0, tk_ok=0) + if test "$tk_ok" = 1; then + AC_MSG_RESULT(ok) + else + AC_MSG_RESULT(buggy) + AC_DEFINE(strtod, fixstrtod) + fi + fi +]) + +#-------------------------------------------------------------------- +# SC_TCL_LINK_LIBS +# +# Search for the libraries needed to link the Tcl shell. +# Things like the math library (-lm) and socket stuff (-lsocket vs. +# -lnsl) are dealt with here. +# +# Arguments: +# Requires the following vars to be set in the Makefile: +# DL_LIBS +# LIBS +# MATH_LIBS +# +# Results: +# +# Subst's the following var: +# TCL_LIBS +# MATH_LIBS +# +# Might append to the following vars: +# LIBS +# +# Might define the following vars: +# HAVE_NET_ERRNO_H +# +#-------------------------------------------------------------------- + +AC_DEFUN(SC_TCL_LINK_LIBS, [ + #-------------------------------------------------------------------- + # On a few very rare systems, all of the libm.a stuff is + # already in libc.a. Set compiler flags accordingly. + # Also, Linux requires the "ieee" library for math to work + # right (and it must appear before "-lm"). + #-------------------------------------------------------------------- + + AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") + AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"]) + + #-------------------------------------------------------------------- + # On AIX systems, libbsd.a has to be linked in to support + # non-blocking file IO. This library has to be linked in after + # the MATH_LIBS or it breaks the pow() function. The way to + # insure proper sequencing, is to add it to the tail of MATH_LIBS. + # This library also supplies gettimeofday. + #-------------------------------------------------------------------- + + libbsd=no + if test "`uname -s`" = "AIX" ; then + AC_CHECK_LIB(bsd, gettimeofday, libbsd=yes) + if test $libbsd = yes; then + MATH_LIBS="$MATH_LIBS -lbsd" + fi + fi + + + #-------------------------------------------------------------------- + # Interactive UNIX requires -linet instead of -lsocket, plus it + # needs net/errno.h to define the socket-related error codes. + #-------------------------------------------------------------------- + + AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) + AC_CHECK_HEADER(net/errno.h, AC_DEFINE(HAVE_NET_ERRNO_H)) + + #-------------------------------------------------------------------- + # Check for the existence of the -lsocket and -lnsl libraries. + # The order here is important, so that they end up in the right + # order in the command line generated by make. Here are some + # special considerations: + # 1. Use "connect" and "accept" to check for -lsocket, and + # "gethostbyname" to check for -lnsl. + # 2. Use each function name only once: can't redo a check because + # autoconf caches the results of the last check and won't redo it. + # 3. Use -lnsl and -lsocket only if they supply procedures that + # aren't already present in the normal libraries. This is because + # IRIX 5.2 has libraries, but they aren't needed and they're + # bogus: they goof up name resolution if used. + # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. + # To get around this problem, check for both libraries together + # if -lsocket doesn't work by itself. + #-------------------------------------------------------------------- + + tcl_checkBoth=0 + AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) + if test "$tcl_checkSocket" = 1; then + AC_CHECK_LIB(socket, main, LIBS="$LIBS -lsocket", tcl_checkBoth=1) + fi + if test "$tcl_checkBoth" = 1; then + tk_oldLibs=$LIBS + LIBS="$LIBS -lsocket -lnsl" + AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) + fi + AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, main, + [LIBS="$LIBS -lnsl"])) + + # Don't perform the eval of the libraries here because DL_LIBS + # won't be set until we call SC_CONFIG_CFLAGS + + TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}' + AC_SUBST(TCL_LIBS) + AC_SUBST(MATH_LIBS) +]) + +#------------------------------------------------------------------------ +# SC_MAKE_LIB -- +# +# Generate a line that can be used to build a shared/unshared library +# in a platform independent manner. +# +# Arguments: +# none +# +# Requires: +# +# Results: +# +# Defines the following vars: +# MAKE_LIB Makefile rule for building a library +# MAKE_SHARED_LIB Makefile rule for building a shared library +# MAKE_UNSHARED_LIB Makefile rule for building a static +# library +#------------------------------------------------------------------------ + +AC_DEFUN(SC_MAKE_LIB, [ + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + if test "${CC-cc}" = "cl"; then + MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(\[$]@_OBJECTS) " + MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LDFLAGS} \${SHLIB_LD_LIBS} \$(LDFLAGS) -out:\[$]@ \$(\[$]@_OBJECTS) " + fi + ;; + *) + MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(\[$]@_OBJECTS)" + MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(\[$]@_OBJECTS) \${SHLIB_LDFLAGS} \${SHLIB_LD_LIBS}" + ;; + esac + + if test "${SHARED_BUILD}" = "1" ; then + MAKE_LIB=${MAKE_SHARED_LIB} + else + MAKE_LIB=${MAKE_STATIC_LIB} + fi + + AC_SUBST(MAKE_LIB) + AC_SUBST(MAKE_SHARED_LIB) + AC_SUBST(MAKE_STATIC_LIB) +]) + +#------------------------------------------------------------------------ +# SC_LIB_SPEC -- +# +# Compute the name of an existing object library located in libdir +# from the given base name and produce the appropriate linker flags. +# +# Arguments: +# basename The base name of the library without version +# numbers, extensions, or "lib" prefixes. +# extra_dir Extra directory in which to search for the +# library. This location is used first, then +# $prefix/$exec-prefix, then some defaults. +# +# Requires: +# CYGPATH command used to generate native style paths +# +# Results: +# +# Defines the following vars: +# ${basename}_LIB_NAME The computed library name. +# ${basename}_LIB_SPEC The computed linker flags. +#------------------------------------------------------------------------ + +AC_DEFUN(SC_LIB_SPEC, [ + AC_MSG_CHECKING(for $1 library) + + # Look in exec-prefix and prefix for the library. If neither of + # these were specified, look in libdir. It doesn't matter if libdir + # wasn't specified since a search in the unspecified directory will + # fail (NONE/lib) + + if test x"${exec_prefix}" != x"NONE" ; then + sc_lib_name_dir="${exec_prefix}/lib" + elif test x"${prefix}" != "NONE" ; then + sc_lib_name_dir="${prefix}/lib" + else + eval "sc_lib_name_dir=${libdir}" + fi + + if test x"$2" != x ; then + sc_extra_lib_dir=$2 + else + sc_extra_lib_dir=NONE + fi + + for i in \ + `ls -dr ${sc_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${sc_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr ${sc_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr ${sc_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ + `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ + `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do + if test -f "$i" ; then + + sc_lib_name_dir=`dirname $i` + $1_LIB_NAME=`basename $i` + $1_LIB_PATH_NAME=$i + break + fi + done + + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME}`\" + ;; + *) + # Strip off the leading "lib" and trailing ".a" or ".so" + + sc_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//'` + $1_LIB_SPEC="-L${sc_lib_name_dir} -l${sc_lib_name_lib}" + ;; + esac + if test "x$1_LIB_NAME" = x ; then + AC_MSG_ERROR(not found) + else + AC_MSG_RESULT(${$1_LIB_SPEC}) + fi + AC_SUBST($1_LIB_SPEC) + AC_SUBST($1_LIB_NAME) +]) + +#------------------------------------------------------------------------ +# SC_PRIVATE_TCL_HEADERS -- +# +# Locate the private Tcl include files +# +# Arguments: +# +# Requires: +# TCL_SRC_DIR Assumes that SC_LOAD_TCLCONFIG has +# already been called. +# +# Results: +# +# Substs the following vars: +# TCL_TOP_DIR_NATIVE +# TCL_GENERIC_DIR_NATIVE +# TCL_UNIX_DIR_NATIVE +# TCL_WIN_DIR_NATIVE +# TCL_BMAP_DIR_NATIVE +# TCL_TOOL_DIR_NATIVE +# TCL_PLATFORM_DIR_NATIVE +# TCL_BIN_DIR_NATIVE +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PRIVATE_TCL_HEADERS, [ + AC_MSG_CHECKING(for Tcl private include files) + + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + TCL_TOP_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/..`\" + TCL_GENERIC_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/../generic`\" + TCL_UNIX_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/../unix`\" + TCL_WIN_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/../win`\" + TCL_BMAP_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/../bitmaps`\" + TCL_TOOL_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/../tools`\" + TCL_COMPAT_DIR_NATIVE=\"`${CYGPATH} ${TCL_SRC_DIR}/../compat`\" + TCL_PLATFORM_DIR_NATIVE=${TCL_WIN_DIR_NATIVE} + ;; + *) + TCL_TOP_DIR_NATIVE='$(TCL_SRC_DIR)' + TCL_GENERIC_DIR_NATIVE='$(TCL_TOP_DIR_NATIVE)/generic' + TCL_UNIX_DIR_NATIVE='$(TCL_TOP_DIR_NATIVE)/unix' + TCL_WIN_DIR_NATIVE='$(TCL_TOP_DIR_NATIVE)/win' + TCL_BMAP_DIR_NATIVE='$(TCL_TOP_DIR_NATIVE)/bitmaps' + TCL_TOOL_DIR_NATIVE='$(TCL_TOP_DIR_NATIVE)/tools' + TCL_COMPAT_DIR_NATIVE='$(TCL_TOP_DIR_NATIVE)/compat' + TCL_PLATFORM_DIR_NATIVE=${TCL_UNIX_DIR_NATIVE} + ;; + esac + + AC_SUBST(TCL_TOP_DIR_NATIVE) + AC_SUBST(TCL_GENERIC_DIR_NATIVE) + AC_SUBST(TCL_UNIX_DIR_NATIVE) + AC_SUBST(TCL_WIN_DIR_NATIVE) + AC_SUBST(TCL_BMAP_DIR_NATIVE) + AC_SUBST(TCL_TOOL_DIR_NATIVE) + AC_SUBST(TCL_PLATFORM_DIR_NATIVE) + + TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" + AC_SUBST(TCL_INCLUDES) + AC_MSG_RESULT(Using srcdir found in tclConfig.sh) +]) + +#------------------------------------------------------------------------ +# SC_PUBLIC_TCL_HEADERS -- +# +# Locate the installed public Tcl header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tclinclude switch to configure. +# Result is cached. +# +# Substs the following vars: +# TCL_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PUBLIC_TCL_HEADERS, [ + AC_MSG_CHECKING(for Tcl public headers) + + AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files.], with_tclinclude=${withval}) + + if test x"${with_tclinclude}" != x ; then + if test -f "${with_tclinclude}/tcl.h" ; then + ac_cv_c_tclh=${with_tclinclude} + else + AC_MSG_ERROR([${with_tclinclude} directory does not contain Tcl public header file tcl.h]) + fi + else + AC_CACHE_VAL(ac_cv_c_tclh, [ + # Use the value from --with-tclinclude, if it was given + + if test x"${with_tclinclude}" != x ; then + ac_cv_c_tclh=${with_tclinclude} + else + # Check in the includedir, if --prefix was specified + + eval "temp_includedir=${includedir}" + for i in \ + `ls -d ${temp_includedir} 2>/dev/null` \ + /usr/local/include /usr/include ; do + if test -f "$i/tcl.h" ; then + ac_cv_c_tclh=$i + break + fi + done + fi + ]) + fi + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tclh}" = x ; then + AC_MSG_ERROR(tcl.h not found. Please specify its location with --with-tclinclude) + else + AC_MSG_RESULT(${ac_cv_c_tclh}) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` + + TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TCL_INCLUDES) +]) + +#------------------------------------------------------------------------ +# SC_PRIVATE_TK_HEADERS -- +# +# Locate the private Tk include files +# +# Arguments: +# +# Requires: +# TK_SRC_DIR Assumes that SC_LOAD_TKCONFIG has +# already been called. +# +# Results: +# +# Substs the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PRIVATE_TK_HEADERS, [ + AC_MSG_CHECKING(for Tk private include files) + + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + TK_UNIX_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/../unix`\" + TK_WIN_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/../win`\" + TK_GENERIC_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/../generic`\" + TK_XLIB_DIR_NATIVE=\"`${CYGPATH} ${TK_SRC_DIR}/../xlib`\" + TK_PLATFORM_DIR_NATIVE=${TK_WIN_DIR_NATIVE} + + TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE} -I${TK_XLIB_DIR_NATIVE}" + ;; + *) + TK_GENERIC_DIR_NATIVE='$(TK_TOP_DIR_NATIVE)/generic' + TK_UNIX_DIR_NATIVE='$(TK_TOP_DIR_NATIVE)/unix' + TK_WIN_DIR_NATIVE='$(TK_TOP_DIR_NATIVE)/win' + TK_PLATFORM_DIR_NATIVE=${TK_UNIX_DIR_NATIVE} + + TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" + ;; + esac + + AC_SUBST(TK_UNIX_DIR_NATIVE) + AC_SUBST(TK_WIN_DIR_NATIVE) + AC_SUBST(TK_GENERIC_DIR_NATIVE) + AC_SUBST(TK_XLIB_DIR_NATIVE) + AC_SUBST(TK_PLATFORM_DIR_NATIVE) + + AC_SUBST(TK_INCLUDES) + AC_MSG_RESULT(Using srcdir found in tkConfig.sh) +]) + +#------------------------------------------------------------------------ +# SC_PUBLIC_TK_HEADERS -- +# +# Locate the installed public Tk header files +# +# Arguments: +# None. +# +# Requires: +# CYGPATH must be set +# +# Results: +# +# Adds a --with-tkinclude switch to configure. +# Result is cached. +# +# Substs the following vars: +# TK_INCLUDES +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PUBLIC_TK_HEADERS, [ + AC_MSG_CHECKING(for Tk public headers) + + AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files.], with_tkinclude=${withval}) + + if test x"${with_tkinclude}" != x ; then + if test -f "${with_tkinclude}/tk.h" ; then + ac_cv_c_tkh=${with_tkinclude} + else + AC_MSG_ERROR([${with_tkinclude} directory does not contain Tk public header file tk.h]) + fi + else + AC_CACHE_VAL(ac_cv_c_tkh, [ + # Use the value from --with-tkinclude, if it was given + + if test x"${with_tkinclude}" != x ; then + ac_cv_c_tkh=${with_tkinclude} + else + # Check in the includedir, if --prefix was specified + + eval "temp_includedir=${includedir}" + for i in \ + `ls -d ${temp_includedir} 2>/dev/null` \ + /usr/local/include /usr/include ; do + if test -f "$i/tk.h" ; then + ac_cv_c_tkh=$i + break + fi + done + fi + ]) + fi + + # Print a message based on how we determined the include path + + if test x"${ac_cv_c_tkh}" = x ; then + AC_MSG_ERROR(tk.h not found. Please specify its location with --with-tkinclude) + else + AC_MSG_RESULT(${ac_cv_c_tkh}) + fi + + # Convert to a native path and substitute into the output files. + + INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` + + TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" + + AC_SUBST(TK_INCLUDES) +]) + +#------------------------------------------------------------------------ +# SC_SIMPLE_EXEEXT +# Select the executable extension based on the host type. This +# is a lightweight replacement for AC_EXEEXT that doesn't require +# a compiler. +# +# Arguments +# none +# +# Results +# Subst's the following values: +# EXEEXT +#------------------------------------------------------------------------ + +AC_DEFUN(SC_SIMPLE_EXEEXT, [ + AC_MSG_CHECKING(executable extension based on host type) + + case "`uname -s`" in + *win32* | *WIN32* | *CYGWIN_NT*) + EXEEXT=".exe" + ;; + *) + EXEEXT="" + ;; + esac + + AC_MSG_RESULT(${EXEEXT}) + AC_SUBST(EXEEXT) +]) + +#------------------------------------------------------------------------ +# SC_PROG_TCLSH +# Locate a tclsh shell in the following directories: +# ${exec_prefix}/bin +# ${prefix}/bin +# ${TCL_BIN_DIR} +# ${TCL_BIN_DIR}/../bin +# ${PATH} +# +# Arguments +# none +# +# Results +# Subst's the following values: +# TCLSH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PROG_TCLSH, [ + AC_MSG_CHECKING([for tclsh]) + + AC_CACHE_VAL(ac_cv_path_tclsh, [ + search_path=`echo ${exec_prefix}/bin:${prefix}/bin:${TCL_BIN_DIR}:${TCL_BIN_DIR}/../bin:${PATH} | sed -e 's/:/ /g'` + for dir in $search_path ; do + for j in `ls -r $dir/tclsh[[8-9]]* 2> /dev/null` \ + `ls -r $dir/tclsh* 2> /dev/null` ; do + if test x"$ac_cv_path_tclsh" = x ; then + if test -f "$j" ; then + ac_cv_path_tclsh=$j + break + fi + fi + done + done + ]) + + if test -f "$ac_cv_path_tclsh" ; then + TCLSH_PROG=$ac_cv_path_tclsh + AC_MSG_RESULT($TCLSH_PROG) + else + AC_MSG_ERROR(No tclsh found in PATH: $search_path) + fi + AC_SUBST(TCLSH_PROG) +]) + +#------------------------------------------------------------------------ +# SC_PROG_WISH +# Locate a wish shell in the following directories: +# ${exec_prefix}/bin +# ${prefix}/bin +# ${TCL_BIN_DIR} +# ${TCL_BIN_DIR}/../bin +# ${PATH} +# +# Arguments +# none +# +# Results +# Subst's the following values: +# WISH_PROG +#------------------------------------------------------------------------ + +AC_DEFUN(SC_PROG_WISH, [ + AC_MSG_CHECKING([for wish]) + + AC_CACHE_VAL(ac_cv_path_wish, [ + search_path=`echo ${exec_prefix}/bin:${prefix}/bin:${TCL_BIN_DIR}:${TCL_BIN_DIR}/../bin:${PATH} | sed -e 's/:/ /g'` + for dir in $search_path ; do + for j in `ls -r $dir/wish[[8-9]]* 2> /dev/null` \ + `ls -r $dir/wish* 2> /dev/null` ; do + if test x"$ac_cv_path_wish" = x ; then + if test -f "$j" ; then + ac_cv_path_wish=$j + break + fi + fi + done + done + ]) + + if test -f "$ac_cv_path_wish" ; then + WISH_PROG=$ac_cv_path_wish + AC_MSG_RESULT($WISH_PROG) + else + AC_MSG_ERROR(No wish found in PATH: $search_path) + fi + AC_SUBST(WISH_PROG) +]) + ADDED tclOpts.h Index: tclOpts.h ================================================================== --- /dev/null +++ tclOpts.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 1997-1999 Matt Newman + * + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tclOpts.h,v 1.1.1.1 2000/01/19 22:10:58 aborr Exp $ + * + * Stylized option processing - requires consitent + * external vars: opt, idx, objc, objv + */ +#ifndef _TCL_OPTS_H +#define _TCL_OPTS_H + +#define OPT_PROLOG(option) \ + if (strcmp(opt, (option)) == 0) { \ + if (++idx >= objc) { \ + Tcl_AppendResult(interp, \ + "no argument given for ", \ + (option), " option", \ + (char *) NULL); \ + return TCL_ERROR; \ + } +#define OPT_POSTLOG() \ + continue; \ + } +#define OPTOBJ(option, var) \ + OPT_PROLOG(option) \ + var = objv[idx]; \ + OPT_POSTLOG() + +#define OPTSTR(option, var) \ + OPT_PROLOG(option) \ + var = Tcl_GetStringFromObj(objv[idx], NULL);\ + OPT_POSTLOG() + +#define OPTINT(option, var) \ + OPT_PROLOG(option) \ + if (Tcl_GetIntFromObj(interp, objv[idx], \ + &(var)) != TCL_OK) { \ + return TCL_ERROR; \ + } \ + OPT_POSTLOG() + +#define OPTBOOL(option, var) \ + OPT_PROLOG(option) \ + if (Tcl_GetBooleanFromObj(interp, objv[idx],\ + &(var)) != TCL_OK) { \ + return TCL_ERROR; \ + } \ + OPT_POSTLOG() + +#define OPTBAD(type, list) \ + Tcl_AppendResult(interp, "bad ", (type), \ + " \"", opt, "\": must be ", \ + (list), (char *) NULL) + +#endif /* _TCL_OPTS_H */ ADDED tests/client.pem Index: tests/client.pem ================================================================== --- /dev/null +++ tests/client.pem @@ -0,0 +1,24 @@ +issuer= /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit) +subject=/C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Client test cert (512 bit) +-----BEGIN CERTIFICATE----- +MIIB6TCCAVICAQIwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV +BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD +VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNOTcwNjA5MTM1NzU2WhcNOTgwNjA5 +MTM1NzU2WjBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgG +A1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGkNsaWVudCB0ZXN0IGNl +cnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALtv55QyzG6i2Plw +Z1pah7++Gv8L5j6Hnyr/uTZE1NLG0ABDDexmq/R4KedLjFEIYjocDui+IXs62NNt +XrT8odkCAwEAATANBgkqhkiG9w0BAQQFAAOBgQBwtMmI7oGUG8nKmftQssATViH5 +NRRtoEw07DxJp/LfatHdrhqQB73eGdL5WILZJXk46Xz2e9WMSUjVCSYhdKxtflU3 +UR2Ajv1Oo0sTNdfz0wDqJNirLNtzyhhsaq8qMTrLwXrCP31VxBiigFSQSUFnZyTE +9TKwhS4GlwbtCfxSKQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALtv55QyzG6i2PlwZ1pah7++Gv8L5j6Hnyr/uTZE1NLG0ABDDexm +q/R4KedLjFEIYjocDui+IXs62NNtXrT8odkCAwEAAQJAbwXq0vJ/+uyEvsNgxLko +/V86mGXQ/KrSkeKlL0r4ENxjcyeMAGoKu6J9yMY7+X9+Zm4nxShNfTsf/+Freoe1 +HQIhAPOSm5Q1YI+KIsII2GeVJx1U69+wnd71OasIPakS1L1XAiEAxQAW+J3/JWE0 +ftEYakbhUOKL8tD1OaFZS71/5GdG7E8CIQCefUMmySSvwd6kC0VlATSWbW+d+jp/ +nWmM1KvqnAo5uQIhALqEADu5U1Wvt8UN8UDGBRPQulHWNycuNV45d3nnskWPAiAw +ueTyr6WsZ5+SD8g/Hy3xuvF3nPmJRH+rwvVihlcFOg== +-----END RSA PRIVATE KEY----- ADDED tests/server.pem Index: tests/server.pem ================================================================== --- /dev/null +++ tests/server.pem @@ -0,0 +1,369 @@ +issuer= /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit) +subject=/C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Server test cert (512 bit) +-----BEGIN CERTIFICATE----- +MIIB6TCCAVICAQQwDQYJKoZIhvcNAQEEBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV +BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD +VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNOTgwNjI5MjM1MjQwWhcNMDAwNjI4 +MjM1MjQwWjBjMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgG +A1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxIzAhBgNVBAMTGlNlcnZlciB0ZXN0IGNl +cnQgKDUxMiBiaXQpMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+zw4Qnlf8SMVIP +Fe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/7tdkuD8Ey2// +Kv7+ue0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCVvvfkGSe2GHgDFfmOua4Isjb9 +JVhImWMASiOClkZlMESDJjsszg/6+d/W+8TrbObhazpl95FivXBVucbj9dudh7AO +IZu1h1MAPlyknc9Ud816vz3FejB4qqUoaXjnlkrIgEbr/un7jSS86WOe0hRhwHkJ +FUGcPZf9ND22Etc+AQ== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD +TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu +OA4NACqoiFqyblo7yc2tM4h4xMbC3Yx5UKMN9ZkCtX0gzrz6DyF47bdKcWBzNWCj +gQIhANEoojVt7hq+SQ6MCN6FTAysGgQf56Q3TYoJMoWvdiXVAiEAw3e3rc+VJpOz +rHuDo6bgpjUAAXM+v3fcpsfZSNO6V7kCIQCtbVjanpUwvZkMI9by02oUk9taki3b +PzPfAfNPYAbCJQIhAJXNQDWyqwn/lGmR11cqY2y9nZ1+5w3yHGatLrcDnQHxAiEA +vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU= +-----END RSA PRIVATE KEY----- +subject=/C=US/O=AT&T Bell Laboratories/OU=Prototype Research CA +issuer= /C=US/O=AT&T Bell Laboratories/OU=Prototype Research CA +notBefore=950413210656Z +notAfter =970412210656Z +-----BEGIN X509 CERTIFICATE----- + +MIICCDCCAXECAQAwDQYJKoZIhvcNAQEEBQAwTjELMAkGA1UEBhMCVVMxHzAdBgNV +BAoUFkFUJlQgQmVsbCBMYWJvcmF0b3JpZXMxHjAcBgNVBAsUFVByb3RvdHlwZSBS +ZXNlYXJjaCBDQTAeFw05NTA0MTMyMTA2NTZaFw05NzA0MTIyMTA2NTZaME4xCzAJ +BgNVBAYTAlVTMR8wHQYDVQQKFBZBVCZUIEJlbGwgTGFib3JhdG9yaWVzMR4wHAYD +VQQLFBVQcm90b3R5cGUgUmVzZWFyY2ggQ0EwgZwwDQYJKoZIhvcNAQEBBQADgYoA +MIGGAoGAebOmgtSCl+wCYZc86UGYeTLY8cjmW2P0FN8ToT/u2pECCoFdrlycX0OR +3wt0ZhpFXLVNeDnHwEE9veNUih7pCL2ZBFqoIoQkB1lZmXRiVtjGonz8BLm/qrFM +YHb0lme/Ol+s118mwKVxnn6bSAeI/OXKhLaVdYZWk+aEaxEDkVkCAQ8wDQYJKoZI +hvcNAQEEBQADgYEAAZMG14lZmZ8bahkaHaTV9dQf4p2FZiQTFwHP9ZyGsXPC+LT5 +dG5iTaRmyjNIJdPWohZDl97kAci79aBndvuEvRKOjLHs3WRGBIwERnAcnY9Mz8u/ +zIHK23PjYVxGGaZd669OJwD0CYyqH22HH9nFUGaoJdsv39ChW0NRdLE9+y8= +-----END X509 CERTIFICATE----- +issuer= /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test PCA (1024 bit) +subject=/C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit) +-----BEGIN CERTIFICATE----- +MIICJjCCAY8CAQAwDQYJKoZIhvcNAQEEBQAwXDELMAkGA1UEBhMCQVUxEzARBgNV +BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYD +VQQDExNUZXN0IFBDQSAoMTAyNCBiaXQpMB4XDTk3MDYwOTEzNTc0M1oXDTAxMDYw +OTEzNTc0M1owWzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxGjAY +BgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYDVQQDExJUZXN0IENBICgxMDI0 +IGJpdCkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKO7o8t116VP6cgybTsZ +DCZhr95nYlZuya3aCi1IKoztqwWnjbmDFIriOqGFPrZQ+moMETC9D59iRW/dFXSv +1F65ka/XY2hLh9exCCo7XuUcDs53Qp3bI3AmMqHjgzE8oO3ajyJAzJkTTOUecQU2 +mw/gI4tMM0LqWMQS7luTy4+xAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAM7achv3v +hLQJcv/65eGEpBXM40ZDVoFQFFJWaY5p883HTqLB1x4FdzsXHH0QKBTcKpWwqyu4 +YDm3fb8oDugw72bCzfyZK/zVZPR/hVlqI/fvU109Qoc+7oPvIXWky71HfcK6ZBCA +q30KIqGM/uoM60INq97qjDmCJapagcNBGQs= +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCju6PLddelT+nIMm07GQwmYa/eZ2JWbsmt2gotSCqM7asFp425 +gxSK4jqhhT62UPpqDBEwvQ+fYkVv3RV0r9ReuZGv12NoS4fXsQgqO17lHA7Od0Kd +2yNwJjKh44MxPKDt2o8iQMyZE0zlHnEFNpsP4COLTDNC6ljEEu5bk8uPsQIDAQAB +AoGAVZmpFZsDZfr0l2S9tLLwpjRWNOlKATQkno6q2WesT0eGLQufTciY+c8ypfU6 +hyio8r5iUl/VhhdjhAtKx1mRpiotftHo/eYf8rtsrnprOnWG0bWjLjtIoMbcxGn2 +J3bN6LJmbJMjDs0eJ3KnTu646F3nDUw2oGAwmpzKXA1KAP0CQQDRvQhxk2D3Pehs +HvG665u2pB5ipYQngEFlZO7RHJZzJOZEWSLuuMqaF/7pTfA5jiBvWqCgJeCRRInL +21ru4dlPAkEAx9jj7BgKn5TYnMoBSSe0afjsV9oApVpN1Nacb1YDtCwy+scp3++s +nFxlv98wxIlSdpwMUn+AUWfjiWR7Tu/G/wJBAJ/KjwZIrFVxewP0x2ILYsTRYLzz +MS4PDsO7FB+I0i7DbBOifXS2oNSpd3I0CNMwrxFnUHzynpbOStVfN3ZL5w0CQQCa +pwFahxBRhkJKsxhjoFJBX9yl75JoY4Wvm5Tbo9ih6UJaRx3kqfkN14L2BKYcsZgb +KY9vmDOYy6iNfjDeWTfJAkBkfPUb8oTJ/nSP5zN6sqGxSY4krc4xLxpRmxoJ8HL2 +XfhqXkTzbU13RX9JJ/NZ8vQN9Vm2NhxRGJocQkmcdVtJ +-----END RSA PRIVATE KEY----- +-----BEGIN X509 CERTIFICATE----- +MIICYDCCAiACAgEoMAkGBSsOAwINBQAwfDELMAkGA1UEBhMCVVMxNjA0BgNVBAoT +LU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEZ +MBcGA1UECxMQVGVzdCBFbnZpcm9ubWVudDEaMBgGA1UECxMRRFNTLU5BU0EtUGls +b3QtQ0EwHhcNOTYwMjI2MTYzMjQ1WhcNOTcwMjI1MTYzMjQ1WjB8MQswCQYDVQQG +EwJVUzE2MDQGA1UEChMtTmF0aW9uYWwgQWVyb25hdXRpY3MgYW5kIFNwYWNlIEFk +bWluaXN0cmF0aW9uMRkwFwYDVQQLExBUZXN0IEVudmlyb25tZW50MRowGAYDVQQL +ExFEU1MtTkFTQS1QaWxvdC1DQTCB8jAJBgUrDgMCDAUAA4HkADCB4AJBAMA/ssKb +hPNUG7ZlASfVwEJU21O5OyF/iyBzgHI1O8eOhJGUYO8cc8wDMjR508Mr9cp6Uhl/ +ZB7FV5GkLNEnRHYCQQDUEaSg45P2qrDwixTRhFhmWz5Nvc4lRFQ/42XPcchiJBLb +bn3QK74T2IxY1yY+kCNq8XrIqf5fJJzIH0J/xUP3AhUAsg2wsQHfDGYk/BOSulX3 +fVd0geUCQQCzCFUQAh+ZkEmp5804cs6ZWBhrUAfnra8lJItYo9xPcXgdIfLfibcX +R71UsyO77MRD7B0+Ag2tq794IleCVcEEMAkGBSsOAwINBQADLwAwLAIUUayDfreR +Yh2WeU86/pHNdkUC1IgCFEfxe1f0oMpxJyrJ5XIxTi7vGdoK +-----END X509 CERTIFICATE----- +-----BEGIN X509 CERTIFICATE----- + +MIICGTCCAdgCAwCqTDAJBgUrDgMCDQUAMHwxCzAJBgNVBAYTAlVTMTYwNAYDVQQK +Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x +GTAXBgNVBAsTEFRlc3QgRW52aXJvbm1lbnQxGjAYBgNVBAsTEURTUy1OQVNBLVBp +bG90LUNBMB4XDTk2MDUxNDE3MDE0MVoXDTk3MDUxNDE3MDE0MVowMzELMAkGA1UE +BhMCQVUxDzANBgNVBAoTBk1pbmNvbTETMBEGA1UEAxMKRXJpYyBZb3VuZzCB8jAJ +BgUrDgMCDAUAA4HkADCB4AJBAKbfHz6vE6pXXMTpswtGUec2tvnfLJUsoxE9qs4+ +ObZX7LmLvragNPUeiTJx7UOWZ5DfBj6bXLc8eYne0lP1g3ACQQDUEaSg45P2qrDw +ixTRhFhmWz5Nvc4lRFQ/42XPcchiJBLbbn3QK74T2IxY1yY+kCNq8XrIqf5fJJzI +H0J/xUP3AhUAsg2wsQHfDGYk/BOSulX3fVd0geUCQQCzCFUQAh+ZkEmp5804cs6Z +WBhrUAfnra8lJItYo9xPcXgdIfLfibcXR71UsyO77MRD7B0+Ag2tq794IleCVcEE +MAkGBSsOAwINBQADMAAwLQIUWsuuJRE3VT4ueWkWMAJMJaZjj1ECFQCYY0zX4bzM +LC7obsrHD8XAHG+ZRG== +-----END X509 CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICTTCCAbagAwIBAgIBADANBgkqhkiG9w0BAQQFADBMMQswCQYDVQQGEwJHQjEM +MAoGA1UEChMDVUNMMRgwFgYDVQQLEw9JQ0UtVEVMIFByb2plY3QxFTATBgNVBAMT +DFRydXN0RmFjdG9yeTAeFw05NzA0MjIxNDM5MTRaFw05ODA0MjIxNDM5MTRaMEwx +CzAJBgNVBAYTAkdCMQwwCgYDVQQKEwNVQ0wxGDAWBgNVBAsTD0lDRS1URUwgUHJv +amVjdDEVMBMGA1UEAxMMVHJ1c3RGYWN0b3J5MIGcMAoGBFUIAQECAgQAA4GNADCB +iQKBgQCEieR8NcXkUW1f0G6aC6u0i8q/98JqS6RxK5YmHIGKCkuTWAUjzLfUa4dt +U9igGCjTuxaDqlzEim+t/02pmiBZT9HaX++35MjQPUWmsChcYU5WyzGErXi+rQaw +zlwS73zM8qiPj/97lXYycWhgL0VaiDSPxRXEUdWoaGruom4mNQIDAQABo0IwQDAd +BgNVHQ4EFgQUHal1LZr7oVg5z6lYzrhTgZRCmcUwDgYDVR0PAQH/BAQDAgH2MA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAfaggfl6FZoioecjv0dq8 +/DXo/u11iMZvXn08gjX/zl2b4wtPbShOSY5FhkSm8GeySasz+/Nwb/uzfnIhokWi +lfPZHtlCWtXbIy/TN51eJyq04ceDCQDWvLC2enVg9KB+GJ34b5c5VaPRzq8MBxsA +S7ELuYGtmYgYm9NZOIr7yU0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB6jCCAZQCAgEtMA0GCSqGSIb3DQEBBAUAMIGAMQswCQYDVQQGEwJVUzE2MDQG +A1UEChMtTmF0aW9uYWwgQWVyb25hdXRpY3MgYW5kIFNwYWNlIEFkbWluaXN0cmF0 +aW9uMRkwFwYDVQQLExBUZXN0IEVudmlyb25tZW50MR4wHAYDVQQLExVNRDUtUlNB +LU5BU0EtUGlsb3QtQ0EwHhcNOTYwNDMwMjIwNTAwWhcNOTcwNDMwMjIwNTAwWjCB +gDELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu +ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEZMBcGA1UECxMQVGVzdCBFbnZpcm9ubWVu +dDEeMBwGA1UECxMVTUQ1LVJTQS1OQVNBLVBpbG90LUNBMFkwCgYEVQgBAQICAgAD +SwAwSAJBALmmX5+GqAvcrWK13rfDrNX9UfeA7f+ijyBgeFQjYUoDpFqapw4nzQBL +bAXug8pKkRwa2Zh8YODhXsRWu2F/UckCAwEAATANBgkqhkiG9w0BAQQFAANBAH9a +OBA+QCsjxXgnSqHx04gcU8S49DVUb1f2XVoLnHlIb8RnX0k5O6mpHT5eti9bLkiW +GJNMJ4L0AJ/ac+SmHZc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICajCCAdMCBDGA0QUwDQYJKoZIhvcNAQEEBQAwfTELMAkGA1UEBhMCQ2ExDzAN +BgNVBAcTBk5lcGVhbjEeMBwGA1UECxMVTm8gTGlhYmlsaXR5IEFjY2VwdGVkMR8w +HQYDVQQKExZGb3IgRGVtbyBQdXJwb3NlcyBPbmx5MRwwGgYDVQQDExNFbnRydXN0 +IERlbW8gV2ViIENBMB4XDTk2MDQyNjEzMzUwMVoXDTA2MDQyNjEzMzUwMVowfTEL +MAkGA1UEBhMCQ2ExDzANBgNVBAcTBk5lcGVhbjEeMBwGA1UECxMVTm8gTGlhYmls +aXR5IEFjY2VwdGVkMR8wHQYDVQQKExZGb3IgRGVtbyBQdXJwb3NlcyBPbmx5MRww +GgYDVQQDExNFbnRydXN0IERlbW8gV2ViIENBMIGdMA0GCSqGSIb3DQEBAQUAA4GL +ADCBhwKBgQCaroS7O1DA0hm4IefNYU1cx/nqOmzEnk291d1XqznDeF4wEgakbkCc +zTKxK791yNpXG5RmngqH7cygDRTHZJ6mfCRn0wGC+AI00F2vYTGqPGRQL1N3lZT0 +YDKFC0SQeMMjFIZ1aeQigroFQnHo0VB3zWIMpNkka8PY9lxHZAmWwQIBAzANBgkq +hkiG9w0BAQQFAAOBgQBAx0UMVA1s54lMQyXjMX5kj99FJN5itb8bK1Rk+cegPQPF +cWO9SEWyEjjBjIkjjzAwBkaEszFsNGxemxtXvwjIm1xEUMTVlPEWTs2qnDvAUA9W +YqhWbhH0toGT36236QAsqCZ76rbTRVSSX2BHyJwJMG2tCRv7kRJ//NIgxj3H4w== +-----END CERTIFICATE----- + +issuer= /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test PCA (1024 bit) +subject=/C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test PCA (1024 bit) +-----BEGIN CERTIFICATE----- +MIICJzCCAZACAQAwDQYJKoZIhvcNAQEEBQAwXDELMAkGA1UEBhMCQVUxEzARBgNV +BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYD +VQQDExNUZXN0IFBDQSAoMTAyNCBiaXQpMB4XDTk3MDYwOTEzNTczN1oXDTAxMDYw +OTEzNTczN1owXDELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxGjAY +BgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYDVQQDExNUZXN0IFBDQSAoMTAy +NCBiaXQpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdoWk/3+WcMlfjIrkg +40ketmnQaEogQe1LLcuOJV6rKfUSAsPgwgsabJ/wn8TxA1yy3eKJbFl3OiUXMRsp +22Jp85PmemiDzyUIStwk72qhp1imbANZvlmlCFKiQrjUyuDfu4TABmn+kkt3vR1Y +BEOGt+IFye1UBVSATVdRJ2UVhwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABNA1u/S +Cg/LJZWb7GliiKJsvuhxlE4E5JxQF2zMub/CSNbF97//tYSyj96sxeFQxZXbcjm9 +xt6mr/xNLA4szNQMJ4P+L7b5e/jC5DSqlwS+CUYJgaFs/SP+qJoCSu1bR3IM9XWO +cRBpDmcBbYLkSyB92WURvsZ1LtjEcn+cdQVI +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQCdoWk/3+WcMlfjIrkg40ketmnQaEogQe1LLcuOJV6rKfUSAsPg +wgsabJ/wn8TxA1yy3eKJbFl3OiUXMRsp22Jp85PmemiDzyUIStwk72qhp1imbANZ +vlmlCFKiQrjUyuDfu4TABmn+kkt3vR1YBEOGt+IFye1UBVSATVdRJ2UVhwIDAQAB +AoGAba4fTtuap5l7/8ZsbE7Z1O32KJY4ZcOZukLOLUUhXxXduT+FTgGWujc0/rgc +z9qYCLlNZHOouMYTgtSfYvuMuLZ11VIt0GYH+nRioLShE59Yy+zCRyC+gPigS1kz +xvo14AsOIPYV14Tk/SsHyq6E0eTk7VzaIE197giiINUERPECQQDSKmtPTh/lRKw7 +HSZSM0I1mFWn/1zqrAbontRQY5w98QWIOe5qmzYyFbPXYT3d9BzlsMyhgiRNoBbD +yvohSHXJAkEAwAHx6ezAZeWWzD5yXD36nyjpkVCw7Tk7TSmOceLJMWt1QcrCfqlS +xA5jjpQ6Z8suU5DdtWAryM2sAir1WisYzwJAd6Zcx56jvAQ3xcPXsE6scBTVFzrj +7FqZ6E+cclPzfLQ+QQsyOBE7bpI6e/FJppY26XGZXo3YGzV8IGXrt40oOQJALETG +h86EFXo3qGOFbmsDy4pdP5nBERCu8X1xUCSfintiD4c2DInxgS5oGclnJeMcjTvL +QjQoJCX3UJCi/OUO1QJBAKgcDHWjMvt+l1pjJBsSEZ0HX9AAIIVx0RQmbFGS+F2Q +hhu5l77WnnZOQ9vvhV5u7NPCUF9nhU3jh60qWWO8mkc= +-----END RSA PRIVATE KEY----- +subject=/C=US/O=RSA Data Security, Inc./OU=Commercial Certification Authority +issuer= /C=US/O=RSA Data Security, Inc./OU=Commercial Certification Authority +notBefore=941104185834Z +notAfter =991103185834Z +-----BEGIN X509 CERTIFICATE----- + +MIICIzCCAZACBQJBAAAWMA0GCSqGSIb3DQEBAgUAMFwxCzAJBgNVBAYTAlVTMSAw +HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVy +Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NDExMDQxODU4MzRaFw05 +OTExMDMxODU4MzRaMFwxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdSU0EgRGF0YSBT +ZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVyY2lhbCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTCBmzANBgkqhkiG9w0BAQEFAAOBiQAwgYUCfgCk+4Fie84QJ93o +975sbsZwmdu41QUDaSiCnHJ/lj+O7Kwpkj+KFPhCdr69XQO5kNTQvAayUTNfxMK/ +touPmbZiImDd298ggrTKoi8tUO2UMt7gVY3UaOLgTNLNBRYulWZcYVI4HlGogqHE +7yXpCuaLK44xZtn42f29O2nZ6wIDAQABMA0GCSqGSIb3DQEBAgUAA34AdrW2EP4j +9/dZYkuwX5zBaLxJu7NJbyFHXSudVMQAKD+YufKKg5tgf+tQx6sFEC097TgCwaVI +0v5loMC86qYjFmZsGySp8+x5NRhPJsjjr1BKx6cxa9B8GJ1Qv6km+iYrRpwUqbtb +MJhCKLVLU7tDCZJAuqiqWqTGtotXTcU= +-----END X509 CERTIFICATE----- +subject=/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority +issuer= /C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority +notBefore=941109235417Z +notAfter =991231235417Z +-----BEGIN X509 CERTIFICATE----- + +MIICKTCCAZYCBQJBAAABMA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMSAw +HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjEuMCwGA1UECxMlU2VjdXJl +IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NDExMDkyMzU0MTda +Fw05OTEyMzEyMzU0MTdaMF8xCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdSU0EgRGF0 +YSBTZWN1cml0eSwgSW5jLjEuMCwGA1UECxMlU2VjdXJlIFNlcnZlciBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCBmzANBgkqhkiG9w0BAQEFAAOBiQAwgYUCfgCSznrB +roM+WqqJg1esJQF2DK2ujiw3zus1eGRUA+WEQFHJv48I4oqCCNIWhjdV6bEhAq12 +aIGaBaJLyUslZiJWbIgHj/eBWW2EB2VwE3F2Ppt3TONQiVaYSLkdpykaEy5KEVmc +HhXVSVQsczppgrGXOZxtcGdI5d0t1sgeewIDAQABMA0GCSqGSIb3DQEBAgUAA34A +iNHReSHO4ovo+MF9NFM/YYPZtgs4F7boviGNjwC4i1N+RGceIr2XJ+CchcxK9oU7 +suK+ktPlDemvXA4MRpX/oRxePug2WHpzpgr4IhFrwwk4fia7c+8AvQKk8xQNMD9h +cHsg/jKjn7P0Z1LctO6EjJY2IN6BCINxIYoPnqk= +-----END X509 CERTIFICATE----- +subject=/C=ZA/SP=Western Cape/L=Cape Town/O=Thawte Consulting cc + /OU=Certification Services Division/CN=Thawte Server CA + /Email=server-certs@thawte.com +issuer= /C=ZA/SP=Western Cape/L=Cape Town/O=Thawte Consulting cc + /OU=Certification Services Division/CN=Thawte Server CA + /Email=server-certs@thawte.com +-----BEGIN CERTIFICATE----- +MIIC+TCCAmICAQAwDQYJKoZIhvcNAQEEBQAwgcQxCzAJBgNVBAYTAlpBMRUwEwYD +VQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU +VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy +dmljZXMgRGl2aXNpb24xGTAXBgNVBAMTEFRoYXd0ZSBTZXJ2ZXIgQ0ExJjAkBgkq +hkiG9w0BCQEWF3NlcnZlci1jZXJ0c0B0aGF3dGUuY29tMB4XDTk2MDcyNzE4MDc1 +N1oXDTk4MDcyNzE4MDc1N1owgcQxCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0 +ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMUVGhhd3RlIENv +bnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 +aXNpb24xGTAXBgNVBAMTEFRoYXd0ZSBTZXJ2ZXIgQ0ExJjAkBgkqhkiG9w0BCQEW +F3NlcnZlci1jZXJ0c0B0aGF3dGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQDTpFBuyP9Wa+bPXbbqDGh1R6KqwtqEJfyo9EdR2oW1IHSUhh4PdcnpCGH1 +Bm0wbhUZAulSwGLbTZme4moMRDjN/r7jZAlwxf6xaym2L0nIO9QnBCUQly/nkG3A +KEKZ10xD3sP1IW1Un13DWOHA5NlbsLjctHvfNjrCtWYiEtaHDQIDAQABMA0GCSqG +SIb3DQEBBAUAA4GBAIsvn7ifX3RUIrvYXtpI4DOfARkTogwm6o7OwVdl93yFhDcX +7h5t0XZ11MUAMziKdde3rmTvzUYIUCYoY5b032IwGMTvdiclK+STN6NP2m5nvFAM +qJT5gC5O+j/jBuZRQ4i0AMYQr5F4lT8oBJnhgafw6PL8aDY2vMHGSPl9+7uf +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIDDTCCAnYCAQAwDQYJKoZIhvcNAQEEBQAwgc4xCzAJBgNVBAYTAlpBMRUwEwYD +VQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU +VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy +dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBD +QTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTAeFw05 +NjA3MjcxODA3MTRaFw05ODA3MjcxODA3MTRaMIHOMQswCQYDVQQGEwJaQTEVMBMG +A1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xHTAbBgNVBAoT +FFRoYXd0ZSBDb25zdWx0aW5nIGNjMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzIERpdmlzaW9uMSEwHwYDVQQDExhUaGF3dGUgUHJlbWl1bSBTZXJ2ZXIg +Q0ExKDAmBgkqhkiG9w0BCQEWGXByZW1pdW0tc2VydmVyQHRoYXd0ZS5jb20wgZ8w +DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANI2NmqL18JbntqBQWKPOO5JBFXW0O8c +G5UWR+8YSDU6UvQragaPOy/qVuOvho2eF/eetGV1Ak3vywmiIVHYm9Bn0LoNkgYU +c9STy5cqAJxcTgy8+hVS/PJEbtoRSm4Iny8t4/mqOoZztkZTWMiJBb2DEbhzP6oH +jfRCTedAnRw3AgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAutFIgTRZVYerIZfL9lvR +w9Eifvvo5KTZ3h+Bj+VzNnyw4Qc/IyXkPOu6SIiH9LQ3sCmWBdxpe+qr4l77rLj2 +GYuMtESFfn1XVALzkYgC7JcPuTOjMfIiMByt+uFf8AV8x0IW/Qkuv+hEQcyM9vxK +3VZdLbCVIhNoEsysrxCpxcI= +-----END CERTIFICATE----- +Tims test GCI CA + +-----BEGIN CERTIFICATE----- +MIIB8DCCAZoCAQAwDQYJKoZIhvcNAQEEBQAwgYIxCzAJBgNVBAYTAkFVMRMwEQYD +VQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgGA1UEChMRQ3J5 +cHRTb2Z0IFB0eSBMdGQxFDASBgNVBAsTC2RldmVsb3BtZW50MRkwFwYDVQQDExBD +cnlwdFNvZnQgRGV2IENBMB4XDTk3MDMyMjEzMzQwNFoXDTk4MDMyMjEzMzQwNFow +gYIxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhC +cmlzYmFuZTEaMBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxFDASBgNVBAsTC2Rl +dmVsb3BtZW50MRkwFwYDVQQDExBDcnlwdFNvZnQgRGV2IENBMFwwDQYJKoZIhvcN +AQEBBQADSwAwSAJBAOAOAqogG5QwAmLhzyO4CoRnx/wVy4NZP4dxJy83O1EnL0rw +OdsamJKvPOLHgSXo3gDu9uVyvCf/QJmZAmC5ml8CAwEAATANBgkqhkiG9w0BAQQF +AANBADRRS/GVdd7rAqRW6SdmgLJduOU2yq3avBu99kRqbp9A/dLu6r6jU+eP4oOA +TfdbFZtAAD2Hx9jUtY3tfdrJOb8= +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIICVjCCAgACAQAwDQYJKoZIhvcNAQEEBQAwgbUxCzAJBgNVBAYTAkFVMRMwEQYD +VQQIEwpRdWVlbnNsYW5kMREwDwYDVQQHEwhCcmlzYmFuZTEaMBgGA1UEChMRQ3J5 +cHRTb2Z0IFB0eSBMdGQxLDAqBgNVBAsTI1dPUlRITEVTUyBDRVJUSUZJQ0FUSU9O +IEFVVEhPUklUSUVTMTQwMgYDVQQDEytaRVJPIFZBTFVFIENBIC0gREVNT05TVFJB +VElPTiBQVVJQT1NFUyBPTkxZMB4XDTk3MDQwMzEzMjI1NFoXDTk4MDQwMzEzMjI1 +NFowgbUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMREwDwYDVQQH +EwhCcmlzYmFuZTEaMBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxLDAqBgNVBAsT +I1dPUlRITEVTUyBDRVJUSUZJQ0FUSU9OIEFVVEhPUklUSUVTMTQwMgYDVQQDEyta +RVJPIFZBTFVFIENBIC0gREVNT05TVFJBVElPTiBQVVJQT1NFUyBPTkxZMFwwDQYJ +KoZIhvcNAQEBBQADSwAwSAJBAOZ7T7yqP/tyspcko3yPY1y0Cm2EmwNvzW4QgVXR +Fjs3HmJ4xtSpXdo6mwcGezL3Abt/aQXaxv9PU8xt+Jr0OFUCAwEAATANBgkqhkiG +9w0BAQQFAANBAOQpYmGgyCqCy1OljgJhCqQOu627oVlHzK1L+t9vBaMfn40AVUR4 +WzQVWO31KTgi5vTK1U+3h46fgUWqQ0h+6rU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIAwgKADAgECAgEAMA0GCSqGSIb3DQEBBAUAMGIxETAPBgNVBAcTCEludGVybmV0 +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE0MDIGA1UECxMrVmVyaVNpZ24gQ2xh +c3MgMSBDQSAtIEluZGl2aWR1YWwgU3Vic2NyaWJlcjAeFw05NjA0MDgxMDIwMjda +Fw05NzA0MDgxMDIwMjdaMGIxETAPBgNVBAcTCEludGVybmV0MRcwFQYDVQQKEw5W +ZXJpU2lnbiwgSW5jLjE0MDIGA1UECxMrVmVyaVNpZ24gQ2xhc3MgMSBDQSAtIElu +ZGl2aWR1YWwgU3Vic2NyaWJlcjCAMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2 +FKbPTdAFDdjKI9BvqrQpkmOOLPhvltcunXZLEbE2jVfJw/0cxrr+Hgi6M8qV6r7j +W80GqLd5HUQq7XPysVKDaBBwZJHXPmv5912dFEObbpdFmIFH0S3L3bty10w/cari +QPJUObwW7s987LrbP2wqsxaxhhKdrpM01bjV0Pc+qQIDAQABAAAAADANBgkqhkiG +9w0BAQQFAAOBgQA+1nJryNt8VBRjRr07ArDAV/3jAH7GjDc9jsrxZS68ost9v06C +TvTNKGL+LISNmFLXl+JXhgGB0JZ9fvyYzNgHQ46HBUng1H6voalfJgS2KdEo50wW +8EFZYMDkT1k4uynwJqkVN2QJK/2q4/A/VCov5h6SlM8Affg2W+1TLqvqkwAA +-----END CERTIFICATE----- + + subject=/L=Internet/O=VeriSign, Inc./OU=VeriSign Class 2 CA - Individual Subscriber + issuer= /L=Internet/O=VeriSign, Inc./OU=VeriSign Class 2 CA - Individual Subscriber + +-----BEGIN CERTIFICATE----- +MIIEkzCCA/ygAwIBAgIRANDTUpSRL3nTFeMrMayFSPAwDQYJKoZIhvcNAQECBQAw +YjERMA8GA1UEBxMISW50ZXJuZXQxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTQw +MgYDVQQLEytWZXJpU2lnbiBDbGFzcyAyIENBIC0gSW5kaXZpZHVhbCBTdWJzY3Jp +YmVyMB4XDTk2MDYwNDAwMDAwMFoXDTk4MDYwNDIzNTk1OVowYjERMA8GA1UEBxMI +SW50ZXJuZXQxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTQwMgYDVQQLEytWZXJp +U2lnbiBDbGFzcyAyIENBIC0gSW5kaXZpZHVhbCBTdWJzY3JpYmVyMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQC6A+2czKGRcYMfm8gdnk+0de99TDDzsqo0v5nb +RsbUmMcdRQ7nsMbRWe0SAb/9QoLTZ/cJ0iOBqdrkz7UpqqKarVoTSdlSMVM92tWp +3bJncZHQD1t4xd6lQVdI1/T6R+5J0T1ukOdsI9Jmf+F28S6g3R3L1SFwiHKeZKZv +z+793wIDAQABo4ICRzCCAkMwggIpBgNVHQMBAf8EggIdMIICGTCCAhUwggIRBgtg +hkgBhvhFAQcBATCCAgAWggGrVGhpcyBjZXJ0aWZpY2F0ZSBpbmNvcnBvcmF0ZXMg +YnkgcmVmZXJlbmNlLCBhbmQgaXRzIHVzZSBpcyBzdHJpY3RseSBzdWJqZWN0IHRv +LCB0aGUgVmVyaVNpZ24gQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQg +KENQUyksIGF2YWlsYWJsZSBhdDogaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL0NQ +Uy0xLjA7IGJ5IEUtbWFpbCBhdCBDUFMtcmVxdWVzdHNAdmVyaXNpZ24uY29tOyBv +ciBieSBtYWlsIGF0IFZlcmlTaWduLCBJbmMuLCAyNTkzIENvYXN0IEF2ZS4sIE1v +dW50YWluIFZpZXcsIENBIDk0MDQzIFVTQSBUZWwuICsxICg0MTUpIDk2MS04ODMw +IENvcHlyaWdodCAoYykgMTk5NiBWZXJpU2lnbiwgSW5jLiAgQWxsIFJpZ2h0cyBS +ZXNlcnZlZC4gQ0VSVEFJTiBXQVJSQU5USUVTIERJU0NMQUlNRUQgYW5kIExJQUJJ +TElUWSBMSU1JVEVELqAOBgxghkgBhvhFAQcBAQGhDgYMYIZIAYb4RQEHAQECMC8w +LRYraHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvQ1BTLTEuMDAU +BglghkgBhvhCAQEBAf8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEApRJRkNBqLLgs +53IR/d18ODdLOWMTZ+QOOxBrq460iBEdUwgF8vmPRX1ku7UiDeNzaLlurE6eFqHq +2zPyK5j60zfTLVJMWKcQWwTJLjHtXrW8pxhNtFc6Fdvy5ZkHnC/9NIl7/t4U6WqB +p4y+p7SdMIkEwIZfds0VbnQyX5MRUJY= +-----END CERTIFICATE----- + + subject=/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority + issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority +-----BEGIN CERTIFICATE----- +MIICMTCCAZoCBQKhAAABMA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NjAxMjkwMDAwMDBa +Fw05OTEyMzEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2ln +biwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyVxZ +nvIbigEUtBDfBEDb41evakVAj4QMC9Ez2dkRz+4CWB8l9yqoRAWq7AMfeH+ek7ma +AKojfdashaJjRcdyJ8z0TMZ1cdI5709C8HXfCpDGjiBvmA/4rCNfcCk2pMmG57Ga +IMtTpYXnPb59mv4kRTPcdhXtD6JxZExlLoFoRacCAwEAATANBgkqhkiG9w0BAQIF +AAOBgQB1Zmw+0c2B27X4LzZRtvdCvM1Cr9wO+hVs+GeTVzrrtpLotgHKjLeOQ7RJ +Zfk+7r11Ri7J/CVdqMcvi5uPaM+0nJcYwE3vH9mvgrPmZLiEXIqaB1JDYft0nls6 +NvxMsvwaPxUupVs8G5DsiCnkWRb5zget7Ond2tIxik/W2O8XjQ== +-----END CERTIFICATE----- + subject=/C=US/O=VeriSign, Inc./OU=Class 4 Public Primary Certification Authority + issuer= /C=US/O=VeriSign, Inc./OU=Class 4 Public Primary Certification Authority +-----BEGIN CERTIFICATE----- +MIICMTCCAZoCBQKmAAABMA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NjAxMjkwMDAwMDBa +Fw05OTEyMzEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2ln +biwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LJ1 +9njQrlpQ9OlQqZ+M1++RlHDo0iSQdomF1t+s5gEXMoDwnZNHvJplnR+Xrr/phnVj +IIm9gFidBAydqMEk6QvlMXi9/C0MN2qeeIDpRnX57aP7E3vIwUzSo+/1PLBij0pd +O92VZ48TucE81qcmm+zDO3rZTbxtm+gVAePwR6kCAwEAATANBgkqhkiG9w0BAQIF +AAOBgQBT3dPwnCR+QKri/AAa19oM/DJhuBUNlvP6Vxt/M3yv6ZiaYch6s7f/sdyZ +g9ysEvxwyR84Qu1E9oAuW2szaayc01znX1oYx7EteQSWQZGZQbE8DbqEOcY7l/Am +yY7uvcxClf8exwI/VAx49byqYHwCaejcrOICdmHEPgPq0ook0Q== +-----END CERTIFICATE----- ADDED tests/tls.tcl Index: tests/tls.tcl ================================================================== --- /dev/null +++ tests/tls.tcl @@ -0,0 +1,25 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tls.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# +set dir [file dirname [info script]] +regsub {\.} [info tclversion] {} vshort +if {$tcl_platform(platform) == "windows"} { + if {[info exists tcl_platform(debug)]} { + load $dir/../win/Debug$vshort/tls.dll + } else { + load $dir/../win/Release$vshort/tls.dll + } +} else { + load [glob $dir/../unix/libtls*] +} + +proc bgerror {err} { + global errorInfo + puts stderr "BG Error: $errorInfo" +} + +source $dir/../library/tls.tcl +set tls::debug 2 + ADDED tests/tlsAuto.tcl Index: tests/tlsAuto.tcl ================================================================== --- /dev/null +++ tests/tlsAuto.tcl @@ -0,0 +1,58 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tlsAuto.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# + +set dir [file dirname [info script]] +cd $dir +source tls.tcl + +proc fromServer {chan} { + if {[catch {read $chan 10} data]} { + catch {close $chan} + tclLog "EOF ($data)" + set ::/Exit 1 + return + } + if {[eof $chan]} { + close $chan + set ::/Exit 1 + } + if {$data != ""} { + puts -nonewline stderr "$data" + } +} +proc doit {chan count {delay 1000}} { + if {$count == 0} { + close $chan + set ::/Exit 0 + return + } + puts $chan line$count + flush $chan + + incr count -1 + after $delay doit $chan $count $delay +} +array set opts { + -port 1234 + -host localhost +} +array set opts $argv +# +# Initialize context +# +#tls::init -certfile client.pem -cafile server.pem ;#-cipher RC4-MD5 +tls::init +# +# Create socket and import SSL layer +# +#set chan [tls::socket -async -request 0 $opts(-host) $opts(-port)] +set chan [tls::socket -request 0 $opts(-host) $opts(-port)] + +fconfigure $chan -buffering none -blocking 0 -translation binary +fileevent $chan readable [list fromServer $chan] + +doit $chan 1000 100 +vwait /Exit ADDED tests/tlsBlocking.tcl Index: tests/tlsBlocking.tcl ================================================================== --- /dev/null +++ tests/tlsBlocking.tcl @@ -0,0 +1,38 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tlsBlocking.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# + +set dir [file dirname [info script]] +cd $dir +source tls.tcl + +proc bgerror {msg} {tclLog "BG: $msg"} + +array set opts { + -port 1234 + -host localhost +} +array set opts $argv +# +# Initialize Context +# +# Comment out next line for non-RSA testing +#tls::init -cafile server.pem -certfile client.pem +#tls::init +# +# Create socket and import +# +set chan [tls::socket -require 0 $opts(-host) $opts(-port)] +tls::handshake $chan + +set max 10 +#set max 100 +#set max 3 +for {set i 0} {$i < $max} {incr i} { + puts $chan line$i + flush $chan + puts stdout [gets $chan] +} +close $chan ADDED tests/tlsCiphers.tcl Index: tests/tlsCiphers.tcl ================================================================== --- /dev/null +++ tests/tlsCiphers.tcl @@ -0,0 +1,16 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tlsCiphers.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# + +set dir [file dirname [info script]] +cd $dir +source tls.tcl + +if {[llength $argv] == 0} { + puts stderr "Usage: ciphers protocol ?verbose?" + exit 1 +} +puts [join [eval tls::ciphers $argv] \n] +exit 0 ADDED tests/tlsHttp.tcl Index: tests/tlsHttp.tcl ================================================================== --- /dev/null +++ tests/tlsHttp.tcl @@ -0,0 +1,38 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tlsHttp.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# +package require base64 + +set dir [file dirname [info script]] +cd $dir +source tls.tcl +package require http + +# +# Initialize context +# +#tls::init -certfile client.pem -cafile server.pem -ssl2 1 -ssl3 1 -tls1 0 ;#-cipher RC4-MD5 +tls::init -cafile server.pem +# +# Register with http module +# +http::register https 443 [list ::tls::socket -require 1] + +set user novadigm\\matt +set pass sensus + +set auth [Base64_Encode "${user}:$pass"] +set hdrs [list Authorization [list Basic $auth]] +#set hdrs {} + +set url http://localhost:3466/ +set url https://intranet.novadigm.com/ +set url https://localhost/ +set url https://developer.netscape.com/ + +set tok [http::geturl $url -headers $hdrs] + +parray $tok +exit ADDED tests/tlsSrv.tcl Index: tests/tlsSrv.tcl ================================================================== --- /dev/null +++ tests/tlsSrv.tcl @@ -0,0 +1,61 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tlsSrv.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# +# Sample Tls-enabled server +# +set dir [file dirname [info script]] +cd $dir +source tls.tcl +#lappend auto_path d:/tcl80/lib +#package require tls + +# +# Sample callback - just reflect data back to client +# +proc reflectCB {chan {verbose 0}} { + set x hello + if {[catch {read $chan 1024} data]} { + puts stderr "EOF ($data)" + catch {close $chan} + return + } + + if {$verbose && $data != ""} { + puts -nonewline stderr $data + } + if {[eof $chan]} { ;# client gone or finished + puts stderr "EOF" + close $chan ;# release the servers client channel + return + } + puts -nonewline $chan $data + flush $chan +} +proc acceptCB { chan ip port } { + puts "accept: $chan $ip $port [fconfigure $chan]" + if {[catch { + tls::handshake $chan + } err]} { + catch {close $chan} + return + } + puts [tls::status $chan] + + fconfigure $chan -buffering none -blocking 0 + fileevent $chan readable [list reflectCB $chan 1] +} +#tls::init -cafile server.pem -certfile server.pem +tls::init -cafile server.pem +#tls::init + +set chan [tls::socket -server acceptCB \ + -request 1 -require 0 1234] +# -require 1 -command tls::callback 1234] + +puts "Server waiting connection on $chan (1234)" +puts [fconfigure $chan] + +# Go into the eventloop +vwait /Exit ADDED tests/tlsSrv2.tcl Index: tests/tlsSrv2.tcl ================================================================== --- /dev/null +++ tests/tlsSrv2.tcl @@ -0,0 +1,56 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tlsSrv2.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# +# Sample Tls-enabled server +# +set dir [file dirname [info script]] +cd $dir +source tls.tcl +#lappend auto_path d:/tcl80/lib +#package require tls + +# +# Sample callback - just reflect data back to client +# +proc reflectCB {chan {verbose 0}} { + if {[catch {read $chan 1024} data]} { + puts stderr "EOF ($data)" + catch {close $chan} + return + } + + if {$verbose && $data != ""} { + puts -nonewline stderr $data + } + if {[eof $chan]} { ;# client gone or finished + puts stderr "EOF" + close $chan ;# release the servers client channel + return + } + puts -nonewline $chan $data + flush $chan +} +proc acceptCB { chan ip port } { + puts "accept: $chan $ip $port" + + if {![tls::handshake $chan]} { + puts stderr "Handshake pending" + return + } + array set cert [tls::status $chan] + parray cert + + fconfigure $chan -buffering none -blocking 0 + fileevent $chan readable [list reflectCB $chan 1] +} +tls::init -certfile server.pem -tls1 1 ;#-cipher RC4-SHA + +set chan [tls::socket -server acceptCB \ + -request 1 -require 0 -command tls::callback 1234] + +puts "Server waiting connection on $chan (1234)" + +# Go into the eventloop +vwait /Exit ADDED tests/tlsUpload.tcl Index: tests/tlsUpload.tcl ================================================================== --- /dev/null +++ tests/tlsUpload.tcl @@ -0,0 +1,57 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tests/Attic/tlsUpload.tcl,v 1.1.1.1 2000/01/19 22:10:59 aborr Exp $ +# + +set dir [file dirname [info script]] +cd $dir +source tls.tcl + +proc fromServer {chan} { + if {[catch {read $chan 10} data]} { + catch {close $chan} + tclLog "EOF ($data)" + set ::/Exit 1 + return + } + if {[eof $chan]} { + close $chan + set ::/Exit 1 + } + if {$data != ""} { + puts -nonewline stderr "$data" + } +} +proc doit {chan count {delay 1000}} { + if {$count == 0} { + close $chan + set ::/Exit 0 + return + } + puts $chan line$count + flush $chan + + incr count -1 + after $delay doit $chan $count $delay +} +proc done {chan bytes {error ""}} { + set ::/Exit 1 + tclLog "fcopy done: $bytes ($error) eof=[eof $chan]" +} +# +# Initialize Context +# +tls::init -certfile client.pem -cafile server.pem +# +# Create and import socket +# +set chan [tls::socket -request 1 localhost 1234] + +fconfigure $chan -buffering full + +set fp [open [lindex $argv 0]] +fcopy $fp $chan -command [list done $chan] +#fileevent $chan readable [list fromServer $chan] +vwait /Exit +tclLog Exiting... ADDED tls.c Index: tls.c ================================================================== --- /dev/null +++ tls.c @@ -0,0 +1,1094 @@ +/* + * Copyright (C) 1997-1999 Matt Newman + * + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tls.c,v 1.1.1.1 2000/01/19 22:10:58 aborr 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 + * OpenSSL 0.9.2B + * + * Addition credit is due for Andreas Kupries (a.kupries@westend.com), for + * providing the Tcl_ReplaceChannel mechanism and working closely with me + * to enhance it to support full fileevent semantics. + * + * Also work done by the follow people provided the impetus to do this "right": + * tclSSL (Colin McCormack, Shared Technology) + * SSLtcl (Peter Antman) + * + */ + +#include "tlsInt.h" +#include "tclOpts.h" + +/* + * External functions + */ + +/* + * Forward declarations + */ + +#define F2N( key, dsp) \ + (((key) == NULL)?(char*)NULL:Tcl_TranslateFileName( interp, (key), (dsp))) +#define REASON() ERR_reason_error_string(ERR_get_error()) + +static int CiphersObjCmd _ANSI_ARGS_ ((ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); + +static int HandshakeObjCmd _ANSI_ARGS_ ((ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); + +static int ImportObjCmd _ANSI_ARGS_ ((ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); + +static int StatusObjCmd _ANSI_ARGS_ ((ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +static SSL_CTX *CTX_Init _ANSI_ARGS_((Tcl_Interp *interp, int proto, char *key, + char *cert, char *CAdir, char *CAfile, char *ciphers)); + +#define TLS_PROTO_SSL2 0x01 +#define TLS_PROTO_SSL3 0x02 +#define TLS_PROTO_TLS1 0x04 +#define ENABLED(flag, mask) (((flag) & (mask)) == (mask)) +/* + * Static data structures + */ + +#ifndef NO_DH +/* from openssl/apps/s_server.c */ + +static unsigned char dh512_p[]={ + 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, + 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, + 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, + 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, + 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, + 0x47,0x74,0xE8,0x33, + }; +static unsigned char dh512_g[]={ + 0x02, +}; + +static DH *get_dh512() +{ + DH *dh=NULL; + + if ((dh=DH_new()) == NULL) return(NULL); + + dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); + dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); + + if ((dh->p == NULL) || (dh->g == NULL)) + return(NULL); + return(dh); +} +#endif + +/* + * Per OpenSSL 0.9.4 Compat + */ +#ifndef STACK_OF +#define STACK_OF(x) STACK +#define sk_SSL_CIPHER_num(sk) sk_num((sk)) +#define sk_SSL_CIPHER_value( sk, index) (SSL_CIPHER*)sk_value((sk), (index)) +#endif + +/* + *------------------------------------------------------------------- + * + * InfoCallback -- + * + * monitors SSL connection process + * + * Results: + * None + * + * Side effects: + * Calls callback (if defined) + *------------------------------------------------------------------- + */ +static void +InfoCallback(SSL *ssl, int where, int ret) +{ + State *statePtr = (State*)SSL_get_app_data(ssl); + Tcl_Obj *cmdPtr; + char *major; char *minor; + int w; + + if (statePtr->callback == (Tcl_Obj*)NULL) + return; + + cmdPtr = Tcl_DuplicateObj(statePtr->callback); + +#if 0 + if (where & SSL_CB_ALERT) { + sev = SSL_alert_type_string_long(ret); + if (strcmp( sev, "fatal")==0) { /* Map to error */ + Tls_Error(statePtr, SSL_ERROR(ssl, 0)); + return; + } + } +#endif + if (where & SSL_CB_HANDSHAKE_START) { + major = "handshake"; + minor = "start"; + } else if (where & SSL_CB_HANDSHAKE_DONE) { + major = "handshake"; + minor = "done"; + } else { + if (where & SSL_CB_ALERT) major = "alert"; + else if (where & SSL_ST_CONNECT) major = "connect"; + else if (where & SSL_ST_ACCEPT) major = "accept"; + else major = "unknown"; + + if (where & SSL_CB_READ) minor = "read"; + else if (where & SSL_CB_WRITE) minor = "write"; + else if (where & SSL_CB_LOOP) minor = "loop"; + else if (where & SSL_CB_EXIT) minor = "exit"; + else minor = "unknown"; + } + + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( "info", -1)); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( Tcl_GetChannelName(statePtr->self), -1) ); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( major, -1) ); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( minor, -1) ); + + if (where & (SSL_CB_LOOP|SSL_CB_EXIT)) { + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( SSL_state_string_long(ssl), -1) ); + } else if (where & SSL_CB_ALERT) { + char *cp = SSL_alert_desc_string_long(ret); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( cp, -1) ); + } else { + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( SSL_state_string_long(ssl), -1) ); + } + Tcl_Preserve( (ClientData) statePtr->interp); + Tcl_Preserve( (ClientData) statePtr); + + Tcl_IncrRefCount( cmdPtr); + (void) Tcl_GlobalEvalObj(statePtr->interp, cmdPtr); + Tcl_DecrRefCount( cmdPtr); + + Tcl_Release( (ClientData) statePtr); + Tcl_Release( (ClientData) statePtr->interp); + +} + +/* + *------------------------------------------------------------------- + * + * VerifyCallback -- + * + * monitors SSL cerificate validation process + * This is called whenever a certificate is inspected + * or decided invalid + * + * Results: + * ok - let SSL handle it + * + * Side effects: + * The err field of the currently operative State is set + * to a string describing the SSL negotiation failure reason + *------------------------------------------------------------------- + */ +static int +VerifyCallback(int ok, X509_STORE_CTX *ctx) +{ + SSL *ssl = (SSL*)X509_STORE_CTX_get_app_data(ctx); + X509 *cert = X509_STORE_CTX_get_current_cert(ctx); + State *statePtr = (State*)SSL_get_app_data(ssl); + Tcl_Obj *cmdPtr; + int depth = X509_STORE_CTX_get_error_depth(ctx); + int err = X509_STORE_CTX_get_error(ctx); + char *errStr; + + dprintf(stderr, "Verify: %d\n", ok); + + if (!ok) + errStr = (char*)X509_verify_cert_error_string(err); + else + errStr = (char *)0; + + if (statePtr->callback == (Tcl_Obj*)NULL) { + if (statePtr->vflags & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + return ok; + else + return 1; + } + cmdPtr = Tcl_DuplicateObj(statePtr->callback); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( "verify", -1)); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( Tcl_GetChannelName(statePtr->self), -1) ); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewIntObj( depth) ); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tls_NewX509Obj( statePtr->interp, cert) ); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewIntObj( ok) ); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( errStr ? errStr : "", -1) ); + + Tcl_Preserve( (ClientData) statePtr->interp); + Tcl_Preserve( (ClientData) statePtr); + + Tcl_IncrRefCount( cmdPtr); + if (Tcl_GlobalEvalObj(statePtr->interp, cmdPtr) != TCL_OK) { + /* it got an error - reject the certificate */ + Tcl_BackgroundError( statePtr->interp); + ok = 0; + } else { + if (Tcl_GetIntFromObj( statePtr->interp, + Tcl_GetObjResult( statePtr->interp), &ok) != TCL_OK) { + Tcl_BackgroundError( statePtr->interp); + ok = 0; + } + } + Tcl_DecrRefCount( cmdPtr); + + Tcl_Release( (ClientData) statePtr); + Tcl_Release( (ClientData) statePtr->interp); + + return(ok); /* leave the disposition as SSL set it */ +} + +/* + *------------------------------------------------------------------- + * + * Tls_Error -- + * + * Calls callback with $fd and $msg - so the callback can decide + * what to do with errors. + * + * Results: + * ok - let SSL handle it + * + * Side effects: + * The err field of the currently operative State is set + * to a string describing the SSL negotiation failure reason + *------------------------------------------------------------------- + */ +void +Tls_Error(State *statePtr, char *msg) +{ + Tcl_Obj *cmdPtr; + + if (msg && *msg) { + Tcl_SetErrorCode( statePtr->interp, "SSL", msg, (char *)NULL); + } else { + msg = Tcl_GetStringFromObj(Tcl_GetObjResult(statePtr->interp), NULL); + } + statePtr->err = msg; + + if (statePtr->callback == (Tcl_Obj*)NULL) { + char buf[BUFSIZ]; + sprintf(buf, "SSL channel \"%s\": error: %s", + Tcl_GetChannelName(statePtr->self), msg); + Tcl_SetResult( statePtr->interp, buf, TCL_VOLATILE); + Tcl_BackgroundError( statePtr->interp); + return; + } + cmdPtr = Tcl_DuplicateObj(statePtr->callback); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( "error", -1)); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( Tcl_GetChannelName(statePtr->self), -1) ); + + Tcl_ListObjAppendElement( statePtr->interp, cmdPtr, + Tcl_NewStringObj( msg, -1) ); + + Tcl_Preserve( (ClientData) statePtr->interp); + Tcl_Preserve( (ClientData) statePtr); + + Tcl_IncrRefCount( cmdPtr); + if (Tcl_GlobalEvalObj(statePtr->interp, cmdPtr) != TCL_OK) { + Tcl_BackgroundError( statePtr->interp); + } + Tcl_DecrRefCount( cmdPtr); + + Tcl_Release( (ClientData) statePtr); + Tcl_Release( (ClientData) statePtr->interp); +} + +/* + *------------------------------------------------------------------- + * + * PasswordCallback -- + * + * Called when a password is needed to unpack RSA and PEM keys + * Evals the tcl proc: tls::password and returns the result as + * the password + *------------------------------------------------------------------- + */ +#ifdef PRE_OPENSSL_0_9_4 +/* + * No way to handle user-data therefore no way without a global + * variable to access the Tcl interpreter. +*/ +static int +PasswordCallback(char *buf, int size, int verify) +{ + return -1; +} +#else +static int +PasswordCallback(char *buf, int size, int verify, void *udata) +{ + Tcl_Interp *interp = (Tcl_Interp*)udata; + + if (Tcl_Eval(interp, "tls::password") == TCL_OK) { + char *ret = Tcl_GetStringResult(interp); + strncpy(buf, ret, size); + return strlen(ret); + } else { + return -1; + } +} +#endif + +/* + *------------------------------------------------------------------- + * + * CiphersObjCmd -- list available ciphers + * + * This procedure is invoked to process the "tls::ciphers" command + * to list available ciphers, based upon protocol selected. + * + * Results: + * A standard Tcl result list. + * + * Side effects: + * constructs and destroys SSL context (CTX) + * + *------------------------------------------------------------------- + */ +static int +CiphersObjCmd(clientData, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; +{ + static char *protocols[] = { + "ssl2", + "ssl3", + "tls1", + NULL + }; + enum protocol { + TLS_SSL2, + TLS_SSL3, + TLS_TLS1, + TLS_NONE + }; + Tcl_Obj *objPtr; + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + STACK_OF(SSL_CIPHER) *sk; + char *cp, buf[BUFSIZ]; + int index, verbose = 0; + + if (objc < 2 || objc > 3) { + Tcl_WrongNumArgs(interp, 1, objv, "protocol ?verbose?"); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj( interp, objv[1], protocols, "protocol", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (objc > 2 && Tcl_GetBooleanFromObj( interp, objv[2], + &verbose) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum protocol)index) { + case TLS_SSL2: +#if defined(NO_SSL2) + Tcl_AppendResult(interp, "protocol not supported", NULL); + return TCL_ERROR; +#else + ctx = SSL_CTX_new(SSLv2_method()); break; +#endif + case TLS_SSL3: +#if defined(NO_SSL3) + Tcl_AppendResult(interp, "protocol not supported", NULL); + return TCL_ERROR; +#else + ctx = SSL_CTX_new(SSLv3_method()); break; +#endif + case TLS_TLS1: +#if defined(NO_TLS1) + Tcl_AppendResult(interp, "protocol not supported", NULL); + return TCL_ERROR; +#else + ctx = SSL_CTX_new(TLSv1_method()); break; +#endif + } + if (ctx == NULL) { + Tcl_AppendResult(interp, REASON(), + (char *) NULL); + return TCL_ERROR; + } + ssl = SSL_new(ctx); + if (ssl == NULL) { + Tcl_AppendResult(interp, REASON(), + (char *) NULL); + SSL_CTX_free(ctx); + return TCL_ERROR; + } + objPtr = Tcl_NewListObj( 0, NULL); + + if (!verbose) { + for (index = 0; ; index++) { + cp = (char*)SSL_get_cipher_list( ssl, index); + if (cp == NULL) break; + Tcl_ListObjAppendElement( interp, objPtr, + Tcl_NewStringObj( cp, -1) ); + } + } else { + sk = SSL_get_ciphers(ssl); + + for (index = 0; index < sk_SSL_CIPHER_num(sk); index++) { + register int i; + SSL_CIPHER_description( sk_SSL_CIPHER_value( sk, index), + buf, sizeof(buf)); + for (i = strlen(buf) - 1; i ; i--) { + if (buf[i] == ' ' || buf[i] == '\n' || + buf[i] == '\r' || buf[i] == '\t') { + buf[i] = '\0'; + } else { + break; + } + } + Tcl_ListObjAppendElement( interp, objPtr, + Tcl_NewStringObj( buf, -1) ); + } + } + SSL_free(ssl); + SSL_CTX_free(ctx); + + Tcl_SetObjResult( interp, objPtr); + return TCL_OK; +} + +/* + *------------------------------------------------------------------- + * + * HandshakeObjCmd -- + * + * This command is used to verify whether the handshake is complete + * or not. + * + * Results: + * A standard Tcl result. 1 means handshake complete, 0 means pending. + * + * Side effects: + * May force SSL negotiation to take place. + * + *------------------------------------------------------------------- + */ + +static int +HandshakeObjCmd(clientData, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; +{ + Tcl_Channel chan; /* The channel to set a mode on. */ + State *statePtr; /* client state for ssl socket */ + int ret = 1; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "channel"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL); + if (chan == (Tcl_Channel) NULL) { + return TCL_ERROR; + } + if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { + Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan), + "\": not a TLS channel", NULL); + return TCL_ERROR; + } + statePtr = (State *)Tcl_GetChannelInstanceData( chan); + + if (!SSL_is_init_finished(statePtr->ssl)) { + int err; + ret = Tls_WaitForConnect(statePtr, &err); + if (ret < 0) { + char *errStr = statePtr->err; + Tcl_ResetResult(interp); + Tcl_SetErrno(err); + + if (!errStr || *errStr == 0) + errStr = Tcl_PosixError(interp); + + Tcl_AppendResult(interp, "handshake failed: ", errStr, (char*)NULL); + return TCL_ERROR; + } + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(ret)); + return TCL_OK; +} + +/* + *------------------------------------------------------------------- + * + * ImportObjCmd -- + * + * This procedure is invoked to process the "ssl" command + * + * The ssl command pushes SSL over a (newly connected) tcp socket + * + * Results: + * A standard Tcl result. + * + * Side effects: + * May modify the behavior of an IO channel. + * + *------------------------------------------------------------------- + */ + +static int +ImportObjCmd(clientData, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; +{ + Tcl_Channel chan; /* The channel to set a mode on. */ + BIO *bio; + State *statePtr; /* client state for ssl socket */ + SSL_CTX *ctx = NULL; + Tcl_Obj *script = NULL; + int idx; + int flags = TLS_TCL_INIT; + int server = 0; /* is connection incoming or outgoing? */ + char *key = NULL; + char *cert = NULL; + char *ciphers = NULL; + char *CAfile = NULL; + char *CAdir = NULL; + char *model = NULL; +#if defined(NO_SSL2) + int ssl2 = 0; +#else + int ssl2 = 1; +#endif +#if defined(NO_SSL3) + int ssl3 = 0; +#else + int ssl3 = 1; +#endif +#if defined(NO_SSL2) && defined(NO_SSL3) + int tls1 = 1; +#else + int tls1 = 0; +#endif + int proto = 0; + int verify = 0, require = 0, request = 1; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "channel ?options?"); + return TCL_ERROR; + } + + chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL); + if (chan == (Tcl_Channel) NULL) { + return TCL_ERROR; + } + + for (idx = 2; idx < objc; idx++) { + char *opt = Tcl_GetStringFromObj(objv[idx], NULL); + + if (opt[0] != '-') + break; + + OPTSTR( "-cafile", CAfile); + OPTSTR( "-cadir", CAdir); + OPTSTR( "-certfile", cert); + OPTSTR( "-cipher", ciphers); + OPTOBJ( "-command", script); + OPTSTR( "-keyfile", key); + OPTSTR( "-model", model); + OPTBOOL( "-require", require); + OPTBOOL( "-request", request); + OPTBOOL( "-server", server); + + OPTBOOL( "-ssl2", ssl2); + OPTBOOL( "-ssl3", ssl3); + OPTBOOL( "-tls1", tls1); + + OPTBAD( "option", "-cafile, -cadir, -certfile, -cipher, -command, -keyfile, -model, -require, -request, -ssl2, -ssl3, -server, or -tls1"); + + return TCL_ERROR; + } + if (request) verify |= SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_PEER; + if (request && require) verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + if (verify == 0) verify = SSL_VERIFY_NONE; + + proto |= (ssl2 ? TLS_PROTO_SSL2 : 0); + proto |= (ssl3 ? TLS_PROTO_SSL3 : 0); + proto |= (tls1 ? TLS_PROTO_TLS1 : 0); + + if (model != NULL) { + int mode; + /* Get the "model" context */ + chan = Tcl_GetChannel( interp, model, &mode); + if (chan == (Tcl_Channel)0) { + return TCL_ERROR; + } + if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { + Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan), + "\": not a TLS channel", NULL); + return TCL_ERROR; + } + statePtr = (State *)Tcl_GetChannelInstanceData( chan); + ctx = statePtr->ctx; + } else { + if ((ctx = CTX_Init( interp, proto, key, cert, CAdir, CAfile, ciphers)) + == (SSL_CTX*)0) { + return TCL_ERROR; + } + } + + /* new SSL state */ + statePtr = (State *) Tcl_Alloc((unsigned) sizeof(State)); + statePtr->self = (Tcl_Channel)NULL; + statePtr->timer = (Tcl_TimerToken)NULL; + + statePtr->flags = flags; + statePtr->watchMask = 0; + statePtr->mode = 0; + + statePtr->interp = interp; + statePtr->callback = (Tcl_Obj *)0; + + statePtr->vflags = verify; + statePtr->ssl = (SSL*)0; + statePtr->ctx = ctx; + statePtr->bio = (BIO*)0; + statePtr->p_bio = (BIO*)0; + + statePtr->err = ""; + + Tcl_SetChannelOption(interp, chan, "-translation", "binary"); + Tcl_SetChannelOption(interp, chan, "-buffering", "none"); + +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 2 + statePtr->parent = chan; + statePtr->self = Tcl_ReplaceChannel( interp, + Tls_ChannelType(), (ClientData) statePtr, + (TCL_READABLE | TCL_WRITABLE), statePtr->parent); +#else + statePtr->self = chan; + Tcl_StackChannel( interp, Tls_ChannelType(), (ClientData) statePtr, + (TCL_READABLE | TCL_WRITABLE), chan); +#endif + if (statePtr->self == (Tcl_Channel) NULL) { + Tcl_EventuallyFree( (ClientData)statePtr, Tls_Free); + return TCL_ERROR; + } + + /* allocate script */ + if (script) { + char * tmp = Tcl_GetStringFromObj(script, NULL); + if (tmp && *tmp) { + statePtr->callback = Tcl_DuplicateObj(script); + Tcl_IncrRefCount( statePtr->callback); + } + } + /* This is only needed because of a bug in OpenSSL, where the + * ssl->verify_callback is not referenced!!! (Must be done + * *before* SSL_new() is called! + */ + SSL_CTX_set_verify(statePtr->ctx, verify, VerifyCallback); + + /* + * SSL Initialization + */ + + statePtr->ssl = SSL_new(statePtr->ctx); + if (!statePtr->ssl) { + /* SSL library error */ + Tcl_AppendResult(interp, + "couldn't construct ssl session: ", REASON(), + (char *) NULL); + Tcl_EventuallyFree( (ClientData)statePtr, Tls_Free); + return TCL_ERROR; + } + + /* + * SSL Callbacks + */ + + SSL_set_app_data(statePtr->ssl, (VOID *)statePtr); /* point back to us */ + + /* + * The following is broken - we need is to set the + * verify_mode, but the library ignores the verify_callback!!! + */ + /*SSL_set_verify(statePtr->ssl, verify, VerifyCallback);*/ + + SSL_CTX_set_info_callback( statePtr->ctx, InfoCallback); + + /* Create Tcl_Channel BIO Handler */ + statePtr->p_bio = bio = BIO_new_tcl( statePtr, BIO_CLOSE); + statePtr->bio = BIO_new(BIO_f_ssl()); + + if (server) { + statePtr->flags |= TLS_TCL_SERVER; + SSL_set_accept_state(statePtr->ssl); + } else { + SSL_set_connect_state(statePtr->ssl); + } + SSL_set_bio(statePtr->ssl, bio, bio); + BIO_set_ssl(statePtr->bio, statePtr->ssl, BIO_CLOSE); + + /* + * End of SSL Init + */ + Tcl_SetResult(interp, Tcl_GetChannelName(statePtr->self), TCL_VOLATILE); + return TCL_OK; +} + +/* + *------------------------------------------------------------------- + * + * CTX_Init -- construct a SSL_CTX instance + * + * Results: + * A valid SSL_CTX instance or NULL. + * + * Side effects: + * constructs SSL context (CTX) + * + *------------------------------------------------------------------- + */ + +static SSL_CTX * +CTX_Init(interp, proto, key, cert, CAdir, CAfile, ciphers) + Tcl_Interp *interp; + int proto; + char *key; + char *cert; + char *CAdir; + char *CAfile; + char *ciphers; +{ + SSL_CTX *ctx = NULL; + Tcl_DString ds; + Tcl_DString ds1; + int off = 0; + + /* create SSL context */ +#if !defined(NO_SSL2) && !defined(NO_SSL3) + if (ENABLED(proto, TLS_PROTO_SSL2) && + ENABLED(proto, TLS_PROTO_SSL3)) { + ctx = SSL_CTX_new(SSLv23_method()); + } else +#endif + if (ENABLED(proto, TLS_PROTO_SSL2)) { +#if defined(NO_SSL2) + Tcl_AppendResult(interp, "protocol not supported", NULL); + return (SSL_CTX *)0; +#else + ctx = SSL_CTX_new(SSLv2_method()); +#endif + } else if (ENABLED(proto, TLS_PROTO_TLS1)) { + ctx = SSL_CTX_new(TLSv1_method()); + } else if (ENABLED(proto, TLS_PROTO_SSL3)) { +#if defined(NO_SSL3) + Tcl_AppendResult(interp, "protocol not supported", NULL); + return (SSL_CTX *)0; +#else + ctx = SSL_CTX_new(SSLv3_method()); +#endif + } else { + Tcl_AppendResult(interp, "no valid protocol selected", NULL); + return (SSL_CTX *)0; + } + off |= (ENABLED(proto, TLS_PROTO_TLS1) ? 0 : SSL_OP_NO_TLSv1); + off |= (ENABLED(proto, TLS_PROTO_SSL2) ? 0 : SSL_OP_NO_SSLv2); + off |= (ENABLED(proto, TLS_PROTO_SSL3) ? 0 : SSL_OP_NO_SSLv3); + + SSL_CTX_set_app_data( ctx, (VOID*)interp); /* remember the interpreter */ + SSL_CTX_set_options( ctx, SSL_OP_ALL); /* all SSL bug workarounds */ + SSL_CTX_set_options( ctx, off); /* all SSL bug workarounds */ + SSL_CTX_sess_set_cache_size( ctx, 128); + + if (ciphers != NULL) + SSL_CTX_set_cipher_list(ctx, ciphers); + + /* set some callbacks */ + SSL_CTX_set_default_passwd_cb(ctx, PasswordCallback); + SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)interp); + +#ifndef NO_DH + { + DH* dh = get_dh512(); + SSL_CTX_set_tmp_dh(ctx, dh); + DH_free(dh); + } +#endif + + /* set our certificate */ + if (cert != NULL) { + Tcl_DStringInit(&ds); + + if (SSL_CTX_use_certificate_file(ctx, F2N( cert, &ds), + SSL_FILETYPE_PEM) <= 0) { + Tcl_DStringFree(&ds); + Tcl_AppendResult(interp, + "unable to set certificate file ", cert, ": ", + REASON(), (char *) NULL); + SSL_CTX_free(ctx); + return (SSL_CTX *)0; + } + + /* get the private key associated with this certificate */ + if (key == NULL) key=cert; + + if (SSL_CTX_use_PrivateKey_file(ctx, F2N( key, &ds), + SSL_FILETYPE_PEM) <= 0) { + Tcl_DStringFree(&ds); + Tcl_AppendResult(interp, + "unable to set public key file ", key, " ", + REASON(), (char *) NULL); + SSL_CTX_free(ctx); + return (SSL_CTX *)0; + } + Tcl_DStringFree(&ds); + /* Now we know that a key and cert have been set against + * the SSL context */ + if (!SSL_CTX_check_private_key(ctx)) { + Tcl_AppendResult(interp, + "private key does not match the certificate public key", + (char *) NULL); + SSL_CTX_free(ctx); + return (SSL_CTX *)0; + } + } else { + cert = (char*)X509_get_default_cert_file(); + + if (SSL_CTX_use_certificate_file(ctx, cert, + SSL_FILETYPE_PEM) <= 0) { +#if 0 + Tcl_DStringFree(&ds); + Tcl_AppendResult(interp, + "unable to use default certificate file ", cert, ": ", + REASON(), (char *) NULL); + SSL_CTX_free(ctx); + return (SSL_CTX *)0; +#endif + } + } + + Tcl_DStringInit(&ds); + Tcl_DStringInit(&ds1); + if (!SSL_CTX_load_verify_locations(ctx, F2N(CAfile, &ds), F2N(CAdir, &ds1)) || + !SSL_CTX_set_default_verify_paths(ctx)) { +#if 0 + Tcl_DStringFree(&ds); + Tcl_DStringFree(&ds1); + /* Don't currently care if this fails */ + Tcl_AppendResult(interp, "SSL default verify paths: ", + REASON(), (char *) NULL); + SSL_CTX_free(ctx); + return (SSL_CTX *)0; +#endif + } + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file( F2N(CAfile, &ds) )); + + Tcl_DStringFree(&ds); + Tcl_DStringFree(&ds1); + return ctx; +} + +/* + *------------------------------------------------------------------- + * + * StatusObjCmd -- return certificate for connected peer. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *------------------------------------------------------------------- + */ +static int +StatusObjCmd(clientData, interp, objc, objv) + ClientData clientData; /* Not used. */ + Tcl_Interp *interp; + int objc; + Tcl_Obj *CONST objv[]; +{ + State *statePtr; + X509 *peer; + Tcl_Obj *objPtr; + Tcl_Channel chan; + char *channelName, *ciphers; + int mode; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "channel"); + return TCL_ERROR; + } + channelName = Tcl_GetStringFromObj(objv[1], NULL); + + chan = Tcl_GetChannel( interp, channelName, &mode); + if (chan == (Tcl_Channel)0) { + return TCL_ERROR; + } + if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { + Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan), + "\": not a TLS channel", NULL); + return TCL_ERROR; + } + statePtr = (State *)Tcl_GetChannelInstanceData( chan); + peer = SSL_get_peer_certificate(statePtr->ssl); + if (peer) + objPtr = Tls_NewX509Obj( interp, peer); + else + objPtr = Tcl_NewListObj( 0, NULL); + + ciphers = (char*)SSL_get_cipher(statePtr->ssl); + if (ciphers != NULL && strcmp(ciphers, "(NONE)")!=0) { + Tcl_ListObjAppendElement( interp, objPtr, + Tcl_NewStringObj( "cipher", -1) ); + Tcl_ListObjAppendElement( interp, objPtr, + Tcl_NewStringObj( SSL_get_cipher(statePtr->ssl), -1) ); + } + Tcl_SetObjResult( interp, objPtr); + return TCL_OK; +} + +/* + *------------------------------------------------------------------- + * + * Tls_Free -- + * + * This procedure cleans up when a SSL socket based channel + * is closed and its reference count falls below 1 + * + * Results: + * none + * + * Side effects: + * Frees all the state + * + *------------------------------------------------------------------- + */ +void +Tls_Free( char *blockPtr ) +{ + State *statePtr = (State *)blockPtr; + + /* we're assuming here that we're single-threaded */ + if (statePtr->ssl) { + SSL_shutdown(statePtr->ssl); + SSL_free(statePtr->ssl); + } + if (statePtr->callback) + Tcl_DecrRefCount(statePtr->callback); + + if (statePtr->timer != (Tcl_TimerToken)NULL) + Tcl_DeleteTimerHandler (statePtr->timer); + + Tcl_Free((char *)statePtr); +} + +/* + *------------------------------------------------------------------- + * + * Tls_Init -- + * + * This is a package initialization procedure, which is called + * by Tcl when this package is to be added to an interpreter. + * + * Results: Ssl configured and loaded + * + * Side effects: + * create the ssl command, initialise ssl context + * + *------------------------------------------------------------------- + */ + +int +Tls_Init(Tcl_Interp *interp) /* Interpreter in which the package is + * to be made available. */ +{ +#if TCL_MAJOR_VERSION >= 8 && TCL_MINOR_VERSION >= 2 + if (!Tcl_InitStubs(interp, TCL_VERSION, 0)) { + return TCL_ERROR; + } +#endif + SSL_load_error_strings(); + ERR_load_crypto_strings(); + SSL_library_init(); + + Tcl_CreateObjCommand(interp, "tls::ciphers", CiphersObjCmd , (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateObjCommand(interp, "tls::handshake", HandshakeObjCmd , (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateObjCommand(interp, "tls::import", ImportObjCmd , (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateObjCommand(interp, "tls::status", StatusObjCmd , (ClientData) 0, + (Tcl_CmdDeleteProc *) NULL); + + return Tcl_PkgProvide(interp, PACKAGE, VERSION); +} + + +/* + *------------------------------------------------------* + * + * Tls_SafeInit -- + * + * ------------------------------------------------* + * Standard procedure required by 'load'. + * Initializes this extension for a safe interpreter. + * ------------------------------------------------* + * + * Sideeffects: + * As of 'Tls_Init' + * + * Result: + * A standard Tcl error code. + * + *------------------------------------------------------* + */ + +int +Tls_SafeInit (Tcl_Interp* interp) +{ + return Tls_Init (interp); +} ADDED tls.h Index: tls.h ================================================================== --- /dev/null +++ tls.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 1997-1999 Matt Newman + * + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tls.h,v 1.1.1.1 2000/01/19 22:10:58 aborr 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 + * + * Addition credit is due for Andreas Kupries (a.kupries@westend.com), for + * providing the Tcl_ReplaceChannel mechanism and working closely with me + * to enhance it to support full fileevent semantics. + * + * Also work done by the follow people provided the impetus to do this "right":- + * tclSSL (Colin McCormack, Shared Technology) + * SSLtcl (Peter Antman) + * + */ +#ifndef _TLS_H +#define _TLS_H + +#include /* Internal definitions for Tcl. */ + +#ifdef TCL_STORAGE_CLASS +# undef TCL_STORAGE_CLASS +#endif +#ifdef BUILD_tls +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# define TCL_STORAGE_CLASS DLLIMPORT +#endif + +/* + * Forward declarations + */ + +EXTERN int Tls_Init _ANSI_ARGS_ ((Tcl_Interp *)); +EXTERN int Tls_SafeInit _ANSI_ARGS_ ((Tcl_Interp *)); + +#endif /* _TLS_H */ ADDED tls.htm Index: tls.htm ================================================================== --- /dev/null +++ tls.htm @@ -0,0 +1,257 @@ + + + + + + + +TLS (SSL) Tcl Commands + + + + +
+
NAME
+
tls - binding to OpenSSL + toolkit.
+
+
+
SYNOPSIS
+
+
package require tls ?1.3?
+
 
+
tls::init ?options?
+
tls::socket ?options? host port
+
tls::socket ?-server command? + ?options? port
+
tls::handshake channel
+
tls::status channel
+
tls::import channel ?options?
+
tls::ciphers protocol ?verbose?
+
+
+
COMMANDS
+
CONFIGURATION OPTIONS
+
HTTPS EXAMPLE
+
SPECIAL CONSIDERATIONS
+
SEE ALSO
+
+ +
+ +

NAME

+ +

tls - binding to OpenSSL +toolkit.

+ +

SYNOPSIS

+ +

package require tls ?1.3?
+
+tls::init ?options?
+
tls::socket ?options? host +port
+tls::socket ?-server command? ?options? port
+
tls::status channel
+
tls::handshake channel
+
+tls::import channel ?options?
+tls::ciphers +protocol ?verbose?

+ +

DESCRIPTION

+ +

This extension provides a generic binding to OpenSSL, utilizing the Trf +Channel Stacking patch for Tcl 8.[01] and the new Tcl_StackChannel +API for Tcl 8.2 and higher. The sockets behave exactly the same +as channels created using Tcl's built-in socket +command with additional options for controlling the SSL session.

+ +

COMMANDS

+ +

Typically one would use the tls::socket command +which provides compatibility with the native Tcl socket +command. In such cases tls::import should not be +used directly.

+ +
+
tls::init ?options?
+
This routine sets the default options used by tls::socket + and is optional. If you call tls::import + directly this routine has no effect. Any of the options + that tls::socket accepts can be set + using this command, though you should limit your options + to only TLS related ones.
+
 
+
tls::socket ?options? + host port
+
tls::socket ?-server command? ?options? port
+
This is a helper function that utilizes the underlying + commands (tls::import). It behaves + exactly the same as the native Tcl socket + command except that the options can include any of the + applicable tls:import + options.
+
 
+
tls::handshake channel
+
Forces handshake to take place, and returns 0 if + handshake is still in progress (non-blocking), or 1 if + the handshake was successful. If the handshake failed + this routine will throw an error.
+
 
+
tls::status channel
+
Returns the current security status of a SSL channel. The + result is a list of key value pairs describing the + connected peer. If the result is an empty list then the + SSL handshake has not yet completed.
+
+ +
+
+
issuer dn
+
The distinguished name (DN) of the certificate + issuer.
+
subject dn
+
The distinguished name (DN) of the certificate + subject.
+
notBefore date
+
The begin date for the validity of the certificate.
+
notAfter date
+
The expiry date for the certificate.
+
serial n
+
The serial number of the certificate.
+
cipher cipher
+
The current cipher in use between the client and + server channels.
+
+
+ +
+
tls::import channel + ?options?
+
SSL-enable a regular Tcl channel - it need not be a + socket, but must provide bi-directional flow. Also + setting session parameters for SSL handshake.
+
+ +
+
+
-cafile filename
+
Provide the CA file.
+
-cadir dir
+
Provide the directory containing the CA certificates.
+
-certfile filename
+
Provide the certificate to use.
+
-cipher string
+
Provide the cipher suites to use. Syntax is as per + OpenSSL.
+
-command callback
+
This callback is invoked to pass errors, tracing + information and to allow Tcl scripts to perform + additional verification of the certificate, which can + override the default validation in OpenSSL.
+
-keyfile filename
+
Provide the private key file. (default: + value of -certfile)
+
-model channel
+
This will force this channel to share the same SSL_CTX + structure as the specified channel, and + therefore share callbacks etc.
+
-request bool
+
Request a certificate from peer during SSL handshake. + (default: true)
+
-require bool
+
Require a valid certificate from peer during SSL + handshake. If this is set to true then -request + must also be set to true. (default: false)
+
-server bool
+
Handshake as server if true, else handshake as + client.(default: false) [Not + available to tls::socket]
+
-ssl2 bool
+
Enable use of SSL v2. (default: true + unless -DNO_PATENTS was specified in build)
+
-ssl3 bool
+
Enable use of SSL v3. (default: true)
+
-tls1 bool
+
Enable use of TLS v1. (default: false)
+
+
+ +
+
tls::ciphers + protocol ?verbose?
+
Returns list of supported ciphers based on the protocol + you supply, which must be one of ssl2, ssl3, or tls1. + If verbose is specified as true then a verbose, + semi-human readable list is returned providing additional + information on the nature of the cipher support. In each + case the result is a Tcl list.
+
+ +

CONFIGURATION OPTIONS

+ +

In addition to the options listed above you can set the tls::debug +flag to a non-zero value to see the output from the default +command callback (tls::callback) which shows the +progression of the SSL handshake. Setting this value to greated +than 1 will cause the default verify method in tls::callback +to always accept the certificate, even if it is invalid.

+ +

In a real-world deployment you should substitute your own +callback in place of tls::callback, via the -command +option to tls::socket or tls::import.

+ +

When the TLS layer needs to obtain a password, typically for a +certificate, the software will invoke a Tcl command called tls::password, +which should return a string which represents the password to be +used. A default implementation is provided, which simply returns +"secret" - you should redefine this procedure +after issuing the package require tls.

+ +

HTTPS EXAMPLE

+ +

This example requires a patch to the http +module that ships with Tcl - this patch has been submitted for +inclusion in Tcl 8.2.1, but is also provided in the tls directory +if needed. A sample server.pem is provided with the TLS release, +courtesy of the OpenSSL project.

+ +
package require http
+package require tls
+
+http::register https 443 [list ::tls::socket -require 1 -cafile ./server.pem]
+
+set tok [http::geturl https://developer.netscape.com/]
+
+ +

SPECIAL CONSIDERATIONS

+ +

The capabilities of this package can vary enormously based +upon how your OpenSSL library was configured and built. At the +most macro-level OpenSSL supports a "no patents" build, +which disables RSA, IDEA, RC(2,4,5) and SSL2 - if your OpenSSL is +configured this way then you will need to build TLS with the +-DNO_PATENTS option - and the resultant module will function +correctly and also support ADH certificate-less encryption, +however you will be unable to utilize this to speak to normal Web +Servers, which typically require RSA support. Please see http://www.openssl.org/ for +more information on the whole issue of patents and US export +restrictions.

+ +

SEE ALSO

+ +

socket, fileevent, OpenSSL

+ +
+ +
+Copyright © 1999 Matt Newman.
+ + ADDED tls.tcl Index: tls.tcl ================================================================== --- /dev/null +++ tls.tcl @@ -0,0 +1,197 @@ +# +# Copyright (C) 1997-1999 Matt Newman +# +# $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tls.tcl,v 1.1.1.1 2000/01/19 22:10:58 aborr Exp $ +# +namespace eval tls { + variable logcmd tclLog + variable debug 0 + + # Default flags passed to tls::import + variable defaults {} + + # Maps UID to Server Socket + variable srvmap + variable srvuid 0 +} +# +# Backwards compatibility, also used to set the default +# context options +# +proc tls::init {args} { + variable defaults + + set defaults $args +} +# +# Helper function - behaves exactly as the native socket command. +# +proc tls::socket {args} { + set idx [lsearch $args -server] + if {$idx != -1} { + set server 1 + set callback [lindex $args [expr {$idx+1}]] + set args [lreplace $args $idx [expr {$idx+1}]] + + set usage "wrong # args: should be \"tls::socket -server command ?options? port\"" + set options "-cadir, -cafile, -certfile, -cipher, -keyfile, -myaddr, -request, -require, -ssl2, -ssl3, or -tls1" + } else { + set server 0 + + set usage "wrong # args: should be \"tls::socket ?options? host port\"" + set options "-async, -cadir, -cafile, -certfile, -cipher, -keyfile, -myaddr, -myport, -request, -require, -ssl2, -ssl3, or -tls1" + } + set argc [llength $args] + set sopts {} + set iopts [concat [list -server $server] ${tls::defaults}] ;# Import options + + for {set idx 0} {$idx < $argc} {incr idx} { + set arg [lindex $args $idx] + switch -glob -- $server,$arg { + 0,-myport - + *,-myaddr {lappend sopts $arg [lindex $args [incr idx]]} + 0,-async {lappend sopts $arg} + *,-cadir - + *,-cafile - + *,-certfile - + *,-keyfile - + *,-command - + *,-request - + *,-require - + *,-ssl2 - + *,-ssl3 - + *,-tls1 {lappend iopts $arg [lindex $args [incr idx]]} + -* {return -code error "bad option \"$arg\": must be one of $options"} + default {break} + } + } + if {$server} { + if {($idx + 1) != $argc} { + return -code error $usage + } + set uid [incr ::tls::srvuid] + + set port [lindex $args [expr {$argc-1}]] + lappend sopts $port + set sopts [linsert $sopts 0 -server [list tls::_accept $iopts $callback]] + #set sopts [linsert $sopts 0 -server [list tls::_accept $uid $callback]] + } else { + if {($idx + 2) != $argc} { + return -code error $usage + } + set host [lindex $args [expr {$argc-2}]] + set port [lindex $args [expr {$argc-1}]] + lappend sopts $host $port + } + # + # Create TCP/IP socket + # + set chan [eval ::socket $sopts] + if {!$server && [catch { + # + # Push SSL layer onto socket + # + eval [list tls::import] $chan $iopts + } err]} { + set info ${::errorInfo} + catch {close $chan} + return -code error -errorinfo $info $err + } + return $chan +} +proc tls::_accept { iopts callback chan ipaddr port } { + log 2 [list tls::_accept $iopts $callback $chan $ipaddr $port] + + set chan [eval [list tls::import $chan] $iopts] + + lappend callback $chan $ipaddr $port + uplevel #0 $callback +} +# +# Sample callback for hooking: - +# +# error +# info +# password +# verify +# +proc tls::callback {option args} { + variable debug + + #log 2 [concat $option $args] + + switch -- $option { + "error" { + foreach {chan msg} $args break + + log 0 "TLS/$chan: error: $msg" + } + "verify" { + # poor man's lassign + foreach {chan depth cert rc err} $args break + + array set c $cert + + if {$rc != "1"} { + log 1 "TLS/$chan: verify/$depth: Bad Cert: $err (rc = $rc)" + } else { + log 2 "TLS/$chan: verify/$depth: $c(subject)" + } + if {$debug > 0} { + return 1; # FORCE OK + } else { + return $rc + } + } + "info" { + # poor man's lassign + foreach {chan major minor state msg} $args break + + if {$msg != ""} { + append state ": $msg" + } + # For tracing + upvar #0 tls::$chan cb + set cb($major) $minor + + log 2 "TLS/$chan: $major/$minor: $state" + } + default { + return -code error "bad option \"$option\": must be one of error, info, or verify" + } + };#sw +} + +proc tls::xhandshake {chan} { + upvar #0 tls::$chan cb + + if {[info exists cb(handshake)] && \ + $cb(handshake) == "done"} { + return 1 + } + while {1} { + vwait tls::${chan}(handshake) + if {![info exists cb(handshake)]} { + return 0 + } + if {$cb(handshake) == "done"} { + return 1 + } + } +} +proc tls::password {} { + log 0 "TLS/Password: did you forget to set your passwd!" + # Return the worlds best kept secret password. + return "secret" +} +proc tls::log {level msg} { + variable debug + variable logcmd + + if {$level > $debug || $logcmd == ""} { + return + } + set cmd $logcmd + lappend cmd $msg + uplevel #0 $cmd +} ADDED tlsBIO.c Index: tlsBIO.c ================================================================== --- /dev/null +++ tlsBIO.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 1997-1999 Matt Newman + * + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsBIO.c,v 1.1.1.1 2000/01/19 22:10:58 aborr Exp $ + * + * Provides BIO layer to interface openssl to Tcl. + */ + +#include "tlsInt.h" + +/* + * Forward declarations + */ + +static int BioWrite _ANSI_ARGS_ ((BIO *h, char *buf, int num)); +static int BioRead _ANSI_ARGS_ ((BIO *h, char *buf, int num)); +static int BioPuts _ANSI_ARGS_ ((BIO *h, char *str)); +static long BioCtrl _ANSI_ARGS_ ((BIO *h, int cmd, long arg1, char *ptr)); +static int BioNew _ANSI_ARGS_ ((BIO *h)); +static int BioFree _ANSI_ARGS_ ((BIO *h)); + + +static BIO_METHOD BioMethods = { + BIO_TYPE_TCL, "tcl", + BioWrite, + BioRead, + BioPuts, + NULL, /* BioGets */ + BioCtrl, + BioNew, + BioFree, +}; + +BIO * +BIO_new_tcl(statePtr, flags) + State *statePtr; + int flags; +{ + BIO *bio; + + bio = BIO_new(&BioMethods); + bio->ptr = (char*)statePtr; + bio->init = 1; + bio->shutdown = flags; + + return bio; +} + +BIO_METHOD * +BIO_s_tcl() +{ + return &BioMethods; +} + +static int +BioWrite (bio, buf, bufLen) + BIO *bio; + char *buf; + int bufLen; +{ + Tcl_Channel chan = Tls_GetParent((State*)bio->ptr); + int ret; + + dprintf(stderr,"\nBioWrite(0x%x, , %d) [0x%x]", bio, bufLen, chan); + + ret = Tcl_Write( chan, buf, bufLen); + + dprintf(stderr,"\n[0x%x] BioWrite(%d) -> %d [%d.%d]", chan, bufLen, ret, + Tcl_Eof( chan), Tcl_GetErrno()); + + BIO_clear_flags(bio, BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + + if (ret == 0) { + if (!Tcl_Eof( chan)) { + BIO_set_retry_write(bio); + ret = -1; + } + } + if (BIO_should_read(bio)) + BIO_set_retry_read(bio); + return ret; +} + +static int +BioRead (bio, buf, bufLen) + BIO *bio; + char *buf; + int bufLen; +{ + Tcl_Channel chan = Tls_GetParent((State*)bio->ptr); + int ret = 0; + + dprintf(stderr,"\nBioRead(0x%x, , %d) [0x%x]", bio, bufLen, chan); + + if (buf == NULL) return 0; + + ret = Tcl_Read( chan, buf, bufLen); + + dprintf(stderr,"\n[0x%x] BioRead(%d) -> %d [%d.%d]", chan, bufLen, ret, + Tcl_Eof(chan), Tcl_GetErrno()); + + BIO_clear_flags(bio, BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + + if (ret == 0) { + if (!Tcl_Eof( chan)) { + BIO_set_retry_read(bio); + ret = -1; + } + } + if (BIO_should_write(bio)) + BIO_set_retry_write(bio); + return ret; +} + +static int +BioPuts (bio, str) + BIO *bio; + char *str; +{ + return BioWrite( bio, str, strlen(str)); +} + +static long +BioCtrl (bio, cmd, num, ptr) + BIO *bio; + int cmd; + long num; + char *ptr; +{ + Tcl_Channel chan = Tls_GetParent((State*)bio->ptr); + long ret = 1; + int *ip; + + dprintf(stderr,"\nBioCtrl(0x%x, 0x%x, 0x%x, 0x%x)", bio, cmd, num, ptr); + + switch (cmd) { + case BIO_CTRL_RESET: + num = 0; + case BIO_C_FILE_SEEK: + case BIO_C_FILE_TELL: + ret = 0; + 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; + case BIO_C_GET_FD: + if (bio->init) { + ip=(int *)ptr; + if (ip != NULL) *ip=bio->num; + ret=bio->num; + } else { + ret= -1; + } + break; + case BIO_CTRL_GET_CLOSE: + ret=bio->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + bio->shutdown=(int)num; + break; + case BIO_CTRL_EOF: + dprintf(stderr, "BIO_CTRL_EOF\n"); + ret = Tcl_Eof( chan); + break; + case BIO_CTRL_PENDING: + if (Tcl_InputBuffered(chan)) + ret = 1; + else + ret = 0; + dprintf(stderr, "BIO_CTRL_PENDING(%d)\n", ret); + break; + case BIO_CTRL_WPENDING: + ret=0; + break; + case BIO_CTRL_DUP: + break; + case BIO_CTRL_FLUSH: + dprintf(stderr, "BIO_CTRL_FLUSH\n"); + if (Tcl_Flush( chan) == TCL_OK) + ret=1; + else + ret=-1; + break; + default: + ret=0; + break; + } + return(ret); +} + +static int +BioNew (bio) + BIO *bio; +{ + bio->init = 0; + bio->num = 0; + bio->ptr = NULL; + bio->flags = 0; + + return 1; +} + +static int +BioFree (bio) + BIO *bio; +{ + if (bio == NULL) + return 0; + + if (bio->shutdown) { + if (bio->init) { + /*shutdown(bio->num, 2) */ + /*closesocket(bio->num) */ + } + bio->init = 0; + bio->flags = 0; + bio->num = 0; + } + return 1; +} ADDED tlsIO.c Index: tlsIO.c ================================================================== --- /dev/null +++ tlsIO.c @@ -0,0 +1,652 @@ +/* + * Copyright (C) 1997-1999 Matt Newman + * + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.1.1.1 2000/01/19 22:10:58 aborr 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 + * + * Addition credit is due for Andreas Kupries (a.kupries@westend.com), for + * providing the Tcl_ReplaceChannel mechanism and working closely with me + * to enhance it to support full fileevent semantics. + * + * Also work done by the follow people provided the impetus to do this "right": + * tclSSL (Colin McCormack, Shared Technology) + * SSLtcl (Peter Antman) + * + */ + +#include "tlsInt.h" + +/* + * External functions + */ + +/* + * Local Defines + */ + +/* + * Forward declarations + */ + +static int BlockModeProc _ANSI_ARGS_((ClientData instanceData, int mode)); +static int CloseProc _ANSI_ARGS_ ((ClientData instanceData, Tcl_Interp *interp)); +static int InputProc _ANSI_ARGS_((ClientData instanceData, + char *buf, int bufSize, int *errorCodePtr)); +static int OutputProc _ANSI_ARGS_((ClientData instanceData, + char *buf, int toWrite, int *errorCodePtr)); +static int GetOptionProc _ANSI_ARGS_ ((ClientData instanceData, + Tcl_Interp *interp, char *optionName, Tcl_DString *dsPtr)); +static void WatchProc _ANSI_ARGS_((ClientData instanceData, int mask)); +static int GetHandleProc _ANSI_ARGS_ ((ClientData instanceData, + int direction, ClientData *handlePtr)); +static void ChannelHandler _ANSI_ARGS_ ((ClientData clientData, int mask)); +static void ChannelHandlerTimer _ANSI_ARGS_ ((ClientData clientData)); + +/* + * This structure describes the channel type structure for TCP socket + * based IO: + */ + +static Tcl_ChannelType tlsChannelType = { + "tls", /* Type name. */ + BlockModeProc, /* Set blocking/nonblocking mode.*/ + CloseProc, /* Close proc. */ + InputProc, /* Input proc. */ + OutputProc, /* Output proc. */ + NULL, /* Seek proc. */ + NULL, /* Set option proc. */ + GetOptionProc, /* Get option proc. */ + WatchProc, /* Initialize notifier. */ + GetHandleProc, /* Get file handle out of channel. */ +}; + +Tcl_ChannelType *Tls_ChannelType() +{ + return &tlsChannelType; +} + +/* + *------------------------------------------------------------------- + * + * BlockModeProc -- + * + * This procedure is invoked by the generic IO level + * to set blocking and nonblocking modes + * Results: + * 0 if successful, errno when failed. + * + * Side effects: + * Sets the device into blocking or nonblocking mode. + * + *------------------------------------------------------------------- + */ + +static int +BlockModeProc(ClientData instanceData, /* Socket state. */ + int mode) /* The mode to set. Can be one of + * TCL_MODE_BLOCKING or + * TCL_MODE_NONBLOCKING. */ +{ + State *statePtr = (State *) instanceData; + + if (mode == TCL_MODE_NONBLOCKING) { + statePtr->flags |= TLS_TCL_ASYNC; + } else { + statePtr->flags &= ~(TLS_TCL_ASYNC); + } + return Tcl_SetChannelOption(statePtr->interp, Tls_GetParent(statePtr), + "-blocking", (mode == TCL_MODE_NONBLOCKING) ? "0" : "1"); +} + +/* + *------------------------------------------------------------------- + * + * CloseProc -- + * + * This procedure is invoked by the generic IO level to perform + * channel-type-specific cleanup when a SSL socket based channel + * is closed. + * + * Note: we leave the underlying socket alone, is this right? + * + * Results: + * 0 if successful, the value of Tcl_GetErrno() if failed. + * + * Side effects: + * Closes the socket of the channel. + * + *------------------------------------------------------------------- + */ +static int +CloseProc(ClientData instanceData, /* The socket to close. */ + Tcl_Interp *interp) /* For error reporting - unused. */ +{ + State *statePtr = (State *) instanceData; +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 2 + Tcl_Channel parent = Tls_GetParent(statePtr); +#else + Tcl_Channel parent = statePtr->self; /* 'self' already refers to our parent */ +#endif + + dprintf(stderr,"\nCloseProc(0x%x)", statePtr); + /* + * Remove event handler to underlying channel, this could + * be because we are closing for real, or being "unstacked". + */ + + Tcl_DeleteChannelHandler( parent, + ChannelHandler, (ClientData) statePtr); + + if (statePtr->timer != (Tcl_TimerToken)NULL) { + Tcl_DeleteTimerHandler (statePtr->timer); + statePtr->timer = (Tcl_TimerToken)NULL; + } + + Tcl_EventuallyFree( (ClientData)statePtr, Tls_Free); + return TCL_OK; +} + +/* + *------------------------------------------------------------------- + * + * InputProc -- + * + * This procedure is invoked by the generic IO level + * to read input from a SSL socket based channel. + * + * Results: + * The number of bytes read is returned or -1 on error. An output + * argument contains the POSIX error code on error, or zero if no + * error occurred. + * + * Side effects: + * Reads input from the input device of the channel. + * + *------------------------------------------------------------------- + */ + +static int +InputProc(ClientData instanceData, /* Socket state. */ + char *buf, /* Where to store data read. */ + int bufSize, /* How much space is available + * in the buffer? */ + int *errorCodePtr) /* Where to store error code. */ +{ + State *statePtr = (State *) instanceData; + int bytesRead; /* How many bytes were read? */ + + *errorCodePtr = 0; + + dprintf(stderr,"\nBIO_read(%d)", bufSize); + + if (!SSL_is_init_finished(statePtr->ssl)) { + bytesRead = Tls_WaitForConnect(statePtr, errorCodePtr); + if (bytesRead <= 0) { + goto input; + } + } + if (statePtr->flags & TLS_TCL_INIT) { + statePtr->flags &= ~(TLS_TCL_INIT); + } + bytesRead = BIO_read(statePtr->bio, buf, bufSize); + dprintf(stderr,"\nBIO_read -> %d", bytesRead); + + if (bytesRead < 0) { + int err = SSL_get_error(statePtr->ssl, bytesRead); + + if (err == SSL_ERROR_SSL) { + Tls_Error(statePtr, SSL_ERROR(statePtr->ssl, bytesRead)); + *errorCodePtr = ECONNABORTED; + goto input; + } else if (BIO_should_retry(statePtr->bio)) { + dprintf(stderr,"RE! "); + *errorCodePtr = EAGAIN; + goto input; + } + if (Tcl_GetErrno() == ECONNRESET) { + /* Soft EOF */ + bytesRead = 0; + goto input; + } else { + *errorCodePtr = Tcl_GetErrno(); + goto input; + } + } +input: + dprintf(stderr, "\nInput(%d) -> %d [%d]", bufSize, bytesRead, *errorCodePtr); + return bytesRead; +} + +/* + *------------------------------------------------------------------- + * + * OutputProc -- + * + * This procedure is invoked by the generic IO level + * to write output to a SSL socket based channel. + * + * Results: + * The number of bytes written is returned. An output argument is + * set to a POSIX error code if an error occurred, or zero. + * + * Side effects: + * Writes output on the output device of the channel. + * + *------------------------------------------------------------------- + */ + +static int +OutputProc(ClientData instanceData, /* Socket state. */ + char *buf, /* The data buffer. */ + int toWrite, /* How many bytes to write? */ + int *errorCodePtr) /* Where to store error code. */ +{ + State *statePtr = (State *) instanceData; + int written, err; + + *errorCodePtr = 0; + + dprintf(stderr,"\nBIO_write(%d)", toWrite); + + if (!SSL_is_init_finished(statePtr->ssl)) { + written = Tls_WaitForConnect(statePtr, errorCodePtr); + if (written <= 0) { + goto output; + } + } + if (statePtr->flags & TLS_TCL_INIT) { + statePtr->flags &= ~(TLS_TCL_INIT); + } + if (toWrite == 0) { + dprintf(stderr, "zero-write\n"); + BIO_flush(statePtr->bio); + written = 0; + goto output; + } else { + written = BIO_write(statePtr->bio, buf, toWrite); + dprintf(stderr,"\nBIO_write(%d) -> [%d]", toWrite, written); + } + if (written < 0 || written == 0) { + switch ((err = SSL_get_error(statePtr->ssl, written))) { + case SSL_ERROR_NONE: + if (written <= 0) { + written = 0; + goto output; + } + break; + case SSL_ERROR_WANT_WRITE: + dprintf(stderr,"write W BLOCK\n"); + break; + case SSL_ERROR_WANT_READ: + dprintf(stderr,"write R BLOCK\n"); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + dprintf(stderr,"write X BLOCK\n"); + break; + case SSL_ERROR_ZERO_RETURN: + dprintf(stderr,"closed\n"); + written = 0; + goto output; + case SSL_ERROR_SYSCALL: + *errorCodePtr = Tcl_GetErrno(); + dprintf(stderr,"[%d] syscall errr: %d\n", written, Tcl_GetErrno()); + written = -1; + goto output; + case SSL_ERROR_SSL: + Tls_Error(statePtr, SSL_ERROR(statePtr->ssl, written)); + *errorCodePtr = ECONNABORTED; + written = -1; + goto output; + default: + dprintf(stderr,"unknown err: %d\n", err); + } + } +output: + dprintf(stderr, "\nOutput(%d) -> %d", toWrite, written); + return written; +} + +/* + *------------------------------------------------------------------- + * + * GetOptionProc -- + * + * Computes an option value for a SSL socket based channel, or a + * list of all options and their values. + * + * Note: This code is based on code contributed by John Haxby. + * + * Results: + * A standard Tcl result. The value of the specified option or a + * list of all options and their values is returned in the + * supplied DString. + * + * Side effects: + * None. + * + *------------------------------------------------------------------- + */ +static int +GetOptionProc(ClientData instanceData, /* Socket state. */ + Tcl_Interp *interp, /* For errors - can be NULL. */ + char *optionName, /* Name of the option to + * retrieve the value for, or + * NULL to get all options and + * their values. */ + Tcl_DString *dsPtr) /* Where to store the computed value + * initialized by caller. */ +{ + State *statePtr = (State *) instanceData; + size_t len = 0; + + if (optionName != (char *) NULL) { + len = strlen(optionName); + } +#if 0 + if ((len == 0) || + ((len > 1) && (optionName[1] == 'c') && + (strncmp(optionName, "-cipher", len) == 0))) { + if (len == 0) { + Tcl_DStringAppendElement(dsPtr, "-cipher"); + } + Tcl_DStringAppendElement(dsPtr, SSL_get_cipher(statePtr->ssl)); + if (len) { + return TCL_OK; + } + } +#endif + return TCL_OK; +} + +/* + *------------------------------------------------------------------- + * + * WatchProc -- + * + * Initialize the notifier to watch Tcl_Files from this channel. + * + * Results: + * None. + * + * Side effects: + * Sets up the notifier so that a future event on the channel + * will be seen by Tcl. + * + *------------------------------------------------------------------- + */ + +static void +WatchProc(ClientData instanceData, /* The socket state. */ + int mask) /* Events of interest; an OR-ed + * combination of TCL_READABLE, + * TCL_WRITABLE and TCL_EXCEPTION. */ +{ + State *statePtr = (State *) instanceData; + + if (mask == statePtr->watchMask) + return; + + if (statePtr->watchMask) { + /* + * Remove event handler to underlying channel, this could + * be because we are closing for real, or being "unstacked". + */ + Tcl_DeleteChannelHandler( Tls_GetParent(statePtr), ChannelHandler, (ClientData) statePtr); + } + statePtr->watchMask = mask; + if (statePtr->watchMask) { + /* Setup active monitor for events on underlying Channel */ + Tcl_CreateChannelHandler( Tls_GetParent(statePtr), statePtr->watchMask, + ChannelHandler, (ClientData) statePtr); + } +} + +/* + *------------------------------------------------------------------- + * + * GetHandleProc -- + * + * Called from Tcl_GetChannelFile to retrieve o/s file handler + * from the SSL socket based channel. + * + * Results: + * The appropriate Tcl_File or NULL if not present. + * + * Side effects: + * None. + * + *------------------------------------------------------------------- + */ +static int +GetHandleProc(ClientData instanceData, /* The socket state. */ + int direction, /* Which Tcl_File to retrieve? */ + ClientData *handlePtr) /* Where to store the handle. */ +{ + State *statePtr = (State *) instanceData; + + return Tcl_GetChannelHandle (Tls_GetParent(statePtr), direction, handlePtr); +} + +/* + *------------------------------------------------------* + * + * ChannelHandler -- + * + * ------------------------------------------------* + * Handler called by Tcl as a result of + * Tcl_CreateChannelHandler - to inform us of activity + * on the underlying channel. + * ------------------------------------------------* + * + * Sideeffects: + * May generate subsequent calls to + * Tcl_NotifyChannel. + * + * Result: + * None. + * + *------------------------------------------------------* + */ + +static void +ChannelHandler (clientData, mask) +ClientData clientData; +int mask; +{ + State *statePtr = (State *) clientData; + +dprintf(stderr, "HANDLER(0x%x)\n", mask); + Tcl_Preserve( (ClientData)statePtr); + + if (mask & TCL_READABLE) { + BIO_set_flags(statePtr->p_bio, BIO_FLAGS_READ); + } else { + BIO_clear_flags(statePtr->p_bio, BIO_FLAGS_READ); + } + + if (mask & TCL_WRITABLE) { + BIO_set_flags(statePtr->p_bio, BIO_FLAGS_WRITE); + } else { + BIO_clear_flags(statePtr->p_bio, BIO_FLAGS_WRITE); + } + + mask = 0; + if (BIO_wpending(statePtr->bio)) { + mask |= TCL_WRITABLE; + } + if (BIO_pending(statePtr->bio)) { + mask |= TCL_READABLE; + } + Tcl_NotifyChannel(statePtr->self, mask); + + if (statePtr->timer != (Tcl_TimerToken)NULL) { + Tcl_DeleteTimerHandler(statePtr->timer); + statePtr->timer = (Tcl_TimerToken)NULL; + } + if ((mask & TCL_READABLE) && Tcl_InputBuffered (statePtr->self) > 0) { + /* + * Data is waiting, flush it out in short time + */ + statePtr->timer = Tcl_CreateTimerHandler (TLS_TCL_DELAY, ChannelHandlerTimer, + (ClientData) statePtr); + } + Tcl_Release( (ClientData)statePtr); +} + +/* + *------------------------------------------------------* + * + * ChannelHandlerTimer -- + * + * ------------------------------------------------* + * Called by the notifier (-> timer) to flush out + * information waiting in channel buffers. + * ------------------------------------------------* + * + * Sideeffects: + * As of 'ChannelHandler'. + * + * Result: + * None. + * + *------------------------------------------------------* + */ + +static void +ChannelHandlerTimer (clientData) +ClientData clientData; /* Transformation to query */ +{ + State *statePtr = (State *) clientData; + int mask = 0; + + statePtr->timer = (Tcl_TimerToken) NULL; + + if (BIO_wpending(statePtr->bio)) { + mask |= TCL_WRITABLE; + } + if (BIO_pending(statePtr->bio)) { + mask |= TCL_READABLE; + } + Tcl_NotifyChannel(statePtr->self, mask); +} + +/* + *------------------------------------------------------* + * + * Tls_WaitForConnect -- + * + * Sideeffects: + * Issues SSL_accept or SSL_connect + * + * Result: + * None. + * + *------------------------------------------------------* + */ +int +Tls_WaitForConnect( statePtr, errorCodePtr) + State *statePtr; + int *errorCodePtr; /* Where to store error code. */ +{ + int err; + + dprintf(stderr,"\nWaitForConnect(0x%x)", statePtr); + + for (;;) { + /* Not initialized yet! */ + if (statePtr->flags & TLS_TCL_SERVER) { + err = SSL_accept(statePtr->ssl); + } else { + err = SSL_connect(statePtr->ssl); + } + /*SSL_write(statePtr->ssl, (char*)&err, 0); HACK!!! */ + if (err > 0) + BIO_flush(statePtr->bio); + + if (err <= 0) { + int rc = SSL_get_error(statePtr->ssl, err); + + if (rc == SSL_ERROR_SSL) { + Tls_Error(statePtr, (char*)ERR_reason_error_string(ERR_get_error())); + *errorCodePtr = ECONNABORTED; + return -1; + } else if (BIO_should_retry(statePtr->bio)) { + if (statePtr->flags & TLS_TCL_ASYNC) { + dprintf(stderr,"E! "); + *errorCodePtr = EAGAIN; + return -1; + } else { + continue; + } + } else if (err == 0) { + dprintf(stderr,"CR! "); + *errorCodePtr = ECONNRESET; + return -1; + } + if (statePtr->flags & TLS_TCL_SERVER) { + err = SSL_get_verify_result(statePtr->ssl); + if (err != X509_V_OK) { + Tls_Error(statePtr, (char*)X509_verify_cert_error_string(err)); + *errorCodePtr = ECONNABORTED; + return -1; + } + } + *errorCodePtr = Tcl_GetErrno(); + dprintf(stderr,"ERR(%d, %d) ", rc, *errorCodePtr); + return -1; + } + dprintf(stderr,"R0! "); + return 1; + } +} + +Tcl_Channel +Tls_GetParent( statePtr ) + State *statePtr; +{ +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 2 + return statePtr->parent; +#else + /* The reason for the existence of this procedure is + * the fact that stacking a transform over another + * transform will leave our internal pointer unchanged, + * and thus pointing to the new transform, and not the + * Channel structure containing the saved state of this + * transform. This is the price to pay for leaving + * Tcl_Channel references intact. The only other solution + * is an extension of Tcl_ChannelType with another driver + * procedure to notify a Channel about the (un)stacking. + * + * It walks the chain of Channel structures until it + * finds the one pointing having 'ctrl' as instanceData + * and then returns the superceding channel to that. (AK) + */ + + Tcl_Channel self = statePtr->self; + Tcl_Channel next; + + while ((ClientData) statePtr != Tcl_GetChannelInstanceData (self)) { + next = Tcl_GetStackedChannel (self); + if (next == (Tcl_Channel) NULL) { + /* 09/24/1999 Unstacking bug, found by Matt Newman . + * + * We were unable to find the channel structure for this + * transformation in the chain of stacked channel. This + * means that we are currently in the process of unstacking + * it *and* there were some bytes waiting which are now + * flushed. In this situation the pointer to the channel + * itself already refers to the parent channel we have to + * write the bytes into, so we return that. + */ + return statePtr->self; + } + self = next; + } + + return Tcl_GetStackedChannel (self); +#endif +} ADDED tlsInt.h Index: tlsInt.h ================================================================== --- /dev/null +++ tlsInt.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 1997-1999 Matt Newman + * + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsInt.h,v 1.1.1.1 2000/01/19 22:10:58 aborr 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 + * + * Addition credit is due for Andreas Kupries (a.kupries@westend.com), for + * providing the Tcl_ReplaceChannel mechanism and working closely with me + * to enhance it to support full fileevent semantics. + * + * Also work done by the follow people provided the impetus to do this "right":- + * tclSSL (Colin McCormack, Shared Technology) + * SSLtcl (Peter Antman) + * + */ +#ifndef _TSLINT_H +#define _TLSINT_H + +#include "tls.h" +#include + +#ifdef NO_PATENTS +#define NO_IDEA +#define NO_RC2 +#define NO_RC4 +#define NO_RC5 +#define NO_RSA +#define NO_SSL2 +#endif + +#include + +#ifdef TCL_STORAGE_CLASS +# undef TCL_STORAGE_CLASS +#endif +#ifdef BUILD_tls +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# define TCL_STORAGE_CLASS DLLIMPORT +#endif + +#ifndef ECONNABORTED +#define ECONNABORTED 130 /* Software caused connection abort */ +#endif +#ifndef ECONNRESET +#define ECONNRESET 131 /* Connection reset by peer */ +#endif + +#ifdef DEBUG +#define dprintf fprintf +#else +#define dprintf if (0) fprintf +#endif + +#define SSL_ERROR(ssl,err) \ + ((char*)ERR_reason_error_string(SSL_get_error((ssl),(err)))) +/* + * OpenSSL BIO Routines + */ +#define BIO_TYPE_TCL (19|0x0400) + +/* + * Defines for State.flags + */ +#define TLS_TCL_ASYNC (1<<0) /* non-blocking mode */ +#define TLS_TCL_SERVER (1<<1) /* Server-Side */ +#define TLS_TCL_INIT (1<<2) /* Initializing connection */ +#define TLS_TCL_DEBUG (1<<3) /* Show debug tracing */ + +#define TLS_TCL_DELAY (5) + +/* + * This structure describes the per-instance state + * of an ssl channel. + * + * The SSL processing context is maintained here, in the ClientData + */ +typedef struct State { + Tcl_Channel self; /* this socket channel */ +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 2 + Tcl_Channel parent; /* underlying channel */ +#endif + Tcl_TimerToken timer; + + int flags; /* currently only CHANNEL_ASYNC */ + int watchMask; /* current WatchProc mask */ + int mode; /* current mode of parent channel */ + + Tcl_Interp *interp; /* interpreter in which this resides */ + Tcl_Obj *callback; /* script called for tracing, verifying and errors */ + + int vflags; /* verify flags */ + SSL *ssl; /* Struct for SSL processing */ + SSL_CTX *ctx; /* SSL Context */ + BIO *bio; /* Struct for SSL processing */ + BIO *p_bio; /* Parent BIO (that is layered on Tcl_Channel) */ + + char *err; +} State; + +/* + * Forward declarations + */ + +EXTERN Tcl_ChannelType *Tls_ChannelType _ANSI_ARGS_((void)); +EXTERN Tcl_Channel Tls_GetParent _ANSI_ARGS_((State *statePtr)); + +EXTERN Tcl_Obj* Tls_NewX509Obj _ANSI_ARGS_ (( Tcl_Interp *interp, X509 *cert)); +EXTERN void Tls_Error _ANSI_ARGS_ ((State *statePtr, char *msg)); +EXTERN void Tls_Free _ANSI_ARGS_ ((char *blockPtr)); +EXTERN int Tls_WaitForConnect _ANSI_ARGS_(( State *statePtr, + int *errorCodePtr)); + +EXTERN BIO_METHOD * BIO_s_tcl _ANSI_ARGS_((void)); +EXTERN BIO * BIO_new_tcl _ANSI_ARGS_((State* statePtr, int flags)); + +#endif /* _TLSINT_H */ ADDED tlsX509.c Index: tlsX509.c ================================================================== --- /dev/null +++ tlsX509.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 1997-1999 Sensus Consulting Ltd. + * Matt Newman + * + * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsX509.c,v 1.1.1.1 2000/01/19 22:10:58 aborr Exp $ + */ +#include "tlsInt.h" + +/* + * ASN1_UTCTIME_tostr -- + */ +static char * +ASN1_UTCTIME_tostr(ASN1_UTCTIME *tm) +{ + static char bp[128]; + char *v; + int gmt=0; + static char *mon[12]={ + "Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec"}; + int i; + int y=0,M=0,d=0,h=0,m=0,s=0; + + i=tm->length; + v=(char *)tm->data; + + if (i < 10) goto err; + if (v[i-1] == 'Z') gmt=1; + for (i=0; i<10; i++) + if ((v[i] > '9') || (v[i] < '0')) goto err; + y= (v[0]-'0')*10+(v[1]-'0'); + if (y < 70) y+=100; + M= (v[2]-'0')*10+(v[3]-'0'); + if ((M > 12) || (M < 1)) goto err; + d= (v[4]-'0')*10+(v[5]-'0'); + h= (v[6]-'0')*10+(v[7]-'0'); + m= (v[8]-'0')*10+(v[9]-'0'); + if ( (v[10] >= '0') && (v[10] <= '9') && + (v[11] >= '0') && (v[11] <= '9')) + s= (v[10]-'0')*10+(v[11]-'0'); + + sprintf(bp,"%s %2d %02d:%02d:%02d %d%s", + mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":""); + return bp; + err: + return "Bad time value"; +} + +/* + *------------------------------------------------------* + * + * Tls_NewX509Obj -- + * + * ------------------------------------------------* + * Converts a X509 certificate into a Tcl_Obj + * ------------------------------------------------* + * + * Sideeffects: + * None + * + * Result: + * A Tcl List Object representing the provided + * X509 certificate. + * + *------------------------------------------------------* + */ + +Tcl_Obj* +Tls_NewX509Obj( interp, cert) + Tcl_Interp *interp; + X509 *cert; +{ + Tcl_Obj *certPtr = Tcl_NewListObj( 0, NULL); + int serial; + char subject[BUFSIZ]; + char issuer[BUFSIZ]; + char notBefore[BUFSIZ]; + char notAfter[BUFSIZ]; + + serial = ASN1_INTEGER_get(X509_get_serialNumber(cert)); + X509_NAME_oneline(X509_get_subject_name(cert),subject,sizeof(subject)); + X509_NAME_oneline(X509_get_issuer_name(cert),issuer,sizeof(issuer)); + + strcpy( notBefore, ASN1_UTCTIME_tostr( X509_get_notBefore(cert) )); + strcpy( notAfter, ASN1_UTCTIME_tostr( X509_get_notAfter(cert) )); + + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( "subject", -1) ); + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( subject, -1) ); + + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( "issuer", -1) ); + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( issuer, -1) ); + + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( "notBefore", -1) ); + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( notBefore, -1) ); + + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( "notAfter", -1) ); + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( notAfter, -1) ); + + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewStringObj( "serial", -1) ); + Tcl_ListObjAppendElement( interp, certPtr, + Tcl_NewIntObj( serial) ); + + return certPtr; +}