diff -Nacr stunnel-3.8.orig/Makefile stunnel-3.8/Makefile
*** stunnel-3.8.orig/Makefile	Wed Dec 31 19:00:00 1969
--- stunnel-3.8/Makefile	Fri Jul 21 13:53:47 2000
***************
*** 0 ****
--- 1,110 ----
+ # Generated automatically from Makefile.in by configure.
+ #####################################################
+ # Makefile for stunnel by Michal Trojnara 1998-2000 #
+ #####################################################
+ 
+ prefix=/usr/local
+ exec_prefix=${prefix}
+ sbindir=${exec_prefix}/sbin
+ libdir=${exec_prefix}/lib
+ man8dir=${prefix}/man/man8
+ piddir=${prefix}/var/klpstunnel
+ ssldir=/usr/local/ssl
+ certdir=$(ssldir)/certs
+ 
+ VERSION=stunnel-3.8
+ RANDOM_OPT=
+ CC=gcc
+ INSTALL=./install-sh -c
+ CFLAGS=-g -O2 -Wall -DNO_IDEA -I/usr/local/ssl/include -I/usr/local/krb5/include  -DVERSION=\"3.8\" -DHAVE_OPENSSL=1 -Dssldir=\"/usr/local/ssl\" -DHAVE_KRB5=1 -DHOST=\"sparc-sun-solaris2.7\" -DHAVE_LIBNSL=1 -DHAVE_LIBSOCKET=1 -DHAVE_LIBPTHREAD=1 -DHAVE_LIBWRAP=1 -DHAVE_DEV_PTMX=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_TCPD_H=1 -DHAVE_PTHREAD_H=1 -DHAVE_STROPTS_H=1 -DHAVE_GETOPT=1 -DHAVE_SNPRINTF=1 -DHAVE_VSNPRINTF=1  -Dcertdir=\"$(certdir)\" -Dlibdir=\"$(libdir)\" -Dpiddir=\"$(piddir)\"
+ LIBS=-lwrap -lpthread -lsocket -lnsl  -L/usr/local/ssl/lib -lssl -lcrypto -L/usr/local/krb5/lib -lgssapi_krb5 -lkrb5 -lcom_err /usr/local/krb5/lib/libcrypto.a -lresolv
+ OBJS=stunnel.o ssl.o protocol.o sthreads.o pty.o log.o  truerand.o
+ DESTFILES=$(sbindir)/klpstunnel $(libdir)/stunnel.so $(man8dir)/stunnel.8 $(certdir)/klpstunnel.pem
+ 
+ # standard external rules
+ 
+ all: klpstunnel stunnel.so klpstunnel.pem
+ 
+ install: all installdirs $(DESTFILES)
+ 
+ uninstall:
+ 	rm -f $(DESTFILES)
+ 
+ install-strip:
+ 	$(MAKE) INSTALL='$(INSTALL) -s' install
+ 
+ clean:
+ 	rm -f klpstunnel stunnel.so $(OBJS) core config.log
+ 
+ distclean: clean
+ 	rm -f stunnel.8 config.cache config.status Makefile
+ 
+ mostlyclean: distclean
+ 
+ maintainer-clean: distclean
+ 
+ dist: distclean ../dist/$(VERSION).exe
+ 	cp -rp . ../dist/$(VERSION)
+ 	tar -cf - -C ../dist $(VERSION) | gzip > ../dist/$(VERSION).tar.gz
+ 	rm -rf ../dist/$(VERSION)
+ 	gpg --yes --armor --detach-sign ../dist/$(VERSION).tar.gz
+ 
+ installdirs: mkinstalldirs
+ 	./mkinstalldirs $(sbindir) $(libdir) $(man8dir) $(certdir) $(piddir)
+ 	chmod a=rwx,+t $(piddir)
+ 
+ # non-standard external rules
+ 
+ stunnel.html: man2html.pl stunnel.8
+ 	./man2html.pl < stunnel.8 > stunnel.html
+ 
+ cert:
+ 	rm -f klpstunnel.pem
+ 	$(MAKE) klpstunnel.pem
+ 
+ # internal rules
+ 
+ klpstunnel: $(OBJS)
+ 	$(CC) $(LDFLAGS) -o klpstunnel $(OBJS) $(LIBS)
+ 
+ stunnel.so: Makefile env.c
+ 	$(CC) -fPIC -shared $(LDFLAGS) -o stunnel.so env.c $(LIBS) || \
+ 	touch stunnel.so
+ 	@test -s klpstunnel.pem || echo
+ 	@test -s klpstunnel.pem || echo "You can ignore this error"
+ 	@test -s klpstunnel.pem || echo "Shared library won't work on your system"
+ 	@test -s klpstunnel.pem || echo
+ 
+ Makefile: configure Makefile.in
+ 	./configure
+ 	$(MAKE) clean
+ 
+ configure: configure.in
+ 	autoconf
+ 
+ $(OBJS): Makefile common.h
+ 
+ klpstunnel.pem: stunnel.cnf
+ 	$(ssldir)/bin/openssl req -new -x509 -days 365 -nodes \
+ 		-config stunnel.cnf -out klpstunnel.pem -keyout klpstunnel.pem
+ 	$(ssldir)/bin/openssl gendh $(RANDOM_OPT) 512 >> klpstunnel.pem
+ 	$(ssldir)/bin/openssl x509 -subject -dates -fingerprint -noout \
+ 		-in klpstunnel.pem
+ 
+ $(sbindir)/klpstunnel: klpstunnel
+ 	$(INSTALL) -m 711 klpstunnel $(sbindir)
+ 
+ $(libdir)/stunnel.so: stunnel.so
+ 	test -s stunnel.so && $(INSTALL) -m 755 stunnel.so $(libdir)
+ 
+ $(man8dir)/stunnel.8: stunnel.8
+ 	$(INSTALL) -m 644 stunnel.8 $(man8dir)
+ 
+ $(certdir)/klpstunnel.pem: klpstunnel.pem
+ 	$(INSTALL) -m 600 klpstunnel.pem $(certdir)
+ 
+ ../dist/$(VERSION).exe: stunnel.exe
+ 	./mkinstalldirs ../dist
+ 	cp -f stunnel.exe ../dist/$(VERSION).exe
+ 	gpg --yes --armor --detach-sign ../dist/$(VERSION).exe
+ 
diff -Nacr stunnel-3.8.orig/Makefile.in stunnel-3.8/Makefile.in
*** stunnel-3.8.orig/Makefile.in	Tue Feb 22 07:08:16 2000
--- stunnel-3.8/Makefile.in	Fri Jul 21 13:53:48 2000
***************
*** 7,13 ****
  sbindir=@sbindir@
  libdir=@libdir@
  man8dir=@mandir@/man8
! piddir=@localstatedir@/stunnel
  ssldir=@ssldir@
  certdir=$(ssldir)/certs
  @SET_MAKE@
--- 7,13 ----
  sbindir=@sbindir@
  libdir=@libdir@
  man8dir=@mandir@/man8
! piddir=@localstatedir@
  ssldir=@ssldir@
  certdir=$(ssldir)/certs
  @SET_MAKE@
***************
*** 17,28 ****
  INSTALL=@INSTALL@
  CFLAGS=@CFLAGS@ @DEFS@ -Dcertdir=\"$(certdir)\" -Dlibdir=\"$(libdir)\" -Dpiddir=\"$(piddir)\"
  LIBS=@LIBS@
! OBJS=stunnel.o ssl.o protocol.o sthreads.o pty.o log.o
! DESTFILES=$(sbindir)/stunnel $(libdir)/stunnel.so $(man8dir)/stunnel.8 $(certdir)/stunnel.pem
  
  # standard external rules
  
! all: stunnel stunnel.so stunnel.pem
  
  install: all installdirs $(DESTFILES)
  
--- 17,28 ----
  INSTALL=@INSTALL@
  CFLAGS=@CFLAGS@ @DEFS@ -Dcertdir=\"$(certdir)\" -Dlibdir=\"$(libdir)\" -Dpiddir=\"$(piddir)\"
  LIBS=@LIBS@
! OBJS=stunnel.o ssl.o protocol.o sthreads.o pty.o log.o  truerand.o nonce.o
! DESTFILES=$(sbindir)/klpstunnel $(libdir)/stunnel.so $(man8dir)/stunnel.8 $(certdir)/klpstunnel.pem
  
  # standard external rules
  
! all: klpstunnel stunnel.so klpstunnel.pem
  
  install: all installdirs $(DESTFILES)
  
***************
*** 33,39 ****
  	$(MAKE) INSTALL='$(INSTALL) -s' install
  
  clean:
! 	rm -f stunnel stunnel.so $(OBJS) core config.log
  
  distclean: clean
  	rm -f stunnel.8 config.cache config.status Makefile
--- 33,39 ----
  	$(MAKE) INSTALL='$(INSTALL) -s' install
  
  clean:
! 	rm -f klpstunnel stunnel.so $(OBJS) core config.log
  
  distclean: clean
  	rm -f stunnel.8 config.cache config.status Makefile
***************
*** 58,78 ****
  	./man2html.pl < stunnel.8 > stunnel.html
  
  cert:
! 	rm -f stunnel.pem
! 	$(MAKE) stunnel.pem
  
  # internal rules
  
! stunnel: $(OBJS)
! 	$(CC) $(LDFLAGS) -o stunnel $(OBJS) $(LIBS)
  
  stunnel.so: Makefile env.c
  	$(CC) -fPIC -shared $(LDFLAGS) -o stunnel.so env.c $(LIBS) || \
  	touch stunnel.so
! 	@test -s stunnel.pem || echo
! 	@test -s stunnel.pem || echo "You can ignore this error"
! 	@test -s stunnel.pem || echo "Shared library won't work on your system"
! 	@test -s stunnel.pem || echo
  
  Makefile: configure Makefile.in
  	./configure
--- 58,78 ----
  	./man2html.pl < stunnel.8 > stunnel.html
  
  cert:
! 	rm -f klpstunnel.pem
! 	$(MAKE) klpstunnel.pem
  
  # internal rules
  
! klpstunnel: $(OBJS)
! 	$(CC) $(LDFLAGS) -o klpstunnel $(OBJS) $(LIBS)
  
  stunnel.so: Makefile env.c
  	$(CC) -fPIC -shared $(LDFLAGS) -o stunnel.so env.c $(LIBS) || \
  	touch stunnel.so
! 	@test -s klpstunnel.pem || echo
! 	@test -s klpstunnel.pem || echo "You can ignore this error"
! 	@test -s klpstunnel.pem || echo "Shared library won't work on your system"
! 	@test -s klpstunnel.pem || echo
  
  Makefile: configure Makefile.in
  	./configure
***************
*** 83,97 ****
  
  $(OBJS): Makefile common.h
  
! stunnel.pem: stunnel.cnf
  	$(ssldir)/bin/openssl req -new -x509 -days 365 -nodes \
! 		-config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
! 	$(ssldir)/bin/openssl gendh $(RANDOM_OPT) 512 >> stunnel.pem
  	$(ssldir)/bin/openssl x509 -subject -dates -fingerprint -noout \
! 		-in stunnel.pem
  
! $(sbindir)/stunnel: stunnel
! 	$(INSTALL) -m 711 stunnel $(sbindir)
  
  $(libdir)/stunnel.so: stunnel.so
  	test -s stunnel.so && $(INSTALL) -m 755 stunnel.so $(libdir)
--- 83,98 ----
  
  $(OBJS): Makefile common.h
  
! klpstunnel.pem: stunnel.cnf
  	$(ssldir)/bin/openssl req -new -x509 -days 365 -nodes \
! 		-config stunnel.cnf -out klpstunnel.pem -keyout klpstunnel.pem
! 	$(ssldir)/bin/openssl gendh $(RANDOM_OPT) 512 >> klpstunnel.pem
  	$(ssldir)/bin/openssl x509 -subject -dates -fingerprint -noout \
! 		-in klpstunnel.pem
! 	chmod 600 klpstunnel.pem
  
! $(sbindir)/klpstunnel: klpstunnel
! 	$(INSTALL) -m 711 klpstunnel $(sbindir)
  
  $(libdir)/stunnel.so: stunnel.so
  	test -s stunnel.so && $(INSTALL) -m 755 stunnel.so $(libdir)
***************
*** 99,106 ****
  $(man8dir)/stunnel.8: stunnel.8
  	$(INSTALL) -m 644 stunnel.8 $(man8dir)
  
! $(certdir)/stunnel.pem: stunnel.pem
! 	$(INSTALL) -m 600 stunnel.pem $(certdir)
  
  ../dist/$(VERSION).exe: stunnel.exe
  	./mkinstalldirs ../dist
--- 100,107 ----
  $(man8dir)/stunnel.8: stunnel.8
  	$(INSTALL) -m 644 stunnel.8 $(man8dir)
  
! $(certdir)/klpstunnel.pem: klpstunnel.pem
! 	$(INSTALL) -m 600 klpstunnel.pem $(certdir)
  
  ../dist/$(VERSION).exe: stunnel.exe
  	./mkinstalldirs ../dist
diff -Nacr stunnel-3.8.orig/common.h stunnel-3.8/common.h
*** stunnel-3.8.orig/common.h	Thu Feb 24 06:35:00 2000
--- stunnel-3.8/common.h	Fri Jul 21 13:53:48 2000
***************
*** 18,23 ****
--- 18,26 ----
   *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
+ /* I/O buffer size */
+ #define BUFFSIZE		8192
+ 
  #define OPT_CLIENT      0x01
  #define OPT_CERT        0x02
  #define OPT_DAEMON      0x04
***************
*** 26,31 ****
--- 29,35 ----
  #define OPT_REMOTE      0x20
  #define OPT_TRANSPARENT 0x40
  #define OPT_PTY         0x80
+ #define	OPT_KHTTPS		0x100
  
  #ifdef USE_WIN32
  
***************
*** 97,105 ****
--- 101,122 ----
  #endif
  
  #include <syslog.h>
+ #include <sys/types.h>   /* u_short, u_long */
+ 
+ #ifdef HAVE_OPENSSL
+ #include <openssl/lhash.h>
+ #include <openssl/ssl.h>
+ #include <openssl/err.h>
+ #else
+ #include <lhash.h>
+ #include <ssl.h>
+ #include <err.h>
+ #endif
  
  #endif /* USE_WIN32 */
  
+ #include "nonce.h"
+ 
  #if defined(sun) && !defined(__svr4__)  /* ie. SunOS 4 */
  #define atexit(a) on_exit((a), NULL)
  extern int sys_nerr;
***************
*** 148,158 ****
      int verify_use_only_my;
      int debug_level;
      long session_timeout;
!     char *cipher_list;
      char *username;
      char *protocol;
      char *setuid_user;
      char *setgid_group;
  } server_options;
  
  /* Prototypes for stunnel.c */
--- 165,179 ----
      int verify_use_only_my;
      int debug_level;
      long session_timeout;
!     char *loc_cipher_list;
!     char *rem_cipher_list;
      char *username;
      char *protocol;
      char *setuid_user;
      char *setgid_group;
+ 	char *kssl_list;
+ 	char *https_proxy;
+ 	Cookie *cookie;
  } server_options;
  
  /* Prototypes for stunnel.c */
***************
*** 163,169 ****
  
  /* Prototypes for ssl.c */
  
- void context_init();
  void context_free();
  void client(int);
  
--- 184,189 ----
***************
*** 190,195 ****
--- 210,264 ----
  int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname, int ttynamelen);
  void pty_release(char *ttyname);
  void pty_make_controlling_tty(int *ttyfd, char *ttyname);
+ 
+ 
+ /*	20000314 VRS - new kssl/https proxy modes; normal = original stunnel 
+ */
+ #define	KM_UNDEF		-1
+ #define	KM_NORMAL		0
+ #define	KM_KSSL_MITM	1
+ #define	KM_LOCAL_HTTPS	2
+ #define	KM_REMOTE_HTTPS	3
+ #define KM_FAULT		86
+ 
+ int 	check_CONNECT(const char *str, char **hp);
+ 
+ /* VRS 20000314 -- new transfer() function for kssl and https proxy
+ */
+ #define	CHAN_CLOSE	0
+ #define	CHAN_OPEN	1
+ #define	CHAN_ALT	2
+ 
+ typedef struct	Channel_	{
+ 	int 	open;
+ 	int 	bytes;
+ 	SSL_CTX	*ctx;
+ 	SSL 	*ssl;
+ 	int 	fd;
+ 	int 	ptr;
+ 	char	buff[BUFFSIZE];
+ 	}	Channel;
+ 
+ int 	rd_local (Channel *local, Channel *remote, int *km_mode);
+ int 	rd_remote(Channel *local, Channel *remote, int *km_mode);
+ int 	wr_local (Channel *local, Channel *remote, int km_mode);
+ int 	wr_remote(Channel *local, Channel *remote, int km_mode);
+ int 	got_cookie(Channel *local, Channel *remote, int km_mode);
+ int 	init_ch(Channel *channel);
+ int 	new_ssl_ch(Channel *chan, char *host);
+ int 	connect_ssl_ch(Channel *chan, char *hp);
+ int 	accept_ssl_ch(Channel *chan);
+ void	shutdown_ssl_ch(Channel *local, Channel *remote);
+ int 	wr_ssl_ch(Channel *from, Channel *to, int *numptr);
+ int 	rd_ssl_ch(Channel *chan, int *numptr);
+ int 	create_remote_sock(Channel *remote, char *hostport);
+ int 	fake_CONNECT(Channel *remote);
+ void	show_sock(int s);
+ 
+ #define	MAX_HP	256
+ 
+ void	name2nums(char *, u_long **, u_short *);
+ SSL_CTX *context_init(char *host);
  
  /* End of common.h */
  
diff -Nacr stunnel-3.8.orig/configure stunnel-3.8/configure
*** stunnel-3.8.orig/configure	Thu Feb 24 06:28:45 2000
--- stunnel-3.8/configure	Fri Jul 21 13:53:48 2000
***************
*** 15,20 ****
--- 15,24 ----
    --with-random=FILE      read randomness from FILE (default=/dev/urandom)"
  ac_help="$ac_help
    --with-ssl=DIR          location of installed SSL libraries/include files"
+ ac_help="$ac_help
+   --with-krb5=DIR         location of installed KRB5 libraries/include files"
+ ac_help="$ac_help
+   --without-idea          disable the idea cipher"
  
  # Initialize some variables set by options.
  # The variables have the same names as the options, with
***************
*** 552,558 ****
  fi
  
  echo $ac_n "checking host system type""... $ac_c" 1>&6
! echo "configure:556: checking host system type" >&5
  
  host_alias=$host
  case "$host_alias" in
--- 556,562 ----
  fi
  
  echo $ac_n "checking host system type""... $ac_c" 1>&6
! echo "configure:560: checking host system type" >&5
  
  host_alias=$host
  case "$host_alias" in
***************
*** 575,581 ****
  # Extract the first word of "gcc", so it can be a program name with args.
  set dummy gcc; ac_word=$2
  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
! echo "configure:579: checking for $ac_word" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 579,585 ----
  # Extract the first word of "gcc", so it can be a program name with args.
  set dummy gcc; ac_word=$2
  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
! echo "configure:583: checking for $ac_word" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 605,611 ****
    # Extract the first word of "cc", so it can be a program name with args.
  set dummy cc; ac_word=$2
  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
! echo "configure:609: checking for $ac_word" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 609,615 ----
    # Extract the first word of "cc", so it can be a program name with args.
  set dummy cc; ac_word=$2
  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
! echo "configure:613: checking for $ac_word" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 656,662 ****
        # Extract the first word of "cl", so it can be a program name with args.
  set dummy cl; ac_word=$2
  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
! echo "configure:660: checking for $ac_word" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 660,666 ----
        # Extract the first word of "cl", so it can be a program name with args.
  set dummy cl; ac_word=$2
  echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
! echo "configure:664: checking for $ac_word" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 688,694 ****
  fi
  
  echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
! echo "configure:692: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
  
  ac_ext=c
  # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
--- 692,698 ----
  fi
  
  echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
! echo "configure:696: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
  
  ac_ext=c
  # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
***************
*** 699,710 ****
  
  cat > conftest.$ac_ext << EOF
  
! #line 703 "configure"
  #include "confdefs.h"
  
  main(){return(0);}
  EOF
! if { (eval echo configure:708: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    ac_cv_prog_cc_works=yes
    # If we can't run a trivial program, we are probably using a cross compiler.
    if (./conftest; exit) 2>/dev/null; then
--- 703,714 ----
  
  cat > conftest.$ac_ext << EOF
  
! #line 707 "configure"
  #include "confdefs.h"
  
  main(){return(0);}
  EOF
! if { (eval echo configure:712: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    ac_cv_prog_cc_works=yes
    # If we can't run a trivial program, we are probably using a cross compiler.
    if (./conftest; exit) 2>/dev/null; then
***************
*** 730,741 ****
    { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
  fi
  echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
! echo "configure:734: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
  echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
  cross_compiling=$ac_cv_prog_cc_cross
  
  echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
! echo "configure:739: checking whether we are using GNU C" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 734,745 ----
    { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
  fi
  echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
! echo "configure:738: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
  echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
  cross_compiling=$ac_cv_prog_cc_cross
  
  echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
! echo "configure:743: checking whether we are using GNU C" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 744,750 ****
    yes;
  #endif
  EOF
! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:748: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
    ac_cv_prog_gcc=yes
  else
    ac_cv_prog_gcc=no
--- 748,754 ----
    yes;
  #endif
  EOF
! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:752: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
    ac_cv_prog_gcc=yes
  else
    ac_cv_prog_gcc=no
***************
*** 763,769 ****
  ac_save_CFLAGS="$CFLAGS"
  CFLAGS=
  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
! echo "configure:767: checking whether ${CC-cc} accepts -g" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 767,773 ----
  ac_save_CFLAGS="$CFLAGS"
  CFLAGS=
  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
! echo "configure:771: checking whether ${CC-cc} accepts -g" >&5
  if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 807,813 ****
  # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
  # ./install, which can be erroneously created by make from ./install.sh.
  echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
! echo "configure:811: checking for a BSD compatible install" >&5
  if test -z "$INSTALL"; then
  if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
--- 811,817 ----
  # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
  # ./install, which can be erroneously created by make from ./install.sh.
  echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
! echo "configure:815: checking for a BSD compatible install" >&5
  if test -z "$INSTALL"; then
  if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
***************
*** 860,866 ****
  test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
  
  echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
! echo "configure:864: checking whether ${MAKE-make} sets \${MAKE}" >&5
  set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
--- 864,870 ----
  test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
  
  echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
! echo "configure:868: checking whether ${MAKE-make} sets \${MAKE}" >&5
  set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
***************
*** 903,909 ****
                  
  ac_safe=`echo ""/dev/urandom"" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for "/dev/urandom"""... $ac_c" 1>&6
! echo "configure:907: checking for "/dev/urandom"" >&5
  if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 907,913 ----
                  
  ac_safe=`echo ""/dev/urandom"" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for "/dev/urandom"""... $ac_c" 1>&6
! echo "configure:911: checking for "/dev/urandom"" >&5
  if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 952,959 ****
      return 1
  }
  
  echo $ac_n "checking for SSL directory""... $ac_c" 1>&6
! echo "configure:957: checking for SSL directory" >&5
  # Check whether --with-ssl or --without-ssl was given.
  if test "${with_ssl+set}" = set; then
    withval="$with_ssl"
--- 956,975 ----
      return 1
  }
  
+ checkkrb5dir() { :
+ 	if test -f "$1/include/krb5.h"; then
+ 		cat >> confdefs.h <<\EOF
+ #define HAVE_KRB5 1
+ EOF
+ 
+ 		krb5dir="$1"
+ 		return 0
+ 	fi
+     return 1
+ }
+ 
  echo $ac_n "checking for SSL directory""... $ac_c" 1>&6
! echo "configure:973: checking for SSL directory" >&5
  # Check whether --with-ssl or --without-ssl was given.
  if test "${with_ssl+set}" = set; then
    withval="$with_ssl"
***************
*** 986,991 ****
--- 1002,1051 ----
  EOF
  
  
+ echo $ac_n "checking for KRB5 directory""... $ac_c" 1>&6
+ echo "configure:1007: checking for KRB5 directory" >&5
+ # Check whether --with-krb5 or --without-krb5 was given.
+ if test "${with_krb5+set}" = set; then
+   withval="$with_krb5"
+   
+ 		if test "$withval" != "yes"; then
+ 						checkkrb5dir "$withval"
+ 		else
+ 						for maindir in /usr/local /usr/lib /usr/pkg /opt; do
+ 				for dir in $maindir $maindir/krb5 ; do
+ 					checkkrb5dir $dir && break 2
+ 				done
+ 			done
+ 		fi
+     
+ else
+   
+         		cat >> confdefs.h <<\EOF
+ #define NO_KRB5 1
+ EOF
+ 
+ 		echo
+     
+ 
+ fi
+ 
+ if test "$krb5dir" != ""; then
+ 	echo "$ac_t""$krb5dir" 1>&6
+     
+ fi
+ 
+ echo $ac_n "checking whether you want to include the idea cipher""... $ac_c" 1>&6
+ echo "configure:1039: checking whether you want to include the idea cipher" >&5
+ # Check whether --with-idea or --without-idea was given.
+ if test "${with_idea+set}" = set; then
+   withval="$with_idea"
+   use_idea=no ; CFLAGS="$CFLAGS -DNO_IDEA"
+ else
+   use_idea=yes
+ fi
+ 
+ echo "$ac_t""$use_idea" 1>&6
+ 
  
  cat >> confdefs.h <<EOF
  #define HOST "$host"
***************
*** 993,999 ****
  
  
  echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
! echo "configure:997: checking for gethostbyname in -lnsl" >&5
  ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
--- 1053,1059 ----
  
  
  echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
! echo "configure:1057: checking for gethostbyname in -lnsl" >&5
  ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
***************
*** 1001,1007 ****
    ac_save_LIBS="$LIBS"
  LIBS="-lnsl  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1005 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
--- 1061,1067 ----
    ac_save_LIBS="$LIBS"
  LIBS="-lnsl  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1065 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
***************
*** 1012,1018 ****
  gethostbyname()
  ; return 0; }
  EOF
! if { (eval echo configure:1016: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
--- 1072,1078 ----
  gethostbyname()
  ; return 0; }
  EOF
! if { (eval echo configure:1076: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
***************
*** 1040,1046 ****
  fi
  
  echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
! echo "configure:1044: checking for socket in -lsocket" >&5
  ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
--- 1100,1106 ----
  fi
  
  echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
! echo "configure:1104: checking for socket in -lsocket" >&5
  ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
***************
*** 1048,1054 ****
    ac_save_LIBS="$LIBS"
  LIBS="-lsocket  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1052 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
--- 1108,1114 ----
    ac_save_LIBS="$LIBS"
  LIBS="-lsocket  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1112 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
***************
*** 1059,1065 ****
  socket()
  ; return 0; }
  EOF
! if { (eval echo configure:1063: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
--- 1119,1125 ----
  socket()
  ; return 0; }
  EOF
! if { (eval echo configure:1123: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
***************
*** 1087,1093 ****
  fi
  
  echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
! echo "configure:1091: checking for pthread_create in -lpthread" >&5
  ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
--- 1147,1153 ----
  fi
  
  echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
! echo "configure:1151: checking for pthread_create in -lpthread" >&5
  ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
***************
*** 1095,1101 ****
    ac_save_LIBS="$LIBS"
  LIBS="-lpthread  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1099 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
--- 1155,1161 ----
    ac_save_LIBS="$LIBS"
  LIBS="-lpthread  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1159 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
***************
*** 1106,1112 ****
  pthread_create()
  ; return 0; }
  EOF
! if { (eval echo configure:1110: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
--- 1166,1172 ----
  pthread_create()
  ; return 0; }
  EOF
! if { (eval echo configure:1170: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
***************
*** 1134,1140 ****
  fi
  
  echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
! echo "configure:1138: checking for pthread_create in -lc_r" >&5
  ac_lib_var=`echo c_r'_'pthread_create | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
--- 1194,1200 ----
  fi
  
  echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
! echo "configure:1198: checking for pthread_create in -lc_r" >&5
  ac_lib_var=`echo c_r'_'pthread_create | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
***************
*** 1142,1148 ****
    ac_save_LIBS="$LIBS"
  LIBS="-lc_r  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1146 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
--- 1202,1208 ----
    ac_save_LIBS="$LIBS"
  LIBS="-lc_r  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1206 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
***************
*** 1153,1159 ****
  pthread_create()
  ; return 0; }
  EOF
! if { (eval echo configure:1157: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
--- 1213,1219 ----
  pthread_create()
  ; return 0; }
  EOF
! if { (eval echo configure:1217: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
***************
*** 1181,1187 ****
  fi
  
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
! echo "configure:1185: checking for openpty in -lutil" >&5
  ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
--- 1241,1247 ----
  fi
  
  echo $ac_n "checking for openpty in -lutil""... $ac_c" 1>&6
! echo "configure:1245: checking for openpty in -lutil" >&5
  ac_lib_var=`echo util'_'openpty | sed 'y%./+-%__p_%'`
  if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
***************
*** 1189,1195 ****
    ac_save_LIBS="$LIBS"
  LIBS="-lutil  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1193 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
--- 1249,1255 ----
    ac_save_LIBS="$LIBS"
  LIBS="-lutil  $LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1253 "configure"
  #include "confdefs.h"
  /* Override any gcc2 internal prototype to avoid an error.  */
  /* We use char because int might match the return type of a gcc2
***************
*** 1200,1206 ****
  openpty()
  ; return 0; }
  EOF
! if { (eval echo configure:1204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
--- 1260,1266 ----
  openpty()
  ; return 0; }
  EOF
! if { (eval echo configure:1264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_lib_$ac_lib_var=yes"
  else
***************
*** 1229,1246 ****
  
  
  echo $ac_n "checking for hosts_access in -lwrap""... $ac_c" 1>&6
! echo "configure:1233: checking for hosts_access in -lwrap" >&5
  saved_LIBS="$LIBS"
  LIBS="-lwrap $saved_LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1237 "configure"
  #include "confdefs.h"
  int hosts_access(); int allow_severity, deny_severity;
  int main() {
  hosts_access()
  ; return 0; }
  EOF
! if { (eval echo configure:1244: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
  #define HAVE_LIBWRAP 1
--- 1289,1306 ----
  
  
  echo $ac_n "checking for hosts_access in -lwrap""... $ac_c" 1>&6
! echo "configure:1293: checking for hosts_access in -lwrap" >&5
  saved_LIBS="$LIBS"
  LIBS="-lwrap $saved_LIBS"
  cat > conftest.$ac_ext <<EOF
! #line 1297 "configure"
  #include "confdefs.h"
  int hosts_access(); int allow_severity, deny_severity;
  int main() {
  hosts_access()
  ; return 0; }
  EOF
! if { (eval echo configure:1304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
  #define HAVE_LIBWRAP 1
***************
*** 1257,1275 ****
  CFLAGS="$CFLAGS -I$ssldir/include"
  LIBS="$LIBS -L$ssldir/lib -lssl -lcrypto"
  
  echo $ac_n "checking for RSAref library""... $ac_c" 1>&6
! echo "configure:1262: checking for RSAref library" >&5
  saved_LIBS="$LIBS"
  LIBS="$saved_LIBS -lRSAglue -lrsaref"
  cat > conftest.$ac_ext <<EOF
! #line 1266 "configure"
  #include "confdefs.h"
  
  int main() {
  
  ; return 0; }
  EOF
! if { (eval echo configure:1273: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    echo "$ac_t""yes" 1>&6; 
  else
--- 1317,1341 ----
  CFLAGS="$CFLAGS -I$ssldir/include"
  LIBS="$LIBS -L$ssldir/lib -lssl -lcrypto"
  
+ if test "$krb5dir" != ""; then
+ CFLAGS="$CFLAGS -I$krb5dir/include"
+ LIBS="$LIBS -L$krb5dir/lib -lgssapi_krb5 -lkrb5 -lcom_err"
+ LIBS="$LIBS $krb5dir/lib/libcrypto.a -lresolv"
+ fi
+ 
  echo $ac_n "checking for RSAref library""... $ac_c" 1>&6
! echo "configure:1328: checking for RSAref library" >&5
  saved_LIBS="$LIBS"
  LIBS="$saved_LIBS -lRSAglue -lrsaref"
  cat > conftest.$ac_ext <<EOF
! #line 1332 "configure"
  #include "confdefs.h"
  
  int main() {
  
  ; return 0; }
  EOF
! if { (eval echo configure:1339: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    echo "$ac_t""yes" 1>&6; 
  else
***************
*** 1283,1289 ****
  
  ac_safe=`echo ""/dev/ptmx"" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for "/dev/ptmx"""... $ac_c" 1>&6
! echo "configure:1287: checking for "/dev/ptmx"" >&5
  if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 1349,1355 ----
  
  ac_safe=`echo ""/dev/ptmx"" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for "/dev/ptmx"""... $ac_c" 1>&6
! echo "configure:1353: checking for "/dev/ptmx"" >&5
  if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 1311,1317 ****
  
  ac_safe=`echo ""/dev/ptc"" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for "/dev/ptc"""... $ac_c" 1>&6
! echo "configure:1315: checking for "/dev/ptc"" >&5
  if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
--- 1377,1383 ----
  
  ac_safe=`echo ""/dev/ptc"" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for "/dev/ptc"""... $ac_c" 1>&6
! echo "configure:1381: checking for "/dev/ptc"" >&5
  if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
***************
*** 1341,1347 ****
  # AC_HEADER_STDC
  # AC_HEADER_SYS_WAIT
  echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
! echo "configure:1345: checking how to run the C preprocessor" >&5
  # On Suns, sometimes $CPP names a directory.
  if test -n "$CPP" && test -d "$CPP"; then
    CPP=
--- 1407,1413 ----
  # AC_HEADER_STDC
  # AC_HEADER_SYS_WAIT
  echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
! echo "configure:1411: checking how to run the C preprocessor" >&5
  # On Suns, sometimes $CPP names a directory.
  if test -n "$CPP" && test -d "$CPP"; then
    CPP=
***************
*** 1356,1368 ****
    # On the NeXT, cc -E runs the code through the compiler's parser,
    # not just through cpp.
    cat > conftest.$ac_ext <<EOF
! #line 1360 "configure"
  #include "confdefs.h"
  #include <assert.h>
  Syntax Error
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    :
--- 1422,1434 ----
    # On the NeXT, cc -E runs the code through the compiler's parser,
    # not just through cpp.
    cat > conftest.$ac_ext <<EOF
! #line 1426 "configure"
  #include "confdefs.h"
  #include <assert.h>
  Syntax Error
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1432: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    :
***************
*** 1373,1385 ****
    rm -rf conftest*
    CPP="${CC-cc} -E -traditional-cpp"
    cat > conftest.$ac_ext <<EOF
! #line 1377 "configure"
  #include "confdefs.h"
  #include <assert.h>
  Syntax Error
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1383: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    :
--- 1439,1451 ----
    rm -rf conftest*
    CPP="${CC-cc} -E -traditional-cpp"
    cat > conftest.$ac_ext <<EOF
! #line 1443 "configure"
  #include "confdefs.h"
  #include <assert.h>
  Syntax Error
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1449: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    :
***************
*** 1390,1402 ****
    rm -rf conftest*
    CPP="${CC-cc} -nologo -E"
    cat > conftest.$ac_ext <<EOF
! #line 1394 "configure"
  #include "confdefs.h"
  #include <assert.h>
  Syntax Error
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1400: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    :
--- 1456,1468 ----
    rm -rf conftest*
    CPP="${CC-cc} -nologo -E"
    cat > conftest.$ac_ext <<EOF
! #line 1460 "configure"
  #include "confdefs.h"
  #include <assert.h>
  Syntax Error
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1466: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    :
***************
*** 1424,1440 ****
  do
  ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
! echo "configure:1428: checking for $ac_hdr" >&5
  if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    cat > conftest.$ac_ext <<EOF
! #line 1433 "configure"
  #include "confdefs.h"
  #include <$ac_hdr>
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1438: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    rm -rf conftest*
--- 1490,1506 ----
  do
  ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
  echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
! echo "configure:1494: checking for $ac_hdr" >&5
  if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    cat > conftest.$ac_ext <<EOF
! #line 1499 "configure"
  #include "confdefs.h"
  #include <$ac_hdr>
  EOF
  ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
! { (eval echo configure:1504: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
  ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
  if test -z "$ac_err"; then
    rm -rf conftest*
***************
*** 1471,1482 ****
  for ac_func in getopt snprintf vsnprintf openpty _getpty
  do
  echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
! echo "configure:1475: checking for $ac_func" >&5
  if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    cat > conftest.$ac_ext <<EOF
! #line 1480 "configure"
  #include "confdefs.h"
  /* System header to define __stub macros and hopefully few prototypes,
      which can conflict with char $ac_func(); below.  */
--- 1537,1548 ----
  for ac_func in getopt snprintf vsnprintf openpty _getpty
  do
  echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
! echo "configure:1541: checking for $ac_func" >&5
  if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
    echo $ac_n "(cached) $ac_c" 1>&6
  else
    cat > conftest.$ac_ext <<EOF
! #line 1546 "configure"
  #include "confdefs.h"
  /* System header to define __stub macros and hopefully few prototypes,
      which can conflict with char $ac_func(); below.  */
***************
*** 1499,1505 ****
  
  ; return 0; }
  EOF
! if { (eval echo configure:1503: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_func_$ac_func=yes"
  else
--- 1565,1571 ----
  
  ; return 0; }
  EOF
! if { (eval echo configure:1569: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
    rm -rf conftest*
    eval "ac_cv_func_$ac_func=yes"
  else
***************
*** 1682,1687 ****
--- 1748,1754 ----
  s%@VERSION@%$VERSION%g
  s%@RANDOM_OPT@%$RANDOM_OPT%g
  s%@ssldir@%$ssldir%g
+ s%@krb5dir@%$krb5dir%g
  s%@CPP@%$CPP%g
  
  CEOF
diff -Nacr stunnel-3.8.orig/configure.in stunnel-3.8/configure.in
*** stunnel-3.8.orig/configure.in	Tue Feb 22 08:19:04 2000
--- stunnel-3.8/configure.in	Fri Jul 21 13:53:48 2000
***************
*** 42,47 ****
--- 42,56 ----
      return 1
  }
  
+ checkkrb5dir() { :
+ 	if test -f "$1/include/krb5.h"; then
+ 		AC_DEFINE(HAVE_KRB5)
+ 		krb5dir="$1"
+ 		return 0
+ 	fi
+     return 1
+ }
+ 
  dnl Check for SSL directory
  AC_MSG_CHECKING([for SSL directory])
  AC_ARG_WITH(ssl,
***************
*** 71,76 ****
--- 80,120 ----
  AC_SUBST(ssldir)
  AC_DEFINE_UNQUOTED(ssldir, "$ssldir")
  
+ dnl Check for KRB5 directory
+ AC_MSG_CHECKING([for KRB5 directory])
+ AC_ARG_WITH(krb5,
+     [  --with-krb5=DIR         location of installed KRB5 libraries/include files],
+     [
+ 		if test "$withval" != "yes"; then
+ 			dnl Check the specified localtion only
+ 			checkkrb5dir "$withval"
+ 		else
+ 			dnl Search default localtions of KRB5 library
+ 			for maindir in /usr/local /usr/lib /usr/pkg /opt; do
+ 				for dir in $maindir $maindir/krb5 ; do
+ 					checkkrb5dir $dir && break 2
+ 				done
+ 			done
+ 		fi
+     ],
+     [
+         dnl Otherwise, no KRB5 for you
+ 		AC_DEFINE(NO_KRB5)
+ 		echo
+     ]
+ )
+ if test "$krb5dir" != ""; then
+ 	AC_MSG_RESULT($krb5dir)
+     AC_SUBST(krb5dir)
+ fi
+ 
+ AC_MSG_CHECKING([whether you want to include the idea cipher])
+ AC_ARG_WITH(idea,
+ [  --without-idea          disable the idea cipher],
+ 	[use_idea=no ; CFLAGS="$CFLAGS -DNO_IDEA"],
+ 	[use_idea=yes])
+ AC_MSG_RESULT($use_idea)
+ 
  dnl Substitute host.
  AC_SUBST(host)
  AC_DEFINE_UNQUOTED(HOST, "$host")
***************
*** 94,99 ****
--- 138,150 ----
  dnl Add SSL includes and libraries
  CFLAGS="$CFLAGS -I$ssldir/include"
  LIBS="$LIBS -L$ssldir/lib -lssl -lcrypto"
+ 
+ if test "$krb5dir" != ""; then
+ dnl Add KRB5 includes and libraries
+ CFLAGS="$CFLAGS -I$krb5dir/include"
+ LIBS="$LIBS -L$krb5dir/lib -lgssapi_krb5 -lkrb5 -lcom_err"
+ LIBS="$LIBS $krb5dir/lib/libcrypto.a -lresolv"
+ fi
  
  dnl Check for RSAref library.
  AC_MSG_CHECKING([for RSAref library])
diff -Nacr stunnel-3.8.orig/ssl.c stunnel-3.8/ssl.c
*** stunnel-3.8.orig/ssl.c	Fri Feb 18 10:26:48 2000
--- stunnel-3.8/ssl.c	Fri Jul 21 13:57:59 2000
***************
*** 18,23 ****
--- 18,35 ----
   *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
+ /*	klpstunnel  stunnel-3.8, modified for use as kerberized local web proxy
+ **	20000310	VRS 	Started.  Changes to transfer() function.
+ */
+ #define	PROXY_VERSION "stunnel-3.8/kssl-0.2"
+ 
+ const char	*connect_response =
+ 		"HTTP/1.0 200 Connection established\n"
+ 		"Proxy-agent: "  PROXY_VERSION  "\n\n";
+ 
+ int 		have_cookie = 0;
+ 
+ 
  /* For US citizens having problems with patents, undefined by default */
  /* Uncomment the next line to disable RSA support */
  /* #define NO_RSA */
***************
*** 41,63 ****
  /* Max number of children */
  #define MAX_CLIENTS    100
  
- /* I/O buffer size */
- #define BUFFSIZE       8192
- 
  #include "common.h"
  
  #include <stdio.h>
  
- #ifdef HAVE_OPENSSL
- #include <openssl/lhash.h>
- #include <openssl/ssl.h>
- #include <openssl/err.h>
- #else
- #include <lhash.h>
- #include <ssl.h>
- #include <err.h>
- #endif
- 
  #ifdef USE_WIN32
  
  #define Win32_Winsock
--- 53,62 ----
***************
*** 116,134 ****
  int auth_user(struct sockaddr_in *);
  
      /* SSL functions */
- void context_init();
- void context_free();
  void client(int);
! static int transfer(SSL *, int);
  #ifndef NO_RSA
  static RSA *tmp_rsa_cb(SSL *, int, int);
  #endif /* NO_RSA */
  static int verify_callback (int, X509_STORE_CTX *);
  static void info_callback(SSL *, int, int);
! static void print_stats();
  static void print_cipher(SSL *);
  static void sslerror(char *);
  
  /* Correct callback definitions overriding ssl.h */
  #ifndef NO_RSA
  #ifdef SSL_CTX_set_tmp_rsa_callback
--- 115,133 ----
  int auth_user(struct sockaddr_in *);
  
      /* SSL functions */
  void client(int);
! static int transfer(Channel *local, Channel *remote);
  #ifndef NO_RSA
  static RSA *tmp_rsa_cb(SSL *, int, int);
  #endif /* NO_RSA */
  static int verify_callback (int, X509_STORE_CTX *);
  static void info_callback(SSL *, int, int);
! static void print_stats(SSL_CTX *ctx);
  static void print_cipher(SSL *);
  static void sslerror(char *);
  
+ void ssl3_send_alert(SSL *s,int level, int desc);
+ 
  /* Correct callback definitions overriding ssl.h */
  #ifndef NO_RSA
  #ifdef SSL_CTX_set_tmp_rsa_callback
***************
*** 138,164 ****
      SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb)
  #endif /* NO_RSA */
  
- SSL_CTX *ctx;           /* global SSL context */
  #ifndef NO_RSA
  RSA *rsa_tmp;           /* temporary RSA key */
  #endif /* NO_RSA */
- #if SSLEAY_VERSION_NUMBER >= 0x0922
- static unsigned char *sid_ctx=(unsigned char *)"stunnel SID";
-     /* const allowed here */
- #endif
  
! void context_init() /* init SSL */
  {
  #ifndef NO_DH
      static DH *dh=NULL;
      BIO *bio=NULL;
  #endif /* NO_DH */
  
      SSLeay_add_ssl_algorithms();
      SSL_load_error_strings();
!     if(options.option&OPT_CLIENT) {
          ctx=SSL_CTX_new(SSLv3_client_method());
!     } else { /* Server mode */
          ctx=SSL_CTX_new(SSLv23_server_method());
  #ifndef NO_RSA
          log(LOG_DEBUG, "Generating %d bit temporary RSA key...", KEYLENGTH);
--- 137,168 ----
      SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,0,(char *)cb)
  #endif /* NO_RSA */
  
  #ifndef NO_RSA
  RSA *rsa_tmp;           /* temporary RSA key */
  #endif /* NO_RSA */
  
! /*	Initialize & return SSL context.
! **	May need args if same option.options don't work for both 
! **	remote (normal) and local legs.  E.g. option.cipher_list?
! */
! SSL_CTX	*context_init(char *host)
  {
+ 	SSL_CTX *ctx;           /* (no longer) global SSL context */
  #ifndef NO_DH
      static DH *dh=NULL;
      BIO *bio=NULL;
  #endif /* NO_DH */
  
+     yaapp_RAND_load_file(NULL, NULL, 0);
      SSLeay_add_ssl_algorithms();
      SSL_load_error_strings();
!     if ((options.option & OPT_KHTTPS)  &&  host  &&  strlen(host))  {
! 		ctx=SSL_CTX_new(SSLv23_client_method());
! 		}
! 	else if ((options.option & OPT_CLIENT)  &&  host  &&  strlen(host))  {
          ctx=SSL_CTX_new(SSLv3_client_method());
! 		}
! 	else  { /* Server mode */
          ctx=SSL_CTX_new(SSLv23_server_method());
  #ifndef NO_RSA
          log(LOG_DEBUG, "Generating %d bit temporary RSA key...", KEYLENGTH);
***************
*** 170,176 ****
          if(!rsa_tmp) {
              sslerror("tmp_rsa_cb");
              exit(1);
!         }
          log(LOG_DEBUG, "Temporary RSA key generated");
          SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
  #endif /* NO_RSA */
--- 174,180 ----
          if(!rsa_tmp) {
              sslerror("tmp_rsa_cb");
              exit(1);
! 			}
          log(LOG_DEBUG, "Temporary RSA key generated");
          SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_cb);
  #endif /* NO_RSA */
***************
*** 239,268 ****
              log(LOG_NOTICE, "Peer certificate location %s", options.clientdir);
      }
      SSL_CTX_set_info_callback(ctx, info_callback);
!     if(options.cipher_list) {
!         if (!SSL_CTX_set_cipher_list(ctx, options.cipher_list)) {
              sslerror("SSL_CTX_set_cipher_list");
              exit(1);
          }
      }
- }
  
! void context_free() /* free SSL */
! {
!     SSL_CTX_free(ctx);
  }
  
  void client(int local)
  {
      struct sockaddr_in addr;
      int addrlen;
-     SSL *ssl;
      int remote;
      struct linger l;
      u_long ip;
  #ifdef USE_LIBWRAP
      struct request_info request;
  #endif
  
      log(LOG_DEBUG, "%s started", options.servname);
      l.l_onoff=1;
--- 243,273 ----
              log(LOG_NOTICE, "Peer certificate location %s", options.clientdir);
      }
      SSL_CTX_set_info_callback(ctx, info_callback);
!     if (options.loc_cipher_list  ||  options.rem_cipher_list) {
! 		char	*cipher_list = (host)?	options.rem_cipher_list:
! 										options.loc_cipher_list;
!         if (cipher_list  &&  strlen(cipher_list)  &&
! 			!SSL_CTX_set_cipher_list(ctx, cipher_list))  {
              sslerror("SSL_CTX_set_cipher_list");
              exit(1);
          }
      }
  
! 	return ctx;
  }
  
  void client(int local)
  {
      struct sockaddr_in addr;
      int addrlen;
      int remote;
      struct linger l;
      u_long ip;
  #ifdef USE_LIBWRAP
      struct request_info request;
  #endif
+     Channel	remote_ch;						/*  Normally SSL	*/
+ 	Channel	local_ch;						/*  Normally socket	*/
  
      log(LOG_DEBUG, "%s started", options.servname);
      l.l_onoff=1;
***************
*** 313,358 ****
          goto cleanup_remote;
      }
  
!     /* do the job */
!     if(!(ssl=SSL_new(ctx))) {
!         sslerror("SSL_new");
!         goto cleanup_remote;
!     }
! #if SSLEAY_VERSION_NUMBER >= 0x0922
!     SSL_set_session_id_context(ssl, sid_ctx, strlen(sid_ctx));
! #endif
!     if(options.option&OPT_CLIENT) {
!         SSL_set_fd(ssl, remote);
!         SSL_set_connect_state(ssl);
!         if(SSL_connect(ssl)<=0) {
!             sslerror("SSL_connect");
!             goto cleanup_ssl;
!         }
!         print_cipher(ssl);
!         if(transfer(ssl, local)<0)
!             goto cleanup_ssl;
!     } else {
!         SSL_set_fd(ssl, local);
!         SSL_set_accept_state(ssl);
!         if(SSL_accept(ssl)<=0) {
!             sslerror("SSL_accept");
!             goto cleanup_ssl;
!         }
!         print_cipher(ssl);
!         if(transfer(ssl, remote)<0)
!             goto cleanup_ssl;
!     }
      /* No error - normal shutdown */
!     SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
!     SSL_free(ssl);
!     ERR_remove_state(0);
      closesocket(remote);
      closesocket(local);
      goto done;
  cleanup_ssl: /* close SSL and reset sockets */
!     SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
!     SSL_free(ssl);
!     ERR_remove_state(0);
  cleanup_remote: /* reset remote and local socket */
      if ((options.option & OPT_REMOTE) &&
          setsockopt(remote, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0 &&
--- 318,347 ----
          goto cleanup_remote;
      }
  
! 	if (!init_ch(&remote_ch)  ||  !init_ch(&local_ch))  {
! 		log(LOG_ERR, "init_ch fails");
!         goto cleanup_local;
! 		}
! 	else  {
! 		/*	200000316 VRS - issues w/ session spanning multiple transfer calls.
! 		**	Orig stunnel reset here, but always to same values (fixed channels)
! 		**	Need to leave wr_remote_sock fd alone across transfers...
! 		**	How do I know when to reset it; i.e. when session ends?
! 		**	20000317 VRS - moved up from transfer() to client()
! 		*/
! 		local_ch.fd  = (options.option&OPT_CLIENT)? local: remote;
! 		remote_ch.fd = (options.option&OPT_CLIENT)? remote: local;
! 		}
! 
! 	if (transfer(&local_ch, &remote_ch) < 0)  goto cleanup_ssl;
! 
      /* No error - normal shutdown */
! 	shutdown_ssl_ch(&local_ch, &remote_ch);
      closesocket(remote);
      closesocket(local);
      goto done;
  cleanup_ssl: /* close SSL and reset sockets */
! 	shutdown_ssl_ch(&local_ch, &remote_ch);
  cleanup_remote: /* reset remote and local socket */
      if ((options.option & OPT_REMOTE) &&
          setsockopt(remote, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0 &&
***************
*** 373,525 ****
      ; /* ANSI C compiler needs it */
  }
  
! static int transfer(SSL *ssl, int sock_fd) /* transfer data */
  {
!     fd_set rd_set, wr_set;
!     int num, fdno, ssl_fd, ssl_bytes, sock_bytes, retval;
!     char sock_buff[BUFFSIZE], ssl_buff[BUFFSIZE];
!     int sock_ptr, ssl_ptr, sock_open, ssl_open;
! #if defined FIONBIO && defined USE_NBIO
!     unsigned long l;
  #endif
  
!     ssl_fd=SSL_get_fd(ssl);
!     fdno=(ssl_fd>sock_fd ? ssl_fd : sock_fd)+1;
!     sock_ptr=0;
!     ssl_ptr=0;
!     sock_open=1;
!     ssl_open=1;
!     sock_bytes=0;
!     ssl_bytes=0;
  
  #if defined FIONBIO && defined USE_NBIO
!     l=1; /* ON */
!     if(ioctlsocket(sock_fd, FIONBIO, &l)<0)
!         sockerror("ioctlsocket (sock)"); /* non-critical */
!     if(ioctlsocket(ssl_fd, FIONBIO, &l)<0)
!         sockerror("ioctlsocket (ssl)"); /* non-critical */
!     log(LOG_DEBUG, "Sockets set to non-blocking mode");
  #endif
  
!     while((sock_open||sock_ptr) && (ssl_open||ssl_ptr)) {
          FD_ZERO(&rd_set);
!         if(sock_open && sock_ptr<BUFFSIZE) /* can read from socket */
!             FD_SET(sock_fd, &rd_set);
!         if(ssl_open && ssl_ptr<BUFFSIZE) /* can read from SSL */
!             FD_SET(ssl_fd, &rd_set);
          FD_ZERO(&wr_set);
!         if(sock_open && ssl_ptr) /* can write to socket */
!             FD_SET(sock_fd, &wr_set);
!         if(ssl_open && sock_ptr) /* can write to SSL */
!             FD_SET(ssl_fd, &wr_set);
          if(select(fdno, &rd_set, &wr_set, NULL, NULL)<0) {
              sockerror("select");
!             goto error;
!         }
!         if(sock_open && FD_ISSET(sock_fd, &rd_set)) {
!             num=readsocket(sock_fd, sock_buff+sock_ptr, BUFFSIZE-sock_ptr);
!             if(num<0 && errno==ECONNRESET) {
!                 log(LOG_NOTICE, "IPC reset (child died)");
!                 break; /* close connection */
!             }
!             if (num < 0 && errno != EIO) {
!                 sockerror("read");
!                 goto error;
!             } else if (num > 0) {
!                 sock_ptr += num;
!             } else { /* close */
!                 log(LOG_DEBUG, "Socket closed on read");
!                 sock_open = 0;
!             }
!         }
!         if(ssl_open && FD_ISSET(ssl_fd, &rd_set)) {
!             num=SSL_read(ssl, ssl_buff+ssl_ptr, BUFFSIZE-ssl_ptr);
!             switch(SSL_get_error(ssl, num)) {
!             case SSL_ERROR_NONE:
!                 ssl_ptr+=num;
!                 break;
!             case SSL_ERROR_WANT_WRITE:
!             case SSL_ERROR_WANT_READ:
!             case SSL_ERROR_WANT_X509_LOOKUP:
!                 log(LOG_DEBUG, "SSL_read returned WANT_ - retry");
!                 break;
!             case SSL_ERROR_SYSCALL:
!                 if(num) { /* not EOF */
!                     sockerror("SSL_read (socket)");
!                     goto error;
!                 }
!             case SSL_ERROR_ZERO_RETURN:
!                 log(LOG_DEBUG, "SSL closed on read");
!                 ssl_open=0;
!                 break;
!             case SSL_ERROR_SSL:
!                 sslerror("SSL_read");
!                 goto error;
!             }
!         }
!         if(sock_open && FD_ISSET(sock_fd, &wr_set)) {
!             num=writesocket(sock_fd, ssl_buff, ssl_ptr);
!             if(num<0) {
!                 sockerror("write");
!                 goto error;
!             }
!             if(num) {
!                 memcpy(ssl_buff, ssl_buff+num, ssl_ptr-num);
!                 ssl_ptr-=num;
!                 sock_bytes+=num;
!             } else { /* close */
!                 log(LOG_DEBUG, "Socket closed on write");
!                 sock_open=0;
!             }
!         }
!         if(ssl_open && FD_ISSET(ssl_fd, &wr_set)) {
!             num=SSL_write(ssl, sock_buff, sock_ptr);
!             switch(SSL_get_error(ssl, num)) {
!             case SSL_ERROR_NONE:
!                 memcpy(sock_buff, sock_buff+num, sock_ptr-num);
!                 sock_ptr-=num;
!                 ssl_bytes+=num;
!                 break;
!             case SSL_ERROR_WANT_WRITE:
!             case SSL_ERROR_WANT_READ:
!             case SSL_ERROR_WANT_X509_LOOKUP:
!                 log(LOG_DEBUG, "SSL_write returned WANT_ - retry");
!                 break;
!             case SSL_ERROR_SYSCALL:
!                 if(num) { /* not EOF */
!                     sockerror("SSL_write (socket)");
!                     goto error;
!                 }
!             case SSL_ERROR_ZERO_RETURN:
!                 log(LOG_DEBUG, "SSL closed on write");
!                 ssl_open=0;
!                 break;
!             case SSL_ERROR_SSL:
!                 sslerror("SSL_write");
!                 goto error;
!             }
          }
      }
!     retval=0;
!     goto done;
! error:
!     retval=-1;
! done:
  
  #if defined FIONBIO && defined USE_NBIO
      l=0; /* OFF */
!     if(ioctlsocket(sock_fd, FIONBIO, &l)<0)
          sockerror("ioctlsocket (sock)"); /* non-critical */
!     if(ioctlsocket(ssl_fd, FIONBIO, &l)<0)
          sockerror("ioctlsocket (ssl)"); /* non-critical */
  #endif
  
      log(LOG_NOTICE,
          "Connection %s: %d bytes sent to SSL, %d bytes sent to socket",
!         retval<0 ? "reset" : "closed", ssl_bytes, sock_bytes);
      return retval;
  }
  
  #ifndef NO_RSA
  static RSA *tmp_rsa_cb(SSL *s, int export, int keylength)
  { /* temporary RSA key callback */
--- 362,1182 ----
      ; /* ANSI C compiler needs it */
  }
  
! 
! /*	Initialize/clear Channel struct.
! **	Returns 0=problem; 1=OK.
! */
! int 	init_ch(Channel *channel)
  {
! 	if (channel == NULL)  return 0;
! 
! 	channel->open	= CHAN_OPEN;
! 	channel->ctx	= NULL;
! 	channel->ssl	= NULL;
! 	channel->fd 	= 0;
! 	channel->bytes	= 0;
! 	channel->ptr	= 0;
! 
! 	return 1;
! }
! 
! 
! void	show_sock(int s)
! {
!     struct sockaddr_in	addr, paddr;
! 	int 				addrlen, paddrlen;
! 	char				*self, *other;
! 	int 				sport, oport;
! 
!     if (getsockname(s, (struct sockaddr *) &addr, &addrlen) < 0)  {
! 		printf("show_sock(%d): getsockname failed\n", s);
! 		}
!     if (getpeername(s, (struct sockaddr *) &paddr, &paddrlen) < 0)  {
! 		printf("show_sock(%d): getpeername failed\n", s);
! 		}
! 	
! 	self = inet_ntoa(addr.sin_addr);	other = inet_ntoa(paddr.sin_addr);
! 	sport= ntohs(addr.sin_port);		oport = ntohs(paddr.sin_port);
! 
! 	if (!self)	self  = "undef";
! 	if (!other)	other = "undef";
! 
! 	printf("Socket %d (%s:%d) is connected to: %s:%d\n", s,
! 					self,sport, other,oport);
! }
! 
! 
! #define	MAX_SESS	40;
! 
! /*	Create SSL connection on (local or remote) channel to given host.
! **	Return 0:Success.
! */
! int 	new_ssl_ch(Channel *chan, char *host)
! {
! 	EVP_MD_CTX		hash_ctx;
! 	unsigned char	*sess_id;
! 	unsigned int 	len = getpid();
! 
! 	if ((!chan->ctx  &&  !(chan->ctx = context_init(host)))  ||
! 		(!chan->ssl  &&  !(chan->ssl = SSL_new(chan->ctx))))  {
!         sslerror("SSL_new");
!         return -1;
! 		}
! 	/*
! 	SSL_clear(chan->ssl);
! 	*/
! 
! #if SSLEAY_VERSION_NUMBER >= 0x0922
! 	EVP_DigestInit(&hash_ctx, EVP_get_digestbyname("ssl3-sha1"));
! 	EVP_DigestUpdate(&hash_ctx, chan->ssl, sizeof(chan));
! 	EVP_DigestUpdate(&hash_ctx, chan, sizeof(chan));
! 	EVP_DigestUpdate(&hash_ctx, &len, sizeof(len));
! 	if (!(sess_id = (unsigned char *) malloc(EVP_MD_size(hash_ctx.digest))))  {
! 		sslerror("session_id_context alloc");
! 		return -1;
! 		}
! 	EVP_DigestFinal(&hash_ctx, sess_id, &len);
!     SSL_set_session_id_context(chan->ssl, sess_id, len);
! 	free(sess_id);
  #endif
  
! #ifndef NO_KRB5
! 	if (chan->ssl->kssl_ctx)  {
! 		kssl_ctx_setstring(chan->ssl->kssl_ctx, KSSL_SERVICE, KRB5SVC);
! 		kssl_ctx_setstring(chan->ssl->kssl_ctx, KSSL_KEYTAB, KRB5KEYTAB);
! 		if (host)  kssl_ctx_setstring(chan->ssl->kssl_ctx, KSSL_SERVER, host);
! 		}
! #endif	/* NO_KRB5 */
! 
! 	return 0;
! }
! 
! 
! /*	Close any SSL channels.
! */
! void	shutdown_ssl_ch(Channel *local, Channel *remote)
! {
! 	have_cookie = 0;
! 
! 	if (local  &&  local->ssl)  {
! 		SSL_set_shutdown(local->ssl,  SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
! 		SSL_free(local->ssl);
! 		local->ssl = NULL;
! 		local->ctx = NULL;
! 		}
! 	if (remote  &&  remote->ssl)  {
! 		SSL_set_shutdown(remote->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
! 		SSL_free(remote->ssl);
! 		remote->ssl = NULL;
! 		remote->ctx = NULL;
! 		}
!     ERR_remove_state(0);
! }
! 
! 
! /*	Set SSL fd and do SSL_connect.
! **	Return 0:Success.
! */
! int 	connect_ssl_ch(Channel *chan, char *hp)
! {
! 	if (!chan->fd  &&  create_remote_sock(chan, hp))  {
! 		sslerror("ssl create remote sock");
! 		return 1;
! 		}
! 	SSL_set_fd(chan->ssl, chan->fd);
! 	SSL_set_connect_state(chan->ssl);
! 	if (SSL_connect(chan->ssl) <= 0)  {
! 		sslerror("SSL_connect");
! 		return 1;
! 		}
! 	/*
! 	print_cipher(chan->ssl);
! 	*/
! 
! 	return 0;
! }
! 
! /*	Set SSL fd and do SSL_accept.
! **	Return 0:Success.
! */
! int 	accept_ssl_ch(Channel *chan)
! {
! 	SSL_set_fd(chan->ssl, chan->fd);
! 	SSL_set_accept_state(chan->ssl);
! 	if (SSL_accept(chan->ssl) <= 0)  {
! 		sslerror("SSL_accept");
! 		return 1;
! 		}
! 	/*
! 	print_cipher(chan->ssl);
! 	*/
! 
! 	return 0;
! }
! 
! /*	Do SSL read on given channel, return number of bytes read through *numptr.
! **	Return 0:Success
! */
! int 	rd_ssl_ch(Channel *chan, int *numptr)
! {
! 	*numptr = SSL_read(chan->ssl, chan->buff + chan->ptr, BUFFSIZE - chan->ptr);
! 
! 	switch (SSL_get_error(chan->ssl, *numptr))  {
! 		case SSL_ERROR_NONE:
! 			chan->ptr += *numptr;
! 			break;
! 		case SSL_ERROR_WANT_WRITE:
! 		case SSL_ERROR_WANT_READ:
! 		case SSL_ERROR_WANT_X509_LOOKUP:
! 			log(LOG_DEBUG, "SSL_read returned WANT_ - retry");
! 			break;
! 		case SSL_ERROR_SYSCALL:
! 			if (*numptr)  { 	/* not EOF */
! 				sockerror("SSL_read (socket)");
! 				return -1;
! 			}
! 		case SSL_ERROR_ZERO_RETURN:
! 			log(LOG_DEBUG, "SSL closed on read");
! 			chan->open = 0;
! 			break;
! 		case SSL_ERROR_SSL:
! 		default:
! 			sslerror("SSL_read");
! 			return -1;
! 		}
! 
! 	return 0;
! }
! 
! /*	Do SSL write on given channel, return #bytes written through *numptr.
! **	Return 0:Success
! */
! int 	wr_ssl_ch(Channel *from, Channel *to, int *numptr)
! {
! 	*numptr = SSL_write(to->ssl, from->buff, from->ptr);
! 
! 	switch (SSL_get_error(to->ssl, *numptr)) {
! 		case SSL_ERROR_NONE:
! 			memcpy(from->buff, from->buff + *numptr, from->ptr - *numptr);
! 			from->ptr -= *numptr;
! 			to->bytes += *numptr;
! 			break;
! 		case SSL_ERROR_WANT_WRITE:
! 		case SSL_ERROR_WANT_READ:
! 		case SSL_ERROR_WANT_X509_LOOKUP:
! 			log(LOG_DEBUG, "SSL_write returned WANT_ - retry");
! 			break;
! 		case SSL_ERROR_SYSCALL:
! 			if (*numptr)  { /* not EOF */
! 				sockerror("SSL_write (socket)");
! 				return -1;
! 				}
! 		case SSL_ERROR_ZERO_RETURN:
! 			log(LOG_DEBUG, "SSL closed on write");
! 			to->open = 0;
! 			break;
! 		case SSL_ERROR_SSL:
! 		default:
! 			sslerror("SSL_write");
! 			return -1;
! 		}
! 
! 	return 0;
! }
! 
! 
! /*	Create and connect any local/remote sockets or ssl connections,
! **	as appropriate for km_mode.  KM_NORMAL mode should match original stunnel.
! **	The local socket connection should already be established.
! **	Return 0:Success.
! */
! int 	connect_ch(Channel *local, Channel *remote, int km_mode, char *hp)
! {
! 	char	*cp, host[MAX_HP+1];
! 	int 	rc = 0;
! 
! 	cp = (km_mode == KM_NORMAL)? options.servname: hp;
! 	if (strlen(cp) >= MAX_HP)  {
! 		sockerror("host name overflow");
! 		return -1;
! 		}
! 	strcpy(host, cp);
! 	cp = strrchr(host, (km_mode == KM_NORMAL)? '.': ':');
! 	if (cp)  *cp = '\0';
! 
! 	switch (km_mode)  {
! 
! 		case KM_NORMAL:
! 				/*	Add remote ssl connection to options.servname		*/
! 				new_ssl_ch(remote, host);
! 
! 				if (options.option & OPT_CLIENT)  {
! 					if (!hp  ||  !strlen(hp))  {
! 						hp = (char *) options.localnames;
! 						if (!hp  ||  !strlen(hp))  hp = "localhost";
! 						snprintf(host, MAX_HP, "%s:%d", hp, options.localport);
! 						hp = host;
! 						}
! 					if (connect_ssl_ch(remote, hp))  return -1;
! 					}
! 				else  {
! 					if (accept_ssl_ch(remote))   return -1;
! 					}
! 				break;
! 
! 		case KM_KSSL_MITM:
! 				/*	Add remote ssl connection to host,
! 				**	Add local ssl connection and use in place of local->fd
! 				*/
! 				rc = new_ssl_ch(remote, host);
! 
! 				/* VRS 20000324 late: maybe blame existing remote->fd = 10 so...
! 				   if (remote->fd)  { closesocket(remote->fd); remote->fd=0; }
! 				*/
! 				  remote->fd = 0;
! 				if (connect_ssl_ch(remote, hp))  return -1;
! 
! 				if (! fake_CONNECT(local))  return -1;
! 
! 				new_ssl_ch(local, NULL);
! 				if (accept_ssl_ch(local))  return -1;
! 
! 				break;
! 
! 		case KM_LOCAL_HTTPS:
! 				/*	Add remote sock connection to host					*/
! 				if (create_remote_sock(remote, hp))  {
! 					sockerror("local https");
! 					return -1;
! 					}
! 
! 				if (! fake_CONNECT(local))  return -1;
! 				break;
! 
! 		case KM_REMOTE_HTTPS:
! 				/*	Add remote sock connection to host					*/
! 				if (create_remote_sock(remote, hp))  {
! 					sockerror("remote https");
! 					return -1;
! 					}
! 				break;
! 
! 		default:
! 				return -1;
! 				break;
! 		}
  
+ 	return 0;
+ }
+ 
+ 
+ static	fd_set	rd_set, wr_set;
+ 
+ /*	transfer data
+ */
+ static int transfer(Channel *local, Channel *remote)
+ {
+     int 	fdno;
+ 	int 	retval = 1;
+ 	int 	km_mode = KM_UNDEF;
  #if defined FIONBIO && defined USE_NBIO
!     unsigned long	l;
! #endif
! 
! #if defined FIONBIO && defined USE_NBIO
! 	l=1; /* ON */
! 	if(ioctlsocket(local->fd, FIONBIO, &l)<0)
! 		sockerror("ioctlsocket (sock)"); /* non-critical */
! 	if(ioctlsocket(remote->fd, FIONBIO, &l)<0)
! 		sockerror("ioctlsocket (ssl)"); /* non-critical */
! 	log(LOG_DEBUG, "Sockets set to non-blocking mode");
  #endif
  
!     while( retval > 0  &&
! 		(local->open||local->ptr) && (remote->open||remote->ptr))  {
! 
! 		fdno = ((remote->fd > local->fd)? remote->fd: local->fd) + 1;
! 
          FD_ZERO(&rd_set);
!         if(local->open && local->ptr<BUFFSIZE) /* can read from socket */
!             if (local->fd)  FD_SET(local->fd, &rd_set);
!         if(remote->open && remote->ptr<BUFFSIZE) /* can read from SSL */
!             if (remote->fd)  FD_SET(remote->fd, &rd_set);
! 
          FD_ZERO(&wr_set);
!         if(local->open && remote->ptr) /* can write to socket */
!             if (local->fd)  FD_SET(local->fd, &wr_set);
!         if(remote->open && local->ptr) /* can write to SSL */
!             if (remote->fd)  FD_SET(remote->fd, &wr_set);
! 
          if(select(fdno, &rd_set, &wr_set, NULL, NULL)<0) {
              sockerror("select");
! 			retval = -1;
! 			break;
          }
+ 
+ 		if ((retval = rd_local (local, remote, &km_mode)) <= 0)  break;
+ 		if ((retval = rd_remote(local, remote, &km_mode)) <= 0)  break;
+ 		if ((retval = got_cookie(local,remote,  km_mode)) <= 0)  break;
+ 		if ((retval = wr_local (local, remote,  km_mode)) <= 0)  break;
+ 		if ((retval = wr_remote(local, remote,  km_mode)) <= 0)  break;
      }
! 
! 	have_cookie = 0;
  
  #if defined FIONBIO && defined USE_NBIO
      l=0; /* OFF */
!     if(ioctlsocket(local->fd, FIONBIO, &l)<0)
          sockerror("ioctlsocket (sock)"); /* non-critical */
!     if(ioctlsocket(remote->fd, FIONBIO, &l)<0)
          sockerror("ioctlsocket (ssl)"); /* non-critical */
  #endif
  
      log(LOG_NOTICE,
          "Connection %s: %d bytes sent to SSL, %d bytes sent to socket",
!         retval<0 ? "reset" : "closed", remote->bytes, local->bytes);
      return retval;
  }
  
+ 
+ /*	Search and destroy cookie in local stream.
+ **	Cookie should look like: "\nCookie: stunnel/kssl=4C7DD01FA175330D\n"
+ **	The search is not confined to HTTP headers;
+ **	consider this a feature to avoid leaking the random nonce ;-)
+ **	Return 1 if good cookie found, 0 otherwise.
+ */
+ int 	eat_cookie(Channel *local, char *header, char *key)
+ {
+ 	char	*found, *nonce, *next;
+ 	char	*eob = &local->buff[local->ptr] - 1;
+ 	char	backup;
+ 	int 	i = 0, taillen;
+ 	int 	rc = 0;
+ 
+ 	backup = local->buff[local->ptr];		local->buff[local->ptr] = '\0';
+ 	found = strstr(local->buff, header);	local->buff[local->ptr] = backup;
+ 	if (!found)  return 0;
+ 
+ 	found += strlen(header);				local->buff[local->ptr] = '\0';
+ 	found = strstr(found, key);				local->buff[local->ptr] = backup;
+ 	if (!found)  return 0;
+ 
+ 	nonce = found + strlen(key);
+ 	rc = (! options.cookie->nonce_len)?
+ 		 0: ! strncmp(nonce, options.cookie->nonce, options.cookie->nonce_len);
+ 
+ 	/*
+ 	**	What happens if cookie line fragmented across BUFFSIZE buffer?
+ 	**	Expect header to be truncated, possibly leaking nonce.
+ 	*/
+ 	for (next=nonce; next<eob && *next!='\n' && !isspace((int)*next); next++) ;
+ 	while (next < eob  &&  *next != '\n'  && isspace((int)*next))  next++;
+ 	taillen = local->ptr - (next - local->buff);
+ 	(void) memcpy(found, next, taillen);
+ 	local->ptr -= next - found;
+ 
+ 	/*	may trim trailing ", "
+ 	*/
+ 	if (found > local->buff  &&  *found == '\n')  {
+ 		eob = found - 1;
+ 		for (i=0;  --eob > local->buff; i++)  {
+ 			if (!isspace((int) *eob)  &&  *eob != ',')  break;
+ 			}
+ 		if (i)  {
+ 			(void) memcpy(found-1-i, found, taillen);
+ 			local->ptr -= i;
+ 			}
+ 		}
+ 
+ 	return rc;
+ }
+ 
+ 
+ /*	Error response for bad/missing auth cookie
+ */
+ const char	*badcookie_response =
+ 		"HTTP/1.0 403 Access to proxy denied\n"
+ 		"Proxy-agent: "  PROXY_VERSION  "\n"
+ 		"Content-type: text/html\n"
+ 		"Content-length: CONTLEN\n"
+ 		"\n"
+ 		"<HTML><Head><Title> Access to proxy denied</Title></Head>\n\n"
+ 		"<Body><H1> 403 Access to proxy denied</H1>\n<P>\n"
+ 		"Access to the klpstunnel proxy was rejected because \n"
+ 		"your web browser did not provide the required cookie. \n"
+ 		"Cookies are provided in the <Code> Cookie:</Code> or \n"
+ 		"<Code> Accept-Language:</Code> HTTP headers. \n"
+ 		"<P>\nPossible remedies:\n<OL>\n"
+ 		"<LI>  You must run the klpstunnel proxy <Strong>before</Strong>\n"
+ 			   "you start up your web browser\n"
+ 		"<!--"
+ 		"<LI>  You must enable cookies in your web browser\n"
+ 		"--> "
+ 		"</OL>\n"
+ 		"</Body></HTML>\n" ;
+ 
+ /*	Search for cookie in local channel, set have_cookie if good one found.
+ **	Return 1:OK if have_cookie is set, or otherwise OK.
+ **	Otherwise return -1:Fail and
+ **		o	Write error message to local channel
+ **		o	Exit proxy if failed connection attempt limit exceeded.
+ */
+ int 	got_cookie(Channel *local, Channel *remote, int km_mode)
+ {
+ 	Channel		badcookie_channel;
+ 	const int	badcookie_len = strlen(badcookie_response);
+ 	const int	com1 = strstr(badcookie_response, "<!--") - badcookie_response;
+ 	const int	com2 = strstr(badcookie_response, "--> ") - badcookie_response;
+ 	char		*cp;
+ 
+ 	/*	Always destroy cookie before sending data to remote side.
+ 	*/
+ 	if (eat_cookie(local, "\nCookie:", COOKIE_TAG "=")  &&
+ 		(options.cookie->ns_auths & AUTH_COOK))  have_cookie = 1;
+ 	if (eat_cookie(local, "\nAccept-Language:", COOKIE_TAG "-")  &&
+ 		(options.cookie->ns_auths & AUTH_LANG))  have_cookie = 1;
+ 	/*	Might should loop this in case multiple cookies in buffer;
+ 	*/
+ 
+ 	/*	Don't freak out until there's something to write to remote side.
+ 	**	This lets the CONNECT msg and response slide by without a cookie.
+ 	*/
+ 	if (!remote->open  ||  !FD_ISSET(remote->fd, &wr_set))  return 1;
+ 
+ 	if (have_cookie)  return 1;
+ 	if (!options.cookie->nonce_len)   return 1; 	/* len=0 diasbles check	*/
+ 
+ 	if (badcookie_len + 1 > BUFFSIZE)  {
+ 		fprintf(stderr, "Programming botch: "
+ 						"badcookie_response exceeds BUFFSIZE (%d)\n", BUFFSIZE);
+ 		exit(1);
+ 		}
+ 	badcookie_channel.ptr = badcookie_len;
+ 	strcpy(badcookie_channel.buff, badcookie_response);
+ 	if ((cp = strstr(badcookie_channel.buff, "CONTLEN")))  {
+ 		snprintf(cp, 7, "%-7d", strlen(cp+9));
+ 		if (strlen(cp) < 10)  cp[strlen(cp)] = '\n';
+ 		}
+ 	if (options.cookie->ns_auths & AUTH_COOK)  {
+ 		strncpy(&badcookie_channel.buff[com1], "    ", 4);
+ 		strncpy(&badcookie_channel.buff[com2], "    ", 4);
+ 		}
+ 	FD_SET(local->fd, &wr_set);
+ 	(void) wr_local (local, &badcookie_channel, km_mode);
+ 
+ 	if (remote->ssl)  {
+ 		ssl3_send_alert(remote->ssl,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+ 		}
+ 
+ 	if (++options.cookie->tries > options.cookie->max_tries)  {
+ 		fprintf(stderr, "proxy exiting after %d failed connection attempts\n",
+ 				options.cookie->tries);
+ 		  /*  printf("VRS DB: should restore prefs here?\n");	*/
+ 		exit(1);
+ 		}
+ 
+ 	return -1;
+ }
+ 
+ 
+ /*	Read local channel (normally socket; ssl in kssl MitM mode)
+ **
+ **	Returns:  1:OK, 0,-1: error
+ */
+ int 	rd_local(Channel *local, Channel *remote, int *km_mode)
+ {
+ 	int 	num, retval;
+ 	char	*hp = NULL;
+ 	int 	in_connect = 0;
+ 
+ 	if (!local->open  ||  !FD_ISSET(local->fd, &rd_set))  return 1;
+ 
+ 	if (*km_mode == KM_KSSL_MITM)  {
+ 		if ((retval = rd_ssl_ch(local, &num)))  return retval;
+ 		}
+ 	else if (	*km_mode == KM_LOCAL_HTTPS	||  *km_mode == KM_NORMAL  ||
+ 				*km_mode == KM_REMOTE_HTTPS	||  *km_mode == KM_UNDEF 	)  {
+ 		num = readsocket(local->fd, local->buff+local->ptr,BUFFSIZE-local->ptr);
+ 		if (num < 0  &&  errno == ECONNRESET)  {
+ 			log(LOG_NOTICE, "IPC reset (child died)");
+ 			return 0;	/* close connection */
+ 			}
+ 		if (num < 0  &&  errno != EIO)  {
+ 			sockerror("read");
+ 			return -1;
+ 			}
+ 		else if (num > 0)  {
+ 			if (*km_mode == KM_UNDEF)  {
+ 				*km_mode = check_CONNECT(local->buff + local->ptr, &hp);
+ 				if (*km_mode == KM_LOCAL_HTTPS  ||  *km_mode == KM_KSSL_MITM) {
+ 					in_connect = 1;
+ 					}
+ 				retval = connect_ch(local, remote, *km_mode, hp);
+ 				if (retval)   return retval;
+ 				}
+ 
+ 			switch (*km_mode)  {
+ 				case KM_LOCAL_HTTPS:
+ 				case KM_KSSL_MITM:
+ 						if (in_connect)  break;		/*  else fall through	*/
+ 				case KM_REMOTE_HTTPS:
+ 				case KM_NORMAL:
+ 						local->ptr += num;
+ 						break;
+ 				default:
+ 						sockerror("check_CONNECT");
+ 						return -1;
+ 				}
+ 			}
+ 		else  { 	/* close */
+ 			log(LOG_DEBUG, "Socket closed on read");
+ 			local->open = 0;
+ 			}
+ 		}
+ 	else  {
+ 		sockerror("rd_local");
+ 		return -1;
+ 		}
+ 
+ 	return 1;
+ }
+ 
+ 
+ /*	Read remote channel (normally ssl; socket in https proxy modes)
+ **
+ **	Returns:  1:OK; 0,-1: error
+ */
+ int 	rd_remote(Channel *local, Channel *remote, int *km_mode)
+ {
+ 	int 	num, retval;
+ 
+ 	if (!remote->open  ||  !FD_ISSET(remote->fd, &rd_set))  return 1;
+ 
+ 	/*	20000428 VRS Network error dialog appears in cases where rd_local
+ 	**	fails (not ready), and we fall into rd_remote with KM_NORMAL mode.
+ 	**	Let's try disabling this and see what happens
+ 	*/
+ 	if (*km_mode == KM_UNDEF)  return 1;	/* Net Error Dialog averted? */
+ 	if (*km_mode == KM_UNDEF)  {
+ 		*km_mode = KM_NORMAL;
+ 		retval = connect_ch(local, remote, *km_mode, "");
+ 		if (retval)   return retval;
+ 		}
+ 
+ 	if (*km_mode == KM_NORMAL  ||  *km_mode == KM_KSSL_MITM)  {
+ 		if ((retval = rd_ssl_ch(remote, &num)))  return retval;
+ 		}
+ 	else if (*km_mode == KM_LOCAL_HTTPS  ||  *km_mode == KM_REMOTE_HTTPS)  {
+ 		num = readsocket(remote->fd,
+ 						 remote->buff + remote->ptr, BUFFSIZE - remote->ptr);
+ 		if (num < 0  &&  errno == ECONNRESET)  {
+ 			log(LOG_NOTICE, "IPC reset (child died)");
+ 			return 0;	/* close connection */
+ 			}
+ 		if (num < 0  &&  errno != EIO)  {
+ 			sockerror("read");
+ 			return -1;
+ 			}
+ 		else if (num > 0)  {
+ 			remote->ptr += num;
+ 			}
+ 		else  { 	/* close */
+ 			log(LOG_DEBUG, "Socket closed on read");
+ 			remote->open = 0;
+ 			}
+ 		}
+ 	else  {
+ 		sockerror("rd_remote");
+ 		return -1;
+ 		}
+ 
+ 	return 1;
+ }
+ 
+ 
+ /*	Write local channel (normally socket; ssl in kssl MitM mode)
+ **
+ **	Returns:  1:OK; 0,-1: error
+ */
+ int 	wr_local(Channel *local, Channel *remote, int km_mode)
+ {
+ 	int 	num;
+ 
+ 	if (!local->open  ||  !FD_ISSET(local->fd, &wr_set))  return 1;
+ 
+ 	if (km_mode == KM_KSSL_MITM)  {
+ 		wr_ssl_ch(remote, local, &num);
+ 		}
+ 	else if (km_mode == KM_LOCAL_HTTPS  ||  km_mode == KM_REMOTE_HTTPS  ||
+ 			 km_mode == KM_NORMAL)  {
+ 		num = writesocket(local->fd, remote->buff, remote->ptr);
+ 		if (num < 0)  {
+ 			sockerror("write");
+ 			return -1;
+ 			}
+ 		if (num)  {
+ 			memcpy(remote->buff, remote->buff+num, remote->ptr-num);
+ 			remote->ptr  -= num;
+ 			local->bytes += num;
+ 			}
+ 		else  { 	/* close */
+ 			log(LOG_DEBUG, "Socket closed on write");
+ 			local->open = 0;
+ 			}
+ 		}
+ 	else  {
+ 		sockerror("wr_local");
+ 		return -1;
+ 		}
+ 
+ 	return 1;
+ }
+ 
+ 
+ /*	Write remote channel (normally ssl; socket in https proxy modes)
+ **
+ **	Returns:  1:OK; 0,-1: error
+ */
+ int 	wr_remote(Channel *local, Channel *remote, int km_mode)
+ {
+ 	int 	num, retval;
+ 
+ 	if (!remote->open  ||  !FD_ISSET(remote->fd, &wr_set))  return 1;
+ 
+ 	if (km_mode == KM_NORMAL  ||  km_mode == KM_KSSL_MITM)  {
+ 		if ((retval = wr_ssl_ch(local, remote, &num)))  return retval;
+ 		}
+ 	else if (km_mode == KM_LOCAL_HTTPS  ||  km_mode == KM_REMOTE_HTTPS)  {
+ 		num = writesocket(remote->fd, local->buff, local->ptr);
+ 		if (num < 0)  {
+ 			sockerror("write");
+ 			return -1;
+ 			}
+ 		if (num)  {
+ 			memcpy(local->buff, local->buff+num, local->ptr-num);
+ 			local->ptr	  -= num;
+ 			remote->bytes += num;
+ 			}
+ 		else  { 	/* close */
+ 			log(LOG_DEBUG, "Socket closed on write");
+ 			local->open = 0;
+ 			}
+ 		}
+ 	else  {
+ 		sockerror("wr_remote");
+ 		return -1;
+ 		}
+ 
+ 	return 1;
+ }
+ 
+ 
+ /*	Check local socket data for https "CONNECT host:port HTTP/1.0" message.
+ **	Return mode in:
+ **		KM_NORMAL, KM_KSSL_MITM, KM_LOCAL_HTTPS, KM_REMOTE_HTTPS, KM_FAULT,
+ **	and set *hp to point to static local buffer with host:port.
+ */
+ int 	check_CONNECT(const char *str, char **hp)
+ {
+ 	static char	hostport[MAX_HP+1];
+ 	int 		hstart, hplen;
+ 	char 		*cp;
+ 
+ 	hostport[0] = '\0';
+ 	*hp = hostport;
+ 
+ 	if (!(options.option & OPT_KHTTPS))  return KM_NORMAL;
+ 
+ 	if (strncmp(str, "CONNECT", 7) == 0)  {
+ 		hstart = 7 + strspn(&str[7], " \t");
+ 		hplen = strcspn(&str[hstart], " \t");
+ 		if (hplen >= MAX_HP)  return KM_FAULT;
+ 		strncpy(hostport, &str[hstart], hplen);
+ 		hostport[hplen] = '\0';
+ 		if (strchr(*hp, ':') == NULL)  return KM_FAULT;
+ 		}
+ 	else  {
+ 		return KM_NORMAL;
+ 		}
+ 
+ 	if (options.kssl_list  &&  (cp = strstr(options.kssl_list, *hp))  && 
+ 		(cp[hplen] == '\0'  ||  cp[hplen] == ','))  {
+ 		return KM_KSSL_MITM;
+ 		}
+ 	else if (options.https_proxy)  {
+ 		if (strlen(options.https_proxy) >= MAX_HP)  return KM_FAULT;
+ 		strcpy(*hp, options.https_proxy);
+ 		return KM_REMOTE_HTTPS;
+ 		}
+ 	else  {
+ 		return KM_LOCAL_HTTPS;
+ 		}
+ }
+ 
+ 
+ /*	Fake a response to local side's "CONNECT" message
+ **	by pushing remote side's "200 OK" message into the remote buffer.
+ **	The caller should prevent delivery of local side's "CONNECT" message
+ **	by purposefully failing to update local->ptr + num.
+ */
+ int 	fake_CONNECT(Channel *local)
+ {
+ 	if (writesocket(local->fd, connect_response,
+ 					strlen(connect_response)) < 0)  {
+ 		sockerror("fake_connect");
+ 		return 0;
+ 		}
+ 	return 1;
+ }
+ 
+ 
+ /*	Make new socket connection to host:port from CONNECT message.
+ **	Reset remote->fd from ssl fd to new fd.
+ **	Return 0:Success, -1:Problem
+ */
+ int 	create_remote_sock(Channel *remote, char *hostport)
+ {
+ 	struct sockaddr_in	addr;
+ 	int 				sock;
+ 	u_long				*host = NULL;
+ 	u_short				port;
+ #if defined FIONBIO && defined USE_NBIO
+ 	long				l;
+ #endif
+ 
+ 	if (!remote  ||  !hostport)  {
+ 		sockerror("create_remote_sock args");
+ 		return -1;
+ 		}
+ 
+ 	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)  {
+ 		sockerror("remote hp socket");
+ 		return -1;
+ 		}
+ 
+ 	memset(&addr, 0, sizeof(addr));
+ 	addr.sin_family = AF_INET;
+ 	name2nums(hostport, &host, &port);
+ 	addr.sin_port = port;
+ 	addr.sin_addr.s_addr = *host;
+ 
+ 	if(!connect(sock, (struct sockaddr *) &addr, sizeof(addr)))  {
+ #if defined FIONBIO && defined USE_NBIO
+ 		l = 1; /* ON */
+ 		if(ioctlsocket(sock, FIONBIO, &l)<0)
+ 			sockerror("ioctlsocket (remote sock)"); /* non-critical */
+ 		log(LOG_DEBUG, "Remote socket set to non-blocking mode");
+ #endif
+ 		remote->fd  = sock;
+ 		return 0;		/* success */
+ 		}
+ 	else  {
+ 		sockerror("remote hp connect");
+ 		return -1;
+ 		}
+ }
+ 
+ 
  #ifndef NO_RSA
  static RSA *tmp_rsa_cb(SSL *s, int export, int keylength)
  { /* temporary RSA key callback */
***************
*** 556,565 ****
  {
      log(LOG_DEBUG, "%s", SSL_state_string_long(s));
      if(where==SSL_CB_HANDSHAKE_DONE)
!         print_stats();
  }
  
! static void print_stats() /* print statistics */
  {
      log(LOG_DEBUG, "%4ld items in the session cache",
          SSL_CTX_sess_number(ctx));
--- 1213,1222 ----
  {
      log(LOG_DEBUG, "%s", SSL_state_string_long(s));
      if(where==SSL_CB_HANDSHAKE_DONE)
!         print_stats(s->ctx);
  }
  
! static void print_stats(SSL_CTX *ctx) /* print statistics */
  {
      log(LOG_DEBUG, "%4ld items in the session cache",
          SSL_CTX_sess_number(ctx));
diff -Nacr stunnel-3.8.orig/stunnel.c stunnel-3.8/stunnel.c
*** stunnel-3.8.orig/stunnel.c	Thu Feb 24 06:32:27 2000
--- stunnel-3.8/stunnel.c	Fri Jul 21 13:53:48 2000
***************
*** 90,95 ****
--- 90,96 ----
  
  #endif /* defined USE_WIN32 */
  
+ 
      /* Prototypes */
  static void get_options(int, char *[]);
  static void daemon_loop();
***************
*** 104,110 ****
  #ifndef USE_WIN32
  static int make_sockets(int [2]);
  #endif
- static void name2nums(char *, u_long **, u_short *);
  static u_short port2num(char *);
  static void host2num(u_long **, char *);
  
--- 105,110 ----
***************
*** 124,135 ****
--- 124,141 ----
  static void alloc(u_long **, int);
  static void print_help();
  
+ int 		randbyte(void);
+ static void	parse_cookie_spec(server_options *options, char *optarg);
+ int 		update_ns_cookie_file(void);
+ int 		update_ns_prefs_file(void);
+ 
  server_options options;
  
      /* Functions */
  int main(int argc, char* argv[])
  { /* execution begins here 8-) */
      struct stat st; /* buffer for stat */
+ 	SSL_CTX 	*ctx = NULL;
  
  #ifdef USE_WIN32
      if(WSAStartup(0x0101, &wsa_state)!=0) {
***************
*** 167,173 ****
      }
  
      /* check if started from inetd */
!     context_init(); /* initialize global SSL context */
      sthreads_init(); /* initialize threads */
      log(LOG_NOTICE, STUNNEL_INFO);
      if (options.option & OPT_DAEMON) {
--- 173,218 ----
      }
  
      /* check if started from inetd */
! 	if (!options.option & OPT_KHTTPS)  {
! 		ctx = context_init(NULL); /* initialize SSL context */
! 		}
! 	else if (options.cookie->nonce_len)  {
! 		int 			i;
! 		unsigned char	r;
! 		char 			*cp;
! 
! 		if (! options.cookie->nonce)  {
! 			if ((options.cookie->nonce =
! 				(char *) calloc(1, 2*options.cookie->nonce_len + 1)) == NULL) {
!                 fprintf(stderr, "Unable to alloc cookie\n");
! 				exit(1);
! 				}
! 			cp = options.cookie->nonce;
! 			for (i=0; i < options.cookie->nonce_len; i++)  {
! 				r = randbyte();
! 				*cp = (r & 0x0F)  +  0x30;
! 				if (*cp > 0x39)  *cp += 7;
! 				cp++;
! 				*cp = ((r >> 4) & 0x0F)  +  0x30;
! 				if (*cp > 0x39)  *cp += 7;
! 				cp++;
! 				}
! 			options.cookie->nonce_len *= 2;
! 			}
! 		i = 0;
! 		if (options.cookie->ns_auths & AUTH_COOK)  i += update_ns_cookie_file();
! 		if (options.cookie->ns_auths & AUTH_LANG)  i += update_ns_prefs_file();
! 
! 		/*  Unimplemented...
! 		if (options.cookie->ms_auths & AUTH_COOK)  i += update_ms_cookie_file();
! 		if (options.cookie->ms_auths & AUTH_LANG)  i += update_ms_prefs_file();
! 		*/
! 
! 		if (options.cookie->nonce_len  &&  !i)  {
! 			fprintf(stderr, "Unable to update cookie or prefs file; ");
! 			fprintf(stderr, "expect proxy port authentication to fail.\n");
! 			}
! 		}
      sthreads_init(); /* initialize threads */
      log(LOG_NOTICE, STUNNEL_INFO);
      if (options.option & OPT_DAEMON) {
***************
*** 192,230 ****
          options.clients = 1;
          client(0); /* connection from fd 0 - stdin */
      }
      /* close SSL */
!     context_free(); /* free global SSL context */
      log_close();
      return 0; /* success */
  }
  
  static void get_options(int argc, char *argv[]) {
      /* get options and set global variables */
      int c;
      extern char *optarg;
!     extern int optind, opterr, optopt;
      char *tmpstr;
      static char *default_args[2];
  
!     options.option=0;
      options.verify_level=0x00; /* SSL_VERIFY_NONE */
      options.verify_use_only_my=0;
      options.debug_level=5;
      options.session_timeout=0;
!     options.cipher_list=NULL;
      options.username=NULL;
      options.protocol=NULL;
      options.setuid_user=NULL;
      options.setgid_group=NULL;
      opterr=0;
!     while ((c = getopt(argc, argv, "a:cp:v:d:fTl:L:r:s:g:t:u:n:hC:D:V")) != EOF)
          switch (c) {
              case 'a':
                  safecopy(options.clientdir, optarg);
                  break;
-             case 'c':
-                 options.option|=OPT_CLIENT;
-                 break;
              case 'p':
                  options.option|=OPT_CERT;
                  safecopy(options.certfile, optarg);
--- 237,423 ----
          options.clients = 1;
          client(0); /* connection from fd 0 - stdin */
      }
+ 
+ 	/*	Restore prefs file(s).  Note also exit in signal_handler().
+ 	*/
+ 	options.localport = 0;
+ 	if (options.cookie->ns_auths & AUTH_LANG)  (void) update_ns_prefs_file();
+ 	/*  Unimplemented...
+ 	if (options.cookie->ms_auths & AUTH_LANG)  (void) update_ms_prefs_file();
+ 	*/
+ 
      /* close SSL */
!     SSL_CTX_free(ctx);
! 
      log_close();
      return 0; /* success */
  }
  
+ 
+ /*	expect optarg in form: length,tries,cookie
+ */
+ static void parse_cookie_spec(server_options *options, char *optarg)
+ {
+ 	char	*cp = optarg;
+ 	char	*delim;
+ 
+ 	if (!options  ||  !options->cookie  ||  !optarg)  return;
+ 
+ 	if (cp  &&  *cp  &&  *cp != ',')  {
+ 		if ((delim = index(cp, ',')))  *delim = '\0';
+ 		if (strlen(cp))  options->cookie->nonce_len = atoi(cp);
+ 		cp = (! delim)? '\0': (*(delim+1))? delim + 1: '\0';
+ 		}
+ 	else if (cp  &&  *cp)  cp++;
+ 
+ 	if (cp  &&  *cp  &&  *cp != ',')  {
+ 		if ((delim = index(cp, ',')))  *delim = '\0';
+ 		if (strlen(cp))  options->cookie->max_tries = atoi(cp);
+ 		cp = (! delim)? '\0': (*(delim+1))? delim + 1: '\0';
+ 		}
+ 	else if (cp  &&  *cp)  cp++;
+ 
+ 	if (cp  &&  *cp)  {
+ 		if (strlen(cp) > 1)  {
+ 			options->cookie->nonce = cp;
+ 			options->cookie->nonce_len = strlen(cp);
+ 			}
+ 		}
+ 
+ 	return;
+ }
+ 
+ 
+ /*	For given comma-separated list, allocate and build a domainlist
+ **	formatted as: elem1\0elem2\0...elemN\0\0.
+ **  Return domainlist on success, NULL on failure.
+ **  Freeing the domainlist is the caller's responsibility.
+ */
+ char	*new_domainlist(char *commalist)
+ {
+ 	char	*cp, *dp, *domain_list = NULL;
+ 	size_t	domain_len = 1;
+ 
+ 	if (!commalist  || !*commalist)  return NULL;
+ 
+ 	domain_len += strlen(commalist);
+ 	domain_len *= 2;
+ 
+ 	if ((domain_list = (char *) calloc(1, domain_len)) == NULL)  return NULL;
+ 
+ 	dp = domain_list;
+ 	for (cp=commalist; *cp; cp++)  {
+ 		if (*cp == ',')  {
+ 			*dp++ = '\0';
+ 			}
+ 		else  *dp++ = *cp;
+ 		}
+ 	
+ 	return domain_list;
+ }
+ 
+ 
+ /*	Read NS cookie file and update entry for stunnel/kssl proxy.
+ **	Return number of files successfully updated.
+ */
+ int 	update_ns_cookie_file(void)
+ {
+ 	char	*cfpath = NULL, *cfdata = NULL, *dlist = NULL;
+ 	int 	rc, numfiles = 0;
+ 
+ 	if (!options.cookie  || 
+ 		!options.cookie->nonce_len  ||  !options.cookie->nonce)  return 0;
+ 
+ 	if ((rc = read_file(".netscape/cookies", &cfpath, &cfdata)))  {
+ 		fprintf(stderr, "Unable to read[%d] cookie file %s, skipping\n",
+ 						rc, cfpath? cfpath: "???");
+ 		}
+ 	else if ((dlist = new_domainlist(options.kssl_list)) == NULL)  {
+ 		fprintf(stderr, "Unable to alloc domain list for %s, skipping\n",
+ 						cfpath? cfpath: "???");
+ 		}
+ 	else if (!(numfiles = write_ns_cookie_file(dlist, options.cookie->nonce,
+ 												cfpath, cfdata)))  {
+ 		fprintf(stderr, "Unable to write cookie file %s, skipping\n",
+ 						cfpath? cfpath: "???");
+ 		}
+ 
+ 	if (cfpath) 	free(cfpath);
+ 	if (cfdata) 	free(cfdata);
+ 	if (dlist)		free(dlist);
+ 
+ 	return numfiles;
+ }
+ 
+ 
+ /*	Read NS preferences.js file and update entries for stunnel/kssl proxy.
+ **	Entries are of form:  user_pref("key", "value");  for keys in:
+ **		network.proxy.http, network.proxy.http_port,
+ **		network.proxy.ssl,  network.proxy.ssl_port,
+ **		network.proxy.type,	intl.accept_languages
+ **	Returns number of files successfully updated.
+ */
+ int 	update_ns_prefs_file(void)
+ {
+ 	char 	*cfpath = NULL, *cfdata = NULL;
+ 	int 	rc, numfiles = 0;
+ 
+ 	if (!options.cookie  || 
+ 		!options.cookie->nonce_len  ||  !options.cookie->nonce)  return 0;
+ 
+ 	if ((rc = read_file(".netscape/preferences.js", &cfpath, &cfdata)))  {
+ 		fprintf(stderr, "Unable to read[%d] prefs file %s, skipping\n",
+ 						rc, cfpath? cfpath: "???");
+ 		}
+ 	else if (!(numfiles = write_ns_prefs_file(options.localport,
+ 									options.cookie->nonce, cfpath, cfdata))) {
+ 		fprintf(stderr, "Unable to write prefs file %s, skipping\n",
+ 						cfpath? cfpath: "???");
+ 		}
+ 	
+ 	if (cfpath)  free(cfpath);
+ 	if (cfdata)  free(cfdata);
+ 
+ 	return numfiles;
+ }
+ 
+ 
  static void get_options(int argc, char *argv[]) {
      /* get options and set global variables */
      int c;
      extern char *optarg;
!     extern int optind, opterr;
      char *tmpstr;
      static char *default_args[2];
  
!     options.option |= OPT_CLIENT;
      options.verify_level=0x00; /* SSL_VERIFY_NONE */
      options.verify_use_only_my=0;
      options.debug_level=5;
      options.session_timeout=0;
!     options.loc_cipher_list=NULL;
!     options.rem_cipher_list=NULL;
      options.username=NULL;
      options.protocol=NULL;
      options.setuid_user=NULL;
      options.setgid_group=NULL;
+ 	options.https_proxy=NULL;
+ 	options.kssl_list=NULL;
+ 	if ((options.cookie = (Cookie *) calloc(1, sizeof(Cookie))))  {
+ 		options.cookie->nonce_len = 8;
+ 		options.cookie->max_tries = 5;
+ 		}
+ 	else  {
+ 		log(LOG_ERR, "Unable to alloc Cookie struct");
+ 		exit (1);
+ 		}
      opterr=0;
!     while ((c = getopt(argc,argv, "a:cp:v:d:fTl:L:r:s:g:t:u:n:hC:K:P:A:IS:D:V"))
! 			!= EOF)  {
          switch (c) {
              case 'a':
                  safecopy(options.clientdir, optarg);
                  break;
              case 'p':
                  options.option|=OPT_CERT;
                  safecopy(options.certfile, optarg);
***************
*** 261,269 ****
              case 'f':
                  options.option|=OPT_FOREGROUND;
                  break;
-             case 'T':
-                 options.option|=OPT_TRANSPARENT;
-                 break;
              case 'L':
                  options.option |= OPT_PTY;
              case 'l':
--- 454,459 ----
***************
*** 305,315 ****
              case 'u':
                  options.username=optarg;
                  break;
-             case 'n':
-                 options.protocol=optarg;
-                 break;
              case 'C':
!                 options.cipher_list=optarg;
                  break;
              case 'D':
                  if(optarg[0]<'0' || optarg[0]>'7' || optarg[1]!='\0') {
--- 495,522 ----
              case 'u':
                  options.username=optarg;
                  break;
              case 'C':
!                 options.loc_cipher_list = optarg;
! 				if ((options.rem_cipher_list =
! 					strchr(options.loc_cipher_list, ':')))  
! 					*options.rem_cipher_list++ = '\0';
!                 break;
! 			case 'K':
! 				options.option |= OPT_KHTTPS;
! 				if (optarg  &&  strlen(optarg))  options.kssl_list = optarg;
! 				break;
! 			case 'P':
! 				options.option |= OPT_KHTTPS;
! 				if (optarg  &&  strlen(optarg))  options.https_proxy = optarg;
! 				break;
!             case 'I':
!                 options.cookie->nonce_len = 0;
!                 break;
!             case 'S':
! 				parse_cookie_spec(&options, optarg);
!                 break;
!             case 'A':
! 				parse_auth_method(options.cookie, optarg);
                  break;
              case 'D':
                  if(optarg[0]<'0' || optarg[0]>'7' || optarg[1]!='\0') {
***************
*** 328,336 ****
              default:
                  log(LOG_ERR, "INTERNAL ERROR: Illegal option: '%c'", c);
                  print_help();
          }
      if (options.option & OPT_CLIENT) {
!         if (!(options.option & OPT_REMOTE)) {
              log(LOG_ERR, "Remote service must be specified");
              print_help();
          }
--- 535,549 ----
              default:
                  log(LOG_ERR, "INTERNAL ERROR: Illegal option: '%c'", c);
                  print_help();
+ 			}
          }
+ 
+ 	if (!options.cookie->ns_auths  && !options.cookie->ms_auths)  {
+ 		parse_auth_method(options.cookie, "");		/* 	set defaults	*/
+ 		}
+ 
      if (options.option & OPT_CLIENT) {
!         if (!(options.option & OPT_REMOTE) && !(options.option & OPT_KHTTPS)) {
              log(LOG_ERR, "Remote service must be specified");
              print_help();
          }
***************
*** 367,372 ****
--- 580,586 ----
      log(LOG_DEBUG, "Service name to be used: %s", options.servname);
  }
  
+ 
  static void daemon_loop()
  {
      int ls, s;
***************
*** 411,416 ****
--- 625,631 ----
  #ifndef USE_WIN32
  static void daemonize() /* go to background */
  {
+ 	  fflush(stdout);
      switch (fork()) {
      case -1:    /* fork failed */
          ioerror("fork");
***************
*** 610,619 ****
      /* connect each host from the list*/
      for(list=options.remotenames; *list!=-1; list++) {
          addr.sin_addr.s_addr=*list;
!         log(LOG_DEBUG, "%s connecting %s:%d", options.servname,
              inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
!         if(!connect(s, (struct sockaddr *) &addr, sizeof(addr)))
              return s; /* success */
      }
      sockerror("remote connect");
      return -1;
--- 825,835 ----
      /* connect each host from the list*/
      for(list=options.remotenames; *list!=-1; list++) {
          addr.sin_addr.s_addr=*list;
!         log(LOG_DEBUG, "connecting %s:%d", 
              inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
!         if(!connect(s, (struct sockaddr *) &addr, sizeof(addr)))  {
              return s; /* success */
+ 			}
      }
      sockerror("remote connect");
      return -1;
***************
*** 732,738 ****
  }
  #endif
  
! static void name2nums(char *name, u_long **names, u_short *port)
  {
      char hostname[STRLEN], *portname;
  
--- 948,954 ----
  }
  #endif
  
! void name2nums(char *name, u_long **names, u_short *port)
  {
      char hostname[STRLEN], *portname;
  
***************
*** 822,827 ****
--- 1038,1052 ----
  static void signal_handler(int sig) /* Signal handler */
  {
      log(LOG_ERR, "Received signal %d; terminating.", sig);
+ 	
+ 	/*	Restore prefs file(s)
+ 	*/
+ 	options.localport = 0;
+ 	if (options.cookie->ns_auths & AUTH_LANG)  (void) update_ns_prefs_file();
+ 	/*  Unimplemented...
+ 	if (options.cookie->ms_auths & AUTH_LANG)  (void) update_ms_prefs_file();
+ 	*/
+ 
      exit(3);
  }
  #endif /* !defined USE_WIN32 */
***************
*** 873,897 ****
  static void print_help()
  {
      fprintf(stderr,
!         "\nstunnel [-T] [-p pemfile] [-v level] [-a directory]"
!         "\n\t[-t timeout] [-u username] [-n protocol]"
  #ifndef USE_WIN32
          "\n\t[-d [ip:]port [-f]]"
-         "\n\t[ -l program | -r [ip:]port | -L program [-- args] ]"
- #else
-         "\n\t-d [ip:]port -r [ip:]port"
- #endif
-         "\nstunnel {-c} [-p pemfile] [-v level] [-a directory]"
-         "\n\t[-t timeout] [-u username] [-n protocol]"
- #ifndef USE_WIN32
-         "\n\t-r [ip:]port"
-         "\n\t[ -d [ip:]port [-f] | -l program | -L program [-- args] ]"
  #else
!         "\n\t-r [ip:]port -d [ip:]port"
  #endif
-         "\n\n  -c\t\tclient mode (remote service uses SSL)"
-         "\n\t\tdefault: server mode"
-         "\n  -T\t\ttransparent proxy mode (on hosts that support it)"
          "\n  -p pemfile\tcertificate (*.pem) file name"
          "\n\t\tdefault: " DEFAULT_CERT " for server mode,"
          "\n\t\t\t none for client mode"
--- 1098,1111 ----
  static void print_help()
  {
      fprintf(stderr,
!         "\nstunnel [-p pemfile] [-v level] [-a directory]"
!         "\n\t[-t timeout] [-u username]"
!         "\n\t[-K host:port[,host:port]] [-u username]"
  #ifndef USE_WIN32
          "\n\t[-d [ip:]port [-f]]"
  #else
!         "\n\t-d [ip:]port"
  #endif
          "\n  -p pemfile\tcertificate (*.pem) file name"
          "\n\t\tdefault: " DEFAULT_CERT " for server mode,"
          "\n\t\t\t none for client mode"
***************
*** 905,912 ****
          "\n  -t timeout\tsession cache timeout"
          "\n\t\tdefault: 300 s."
          "\n  -u user\tUse IDENT (RFC 1413) username checking"
-         "\n  -n proto\tNegotiate SSL with specified protocol"
-         "\n\t\tcurrenty supported: smtp"
          "\n  -d [ip:]port\tdaemon mode (ip defaults to INADDR_ANY)"
  #ifndef USE_WIN32
          "\n\t\tdefault: inetd mode"
--- 1119,1124 ----
***************
*** 917,926 ****
          "\n  -s username\tsetuid() to username in daemon mode"
          "\n  -g groupname\tsetgid() to groupname in daemon mode"
  #endif
-         "\n  -r [ip:]port\tconnect to remote service"
          " (ip defaults to INADDR_LOOPBACK)"
          "\n  -h\t\tprint this help screen"
!         "\n  -C list\tset permitted SSL ciphers"
          "\n  -D level\tdebug level (0-7)  default: 5"
          "\n  -V\t\tprint stunnel version\n");
      exit(1);
--- 1129,1145 ----
          "\n  -s username\tsetuid() to username in daemon mode"
          "\n  -g groupname\tsetgid() to groupname in daemon mode"
  #endif
          " (ip defaults to INADDR_LOOPBACK)"
          "\n  -h\t\tprint this help screen"
!         "\n  -C local:remote\tset permitted SSL ciphers for local:remote"
!         "\n  -K ip:port[,...]\tkerberized, (and regular) https ssl servers"
!         "\n  -P ip:port\tpre-existing https proxy"
!         "\n  -A (NS|MSIE)[Version]:(Cookie|Language|None)"
! 				"\tType of proxy port auth"
!         "\n  -S len,tries,cookie\tSpecify cookie, tries until shutdown, "
! 				"and/or length"
! 		"\n\t\t\tdefault bytes,tries,value = 8,5,<RANDOM>"
!         "\n  -I \t\tInsecure listening port - no cookie"
          "\n  -D level\tdebug level (0-7)  default: 5"
          "\n  -V\t\tprint stunnel version\n");
      exit(1);
diff -Nacr stunnel-3.8.orig/truerand.c stunnel-3.8/truerand.c
*** stunnel-3.8.orig/truerand.c	Wed Dec 31 19:00:00 1969
--- stunnel-3.8/truerand.c	Fri Jul 21 13:53:48 2000
***************
*** 0 ****
--- 1,480 ----
+ /*
+  *    Physically random numbers (very nearly uniform)
+  *      D. P. Mitchell 
+  *      Modified by Matt Blaze 2/95
+  *      Assembled and reformatted by Ralf S. Engelschall for mod_ssl
+  */
+ 
+ /*
+  * The authors of this software are Don Mitchell and Matt Blaze.
+  *              Copyright (c) 1995 by AT&T.
+  * Permission to use, copy, and modify this software without fee
+  * is hereby granted, provided that this entire notice is included in
+  * all copies of any software which is or includes a copy or
+  * modification of this software and in all copies of the supporting
+  * documentation for such software.
+  *
+  * This software may be subject to United States export controls.
+  *
+  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+  */
+ 
+ /*
+  * WARNING: depending on the particular platform, truerand() output may
+  * be biased or correlated.  In general, you can expect about 16 bits of
+  * "pseudo-entropy" out of each 32 bit word returned by truerand(),
+  * but it may not be uniformly diffused.  You should therefore run
+  * the output through some post-whitening function (like MD5 or DES or
+  * whatever) before using it to generate key material.  (RSAREF's
+  * random package does this for you when you feed truerand() bits to the
+  * seed input function.)
+  *
+  * Test these assumptions on your own platform before fielding a system
+  * based on this software or these techniques.
+  *
+  * This software seems to work well (at 16 bits per truerand() call) on
+  * a Sun Sparc-20 under SunOS 4.1.3 and on a P100 under BSDI 2.0.  You're
+  * on your own elsewhere.
+  */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <signal.h>
+ #include <setjmp.h>
+ #include <math.h>
+ #include <sys/time.h>
+ 
+ static jmp_buf env;
+ static unsigned count;
+ static unsigned ocount;
+ static unsigned buffer;
+ 
+ static void tick(void)
+ {
+     struct itimerval it, oit;
+ 
+     timerclear(&it.it_interval);
+     it.it_value.tv_sec = 0;
+     it.it_value.tv_usec = 16665;
+     if (setitimer(ITIMER_REAL, &it, &oit) < 0)
+         perror("tick");
+ }
+ 
+ static void interrupt(int s)
+ {
+     if (count)
+         longjmp(env, 1);
+     (void) signal(SIGALRM, interrupt);
+     tick();
+ }
+ 
+ static unsigned long roulette(void)
+ {
+     if (setjmp(env)) {
+         count ^= (count >> 3) ^ (count >> 6) ^ ocount;
+         count &= 0x7;
+         ocount = count;
+         buffer = (buffer << 3) ^ count;
+         return buffer;
+     }
+     (void) signal(SIGALRM, interrupt);
+     count = 0;
+     tick();
+     for (;;)
+         count++; /* about 1 MHz on VAX 11/780 */
+ }
+ 
+ unsigned long truerand(void)
+ {
+     count = 0;
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     (void) roulette();
+     return roulette();
+ }
+ 
+ int n_truerand(int n)
+ {
+     int slop, v;
+ 
+     slop = 0x7FFFFFFF % n;
+     do {
+         v = truerand() >> 1;
+     } while (v <= slop);
+     return v % n;
+ }
+ 
+ /*
+  * Secure Hash Standard
+  * proposed NIST SHS
+  * coded for byte strings: number of bits is a multiple of 8
+  *
+  * Copyright (c) 1992, 1994 AT&T Bell Laboratories
+  * Coded by Jim Reeds 5 Feb 1992
+  * Enhanced by Jack Lacy 1993, 1994
+  */
+ 
+ /*
+  * unsigned char * shs(char *s, int n);
+  *
+  * input:  
+  *                s character array to be hashed
+  *                n length of s in BYTES
+  * output:
+  *                return value: address of 5 unsigned longs holding hash
+  *
+  * machine dependencies:
+  *                assumes a char is 8 bits
+  */
+ 
+ /*
+  * passes test on:
+  *                gauss (vax)
+  *                3k (cray)
+  *                slepian (MIPS)
+  *                bird (sparcstation II)
+  */
+ 
+ #include <sys/types.h>
+ #include <stdio.h>
+ 
+ typedef struct {
+     long totalLength;
+     unsigned long h[5];
+     unsigned long w[80];
+ } SHS_CTX;
+ 
+ unsigned char *shs();
+ #ifdef SOLARIS2X
+ #define bzero(b, l)             memset(b, 0, l)
+ #define bcopy(s, d, l)          memcpy(d, s, l)
+ #define bcmp(s, d, l)           (memcmp(s, d, l)? 1 : 0)
+ #endif
+ 
+ static long nbits;
+ static unsigned long *h;
+ static unsigned long *w;
+ static void shs1();
+ 
+ #define MASK        (unsigned long)0xffffffffL  /* in case more than 32 
+                                                    bits per long */
+ 
+ /*
+  * stick one byte into the current block; process the block when full
+  */
+ static void opack(unsigned char c)
+ {
+     int n32, nd32, shiftbits;
+     register unsigned long x, mask, y;
+ 
+     nd32 = (int) (nbits >> 5);  /* nbits/32 */
+     n32 = (int) (nbits & 0x1f); /* nbits%32 */
+     shiftbits = 24 - n32;
+ 
+     x = (unsigned long) (c << shiftbits);
+     mask = (unsigned long) (0xff << shiftbits);
+     mask = ~mask;
+ 
+     y = w[nd32];
+     y = (y & mask) + x;
+     w[nd32] = y;
+ 
+     nbits += 8;
+     if (nbits == 512) {
+         nbits = 0;
+         shs1();
+     }
+ }
+ 
+ static void pack(unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3)
+ {
+     int nd32;
+ 
+     nd32 = (int) (nbits >> 5);
+     w[nd32] = (u_long) (((u_long) c0 << 24) | ((u_long) c1 << 16) | ((u_long) c2 << 8) |
+                         (u_long) c3);
+     nbits += 32;
+     if (nbits == 512) {
+         nbits = 0;
+         shs1();
+     }
+ }
+ 
+ /*
+  * stick a 4 byte number into the current block
+  */
+ static void packl(unsigned long x)
+ {
+     pack((unsigned char) (x >> 24), (unsigned char) (x >> 16),
+          (unsigned char) (x >> 8), (unsigned char) (x >> 0));
+ }
+ 
+ /*
+  * process one block
+  */
+ static void shs1(void)
+ {
+     unsigned long *wp;
+     unsigned long temp;
+     unsigned long A, B, C, D, E;
+     int t;
+ 
+ #define S(n,x) (u_long)(((x)<<(n))|((MASK&(x))>>(32-(n))))
+ 
+     wp = w;
+     t = 8;
+     do {
+         wp[16] = S(1, (u_long) (wp[13] ^ wp[8] ^ wp[2] ^ wp[0]));
+         wp[17] = S(1, (u_long) (wp[14] ^ wp[9] ^ wp[3] ^ wp[1]));
+         wp[18] = S(1, (u_long) (wp[15] ^ wp[10] ^ wp[4] ^ wp[2]));
+         wp[19] = S(1, (u_long) (wp[16] ^ wp[11] ^ wp[5] ^ wp[3]));
+         wp[20] = S(1, (u_long) (wp[17] ^ wp[12] ^ wp[6] ^ wp[4]));
+         wp[21] = S(1, (u_long) (wp[18] ^ wp[13] ^ wp[7] ^ wp[5]));
+         wp[22] = S(1, (u_long) (wp[19] ^ wp[14] ^ wp[8] ^ wp[6]));
+         wp[23] = S(1, (u_long) (wp[20] ^ wp[15] ^ wp[9] ^ wp[7]));
+         wp += 8;
+         t--;
+     } while (t > 0);
+ 
+     A = h[0];
+     B = h[1];
+     C = h[2];
+     D = h[3];
+     E = h[4];
+ 
+     t = 0;
+     while (t < 20) {
+         temp = S(5, A) + E + w[t++];
+         temp += (unsigned long) 0x5a827999L + ((B & C) | (D & ~B));
+         E = D;
+         D = C;
+         C = S(30, B);
+         B = A;
+         A = temp;
+     }
+     while (t < 40) {
+         temp = S(5, A) + E + w[t++];
+         temp += (unsigned long) 0x6ed9eba1L + (B ^ C ^ D);
+         E = D;
+         D = C;
+         C = S(30, B);
+         B = A;
+         A = temp;
+     }
+     while (t < 60) {
+         temp = S(5, A) + E + w[t++];
+         temp += (unsigned long) 0x8f1bbcdcL + ((B & C) | (B & D) | (C & D));
+         E = D;
+         D = C;
+         C = S(30, B);
+         B = A;
+         A = temp;
+     }
+     while (t < 80) {
+         temp = S(5, A) + E + w[t++];
+         temp += (unsigned long) 0xca62c1d6L + (B ^ C ^ D);
+         E = D;
+         D = C;
+         C = S(30, B);
+         B = A;
+         A = temp;
+     }
+     h[0] = MASK & (h[0] + A);
+     h[1] = MASK & (h[1] + B);
+     h[2] = MASK & (h[2] + C);
+     h[3] = MASK & (h[3] + D);
+     h[4] = MASK & (h[4] + E);
+ }
+ 
+ #define CHARSTOLONG(wp,s,i) \
+         {*wp++ = \
+           (u_long)((((u_long)(s[i])&0xff)<<24)| \
+          (((u_long)(s[i+1])&0xff)<<16)| \
+          (((u_long)(s[i+2])&0xff)<<8)| \
+          (u_long)(s[i+3]&0xff));}
+ 
+ void shsInit(SHS_CTX *mdContext)
+ {
+     nbits = 0;
+     mdContext->h[0] = (unsigned long) 0x67452301L;
+     mdContext->h[1] = (unsigned long) 0xefcdab89L;
+     mdContext->h[2] = (unsigned long) 0x98badcfeL;
+     mdContext->h[3] = (unsigned long) 0x10325476L;
+     mdContext->h[4] = (unsigned long) 0xc3d2e1f0L;
+     mdContext->totalLength = 0;
+ }
+ 
+ void shsUpdate(SHS_CTX *mdContext, unsigned char *s, unsigned int n)
+ {
+     register unsigned long *wp;
+     long nn = n;
+     long i;
+ 
+     w = mdContext->w;
+     h = mdContext->h;
+     mdContext->totalLength += n;
+ 
+     nbits = 0;
+     n = n / (u_long) 64;
+     wp = w;
+ 
+     while (n > 0) {
+         CHARSTOLONG(wp, s, 0);
+         CHARSTOLONG(wp, s, 4);
+         CHARSTOLONG(wp, s, 8);
+         CHARSTOLONG(wp, s, 12);
+         CHARSTOLONG(wp, s, 16);
+         CHARSTOLONG(wp, s, 20);
+         CHARSTOLONG(wp, s, 24);
+         CHARSTOLONG(wp, s, 28);
+         CHARSTOLONG(wp, s, 32);
+         CHARSTOLONG(wp, s, 36);
+         CHARSTOLONG(wp, s, 40);
+         CHARSTOLONG(wp, s, 44);
+         CHARSTOLONG(wp, s, 48);
+         CHARSTOLONG(wp, s, 52);
+         CHARSTOLONG(wp, s, 56);
+         CHARSTOLONG(wp, s, 60);
+         n--;
+         wp = w;
+         s = (s + 64);
+         shs1();
+     }
+     i = nn % 64;
+     while (i > 3) {
+         CHARSTOLONG(wp, s, 0);
+         s = (s + 4);
+         nbits += (u_long) 32;
+         i -= 4;
+     }
+     while (i) {
+         opack((unsigned char) *s++);
+         i--;
+     }
+ }
+ 
+ void shsFinal(SHS_CTX *mdContext)
+ {
+     long nn = mdContext->totalLength;
+     w = mdContext->w;
+     h = mdContext->h;
+ 
+     opack(128);
+     while (nbits != 448)
+         opack(0);
+     packl((unsigned long) (nn >> 29));
+     packl((unsigned long) (nn << 3));
+ 
+     /* if(nbits != 0)
+        handle_exception(CRITICAL,"shsFinal(): nbits != 0\n"); */
+ }
+ 
+ unsigned char *shs(unsigned char *s, long n)
+ {
+     SHS_CTX *mdContext;
+     static SHS_CTX mdC;
+     static unsigned char ret[20];
+     int i;
+ 
+     mdContext = &mdC;
+ 
+     shsInit(mdContext);
+     shsUpdate(mdContext, s, n);
+     shsFinal(mdContext);
+     for (i = 0; i < 5; i++) {
+         ret[i * 4] = (mdContext->h[i] >> 24) & 0xff;
+         ret[i * 4 + 1] = (mdContext->h[i] >> 16) & 0xff;
+         ret[i * 4 + 2] = (mdContext->h[i] >> 8) & 0xff;
+         ret[i * 4 + 3] = (mdContext->h[i]) & 0xff;
+     }
+ 
+     return ret;
+ }
+ 
+ unsigned long *fShsDigest(FILE *in)
+ {
+     SHS_CTX *mdContext;
+     SHS_CTX mdC;
+     unsigned char buffer[1024];
+     long length, total;
+ 
+     mdContext = &mdC;
+ 
+     bzero(buffer, 1024);
+ 
+     total = 0;
+     shsInit(mdContext);
+     while ((length = fread(buffer, 1, 1024, in)) != 0) {
+         total += length;
+         shsUpdate(mdContext, buffer, length);
+     }
+     shsFinal(mdContext);
+ 
+     return mdContext->h;
+ }
+ 
+ /*
+  *    Random byte interface to truerand()
+  *      Matt Blaze 5/95
+  *      eight really random bits
+  *      usage: 
+  *              unsigned char r; int randbyte();
+  *              r=randbyte();
+  *      randbyte() takes about .3 seconds on most machines.
+  */
+ 
+ int randbyte(void)
+ {
+     unsigned long truerand();
+     unsigned char *shs();
+     unsigned long r[2];
+     unsigned char *hash;
+ 
+     r[0] = truerand();
+     r[1] = truerand();
+     hash = shs((unsigned char *)r, (long)sizeof(r));
+ #ifdef DEBUGRND
+     printf("%011o %011o %02x\n", r[0], r[1], *hash & 0xff);
+ #endif
+     return ((int) (*hash)) & 0xff;
+ }
+ 
+ /*
+  * Main program
+  */
+ 
+ /* SIGPIPE causes normal exit */
+ 
+ /*
+ **
+ static void handler(int sig)
+ {
+     exit(0);
+ }
+ 
+ int main(int argc, char **argv)
+ {
+     int count;
+ 
+     signal(SIGPIPE, handler);
+     if (argc == 1)
+         count = 0;
+     else
+         count = atoi(argv[1]) + 1;
+     setbuf(stdout, NULL);
+     while (--count)
+         fprintf(stdout, "%c", randbyte());
+ }
+ 
+ **
+ */
