This commit is contained in:
Michał Trojnara 2021-12-22 21:44:52 +01:00
Родитель e3f8472f8d
Коммит 689968d14f
193 изменённых файлов: 7950 добавлений и 10517 удалений

Просмотреть файл

@ -20,6 +20,7 @@
--prefix=/opt/openssl-mingw64 mingw64 shared enable-capieng
sed -i 's/"\$(OPENSSLDIR)/"..\/config/' Makefile
sed -i 's/"\$(ENGINESDIR)/"..\/engines/' Makefile
sed -i 's/"\$(MODULESDIR)/"..\/ossl-modules/' Makefile
make
sudo make install
sudo cp ms/applink.c /opt/openssl-mingw64/include/openssl/
@ -54,6 +55,7 @@
--prefix=/opt/openssl-mingw mingw shared enable-capieng
sed -i 's/"\$(OPENSSLDIR)/"..\/config/' Makefile
sed -i 's/"\$(ENGINESDIR)/"..\/engines/' Makefile
sed -i 's/"\$(MODULESDIR)/"..\/ossl-modules/' Makefile
make
sudo make install
sudo cp ms/applink.c /opt/openssl-mingw/include/openssl/

Просмотреть файл

@ -16,7 +16,7 @@ doc_DATA += INSTALL.W32.md INSTALL.WCE.md INSTALL.FIPS.md
EXTRA_DIST = .travis.yml $(doc_DATA)
distcleancheck_listfiles = find -type f -exec sh -c 'test -f $(srcdir)/{} || echo {}' ';'
distcleancheck_listfiles = find . -type f -exec sh -c 'test -f $(srcdir)/{} || echo {}' ';'
distclean-local:
rm -rf autom4te.cache

Просмотреть файл

@ -370,7 +370,7 @@ doc_DATA = README.md TODO.md COPYING.md AUTHORS.md NEWS.md PORTS.md \
BUGS.md COPYRIGHT.md CREDITS.md INSTALL.W32.md INSTALL.WCE.md \
INSTALL.FIPS.md
EXTRA_DIST = .travis.yml $(doc_DATA)
distcleancheck_listfiles = find -type f -exec sh -c 'test -f $(srcdir)/{} || echo {}' ';'
distcleancheck_listfiles = find . -type f -exec sh -c 'test -f $(srcdir)/{} || echo {}' ';'
all: all-recursive
.SUFFIXES:

26
NEWS.md
Просмотреть файл

@ -1,6 +1,31 @@
# stunnel change log
### Version 5.61, 2021.12.22, urgency: LOW
* New features sponsored by the University of Maryland
- Added new "protocol = capwin" and "protocol = capwinctrl"
configuration file options.
* New features for the Windows platform
- Added client mode allowing authenticated users to view
logs, reconfigure and terminate running stunnel services.
- Added support for multiple GUI and service instances
distinguised by the location of stunnel.conf.
- Improved log window scrolling.
- Added a new 'Pause auto-scroll' GUI checkbox.
- Double click on the icon tray replaced with single click.
- OpenSSL DLLs updated to version 3.0.1.
* Other new features
- Rewritten the testing framework in python (thx to
Peter Pentchev for inspiration and initial framework).
- Added support for missing SSL_set_options() values.
- Updated stunnel.spec to support RHEL8.
* Bugfixes
- Fixed OpenSSL 3.0 build.
- Fixed reloading configuration with
"systemctl reload stunnel.service".
- Fixed incorrect messages logged for OpenSSL errors.
- Fixed printing IPv6 socket option defaults on FreeBSD.
### Version 5.60, 2021.08.16, urgency: LOW
* New features
- New 'sessionResume' service-level option to allow
@ -13,7 +38,6 @@
- Enforced minimum WIN32 log window size.
- Fixed support for password-protected private keys with
OpenSSL 3.0 (thx to Dmitry Belyavskiy).
- Added missing TLS options supported in OpenSSL 1.1.1k.
### Version 5.59, 2021.04.05, urgency: HIGH
* Security bugfixes

19
TODO.md
Просмотреть файл

@ -7,16 +7,17 @@ A sponsor could allocate my time to get them faster.
* Add client certificate autoselection based on the list of accepted issuers:
SSL_CTX_set_client_cert_cb(), SSL_get_client_CA_list().
* Add an Apparmor profile.
* Optional line-buffering of the log file.
* Log rotation on Windows.
* Configuration file option to limit the number of concurrent connections.
* Command-line server control interface on both Unix and Windows.
* Separate GUI process running as the current user on Windows.
* An Android GUI.
* OCSP stapling (tlsext_status).
* Indirect CRL support (RFC 3280, section 5).
* Add an Apparmor profile.
* Log rotation on Windows.
* Configuration file option to limit the number of concurrent connections.
* Command-line server control interface on Unix.
* An Android GUI.
* MSI installer for Windows.
* Add 'leastconn' failover strategy to order defined 'connect' targets
by the number of active connections.
* Optional line-buffering of the log file.
### Low priority features
These features will unlikely ever be supported.
@ -27,10 +28,6 @@ These features will unlikely ever be supported.
* Logging to NT EventLog on Windows.
* Internationalization of logged messages (i18n).
* Generic scripting engine instead or static protocol.c.
* Add 'leastconn' failover strategy to order defined 'connect' targets
by the number of active connections.
* Add '-status' command line option reporting the number of clients
connected to each service.
### Rejected features
Features I will not support, unless convinced otherwise by a wealthy sponsor.

220
configure поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for stunnel 5.60.
# Generated by GNU Autoconf 2.69 for stunnel 5.61.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='stunnel'
PACKAGE_TARNAME='stunnel'
PACKAGE_VERSION='5.60'
PACKAGE_STRING='stunnel 5.60'
PACKAGE_VERSION='5.61'
PACKAGE_STRING='stunnel 5.61'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@ -1338,7 +1338,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures stunnel 5.60 to adapt to many kinds of systems.
\`configure' configures stunnel 5.61 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1409,7 +1409,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of stunnel 5.60:";;
short | recursive ) echo "Configuration of stunnel 5.61:";;
esac
cat <<\_ACEOF
@ -1528,7 +1528,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
stunnel configure 5.60
stunnel configure 5.61
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2134,7 +2134,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by stunnel $as_me 5.60, which was
It was created by stunnel $as_me 5.61, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2998,7 +2998,7 @@ fi
# Define the identity of the package.
PACKAGE='stunnel'
VERSION='5.60'
VERSION='5.61'
cat >>confdefs.h <<_ACEOF
@ -3207,197 +3207,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
else
CC="$ac_cv_prog_CC"
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
for ac_prog in cl.exe
for ac_prog in gcc clang cl cc
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
@ -3441,7 +3251,7 @@ fi
fi
if test -z "$CC"; then
ac_ct_CC=$CC
for ac_prog in cl.exe
for ac_prog in gcc clang cl cc
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
@ -3496,8 +3306,6 @@ esac
fi
fi
fi
test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
@ -15972,8 +15780,8 @@ $as_echo_n "checking whether to enable FIPS support... " >&6; }
if test "${enable_fips+set}" = set; then :
enableval=$enable_fips;
case "$enableval" in
yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
use_fips="yes"
$as_echo "#define USE_FIPS 1" >>confdefs.h
@ -16903,7 +16711,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by stunnel $as_me 5.60, which was
This file was extended by stunnel $as_me 5.61, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -16969,7 +16777,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
stunnel config.status 5.60
stunnel config.status 5.61
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

Просмотреть файл

@ -1,6 +1,6 @@
# Process this file with autoconf to produce a configure script.
AC_INIT([stunnel],[5.60])
AC_INIT([stunnel],[5.61])
AC_MSG_NOTICE([**************************************** initialization])
AC_CONFIG_AUX_DIR(auto)
AC_CONFIG_MACRO_DIR([m4])
@ -28,7 +28,7 @@ case "$host_os" in
;;
esac
AC_PROG_CC
AC_PROG_CC([gcc clang cl cc])
AM_PROG_CC_C_O
AC_PROG_INSTALL
AC_PROG_MAKE_SET
@ -299,7 +299,7 @@ AC_ARG_ENABLE(fips,
[ --disable-fips disable OpenSSL FIPS support],
[
case "$enableval" in
yes) AC_MSG_RESULT([no])
yes) AC_MSG_RESULT([yes])
use_fips="yes"
AC_DEFINE([USE_FIPS], [1],
[Define to 1 to enable OpenSSL FIPS support])

Просмотреть файл

@ -71,7 +71,7 @@
.\" ========================================================================
.\"
.IX Title "stunnel 8"
.TH stunnel 8 "2021.05.30" "5.60" "stunnel TLS Proxy"
.TH stunnel 8 "2021.12.22" "5.61" "stunnel TLS Proxy"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@ -700,6 +700,14 @@ Currently supported protocols:
.IX Item "cifs"
Proprietary (undocummented) extension of \s-1CIFS\s0 protocol implemented in Samba.
Support for this extension was dropped in Samba 3.0.0.
.IP "\fIcapwin\fR" 4
.IX Item "capwin"
http://www.capwin.org/ application support
.IP "\fIcapwinctrl\fR" 4
.IX Item "capwinctrl"
http://www.capwin.org/ application support
.Sp
This protocol is only supported in client mode.
.IP "\fIconnect\fR" 4
.IX Item "connect"
Based on \s-1RFC 2817\s0 \- \fIUpgrading to \s-1TLS\s0 Within \s-1HTTP/1.1\s0\fR, section 5.2 \- \fIRequesting a Tunnel with \s-1CONNECT\s0\fR

Просмотреть файл

@ -824,6 +824,20 @@
<p>Proprietary (undocummented) extension of CIFS protocol implemented in Samba. Support for this extension was dropped in Samba 3.0.0.</p>
</dd>
<dt id="capwin"><i>capwin</i></dt>
<dd>
<p>http://www.capwin.org/ application support</p>
</dd>
<dt id="capwinctrl"><i>capwinctrl</i></dt>
<dd>
<p>http://www.capwin.org/ application support</p>
<p>This protocol is only supported in client mode.</p>
</dd>
<dt id="connect"><i>connect</i></dt>
<dd>

Просмотреть файл

@ -71,7 +71,7 @@
.\" ========================================================================
.\"
.IX Title "stunnel 8"
.TH stunnel 8 "2021.05.30" "5.60" "stunnel TLS Proxy"
.TH stunnel 8 "2021.12.22" "5.61" "stunnel TLS Proxy"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@ -719,6 +719,14 @@ Aktualnie wspierane protokoły:
.IX Item "cifs"
Nieudokumentowane rozszerzenie protokołu \s-1CIFS\s0 wspierane przez serwer Samba.
Wsparcie dla tego rozszerzenia zostało zarzucone w wersji 3.0.0 serwera Samba.
.IP "\fIcapwin\fR" 4
.IX Item "capwin"
Wsparcie dla aplikacji http://www.capwin.org/
.IP "\fIcapwinctrl\fR" 4
.IX Item "capwinctrl"
Wsparcie dla aplikacji http://www.capwin.org/
.Sp
Ten protokół jest wspierany wyłącznie w trybie klienckim.
.IP "\fIconnect\fR" 4
.IX Item "connect"
Negocjacja \s-1RFC 2817\s0 \- \fIUpgrading to \s-1TLS\s0 Within \s-1HTTP/1.1\s0\fR, rozdział 5.2 \- \fIRequesting a Tunnel with \s-1CONNECT\s0\fR

Просмотреть файл

@ -822,6 +822,20 @@
<p>Nieudokumentowane rozszerzenie protokołu CIFS wspierane przez serwer Samba. Wsparcie dla tego rozszerzenia zostało zarzucone w wersji 3.0.0 serwera Samba.</p>
</dd>
<dt id="capwin"><i>capwin</i></dt>
<dd>
<p>Wsparcie dla aplikacji http://www.capwin.org/</p>
</dd>
<dt id="capwinctrl"><i>capwinctrl</i></dt>
<dd>
<p>Wsparcie dla aplikacji http://www.capwin.org/</p>
<p>Ten protok&oacute;ł jest wspierany wył&#x105;cznie w trybie klienckim.</p>
</dd>
<dt id="connect"><i>connect</i></dt>
<dd>

Просмотреть файл

@ -756,6 +756,16 @@ Aktualnie wspierane protokoły:
Nieudokumentowane rozszerzenie protokołu CIFS wspierane przez serwer Samba.
Wsparcie dla tego rozszerzenia zostało zarzucone w wersji 3.0.0 serwera Samba.
=item I<capwin>
Wsparcie dla aplikacji http://www.capwin.org/
=item I<capwinctrl>
Wsparcie dla aplikacji http://www.capwin.org/
Ten protokół jest wspierany wyłącznie w trybie klienckim.
=item I<connect>
Negocjacja RFC 2817 - I<Upgrading to TLS Within HTTP/1.1>, rozdział 5.2 - I<Requesting a Tunnel with CONNECT>

Просмотреть файл

@ -739,6 +739,16 @@ Currently supported protocols:
Proprietary (undocummented) extension of CIFS protocol implemented in Samba.
Support for this extension was dropped in Samba 3.0.0.
=item I<capwin>
http://www.capwin.org/ application support
=item I<capwinctrl>
http://www.capwin.org/ application support
This protocol is only supported in client mode.
=item I<connect>
Based on RFC 2817 - I<Upgrading to TLS Within HTTP/1.1>, section 5.2 - I<Requesting a Tunnel with CONNECT>

Просмотреть файл

@ -29,7 +29,7 @@ CLEANFILES = stunnel3
# Red Hat "by design" bug #82369
stunnel_CPPFLAGS = -I$(SYSROOT)/usr/kerberos/include
# Additional preprocesor definitions
# Additional preprocessor definitions
stunnel_CPPFLAGS += -I$(SSLDIR)/include
stunnel_CPPFLAGS += -DLIBDIR='"$(pkglibdir)"'
stunnel_CPPFLAGS += -DCONFDIR='"$(sysconfdir)/stunnel"'

Просмотреть файл

@ -391,7 +391,7 @@ CLEANFILES = stunnel3
# Red Hat "by design" bug #82369
# Additional preprocesor definitions
# Additional preprocessor definitions
stunnel_CPPFLAGS = -I$(SYSROOT)/usr/kerberos/include \
-I$(SSLDIR)/include -DLIBDIR='"$(pkglibdir)"' \
-DCONFDIR='"$(sysconfdir)/stunnel"'

Просмотреть файл

@ -307,6 +307,10 @@ NOEXPORT void client_run(CLI *c) {
"Connection %s: %llu byte(s) sent to TLS, %llu byte(s) sent to socket",
rst ? "reset" : "closed",
(unsigned long long)c->ssl_bytes, (unsigned long long)c->sock_bytes);
#ifdef USE_WIN32
if(capwin_hwnd && err==1 && InterlockedExchange(&capwin_connectivity, 0))
PostMessage(capwin_hwnd, WM_CAPWIN_NET_DOWN, 0, 0);
#endif
/* cleanup temporary (e.g. IDENT) socket */
if(c->fd!=INVALID_SOCKET)
@ -413,15 +417,19 @@ NOEXPORT void local_start(CLI *c) {
addr_len=sizeof(SOCKADDR_UNION);
c->local_rfd.is_socket=!getpeername(c->local_rfd.fd, &addr.sa, &addr_len);
if(c->local_rfd.is_socket) {
/* store the retrieved peer address */
memcpy(&c->peer_addr.sa, &addr.sa, (size_t)addr_len);
c->peer_addr_len=addr_len;
if(socket_options_set(c->opt, c->local_rfd.fd, 1))
if(
#ifdef HAVE_STRUCT_SOCKADDR_UN
addr.sa.sa_family!=AF_UNIX &&
#endif
socket_options_set(c->opt, c->local_rfd.fd, 1)) {
s_log(LOG_WARNING, "Failed to set local socket options");
} else {
if(get_last_socket_error()!=S_ENOTSOCK) {
sockerror("getpeerbyname (local_rfd)");
throw_exception(c, 1);
}
} else if(get_last_socket_error()!=S_ENOTSOCK) {
sockerror("getpeerbyname (local_rfd)");
throw_exception(c, 1);
}
/* check if local_wfd is a socket and get peer address */
@ -431,17 +439,21 @@ NOEXPORT void local_start(CLI *c) {
addr_len=sizeof(SOCKADDR_UNION);
c->local_wfd.is_socket=!getpeername(c->local_wfd.fd, &addr.sa, &addr_len);
if(c->local_wfd.is_socket) {
if(!c->local_rfd.is_socket) { /* already retrieved */
if(!c->local_rfd.is_socket) { /* not retrieved from rfd? */
/* store the retrieved peer address */
memcpy(&c->peer_addr.sa, &addr.sa, (size_t)addr_len);
c->peer_addr_len=addr_len;
}
if(socket_options_set(c->opt, c->local_wfd.fd, 1))
if(
#ifdef HAVE_STRUCT_SOCKADDR_UN
addr.sa.sa_family!=AF_UNIX &&
#endif
socket_options_set(c->opt, c->local_wfd.fd, 1)) {
s_log(LOG_WARNING, "Failed to set local socket options");
} else {
if(get_last_socket_error()!=S_ENOTSOCK) {
sockerror("getpeerbyname (local_wfd)");
throw_exception(c, 1);
}
} else if(get_last_socket_error()!=S_ENOTSOCK) {
sockerror("getpeerbyname (local_wfd)");
throw_exception(c, 1);
}
}
@ -565,10 +577,7 @@ NOEXPORT void ssl_start(CLI *c) {
CRYPTO_THREAD_write_lock(stunnel_locks[LOCK_SSL]);
#endif /* OpenSSL version < 1.1.0 */
if(c->opt->option.client)
i=SSL_connect(c->ssl);
else
i=SSL_accept(c->ssl);
i=c->opt->option.client ? SSL_connect(c->ssl) : SSL_accept(c->ssl);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if(unsafe_openssl)
@ -609,11 +618,10 @@ NOEXPORT void ssl_start(CLI *c) {
#endif
continue;
}
sockerror(c->opt->option.client ? "SSL_connect" : "SSL_accept");
throw_exception(c, 1);
}
if(c->opt->option.client)
sslerror("SSL_connect");
else
sslerror("SSL_accept");
sslerror(c->opt->option.client ? "SSL_connect" : "SSL_accept");
throw_exception(c, 1);
}
print_cipher(c);
@ -774,16 +782,22 @@ NOEXPORT void transfer(CLI *c) {
s_poll_init(c->fds, 0); /* initialize the structure */
/* for plain socket open data strem = open file descriptor */
/* make sure to add each open socket to receive exceptions! */
if(sock_open_rd) /* only poll if the read file descriptor is open */
s_poll_add(c->fds, c->sock_rfd->fd, c->sock_ptr<BUFFSIZE, 0);
if(sock_open_wr) /* only poll if the write file descriptor is open */
s_poll_add(c->fds, c->sock_wfd->fd, 0, c->ssl_ptr>0);
if(c->sock_rfd->fd==c->sock_wfd->fd) {
if(sock_open_rd || sock_open_wr)
s_poll_add(c->fds, c->sock_rfd->fd,
sock_open_rd && c->sock_ptr<BUFFSIZE,
sock_open_wr && c->ssl_ptr>0);
} else {
if(sock_open_rd) /* only poll if the read file descriptor is open */
s_poll_add(c->fds, c->sock_rfd->fd, c->sock_ptr<BUFFSIZE, 0);
if(sock_open_wr) /* only poll if the write file descriptor is open */
s_poll_add(c->fds, c->sock_wfd->fd, 0, c->ssl_ptr>0);
}
/* poll TLS file descriptors unless TLS shutdown was completed */
if(SSL_get_shutdown(c->ssl)!=
(SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) {
s_poll_add(c->fds, c->ssl_rfd->fd,
read_wants_read || write_wants_read || shutdown_wants_read, 0);
s_poll_add(c->fds, c->ssl_wfd->fd, 0,
read_wants_read || write_wants_read || shutdown_wants_read,
read_wants_write || write_wants_write || shutdown_wants_write);
}

Просмотреть файл

@ -104,6 +104,7 @@ typedef __int64 ssize_t;
typedef int ssize_t;
#endif /* _WIN64 */
#endif /* !__MINGW32__ */
#define PRIX64 "I64X"
#define USE_IPv6
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE
@ -242,6 +243,7 @@ typedef int ssize_t;
#include <ws2tcpip.h>
#include <windows.h>
#include <windowsx.h>
#include <process.h> /* _beginthread */
#include <shlobj.h> /* SHGetFolderPath */
@ -411,6 +413,9 @@ extern char *sys_errlist[];
/**************************************** OpenSSL headers */
/* TODO: remove this after migrating to the OpenSSL 3.0 API */
#define OPENSSL_SUPPRESS_DEPRECATED
#define OPENSSL_THREAD_DEFINES
#include <openssl/opensslconf.h>
/* opensslv.h requires prior opensslconf.h to include -fips in version string */
@ -530,6 +535,8 @@ STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
#define offsetof(T, F) ((unsigned)((char *)&((T *)0L)->F - (char *)0L))
#endif
#define is_prefix(a, b) (strncasecmp((a), (b), strlen(b))==0)
#endif /* defined COMMON_H */
/* end of common.h */

Просмотреть файл

@ -139,10 +139,16 @@ typedef long SSL_OPTIONS_TYPE;
int context_init(SERVICE_OPTIONS *section) { /* init TLS context */
/* create a new TLS context */
#if OPENSSL_VERSION_NUMBER>=0x10100000L
if(section->option.client)
section->ctx=SSL_CTX_new(TLS_client_method());
else /* server mode */
section->ctx=SSL_CTX_new(TLS_server_method());
#if OPENSSL_VERSION_NUMBER>=0x30000000L
section->ctx=SSL_CTX_new_ex(NULL,
EVP_default_properties_is_fips_enabled(NULL) ?
"fips=yes" : "provider!=fips",
section->option.client ?
TLS_client_method() : TLS_server_method());
#else /* OPENSSL_VERSION_NUMBER<0x30000000L */
section->ctx=SSL_CTX_new(section->option.client ?
TLS_client_method() : TLS_server_method());
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
if(!SSL_CTX_set_min_proto_version(section->ctx,
section->min_proto_version)) {
s_log(LOG_ERR, "Failed to set the minimum protocol version 0x%X",
@ -233,11 +239,12 @@ int context_init(SERVICE_OPTIONS *section) { /* init TLS context */
/* TLS options: log the configured values */
#if OPENSSL_VERSION_NUMBER>=0x009080dfL
s_log(LOG_DEBUG, "TLS options: 0x%08lX (+0x%08lX, -0x%08lX)",
s_log(LOG_DEBUG,
"TLS options: 0x%" PRIX64 " (+0x%" PRIX64 ", -0x%" PRIX64 ")",
SSL_CTX_get_options(section->ctx),
section->ssl_options_set, section->ssl_options_clear);
#else /* OpenSSL older than 0.9.8m */
s_log(LOG_DEBUG, "TLS options: 0x%08lX (+0x%08lX)",
s_log(LOG_DEBUG, "TLS options: 0x%" PRIX64 " (+0x%" PRIX64 ")",
SSL_CTX_get_options(section->ctx), section->ssl_options_set);
#endif /* OpenSSL 0.9.8m or later */
@ -320,7 +327,8 @@ int context_init(SERVICE_OPTIONS *section) { /* init TLS context */
dh_init(section); /* ignore the result (errors are not critical) */
#endif /* OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH
ecdh_init(section); /* ignore the result (errors are not critical) */
if(ecdh_init(section))
return 1; /* FAILED */
#endif /* OPENSSL_NO_ECDH */
return 0; /* OK */
@ -519,9 +527,7 @@ NOEXPORT int SSL_CTX_set1_groups_list(SSL_CTX *ctx, char *list) {
NOEXPORT int ecdh_init(SERVICE_OPTIONS *section) {
s_log(LOG_DEBUG, "ECDH initialization");
if(!SSL_CTX_set1_groups_list(section->ctx, section->curves)) {
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
sslerror("SSL_CTX_set1_groups_list");
#endif /* OpenSSL version >= 1.1.1 */
s_log(LOG_ERR, "Invalid groups list in 'curves'");
return 1; /* FAILED */
}
s_log(LOG_DEBUG, "ECDH initialized with curves %s", section->curves);

Просмотреть файл

@ -5,32 +5,32 @@
DH *get_dh2048(void)
{
static unsigned char dhp_2048[] = {
0x91, 0xC2, 0x73, 0x35, 0xC8, 0x30, 0xC4, 0xD8, 0xF4, 0xB5,
0x3E, 0xCD, 0xC7, 0x3C, 0xD3, 0x5A, 0x4D, 0xBA, 0x5C, 0x38,
0xB2, 0x7B, 0x5B, 0xCA, 0xFB, 0xF8, 0x9B, 0xC9, 0x98, 0x00,
0x79, 0xDC, 0xA6, 0xFF, 0xE6, 0xB3, 0x61, 0x0E, 0xFB, 0x1B,
0xC0, 0x95, 0xDE, 0xA4, 0xB6, 0x1B, 0xA6, 0x9B, 0x76, 0x8E,
0x7B, 0x84, 0x03, 0xB7, 0x2F, 0x6A, 0x5D, 0x35, 0xE3, 0x04,
0x1A, 0x14, 0x47, 0x27, 0xDC, 0x57, 0x74, 0x81, 0x1B, 0x91,
0x42, 0x87, 0x34, 0xCE, 0x41, 0x96, 0xC8, 0x38, 0xB4, 0xBB,
0x95, 0x41, 0x7A, 0x5F, 0x18, 0x1F, 0xA5, 0x2C, 0x3F, 0xAD,
0xEA, 0xC7, 0xD7, 0x0C, 0x25, 0x13, 0xBA, 0x0A, 0x84, 0x57,
0x7E, 0xD1, 0xE5, 0x9C, 0x0F, 0x62, 0xAA, 0x47, 0x94, 0x75,
0xFA, 0x36, 0x0A, 0xF6, 0xEE, 0xFD, 0x95, 0x40, 0x36, 0x79,
0xD0, 0x35, 0x7A, 0x6D, 0x46, 0xDA, 0xBD, 0xFA, 0xCF, 0xE2,
0x01, 0xEC, 0x49, 0x43, 0x2A, 0x46, 0xC6, 0xA7, 0xBC, 0xC3,
0x1A, 0xA7, 0x6F, 0x54, 0xA6, 0x10, 0x54, 0xDA, 0x5F, 0x21,
0x95, 0x3F, 0xF4, 0x77, 0x99, 0x90, 0xE9, 0xD0, 0x0A, 0xB4,
0x09, 0x10, 0xAC, 0xE7, 0x1D, 0x38, 0x21, 0x14, 0xF5, 0xC9,
0xC9, 0xFA, 0xCA, 0xA7, 0x61, 0x1D, 0x13, 0xB5, 0x84, 0xA2,
0x10, 0x6B, 0xF8, 0x85, 0xB1, 0x1C, 0x1C, 0x1A, 0x67, 0x98,
0xDC, 0x67, 0xA4, 0xE8, 0x52, 0xC1, 0x05, 0xBA, 0x08, 0x9D,
0xDD, 0xAC, 0x56, 0x72, 0x7B, 0x33, 0x25, 0x37, 0xCA, 0x85,
0xAA, 0xB8, 0xB1, 0x60, 0x6D, 0x07, 0x1C, 0xC6, 0xD8, 0x73,
0x76, 0xB2, 0xB3, 0xFC, 0x2A, 0x0F, 0xF8, 0x5F, 0x7D, 0x2B,
0x56, 0x30, 0xB8, 0x00, 0x3B, 0x21, 0x6B, 0xAB, 0x30, 0xEA,
0x7C, 0x62, 0xA4, 0xD2, 0x3B, 0xE2, 0x2F, 0x98, 0xA0, 0xF4,
0x59, 0x31, 0xB5, 0x83, 0x6A, 0x93
0xEA, 0xAB, 0xD1, 0x12, 0x96, 0x57, 0xE6, 0x1C, 0xCB, 0x63,
0xF1, 0xE1, 0x48, 0x10, 0xB7, 0x95, 0x7E, 0xC8, 0x45, 0x7A,
0xCC, 0x4D, 0xDC, 0xA0, 0xEC, 0x46, 0xB3, 0xFF, 0xAE, 0x60,
0x0C, 0xE9, 0xA8, 0x43, 0xA0, 0x1C, 0x9F, 0x96, 0x09, 0x14,
0x4C, 0x63, 0x65, 0x7D, 0x9A, 0x0D, 0x69, 0x42, 0x62, 0xFA,
0x4C, 0x3C, 0x0C, 0xD2, 0xC2, 0xF6, 0xA3, 0x57, 0x99, 0x8C,
0x4A, 0x24, 0x57, 0x97, 0x21, 0x05, 0x6A, 0x7C, 0xF2, 0xE7,
0x69, 0xF2, 0x0A, 0x5F, 0xDF, 0xBD, 0x83, 0x43, 0x1F, 0x6C,
0xDA, 0x21, 0xF5, 0x02, 0x9D, 0x9F, 0x03, 0xA4, 0x6C, 0x6F,
0x8E, 0x5F, 0xE7, 0xD6, 0xBC, 0x93, 0x0E, 0x5A, 0x55, 0x88,
0xED, 0x96, 0x5D, 0x3B, 0x39, 0x80, 0xB0, 0xDA, 0xDF, 0x24,
0xFC, 0xAC, 0xB9, 0xE1, 0xEE, 0xB6, 0xA6, 0x28, 0x84, 0x79,
0x34, 0xDC, 0xBC, 0x8F, 0x39, 0x52, 0x20, 0x6F, 0xAC, 0x57,
0x76, 0xA3, 0x3A, 0x05, 0x28, 0xAD, 0x7F, 0x1C, 0xC1, 0x93,
0x54, 0x75, 0x58, 0x4F, 0x59, 0x79, 0x0D, 0x6F, 0xFE, 0x91,
0x38, 0x7E, 0x6D, 0xEF, 0xB4, 0xCC, 0x10, 0x79, 0x73, 0x04,
0x07, 0x1E, 0xB2, 0x4E, 0x87, 0xA6, 0xA1, 0x7B, 0xCA, 0xFB,
0x5B, 0xF8, 0xFD, 0xC6, 0xDF, 0x32, 0x1F, 0x35, 0x44, 0xB8,
0x70, 0x98, 0xE0, 0x5B, 0xFD, 0x80, 0x76, 0x29, 0x78, 0xFB,
0xEE, 0xB4, 0xAC, 0xFB, 0x6C, 0x44, 0xCF, 0x94, 0x58, 0x13,
0xA6, 0xD3, 0xBD, 0x26, 0x91, 0xA6, 0x4B, 0xFC, 0x5A, 0x04,
0x6C, 0x1C, 0xB8, 0x2E, 0x17, 0x22, 0x9D, 0xD4, 0xA3, 0x79,
0x9A, 0xCB, 0x93, 0x7F, 0x0F, 0x55, 0x0A, 0x4D, 0xFC, 0x48,
0x23, 0xA2, 0xCE, 0x9C, 0xE9, 0x1C, 0x62, 0x36, 0x89, 0x7E,
0xB4, 0xAC, 0xEB, 0xBA, 0xF1, 0xB5, 0x04, 0x80, 0x9B, 0xEE,
0xE3, 0x47, 0x29, 0x49, 0xB9, 0x1B
};
static unsigned char dhg_2048[] = {
0x02
@ -52,4 +52,4 @@ DH *get_dh2048(void)
return dh;
}
#endif /* OPENSSL_NO_DH */
/* built for stunnel 5.60 */
/* built for stunnel 5.61 */

Просмотреть файл

@ -14,19 +14,37 @@
bindir = ../bin/$(win32_arch)
objdir = ../obj/$(win32_arch)
win32_ssl_dir = /opt/openssl-$(win32_mingw)
ifeq ($(win32_ssl_dir),)
win32_ssl_dir := /opt/openssl-$(win32_mingw)
endif
win32_cppflags = -I$(win32_ssl_dir)/include
win32_cflags = -g -mthreads -O2
#win32_cflags += -fstack-protector
win32_cflags += -Wall -Wextra -Wpedantic -Wformat=2 -Wconversion -Wno-long-long
win32_cflags += -fstack-protector
win32_cflags += -Wall -Wextra -Wpedantic -Wconversion -Wno-long-long -ansi
win32_cflags += -D_FORTIFY_SOURCE=2 -DUNICODE -D_UNICODE
win32_ldflags = -g -mthreads
#win32_ldflags += -fstack-protector
# -fstack-protector is broken (at least in x86_64-w64-mingw32-gcc 8.2.0)
win32_ldflags = -g -mthreads -pipe
win32_ldflags += -fstack-protector
win32_ldflags += -Wl,--dynamicbase,--nxcompat,--no-seh,--tsaware,--no-insert-timestamp
ifeq ($(win32_arch),win64)
win32_ldflags += -Wl,--high-entropy-va
else
win32_ldflags += -Wl,--large-address-aware
endif
# -fstack-protector was broken in x86_64-w64-mingw32-gcc 8.2.0
# compiling with -D_FORTIFY_SOURCE=2 may require linking with -lssp
win32_common_libs = -lws2_32 -lkernel32 -lssp
win32_ssl_libs = -L$(win32_ssl_dir)/lib -lcrypto -lssl
ifneq (,$(wildcard $(win32_ssl_dir)/lib64/libcrypto.dll.a))
# use OpenSSL 3.x.x mingw-generated library stubs if available
win32_ssl_libs = -L$(win32_ssl_dir)/lib64 -lcrypto -lssl
else ifneq (,$(wildcard $(win32_ssl_dir)/lib/libcrypto.dll.a))
# use OpenSSL 1.x.x mingw-generated library stubs if available
win32_ssl_libs = -L$(win32_ssl_dir)/lib -lcrypto -lssl
else
# directly import libeay32.dll and ssleay32.dll otherwise
win32_ssl_libs = -L$(win32_ssl_dir)/bin -llibeay32 -lssleay32
endif
win32_gui_libs = $(win32_common_libs) -lgdi32 -lpsapi $(win32_ssl_libs)
win32_cli_libs = $(win32_common_libs) $(win32_ssl_libs)

Просмотреть файл

@ -71,7 +71,12 @@ void s_poll_init(s_poll_set *fds, int main_thread) {
fds->allocated=4; /* prealloc 4 file descriptors */
s_poll_realloc(fds);
fds->main_thread=main_thread;
#ifdef USE_TERMINATE_PIPE
s_poll_add(fds, main_thread ? signal_pipe[0] : terminate_pipe[0], 1, 0);
#else
if(main_thread)
s_poll_add(fds, signal_pipe[0], 1, 0);
#endif
}
void s_poll_add(s_poll_set *fds, SOCKET fd, int rd, int wr) {
@ -375,13 +380,11 @@ void s_poll_init(s_poll_set *fds, int main_thread) {
FD_ZERO(fds->ixfds);
fds->max=0; /* no file descriptors */
fds->main_thread=main_thread;
#ifdef USE_WIN32
/* there seems to be a deadlock in the Windows select() function when
* waiting for the same terminate_pipe socket in multiple threads */
#ifdef USE_TERMINATE_PIPE
s_poll_add(fds, main_thread ? signal_pipe[0] : terminate_pipe[0], 1, 0);
#else
if(main_thread)
s_poll_add(fds, signal_pipe[0], 1, 0);
#else
s_poll_add(fds, main_thread ? signal_pipe[0] : terminate_pipe[0], 1, 0);
#endif
}
@ -512,6 +515,7 @@ void s_poll_sleep(int sec, int msec) {
#ifndef USE_UCONTEXT
NOEXPORT void check_terminate(s_poll_set *fds) {
#ifdef USE_TERMINATE_PIPE
if(!fds->main_thread && s_poll_canread(fds, terminate_pipe[0])) {
#ifdef USE_PTHREAD
pthread_exit(NULL);
@ -531,6 +535,9 @@ NOEXPORT void check_terminate(s_poll_set *fds) {
exit(0);
#endif /* USE_FORK */
}
#else /* USE_TERMINATE_PIPE */
(void)fds; /* squash the unused parameter warning */
#endif /* USE_TERMINATE_PIPE */
}
#endif
@ -681,39 +688,53 @@ void s_write(CLI *c, SOCKET fd, const void *buf, size_t len) {
}
}
void s_read(CLI *c, SOCKET fd, void *ptr, size_t len) {
size_t s_read_eof(CLI *c, SOCKET fd, void *ptr, size_t len) {
/* simulate a blocking read */
ssize_t num;
/* return a value < len on EOF */
size_t total=0;
while(len>0) {
ssize_t num;
s_poll_init(c->fds, 0);
s_poll_add(c->fds, fd, 1, 0); /* read */
switch(s_poll_wait(c->fds, c->opt->timeout_busy, 0)) {
case -1:
sockerror("s_read: s_poll_wait");
sockerror("s_read_eof: s_poll_wait");
throw_exception(c, 1); /* error */
case 0:
s_log(LOG_INFO, "s_read: s_poll_wait:"
s_log(LOG_INFO, "s_read_eof: s_poll_wait:"
" TIMEOUTbusy exceeded: sending reset");
throw_exception(c, 1); /* timeout */
case 1:
break; /* OK */
default:
s_log(LOG_ERR, "s_read: s_poll_wait: unknown result");
s_log(LOG_ERR, "s_read_eof: s_poll_wait: unknown result");
throw_exception(c, 1); /* error */
}
num=readsocket(fd, ptr, len);
switch(num) {
case -1: /* error */
sockerror("readsocket (s_read)");
throw_exception(c, 1);
case 0: /* EOF */
s_log(LOG_ERR, "Unexpected socket close (s_read)");
num=readsocket(fd, (char *)ptr+total, len);
if(num<0) { /* error */
sockerror("readsocket (s_read_eof)");
throw_exception(c, 1);
}
ptr=(uint8_t *)ptr+num;
if(num==0) { /* EOF */
s_log(LOG_DEBUG, "Socket closed (s_read_eof)");
break;
}
total+=(size_t)num;
len-=(size_t)num;
}
return total;
}
void s_read(CLI *c, SOCKET fd, void *ptr, size_t len) {
/* simulate a blocking read */
/* throw an exception on EOF */
if(s_read_eof(c, fd, ptr, len)!=len) {
s_log(LOG_ERR, "Unexpected socket close (s_read)");
throw_exception(c, 1);
}
}
void fd_putline(CLI *c, SOCKET fd, const char *line) {
@ -804,11 +825,14 @@ void s_ssl_write(CLI *c, const void *buf, int len) {
}
}
void s_ssl_read(CLI *c, void *ptr, int len) {
size_t s_ssl_read_eof(CLI *c, void *ptr, int len) {
/* simulate a blocking SSL_read */
int num;
/* return a value < len on EOF */
size_t total=0;
while(len>0) {
int num;
if(!SSL_pending(c->ssl)) {
s_poll_init(c->fds, 0);
s_poll_add(c->fds, c->ssl_rfd->fd, 1, 0); /* read */
@ -827,18 +851,29 @@ void s_ssl_read(CLI *c, void *ptr, int len) {
throw_exception(c, 1); /* error */
}
}
num=SSL_read(c->ssl, ptr, len);
switch(num) {
case -1: /* error */
sockerror("SSL_read (s_ssl_read)");
throw_exception(c, 1);
case 0: /* EOF */
s_log(LOG_ERR, "Unexpected socket close (s_ssl_read)");
num=SSL_read(c->ssl, (char *)ptr+total, len);
if(num<0) { /* error */
sockerror("SSL_read (s_ssl_read_eof)");
throw_exception(c, 1);
}
ptr=(uint8_t *)ptr+num;
if(num==0) { /* EOF */
s_log(LOG_DEBUG, "Socket close (s_ssl_read_eof)");
break;
}
total+=(size_t)num;
len-=num;
}
return total;
}
void s_ssl_read(CLI *c, void *ptr, int len) {
/* simulate a blocking SSL_read */
/* throw an exception on EOF */
if(s_ssl_read_eof(c, ptr, len)!=(size_t)len) {
s_log(LOG_ERR, "Unexpected socket close (s_ssl_read)");
throw_exception(c, 1);
}
}
char *ssl_getstring(CLI *c) { /* get null-terminated string */

Просмотреть файл

@ -108,92 +108,83 @@ typedef struct {
} SSL_OPTION;
static const SSL_OPTION ssl_opts[] = {
{"MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG},
{"NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG},
#ifdef SSL_OP_LEGACY_SERVER_CONNECT
{"LEGACY_SERVER_CONNECT", SSL_OP_LEGACY_SERVER_CONNECT},
#endif
{"NETSCAPE_REUSE_CIPHER_CHANGE_BUG",
SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG},
#ifdef SSL_OP_TLSEXT_PADDING
{"TLSEXT_PADDING", SSL_OP_TLSEXT_PADDING},
#endif
{"MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER},
#ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG
{"SAFARI_ECDHE_ECDSA_BUG", SSL_OP_SAFARI_ECDHE_ECDSA_BUG},
#endif
{"SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG},
{"TLS_D5_BUG", SSL_OP_TLS_D5_BUG},
{"TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG},
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
{"MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING},
#endif
{"SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG},
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
{"DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS},
#endif
#ifdef SSL_OP_ALL
{"ALL", SSL_OP_ALL},
#ifdef SSL_OP_NO_QUERY_MTU
{"NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU},
#endif
#ifdef SSL_OP_COOKIE_EXCHANGE
{"COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE},
#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION
{"ALLOW_CLIENT_RENEGOTIATION", SSL_OP_ALLOW_CLIENT_RENEGOTIATION},
#endif
#ifdef SSL_OP_NO_TICKET
{"NO_TICKET", SSL_OP_NO_TICKET},
#ifdef SSL_OP_ALLOW_NO_DHE_KEX
{"ALLOW_NO_DHE_KEX", SSL_OP_ALLOW_NO_DHE_KEX},
#endif
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
{"ALLOW_UNSAFE_LEGACY_RENEGOTIATION", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION},
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
{"CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE},
#endif
#ifdef SSL_OP_CISCO_ANYCONNECT
{"CISCO_ANYCONNECT", SSL_OP_CISCO_ANYCONNECT},
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
{"NO_SESSION_RESUMPTION_ON_RENEGOTIATION",
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION},
#ifdef SSL_OP_CLEANSE_PLAINTEXT
{"CLEANSE_PLAINTEXT", SSL_OP_CLEANSE_PLAINTEXT},
#endif
#ifdef SSL_OP_COOKIE_EXCHANGE
{"COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE},
#endif
#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG
{"CRYPTOPRO_TLSEXT_BUG", SSL_OP_CRYPTOPRO_TLSEXT_BUG},
#endif
#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES
{"DISABLE_TLSEXT_CA_NAMES", SSL_OP_DISABLE_TLSEXT_CA_NAMES},
#endif
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
{"DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS},
#endif
#ifdef SSL_OP_ENABLE_KTLS
{"ENABLE_KTLS", SSL_OP_ENABLE_KTLS},
#endif
#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
{"ENABLE_MIDDLEBOX_COMPAT", SSL_OP_ENABLE_MIDDLEBOX_COMPAT},
#endif
#ifdef SSL_OP_EPHEMERAL_RSA
{"EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA},
#endif
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
{"IGNORE_UNEXPECTED_EOF", SSL_OP_IGNORE_UNEXPECTED_EOF},
#endif
#ifdef SSL_OP_LEGACY_SERVER_CONNECT
{"LEGACY_SERVER_CONNECT", SSL_OP_LEGACY_SERVER_CONNECT},
#endif
#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
{"MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER},
#endif
#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG
{"MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG},
#endif
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
{"MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING},
#endif
#ifdef SSL_OP_NETSCAPE_CA_DN_BUG
{"NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG},
#endif
#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG
{"NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG},
#endif
#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
{"NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG},
#endif
#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
{"NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG},
#endif
#ifdef SSL_OP_NO_ANTI_REPLAY
{"NO_ANTI_REPLAY", SSL_OP_NO_ANTI_REPLAY},
#endif
#ifdef SSL_OP_NO_COMPRESSION
{"NO_COMPRESSION", SSL_OP_NO_COMPRESSION},
#endif
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
{"ALLOW_UNSAFE_LEGACY_RENEGOTIATION",
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION},
#endif
#ifdef SSL_OP_SINGLE_ECDH_USE
{"SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE},
#endif
{"SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE},
{"EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA},
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
{"CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE},
#endif
{"TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG},
{"NO_SSLv2", SSL_OP_NO_SSLv2},
{"NO_SSLv3", SSL_OP_NO_SSLv3},
{"NO_TLSv1", SSL_OP_NO_TLSv1},
#ifdef SSL_OP_NO_TLSv1_1
{"NO_TLSv1.1", SSL_OP_NO_TLSv1_1},
#else /* ignore if unsupported by OpenSSL */
{"NO_TLSv1.1", 0},
#endif
#ifdef SSL_OP_NO_TLSv1_2
{"NO_TLSv1.2", SSL_OP_NO_TLSv1_2},
#else /* ignore if unsupported by OpenSSL */
{"NO_TLSv1.2", 0},
#endif
#ifdef SSL_OP_NO_TLSv1_3
{"NO_TLSv1.3", SSL_OP_NO_TLSv1_3},
{"NO_TLSv1_3", SSL_OP_NO_TLSv1_3}, /* keep compatibility with our typo */
#else /* ignore if unsupported by OpenSSL */
{"NO_TLSv1.3", 0},
{"NO_TLSv1_3", 0}, /* keep compatibility with our typo */
#endif
{"PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1},
{"PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2},
{"NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG},
#ifdef SSL_OP_NON_EXPORT_FIRST
{"NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST},
#endif
{"NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG},
#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG
{"CRYPTOPRO_TLSEXT_BUG", SSL_OP_CRYPTOPRO_TLSEXT_BUG},
#ifdef SSL_OP_NO_DTLS_MASK
{"NO_DTLS_MASK", SSL_OP_NO_DTLS_MASK},
#endif
#ifdef SSL_OP_NO_DTLSv1
{"NO_DTLSv1", SSL_OP_NO_DTLSv1},
@ -201,50 +192,80 @@ static const SSL_OPTION ssl_opts[] = {
#ifdef SSL_OP_NO_DTLSv1_2
{"NO_DTLSv1_2", SSL_OP_NO_DTLSv1_2},
#endif
#ifdef SSL_OP_NO_SSL_MASK
{"NO_SSL_MASK", SSL_OP_NO_SSL_MASK},
#endif
#ifdef SSL_OP_NO_DTLS_MASK
{"NO_DTLS_MASK", SSL_OP_NO_DTLS_MASK},
#endif
#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC
{"NO_ENCRYPT_THEN_MAC", SSL_OP_NO_ENCRYPT_THEN_MAC},
#endif
#ifdef SSL_OP_ALLOW_NO_DHE_KEX
{"ALLOW_NO_DHE_KEX", SSL_OP_ALLOW_NO_DHE_KEX},
#ifdef SSL_OP_NO_EXTENDED_MASTER_SECRET
{"NO_EXTENDED_MASTER_SECRET", SSL_OP_NO_EXTENDED_MASTER_SECRET},
#endif
#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
{"ENABLE_MIDDLEBOX_COMPAT", SSL_OP_ENABLE_MIDDLEBOX_COMPAT},
#ifdef SSL_OP_NO_QUERY_MTU
{"NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU},
#endif
#ifdef SSL_OP_NO_RENEGOTIATION
{"NO_RENEGOTIATION", SSL_OP_NO_RENEGOTIATION},
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
{"NO_SESSION_RESUMPTION_ON_RENEGOTIATION", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION},
#endif
#ifdef SSL_OP_NO_SSL_MASK
{"NO_SSL_MASK", SSL_OP_NO_SSL_MASK},
#endif
#ifdef SSL_OP_NO_SSLv2
{"NO_SSLv2", SSL_OP_NO_SSLv2},
#endif
#ifdef SSL_OP_NO_SSLv3
{"NO_SSLv3", SSL_OP_NO_SSLv3},
#endif
#ifdef SSL_OP_NO_TICKET
{"NO_TICKET", SSL_OP_NO_TICKET},
#endif
#ifdef SSL_OP_NO_TLSv1
{"NO_TLSv1", SSL_OP_NO_TLSv1},
#endif
#ifdef SSL_OP_NO_TLSv1_1
{"NO_TLSv1_1", SSL_OP_NO_TLSv1_1},
#endif
#ifdef SSL_OP_NO_TLSv1_2
{"NO_TLSv1_2", SSL_OP_NO_TLSv1_2},
#endif
#ifdef SSL_OP_NO_TLSv1_3
{"NO_TLSv1_3", SSL_OP_NO_TLSv1_3},
#endif
#ifdef SSL_OP_PKCS1_CHECK_1
{"PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1},
#endif
#ifdef SSL_OP_PKCS1_CHECK_2
{"PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2},
#endif
#ifdef SSL_OP_PRIORITIZE_CHACHA
{"PRIORITIZE_CHACHA", SSL_OP_PRIORITIZE_CHACHA},
#endif
#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION
{"ALLOW_CLIENT_RENEGOTIATION", SSL_OP_ALLOW_CLIENT_RENEGOTIATION},
#ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG
{"SAFARI_ECDHE_ECDSA_BUG", SSL_OP_SAFARI_ECDHE_ECDSA_BUG},
#endif
#ifdef SSL_OP_BIT
{"BIT", SSL_OP_BIT},
#ifdef SSL_OP_SINGLE_DH_USE
{"SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE},
#endif
#ifdef SSL_OP_CLEANSE_PLAINTEXT
{"CLEANSE_PLAINTEXT", SSL_OP_CLEANSE_PLAINTEXT},
#ifdef SSL_OP_SINGLE_ECDH_USE
{"SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE},
#endif
#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES
{"DISABLE_TLSEXT_CA_NAMES", SSL_OP_DISABLE_TLSEXT_CA_NAMES},
#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
{"SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG},
#endif
#ifdef SSL_OP_ENABLE_KTLS
{"ENABLE_KTLS", SSL_OP_ENABLE_KTLS},
#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
{"SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG},
#endif
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
{"IGNORE_UNEXPECTED_EOF", SSL_OP_IGNORE_UNEXPECTED_EOF},
#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
{"TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG},
#endif
#ifdef SSL_OP_NO_ANTI_REPLAY
{"NO_ANTI_REPLAY", SSL_OP_NO_ANTI_REPLAY},
#ifdef SSL_OP_TLS_D5_BUG
{"TLS_D5_BUG", SSL_OP_TLS_D5_BUG},
#endif
#ifdef SSL_OP_NO_EXTENDED_MASTER_SECRET
{"NO_EXTENDED_MASTER_SECRET", SSL_OP_NO_EXTENDED_MASTER_SECRET},
#ifdef SSL_OP_TLSEXT_PADDING
{"TLSEXT_PADDING", SSL_OP_TLSEXT_PADDING},
#endif
#ifdef SSL_OP_TLS_ROLLBACK_BUG
{"TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG},
#endif
{NULL, 0}
};
@ -288,7 +309,7 @@ NOEXPORT char **arg_dup(char **);
NOEXPORT void arg_free(char **arg);
#endif
char *configuration_file=NULL;
static char *configuration_file=NULL;
GLOBAL_OPTIONS global_options;
SERVICE_OPTIONS service_options;
@ -682,6 +703,9 @@ void service_free(SERVICE_OPTIONS *section) {
NOEXPORT char *parse_global_option(CMD cmd, GLOBAL_OPTIONS *options, char *opt, char *arg) {
void *tmp;
#ifdef USE_FIPS
static int fips_default=-1;
#endif /* USE_FIPS */
if(cmd==CMD_PRINT_DEFAULTS || cmd==CMD_PRINT_HELP) {
s_log(LOG_NOTICE, " ");
@ -871,11 +895,14 @@ NOEXPORT char *parse_global_option(CMD cmd, GLOBAL_OPTIONS *options, char *opt,
switch(cmd) {
case CMD_SET_DEFAULTS:
#ifdef USE_FIPS
if(fips_default==-1) { /* not initialized */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
options->option.fips=0;
fips_default=EVP_default_properties_is_fips_enabled(NULL);
#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
options->option.fips=FIPS_mode()?1:0;
fips_default=FIPS_mode();
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
}
options->option.fips=fips_default?1:0;
#endif /* USE_FIPS */
break;
case CMD_SET_COPY: /* not used for global options */
@ -893,10 +920,8 @@ NOEXPORT char *parse_global_option(CMD cmd, GLOBAL_OPTIONS *options, char *opt,
#endif /* USE_FIPS */
} else if(!strcasecmp(arg, "no")) {
#ifdef USE_FIPS
#if OPENSSL_VERSION_NUMBER < 0x30000000L
if(FIPS_mode())
if(fips_default)
return "Failed to override system-wide FIPS mode";
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
options->option.fips=0;
#endif /* USE_FIPS */
} else {
@ -907,13 +932,8 @@ NOEXPORT char *parse_global_option(CMD cmd, GLOBAL_OPTIONS *options, char *opt,
break;
case CMD_PRINT_DEFAULTS:
#ifdef USE_FIPS
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if(fips_available())
s_log(LOG_NOTICE, "%-22s = %s", "fips", "no");
#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
if(fips_available())
s_log(LOG_NOTICE, "%-22s = %s", "fips", FIPS_mode()?"yes":"no");
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
s_log(LOG_NOTICE, "%-22s = %s", "fips", fips_default?"yes":"no");
#endif /* USE_FIPS */
break;
case CMD_PRINT_HELP:
@ -4417,13 +4437,6 @@ NOEXPORT void socket_options_free(SOCK_OPT *opt) {
NOEXPORT int socket_options_print(void) {
SOCK_OPT *opt, *ptr;
SOCKET fd;
socklen_t optlen;
OPT_UNION val;
char *ta, *tl, *tr, *td;
fd=socket(AF_INET, SOCK_STREAM, 0);
opt=socket_options_init();
s_log(LOG_NOTICE, " ");
s_log(LOG_NOTICE, "Socket option defaults:");
@ -4431,8 +4444,21 @@ NOEXPORT int socket_options_print(void) {
" Option Name | Accept | Local | Remote |OS default");
s_log(LOG_NOTICE,
" --------------------+----------+----------+----------+----------");
opt=socket_options_init();
for(ptr=opt; ptr->opt_str; ++ptr) {
SOCKET fd;
socklen_t optlen;
OPT_UNION val;
char *ta, *tl, *tr, *td;
/* get OS default value */
#if defined(AF_INET6) && defined(IPPROTO_IPV6)
if(ptr->opt_level==IPPROTO_IPV6)
fd=socket(AF_INET6, SOCK_STREAM, 0);
else
#endif
fd=socket(AF_INET, SOCK_STREAM, 0);
optlen=sizeof val;
if(getsockopt(fd, ptr->opt_level,
ptr->opt_name, (void *)&val, &optlen)) {
@ -4449,17 +4475,19 @@ NOEXPORT int socket_options_print(void) {
}
} else
td=socket_option_text(ptr->opt_type, &val);
closesocket(fd);
/* get stunnel default values */
ta=socket_option_text(ptr->opt_type, ptr->opt_val[0]);
tl=socket_option_text(ptr->opt_type, ptr->opt_val[1]);
tr=socket_option_text(ptr->opt_type, ptr->opt_val[2]);
/* print collected data and fee the memory */
/* print collected data and free the allocated memory */
s_log(LOG_NOTICE, " %-20s|%10s|%10s|%10s|%10s",
ptr->opt_str, ta, tl, tr, td);
str_free(ta); str_free(tl); str_free(tr); str_free(td);
}
socket_options_free(opt);
closesocket(fd);
return 0; /* OK */
}

Просмотреть файл

@ -1,11 +1,11 @@
prefix=.
DEFS = -DPACKAGE_NAME=\"stunnel\" \
-DPACKAGE_TARNAME=\"stunnel\" \
-DPACKAGE_VERSION=\"5.60\" \
-DPACKAGE_STRING=\"stunnel\ 5.60\" \
-DPACKAGE_VERSION=\"5.61\" \
-DPACKAGE_STRING=\"stunnel\ 5.61\" \
-DPACKAGE_BUGREPORT=\"\" \
-DPACKAGE=\"stunnel\" \
-DVERSION=\"5.60\" \
-DVERSION=\"5.61\" \
-DSTDC_HEADERS=1 \
-DHAVE_SYS_TYPES_H=1 \
-DHAVE_SYS_STAT_H=1 \

Просмотреть файл

@ -38,7 +38,7 @@
#include "common.h"
#include "prototypes.h"
#define is_prefix(a, b) (strncasecmp((a), (b), strlen(b))==0)
#define CAPWIN_BUFFER_SIZE 100
/* protocol-specific function prototypes */
NOEXPORT char *socks_client(CLI *, SERVICE_OPTIONS *, const PHASE);
@ -71,9 +71,19 @@ NOEXPORT char *connect_client(CLI *, SERVICE_OPTIONS *, const PHASE);
NOEXPORT void ntlm(CLI *, SERVICE_OPTIONS *);
NOEXPORT char *ntlm1();
NOEXPORT char *ntlm3(char *, char *, char *, char *);
NOEXPORT void crypt_DES(DES_cblock, DES_cblock, DES_cblock);
NOEXPORT void crypt_DES(DES_cblock, DES_cblock, unsigned char[7]);
#endif
NOEXPORT char *base64(int, const char *, int);
NOEXPORT char *capwin_server(CLI *, SERVICE_OPTIONS *, const PHASE);
NOEXPORT char *capwin_client(CLI *, SERVICE_OPTIONS *, const PHASE);
NOEXPORT char *capwinctrl_client(CLI *, SERVICE_OPTIONS *, const PHASE);
/* global state */
NOEXPORT char capwin_auth[CAPWIN_BUFFER_SIZE]={0};
#ifdef USE_WIN32
HWND capwin_hwnd=NULL;
LONG capwin_connectivity=0;
#endif
/**************************************** framework */
@ -122,6 +132,14 @@ char *protocol(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) {
return opt->option.client ?
connect_client(c, opt, phase) :
connect_server(c, opt, phase);
if(!strcasecmp(opt->protocol, "capwin"))
return opt->option.client ?
capwin_client(c, opt, phase) :
capwin_server(c, opt, phase);
if(!strcasecmp(opt->protocol, "capwinctrl"))
return opt->option.client ?
capwinctrl_client(c, opt, phase) :
"The 'capwinctrl' protocol is not supported in the server mode";
return "Protocol not supported";
}
@ -652,7 +670,7 @@ NOEXPORT char *cifs_server(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) {
(void)opt; /* squash the unused parameter warning */
if(phase!=PROTOCOL_EARLY)
return NULL;
s_read(c, c->local_rfd.fd, buffer, 4) ;/* NetBIOS header */
s_read(c, c->local_rfd.fd, buffer, 4); /* NetBIOS header */
len=(uint16_t)(((uint16_t)(buffer[2])<<8)|buffer[3]);
if(len>sizeof buffer-4) {
s_log(LOG_ERR, "Received block too long");
@ -1601,4 +1619,250 @@ NOEXPORT char *base64(int encode, const char *in, int len) {
return out;
}
/**************************************** capwin authentication support */
NOEXPORT int capwin_decode(const char *src,
char **cmd, char **user, char **pass, char **ctrl) {
char *us1, *us2, *us3, *fs;
us1=strchr(src, '\x1f');
if(!us1) {
s_log(LOG_ERR, "CapWIN: Malformed credentials (1)");
return 1; /* FAILED */
}
us2=strchr(us1 + 1, '\x1f');
if(!us2) {
s_log(LOG_ERR, "CapWIN: Malformed credentials (2)");
return 1; /* FAILED */
}
us3=strchr(us2 + 1, '\x1f');
if(!us3) {
s_log(LOG_ERR, "CapWIN: Malformed credentials (3)");
return 1; /* FAILED */
}
fs=strchr(us3 + 1, '\x1c');
if(!fs) {
s_log(LOG_ERR, "CapWIN: Malformed credentials (4)");
return 1; /* FAILED */
}
if(cmd) {
size_t len=(size_t)(us1 - src);
*cmd=str_alloc(len + 1);
memcpy(*cmd, src, len);
}
if(user) {
size_t len=(size_t)(us2 - us1) - 1;
*user=str_alloc(len + 1);
memcpy(*user, us1 + 1, len);
}
if(pass) {
size_t len=(size_t)(us3 - us2) - 1;
*pass=str_alloc(len + 1);
memcpy(*pass, us2 + 1, len);
}
if(ctrl) {
size_t len=(size_t)(fs - us3) - 1;
*ctrl=str_alloc(len + 1);
memcpy(*ctrl, us3 + 1, len);
}
return 0; /* SUCCESS */
}
NOEXPORT int ldap_auth(CLI *c, const char *dn, const char *pass) {
size_t dn_len, pass_len, req_len;
SOCKADDR_UNION addr;
int i;
unsigned char *req, resp[22];
const unsigned char resp_ok[22]=
"\x30\x84\x00\x00\x00\x10\x02\x01\x01\x61\x84"
"\x00\x00\x00\x07\x0a\x01\x00\x04\x00\x04\x00";
/* reject parameters too long for simple encoding */
dn_len=strlen(dn);
pass_len=strlen(pass);
req_len=dn_len + pass_len + 14;
if(req_len > 120) {
s_log(LOG_ERR, "LDAP: Request too long");
return 1; /* FAILED */
}
/* connect the configured LDAP server */
if(!name2addr(&addr, c->opt->protocol_host, 0)) {
s_log(LOG_ERR, "LDAP: Failed to resolve protocolHost");
return 1; /* FAILED */
}
c->fd=s_socket(addr.sa.sa_family, SOCK_STREAM, 0, 1, "LDAP socket");
if(c->fd==INVALID_SOCKET)
return 1; /* FAILED */
s_log(LOG_DEBUG, "LDAP: Connecting the server");
if(s_connect(c, &addr, addr_len(&addr))) {
closesocket(c->fd);
c->fd=INVALID_SOCKET; /* avoid double close on cleanup */
return 1; /* FAILED */
}
/* send BindRequest */
req=str_alloc(req_len);
i=0;
req[i++]=0x30; /* SEQUENCE */
req[i++]=(unsigned char)(dn_len + pass_len + 12);
req[i++]=0x02; /* INTEGER */
req[i++]=0x01; /* length */
req[i++]=0x01; /* MessageID */
req[i++]=0x60; /* [APPLICATION 0]: BindRequest */
req[i++]=(unsigned char)(dn_len + pass_len + 7);
req[i++]=0x02; /* INTEGER */
req[i++]=0x01; /* length */
req[i++]=0x03; /* LDAP protocol version */
req[i++]=0x04; /* OCTET STRING */
req[i++]=(unsigned char)dn_len;
memcpy(req + i, dn, dn_len);
i+=(int)dn_len;
req[i++]=0x80; /* [IMPLICIT 0]: simple authentication */
req[i++]=(unsigned char)pass_len;
memcpy(req + i, pass, pass_len);
s_log(LOG_DEBUG, "LDAP: Sending BindRequest");
s_write(c, c->fd, req, req_len);
str_free(req);
/* receive BindResponse */
s_log(LOG_DEBUG, "LDAP: Waiting for BindResponse");
s_read(c, c->fd, resp, sizeof resp);
closesocket(c->fd);
c->fd=INVALID_SOCKET; /* avoid double close on cleanup */
return memcmp(resp, resp_ok, sizeof resp);
}
NOEXPORT char *ldap_escape_dn(const char *src) {
int i=0, j=0;
char *dst=str_alloc(2 * strlen(src) + 1);
while(src[i]) {
if(strchr("+;,\\\"<>#", src[i]))
dst[j++]='\\';
dst[j++]=src[i++];
}
return dst;
}
NOEXPORT char *capwin_server(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) {
char *buffer, *user, *pass, *esc_user, *dn;
const char *success="BINGO", *failure="FAILED";
int i;
(void)opt; /* squash the unused parameter warning */
switch(phase) {
case PROTOCOL_MIDDLE: /* TLS is established */
buffer=str_alloc(CAPWIN_BUFFER_SIZE);
for(i=0; i<CAPWIN_BUFFER_SIZE - 1; ++i) {
s_ssl_read(c, buffer+i, 1);
if(buffer[i] == '\x1c')
break;
}
if(capwin_decode(buffer, NULL, &user, &pass, NULL)) {
/* malformed request: reset instead of sending "FAILED" */
str_free(buffer);
throw_exception(c, 1);
}
str_free(buffer);
esc_user=ldap_escape_dn(user);
str_free(user);
dn=str_printf("uid=%s,ou=people,O=CAPWIN,C=US", esc_user);
str_free(esc_user);
if(ldap_auth(c, dn, pass)) {
str_free(dn);
str_free(pass);
s_log(LOG_ERR, "CapWIN: Authentication failed");
s_ssl_write(c, failure, (int)strlen(failure));
throw_exception(c, 2); /* don't reset */
}
str_free(dn);
str_free(pass);
s_log(LOG_NOTICE, "CapWIN: Authentication succeeded");
break;
case PROTOCOL_LATE: /* remote host is connected */
s_ssl_write(c, success, (int)strlen(success));
break;
default:
break;
}
return NULL;
}
NOEXPORT char *capwin_client(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) {
char *cmd, *user, *pass, *ctrl, *req, resp[5];
(void)opt; /* squash the unused parameter warning */
if(phase!=PROTOCOL_LATE)
return NULL;
/* we extract the username and the password to work around a bug in the
* original server-side code that required unused units to be empty */
/* otherwise, we could simply forward capwin_auth directly */
if(!capwin_auth[0]) {
s_log(LOG_ERR, "CapWIN: No credentials set");
throw_exception(c, 1);
}
if(capwin_decode(capwin_auth, &cmd, &user, &pass, &ctrl))
throw_exception(c, 1);
if(strcmp(cmd, "AUTH")) {
s_log(LOG_ERR, "CapWIN: Invalid authentication request");
str_free(cmd);
str_free(user);
str_free(pass);
str_free(ctrl);
throw_exception(c, 1);
}
str_free(cmd);
req=str_printf("\x1f%s\x1f%s\x1f\x1c", user, pass);
str_free(user);
str_free(pass);
#ifdef USE_WIN32
capwin_hwnd=(HWND)(uintptr_t)atoi(ctrl);
#endif
str_free(ctrl);
s_log(LOG_DEBUG, "CapWIN: Sending credentials");
s_ssl_write(c, req, (int)strlen(req));
str_free(req);
s_log(LOG_DEBUG, "CapWIN: Waiting for response");
s_ssl_read(c, resp, sizeof resp);
#ifdef USE_WIN32
/* we received a response, so network is up */
if(!InterlockedExchange(&capwin_connectivity, 1))
PostMessage(capwin_hwnd, WM_CAPWIN_NET_UP, 0, 0);
#endif
if(memcmp(resp, "BINGO", sizeof resp)) {
s_log(LOG_ERR, "CapWIN: Authentication failed");
#ifdef USE_WIN32
PostMessage(capwin_hwnd, WM_CAPWIN_AUTH_FAIL, 0, 0);
#endif
throw_exception(c, 1);
}
s_log(LOG_NOTICE, "CapWIN: Authentication succeeded");
#ifdef USE_WIN32
PostMessage(capwin_hwnd, WM_CAPWIN_AUTH_OK, 0, 0);
#endif
return NULL;
}
NOEXPORT char *capwinctrl_client(CLI *c, SERVICE_OPTIONS *opt, const PHASE phase) {
switch(phase) {
case PROTOCOL_CHECK:
opt->option.protocol_endpoint=1;
break;
case PROTOCOL_EARLY:
s_log(LOG_DEBUG, "CapWIN: Setting credentials");
memset(capwin_auth, 0, CAPWIN_BUFFER_SIZE);
s_read_eof(c, c->local_rfd.fd, capwin_auth, CAPWIN_BUFFER_SIZE - 1);
s_log(LOG_NOTICE, "CapWIN: Credentials set");
/* skip connecting a remote host */
throw_exception(c, 2); /* don't reset */
default:
break;
}
return NULL;
}
/* end of protocol.c */

Просмотреть файл

@ -44,6 +44,14 @@
#define USE_OS_THREADS
#endif
#ifdef USE_OS_THREADS
#ifndef USE_WIN32
/* FIXME: waiting for a single terminate_pipe socket
* from multiple threads causes a deadlock on WIN32 */
#define USE_TERMINATE_PIPE
#endif /* USE_WIN32 */
#endif /* USE_OS_THREADS */
/**************************************** forward declarations */
typedef struct tls_data_struct TLS_DATA;
@ -246,9 +254,9 @@ typedef struct service_options_struct {
#if OPENSSL_VERSION_NUMBER>=0x10100000L
int security_level;
#endif /* OpenSSL 1.1.0 or later */
long unsigned ssl_options_set;
uint64_t ssl_options_set;
#if OPENSSL_VERSION_NUMBER>=0x009080dfL
long unsigned ssl_options_clear;
uint64_t ssl_options_clear;
#endif /* OpenSSL 0.9.8m or later */
#if OPENSSL_VERSION_NUMBER>=0x10100000L
int min_proto_version, max_proto_version;
@ -486,7 +494,6 @@ void stunnel_info(int);
/**************************************** prototypes for options.c */
extern char *configuration_file;
extern unsigned number_of_sections;
int options_cmdline(char *, char *);
@ -633,6 +640,7 @@ void throw_exception(CLI *, int) NORETURN;
int get_socket_error(const SOCKET);
int s_connect(CLI *, SOCKADDR_UNION *, socklen_t);
void s_write(CLI *, SOCKET fd, const void *, size_t);
size_t s_read_eof(CLI *, SOCKET fd, void *, size_t);
void s_read(CLI *, SOCKET fd, void *, size_t);
void fd_putline(CLI *, SOCKET, const char *);
char *fd_getline(CLI *, SOCKET);
@ -644,6 +652,7 @@ void fd_printf(CLI *, SOCKET, const char *, ...)
;
#endif
void s_ssl_write(CLI *, const void *, int);
size_t s_ssl_read_eof(CLI *, void *, int);
void s_ssl_read(CLI *, void *, int);
char *ssl_getstring(CLI *c);
char *ssl_getline(CLI *c);
@ -664,6 +673,11 @@ typedef enum {
PROTOCOL_LATE
} PHASE;
#ifdef USE_WIN32
extern HWND capwin_hwnd;
extern LONG capwin_connectivity;
#endif
char *protocol(CLI *, SERVICE_OPTIONS *opt, const PHASE);
/**************************************** prototypes for resolver.c */

Просмотреть файл

@ -350,8 +350,10 @@ char *s_ntop(SOCKADDR_UNION *addr, socklen_t addrlen) {
if(err) {
s_log(LOG_ERR, "getnameinfo: %s", s_gai_strerror(err));
retval=str_dup("unresolvable address");
} else
retval=str_printf("%s:%s", host, port);
} else if(!*port && !*host)
retval=str_dup("unnamed socket");
else
retval=str_printf("%s%s%s", host, *host && *port ? ":" : "", port);
str_free(host);
str_free(port);
return retval;

Просмотреть файл

@ -3,7 +3,13 @@
#define WM_VALID_CONFIG (WM_APP+0)
#define WM_INVALID_CONFIG (WM_APP+1)
#define WM_NEW_CHAIN (WM_APP+2)
#define WM_CLIENTS (WM_APP+3)
#define WM_TERMINATE (WM_APP+3)
#define WM_CAPWIN_DESTROY (WM_APP+0x67)
#define WM_CAPWIN_NET_DOWN (WM_APP+0x68)
#define WM_CAPWIN_NET_UP (WM_APP+0x69)
#define WM_CAPWIN_AUTH_OK (WM_APP+0x70)
#define WM_CAPWIN_AUTH_FAIL (WM_APP+0x71)
#define IDI_STUNNEL_MAIN 10
#define IDI_STUNNEL_ACTIVE 11
@ -13,6 +19,7 @@
#define IDE_EDIT 20
#define IDE_PASSEDIT 21
#define IDE_PINEDIT 22
#define IDE_PAUSE 23
#define IDM_TRAYMENU 30
#define IDM_MAINMENU 31

Просмотреть файл

@ -44,7 +44,7 @@ BEGIN
MENUITEM "Reopen &Log File", IDM_REOPEN_LOG, GRAYED
MENUITEM "Co&nnections", IDM_CONNECTIONS
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
MENUITEM "&Terminate", IDM_EXIT
MENUITEM SEPARATOR
MENUITEM "&Close", IDM_CLOSE
END
@ -58,9 +58,9 @@ BEGIN
MENUITEM "&Reload Configuration", IDM_RELOAD_CONFIG
END
#ifdef _WIN32_WCE
POPUP "&Save Peer Certs"
POPUP "&Save Peer Cert", GRAYED
#else
POPUP "&Save Peer Certificate"
POPUP "&Save Peer Certificate", GRAYED
#endif
BEGIN
MENUITEM "dummy", 0, GRAYED
@ -86,7 +86,7 @@ BEGIN
MENUITEM "&Edit Configuration", IDM_EDIT_CONFIG
MENUITEM "&Reload Configuration", IDM_RELOAD_CONFIG
MENUITEM SEPARATOR
POPUP "&Save Peer Certificate"
POPUP "&Save Peer Certificate", GRAYED
BEGIN
MENUITEM "dummy", 0, GRAYED
END
@ -95,7 +95,7 @@ BEGIN
MENUITEM "&Manual", IDM_MANPAGE
MENUITEM "&About", IDM_ABOUT
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
MENUITEM "&Terminate", IDM_EXIT
END
END

Просмотреть файл

@ -70,7 +70,11 @@ NOEXPORT STACK_OF(SSL_COMP) *comp_methods[STUNNEL_COMPS];
int fips_available() { /* either FIPS provider or container is available */
#ifdef USE_FIPS
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
return OSSL_PROVIDER_available(NULL, "fips");
static OSSL_PROVIDER *fips=NULL;
if(!fips)
fips=OSSL_PROVIDER_try_load(NULL, "fips", 1);
return fips && OSSL_PROVIDER_available(NULL, "fips");
#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
/* checking for OPENSSL_FIPS would be less precise, because it only
* depends on the compiled, and not on the running OpenSSL version */
@ -195,24 +199,27 @@ NOEXPORT void cb_free_addr(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
int ssl_configure(GLOBAL_OPTIONS *global) { /* configure global TLS settings */
#ifdef USE_FIPS
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
static OSSL_PROVIDER *prov=NULL;
if(global->option.fips) {
if(!prov) { /* need to load */
if(!EVP_default_properties_is_fips_enabled(NULL)) {
if(!fips_available()) {
s_log(LOG_ERR, "FIPS provider not available");
sslerror("FIPS PROVIDER");
return 1;
}
prov=OSSL_PROVIDER_load(NULL, "fips");
if(!prov) {
sslerror("OSSL_PROVIDER_load");
if(!EVP_default_properties_enable_fips(NULL, 1) ||
!EVP_default_properties_is_fips_enabled(NULL)) {
s_log(LOG_ERR, "Enabling FIPS provider failed");
return 1;
}
s_log(LOG_NOTICE, "FIPS provider enabled");
}
} else {
if(prov) { /* need to unload */
OSSL_PROVIDER_unload(prov);
prov=NULL;
if(EVP_default_properties_is_fips_enabled(NULL)) {
if(!EVP_default_properties_enable_fips(NULL, 0) ||
EVP_default_properties_is_fips_enabled(NULL)) {
s_log(LOG_ERR, "Disabling FIPS provider failed");
return 1;
}
s_log(LOG_NOTICE, "FIPS provider disabled");
}
}
#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */

Просмотреть файл

@ -112,7 +112,7 @@ void thread_id_init(void) {
#if OPENSSL_VERSION_NUMBER>=0x10000000L && OPENSSL_VERSION_NUMBER<0x10100000L
CRYPTO_THREADID_set_callback(threadid_func);
#endif
#if OPENSSL_VERSION_NUMBER<0x10000000L || !defined(OPENSSL_NO_DEPRECATED)
#if OPENSSL_VERSION_NUMBER<0x10000000L
CRYPTO_set_id_callback(stunnel_thread_id);
#endif
}

Просмотреть файл

@ -68,6 +68,7 @@ struct sockaddr_un {
};
#endif
NOEXPORT void terminate_threads();
#if !defined(USE_WIN32) && !defined(USE_OS2)
NOEXPORT void pid_status_nohang(const char *);
NOEXPORT void status_info(int, int, const char *);
@ -90,7 +91,9 @@ NOEXPORT char *signal_name(int);
/**************************************** global variables */
SOCKET signal_pipe[2]={INVALID_SOCKET, INVALID_SOCKET};
#ifdef USE_TERMINATE_PIPE
SOCKET terminate_pipe[2]={INVALID_SOCKET, INVALID_SOCKET};
#endif /* USE_TERMINATE_PIPE */
#ifndef USE_FORK
int max_clients=0;
@ -133,9 +136,11 @@ void main_init() { /* one-time initialization */
if(pipe_init(signal_pipe, "signal_pipe"))
fatal("Signal pipe initialization failed: "
"check your personal firewall");
#ifdef USE_TERMINATE_PIPE
if(pipe_init(terminate_pipe, "terminate_pipe"))
fatal("Terminate pipe initialization failed: "
"check your personal firewall");
#endif /* USE_TERMINATE_PIPE */
stunnel_info(LOG_NOTICE);
if(systemd_fds>0)
s_log(LOG_INFO, "Systemd socket activation: %d descriptors received",
@ -234,14 +239,26 @@ int drop_privileges(int critical) {
return 0;
}
void main_cleanup() {
terminate_threads();
unbind_ports();
s_poll_free(fds);
fds=NULL;
#if 0
str_stats(); /* main thread allocation tracking */
#endif
log_flush(LOG_MODE_BUFFER); /* no more logs */
log_close(SINK_SYSLOG|SINK_OUTFILE);
}
#ifdef __GNUC__
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
#endif /* __GNUC__>=4.6 */
#endif /* __GNUC__ */
void main_cleanup() {
#ifdef USE_OS_THREADS
NOEXPORT void terminate_threads() {
#ifdef USE_TERMINATE_PIPE
CLI *c;
unsigned i, threads;
THREAD_ID *thread_list;
@ -263,7 +280,7 @@ void main_cleanup() {
CRYPTO_THREAD_unlock(stunnel_locks[LOCK_THREAD_LIST]);
if(threads) {
s_log(LOG_NOTICE, "Terminating %u service thread(s)", threads);
s_log(LOG_INFO, "Terminating %u service thread(s)", threads);
writesocket(terminate_pipe[1], "", 1);
for(i=0; i<threads; ++i) { /* join client threads */
#ifdef USE_PTHREAD
@ -277,20 +294,11 @@ void main_cleanup() {
ioerror("CloseHandle");
#endif
}
s_log(LOG_NOTICE, "Service threads terminated");
s_log(LOG_INFO, "Service threads terminated");
}
str_free(thread_list);
#endif /* USE_OS_THREADS */
unbind_ports();
s_poll_free(fds);
fds=NULL;
#if 0
str_stats(); /* main thread allocation tracking */
#endif
log_flush(LOG_MODE_BUFFER); /* no more logs */
log_close(SINK_SYSLOG|SINK_OUTFILE);
#endif /* USE_TERMINATE_PIPE */
}
#ifdef __GNUC__
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
@ -884,18 +892,20 @@ NOEXPORT void reload_config() {
NOEXPORT int process_connections() {
#ifndef USE_FORK
CLI *c;
int n=0;
s_log(LOG_NOTICE, "Active connections:");
s_log(LOG_EMERG, "Active connections:");
CRYPTO_THREAD_write_lock(stunnel_locks[LOCK_THREAD_LIST]);
for(c=thread_head; c; c=c->thread_next) {
s_log(LOG_NOTICE, "Service [%s]: "
s_log(LOG_EMERG, "Active connection %d: Service [%s], "
"%llu byte(s) sent to TLS, "
"%llu byte(s) sent to socket",
c->opt->servname,
++n, c->opt->servname,
(unsigned long long)c->ssl_bytes,
(unsigned long long)c->sock_bytes);
}
CRYPTO_THREAD_unlock(stunnel_locks[LOCK_THREAD_LIST]);
s_log(LOG_EMERG, "Listed %d active connection(s)", n);
#endif /* USE_FORK */
return 0; /* continue execution */
}

Просмотреть файл

@ -65,8 +65,12 @@ int main(int argc, char *argv[]) {
#endif
_tputenv(str_tprintf(TEXT("OPENSSL_ENGINES=%s\\engines"),
stunnel_exe_path));
_tputenv(str_tprintf(TEXT("OPENSSL_MODULES=%s\\ossl-modules"),
stunnel_exe_path));
_tputenv(str_tprintf(TEXT("OPENSSL_CONF=%s\\config\\openssl.cnf"),
stunnel_exe_path));
if(WSAStartup(MAKEWORD(1, 1), &wsa_state))
if(WSAStartup(MAKEWORD(2, 2), &wsa_state))
return 1;
resolver_init();
main_init();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -65,7 +65,7 @@
/* START CUSTOMIZE */
#define VERSION_MAJOR 5
#define VERSION_MINOR 60
#define VERSION_MINOR 61
/* END CUSTOMIZE */
/* all the following macros are ABSOLUTELY NECESSARY to have proper string

Просмотреть файл

@ -3,10 +3,15 @@
SUBDIRS = certs
EXTRA_DIST = make_test test_library recipes execute execute_read execute_write http_request server.py
EXTRA_DIST = maketest.py plugin_collection.py reader.py error.py plugins
# try to find a supported python version (>= 3.7) that works
check-local:
$(srcdir)/make_test
for v in $$(seq 20 -1 7); do command -v python3.$$v && break; done || ( echo "Python 3.7 or later not found" && false )
for v in $$(seq 20 -1 7); do command -v python3.$$v && python3.$$v $(srcdir)/maketest.py --debug=10 && break; done
distclean-local:
rm -f logs/*.log
rm -f certs/*.pem
rm -f certs/*.p12
rm -f certs/*.txt

Просмотреть файл

@ -309,7 +309,7 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = certs
EXTRA_DIST = make_test test_library recipes execute execute_read execute_write http_request server.py
EXTRA_DIST = maketest.py plugin_collection.py reader.py error.py plugins
all: all-recursive
.SUFFIXES:
@ -628,11 +628,16 @@ uninstall-am:
.PRECIOUS: Makefile
# try to find a supported python version (>= 3.7) that works
check-local:
$(srcdir)/make_test
for v in $$(seq 20 -1 7); do command -v python3.$$v && break; done || ( echo "Python 3.7 or later not found" && false )
for v in $$(seq 20 -1 7); do command -v python3.$$v && python3.$$v $(srcdir)/maketest.py --debug=10 && break; done
distclean-local:
rm -f logs/*.log
rm -f certs/*.pem
rm -f certs/*.p12
rm -f certs/*.txt
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

Просмотреть файл

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDwTCCAqmgAwIBAgIUAgntZn82DgFlMtCp03CIJSTafIUwDQYJKoZIhvcNAQEL
BQAwaDELMAkGA1UEBhMCUEwxGzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQ
MA4GA1UECwwHUm9vdCBDQTELMAkGA1UEAwwCQ0ExHTAbBgkqhkiG9w0BCQEWDkNB
QGV4YW1wbGUuY29tMB4XDTIxMDMxODEyNTQxOFoXDTI1MDMxODEyNTQxOFowaDEL
MAkGA1UEBhMCUEwxGzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQMA4GA1UE
CwwHUm9vdCBDQTELMAkGA1UEAwwCQ0ExHTAbBgkqhkiG9w0BCQEWDkNBQGV4YW1w
bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy6NMBiYDSCxb
vjzY//qWDqx8v6SXDWPLfiT8/tHuH/oBcnfsfp9nGygvctjPNg0pl6+IFVi5UdhC
RoRQBFmsSgiDJtmSuvO+Rtb+aG4RMNJOQpeKvOgu+xxxRSOYOyL2l+dOsrSIAnOB
yZ+YMc7GTnx9cl5f/GtifMBVGKUSsODqa6SOVg6BVgn+ftmyKa5s2Gh8mWz2+7Cr
eN4L2IoV3H3x0NhYzUoWCyCwXgLU0y5p2Pzp2w6SVDgy1PjxNYXGzE2BvhXj+ASJ
gFAfYV99sofXdTJMxbjXG/rpY2ymYk/Z66vNZw94p1AdL7byAvYDopCtzVNb338f
lp1aiBpHMwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQXfp8c
sA5qErTdb/lD30wQEcCICjAfBgNVHSMEGDAWgBQXfp8csA5qErTdb/lD30wQEcCI
CjAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEBAG8U/a5founQWwWj
4t77YlwmJL6/+GVNbAYq/q2i9Iit5NrWydLzwxIAyQoVUrw0rkllvfnJFlh7Bpiz
hGvTcq+DW4se+D3gAL1IB3PBMaRJ4oGAoB+7xw9k/sI/b96W1nGcBIA3sKw3F00e
GSLvZkRLwnzEFaDkNVA/Ux2F/Swo0Yx+8JwDlH6cVSZZpiTtZZe/Zk475u13hpVH
o1CWauP3lji72XWV94ohRtUHMWuOTJR6QkL+ekypBIoS/kU/PUH2iqxiv4eTBNFV
S15UAMPlV1Cq0GOSczPcrfyLav4DAQLb37FKIK6wfy609hHDga2w0DDFEKZ3+Sco
JTR4BB4=
-----END CERTIFICATE-----

Просмотреть файл

@ -1,13 +0,0 @@
-----BEGIN X509 CRL-----
MIIB7TCB1gIBATANBgkqhkiG9w0BAQsFADBoMQswCQYDVQQGEwJQTDEbMBkGA1UE
CgwSU3R1bm5lbCBEZXZlbG9wZXJzMRAwDgYDVQQLDAdSb290IENBMQswCQYDVQQD
DAJDQTEdMBsGCSqGSIb3DQEJARYOQ0FAZXhhbXBsZS5jb20XDTIxMDMxODEyNTQx
OFoXDTI1MDMxODEyNTQxOFowFTATAgIQABcNMjEwMzE4MTI1NDE4WqAjMCEwHwYD
VR0jBBgwFoAUF36fHLAOahK03W/5Q99MEBHAiAowDQYJKoZIhvcNAQELBQADggEB
ALfCOE8XUACUlLHCuhfbddnInp2ZRrUjJcZxjjlgDiUbQGvTcBFxT6hoPa0iIiND
ijgzieMr4aoOycpYKi3kcn7YBdntCZ4JZul4BiyU1Y4jyWw38jNmtxQ81UKoSmJM
fee02LykPWAWm3IUvy3QRYoZl+bs3yQHW5E8IEQvqJW2jlTeIpnK+jKLJd/aR3Af
yxwqV1ALkkDbQ4qsvACswsbq2TfVkXnsot6BAmkT1dsvHtmeGbtOFQJPCujIlHoy
Gi2jTuaf4a03wMZz9hIxh5auXExNbhS2HKqX+rZiSLg/H4tGj5Z5BWayZxWqlIG3
2LIZhzCROn6arv/2Xpme+es=
-----END X509 CRL-----

Просмотреть файл

@ -2,10 +2,6 @@
# by Michal Trojnara 1998-2021
EXTRA_DIST = maketestcert.sh openssltest.cnf
EXTRA_DIST += CACertCRL.pem CACert.pem
EXTRA_DIST += server_cert.pem server_cert.p12 client_cert.pem
EXTRA_DIST += revoked_cert.pem stunnel.pem PeerCerts.pem
EXTRA_DIST += psk1.txt psk2.txt secrets.txt
check-local:
$(srcdir)/maketestcert.sh

Просмотреть файл

@ -248,10 +248,7 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
EXTRA_DIST = maketestcert.sh openssltest.cnf CACertCRL.pem CACert.pem \
server_cert.pem server_cert.p12 client_cert.pem \
revoked_cert.pem stunnel.pem PeerCerts.pem psk1.txt psk2.txt \
secrets.txt
EXTRA_DIST = maketestcert.sh openssltest.cnf
all: all-am
.SUFFIXES:

Просмотреть файл

@ -1,44 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDoDCCAoigAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCUEwx
GzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQMA4GA1UECwwHUm9vdCBDQTEL
MAkGA1UEAwwCQ0ExHTAbBgkqhkiG9w0BCQEWDkNBQGV4YW1wbGUuY29tMB4XDTIx
MDMxODEyNTQxOFoXDTI1MDMxODEyNTQxOFowbzELMAkGA1UEBhMCUEwxGzAZBgNV
BAoMElN0dW5uZWwgRGV2ZWxvcGVyczEPMA0GA1UECwwGY2xpZW50MQ8wDQYDVQQD
DAZjbGllbnQxITAfBgkqhkiG9w0BCQEWEmNsaWVudEBleGFtcGxlLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5Oew1AT5Ll2hMhOJ8Z+7s5Bai2
OggPA6veuTYZSgNZFap004BLg3J5mohgV5Itf0qsx6m10JdF5qDGh44cVIM7OYY+
f0XPrjvhzxps0TZmSc7Gb4Kd99evEo/A0PRsQHSC4aYZr/CKMAkWun4HWunxBPV4
XFVMtlPFgibncXM9SoyEhqIn93cvYrbcAGPFBMudJePVwYwIDhAlLGrMOHgExUtt
cgZOpUBCW8ImzwPumEqxNveybmMLwECxMC5hjBXniiOzs3hWxN4Ih3yQWtls7wdN
2D0GdwyIGjUa4AIl0BL2B1BLp5dGPgm//2PVrukZmCKxWSBcOIkQz1FF7ysCAwEA
AaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQUlCst2zML4i8FXy1qi/1+uUd13Rgw
HwYDVR0jBBgwFoAUF36fHLAOahK03W/5Q99MEBHAiAowDQYJKoZIhvcNAQELBQAD
ggEBABafr4e69w/j1/SkD3mtGDphfttJ3XfwySPE47pXN8jaWrvQmRa1Q11x1R+c
oJBGyI/Vg65IAUfbDqAqi7Gropsa+3fF5Zm2yLXtxYkWa15/Bn/6XDOWMwhIuGdM
2OHWa4qmnAzjseE/CPCB+YM4x2Fgqa9hn8rOmteIBZ6KC3rWR4+9gmqcjt1ZNiQ4
1GSiUDBSjmTsPlyb5TLQ2MrowYLYtJjGOLVx3ZaN7plDmh9om+4AeuIkEsLwmB+P
SrUGhEqo4MnaPdj/XKQCwVG7DqAd4BReSc4ZzFegycU98z4ALzJ5qy2bT05yEkCO
UxDcwNGhr3pOLKb/9860qeY5bi0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDoDCCAoigAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCUEwx
GzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQMA4GA1UECwwHUm9vdCBDQTEL
MAkGA1UEAwwCQ0ExHTAbBgkqhkiG9w0BCQEWDkNBQGV4YW1wbGUuY29tMB4XDTIx
MDMxODEyNTQxOFoXDTI1MDMxODEyNTQxOFowbzELMAkGA1UEBhMCUEwxGzAZBgNV
BAoMElN0dW5uZWwgRGV2ZWxvcGVyczEPMA0GA1UECwwGc2VydmVyMQ8wDQYDVQQD
DAZzZXJ2ZXIxITAfBgkqhkiG9w0BCQEWEnNlcnZlckBleGFtcGxlLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNK+CxahWSi4zH4SQgMJjPjiiI+
zG6JTpibWV9Lxuc21b2XRlx9I8xOITsDb3JiKacO6Lg+hWg+EymuyFAE/h5ASmNZ
e9pCEmsvCM8XGYyGw18cxOoNK8v+DzAR4XySF6BOcaeaFnInTcbYUnhK0YDSn0P6
lyv8Ol76xR/C+y4AvuyoYCjVOzvxY2g3HdjlyA7RwVS9ekYgS5nd0s/qdO91gQ+4
imb67HW76bF5LmiCAfZ0XKqHFyvHO5D57QifLq3Kwe6IorTrTSFH/fWre/A/JIji
Bt63dGSlxCnfNzQIJYJjJYdU7tz7cKMnpp0avxSCeFZYw8RsAr1L8JunLtsCAwEA
AaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQU7L61jETM7BttdLW3uOPJuRqs9uUw
HwYDVR0jBBgwFoAUF36fHLAOahK03W/5Q99MEBHAiAowDQYJKoZIhvcNAQELBQAD
ggEBAFfZkSmuYMjMfEBzBUudunL2vOeQUsQcH6KROsYaq+lN09aazMKBX8j+VMTL
6ZSlVxeM5BCXdD3GvpFb+R4ED8EcrRWKbAiqUJz1tAyjLRyHW2GWqfFpOn5yNonK
vsUtZSL+v87V26PGuRs5dQizGkstS2gKx3zFqaKwWdCQE5ldDwT+kDkghvALoGXw
IuFt7+QbZjLQvQ/YdCUXjBVdzICVO5WgEePAZ4IO8r20jrda2aP5OFVmUcc+iA8P
Rn6jCOfdnNyBDWwm+oEf1WecYxTr0Ly0d3QcOxpAUeQTgT6tZawpllGLkwfrUZFV
09YKu45BurR5WZzok/9zyflPv80=
-----END CERTIFICATE-----

Просмотреть файл

@ -1,49 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDoDCCAoigAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCUEwx
GzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQMA4GA1UECwwHUm9vdCBDQTEL
MAkGA1UEAwwCQ0ExHTAbBgkqhkiG9w0BCQEWDkNBQGV4YW1wbGUuY29tMB4XDTIx
MDMxODEyNTQxOFoXDTI1MDMxODEyNTQxOFowbzELMAkGA1UEBhMCUEwxGzAZBgNV
BAoMElN0dW5uZWwgRGV2ZWxvcGVyczEPMA0GA1UECwwGY2xpZW50MQ8wDQYDVQQD
DAZjbGllbnQxITAfBgkqhkiG9w0BCQEWEmNsaWVudEBleGFtcGxlLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5Oew1AT5Ll2hMhOJ8Z+7s5Bai2
OggPA6veuTYZSgNZFap004BLg3J5mohgV5Itf0qsx6m10JdF5qDGh44cVIM7OYY+
f0XPrjvhzxps0TZmSc7Gb4Kd99evEo/A0PRsQHSC4aYZr/CKMAkWun4HWunxBPV4
XFVMtlPFgibncXM9SoyEhqIn93cvYrbcAGPFBMudJePVwYwIDhAlLGrMOHgExUtt
cgZOpUBCW8ImzwPumEqxNveybmMLwECxMC5hjBXniiOzs3hWxN4Ih3yQWtls7wdN
2D0GdwyIGjUa4AIl0BL2B1BLp5dGPgm//2PVrukZmCKxWSBcOIkQz1FF7ysCAwEA
AaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQUlCst2zML4i8FXy1qi/1+uUd13Rgw
HwYDVR0jBBgwFoAUF36fHLAOahK03W/5Q99MEBHAiAowDQYJKoZIhvcNAQELBQAD
ggEBABafr4e69w/j1/SkD3mtGDphfttJ3XfwySPE47pXN8jaWrvQmRa1Q11x1R+c
oJBGyI/Vg65IAUfbDqAqi7Gropsa+3fF5Zm2yLXtxYkWa15/Bn/6XDOWMwhIuGdM
2OHWa4qmnAzjseE/CPCB+YM4x2Fgqa9hn8rOmteIBZ6KC3rWR4+9gmqcjt1ZNiQ4
1GSiUDBSjmTsPlyb5TLQ2MrowYLYtJjGOLVx3ZaN7plDmh9om+4AeuIkEsLwmB+P
SrUGhEqo4MnaPdj/XKQCwVG7DqAd4BReSc4ZzFegycU98z4ALzJ5qy2bT05yEkCO
UxDcwNGhr3pOLKb/9860qeY5bi0=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA3k57DUBPkuXaEyE4nxn7uzkFqLY6CA8Dq965NhlKA1kVqnTT
gEuDcnmaiGBXki1/SqzHqbXQl0XmoMaHjhxUgzs5hj5/Rc+uO+HPGmzRNmZJzsZv
gp33168Sj8DQ9GxAdILhphmv8IowCRa6fgda6fEE9XhcVUy2U8WCJudxcz1KjISG
oif3dy9ittwAY8UEy50l49XBjAgOECUsasw4eATFS21yBk6lQEJbwibPA+6YSrE2
97JuYwvAQLEwLmGMFeeKI7OzeFbE3giHfJBa2WzvB03YPQZ3DIgaNRrgAiXQEvYH
UEunl0Y+Cb//Y9Wu6RmYIrFZIFw4iRDPUUXvKwIDAQABAoIBADuklLEOcwr3bhW5
0QYmo3osp08HbPRiitqey9Qu3sOdMAnmhCQknmSlKYezSWtnl4JCbuMia49aarDx
8sZ25Vm8FwfkVqM1QArC35y4Wz0cHmtCpAJIPYl5aCJ3Wdhp/rUDtGSq+aAwgwi9
N1W+xW6Ego8VNriP907sa6niaHbBF7N5qNls6YrHlevQUUlpEO+ADgIlpfl2ICWs
5cTVhFuqz0yECwoX0CeRGUb8EhcLnd1xMwOd4+olWUHSuhXTUTTUaTYIrEhy6tFD
ua2prlRRbmzmB/l53aCCRSthpDfkPSPC4CL02jDQerIo5E5YHNP0AWUL+PQzLQQ8
tRa197ECgYEA/YEXe6K+06MExN39JFnWCJLqs41zMrYwJ+W3hm0A9VZbbWy/2/xz
ZDLnpEc4qiH8fPLM+hllPc07RlZYY47ni/RpVHfs98mYGOifmXmUfR1QKETv5FhD
n7R/PoKynjQQwhPyrnfPDSz/wkejyv80v2AxgzNgj9dFfrGGjt/IpPMCgYEA4H7C
3dju8UDlJJb0xSe7UrJe/6Yw0iRy4FSMYIgmIBk+X/1DPDvBCxqG6/OUdNPE3ydG
wWCRIZ4UkLLU5+22q2gn6jAfvtNfpwUy9VvKq26Df15/Ir0eK+onyYvXgxx6hP23
kPXh727aENpblwuA9eG8kqfO9YPKdcUrghnEeukCgYEAuvkIqe7KEmxtKwqUF8iO
vXom01GjwqZvdC3RI7un9kvAWT/ZblaPgTqucRL6rzkr8bhfCKPMcT2611D+Fkgj
ba1SNrPROp0cqlqAxIDQzUregST/TorvLY7CPwfE2DyMk6iE2LuTIiOra87M9v8u
F2zKd/tf4BelsSEcnqpdYZMCgYAieVTTXIzU33JQvB26aO+LM3kDKTI2EwLRECq+
aCnyo+3AL9QzW7m5SsmNUkpp5ltFKXLkH0AqOWxPDCdFtmtmxwfaHqnBVBRMQbAh
nYbx7HalCI3dd806USrq+F6P87+czJlz2U5oxk0WaXHHMC0NlSywGLTfXu2oSC72
O57AgQKBgGJhmy4BYJ7IVLJ035SS+j/XqmwpXFTsQKjZ4jQuzlWyjLlIQNVWPk2W
Ci28ttyHZUDA9V/eTTZ24QW/apxV57WKsJEj5t7qDA3UblnozCKRq4ShkF6t8YEX
f5xUTwYrlnao1UCvMXHLCvGYDw5yCqLZQ3fO2qjSmLPcK6wslEQp
-----END RSA PRIVATE KEY-----

Просмотреть файл

@ -1 +0,0 @@
test1:6UoHxibiMes9DaN8P0aDsM0tRbEBCflRoDaTVYefMHc26BFX7I

Просмотреть файл

@ -1 +0,0 @@
test2:3RbLUm5d40p9AUCLXgnr6Y3VrlKziUlZdHr6LqHjCgLUJaexa4

Просмотреть файл

@ -1,49 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDozCCAougAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCUEwx
GzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQMA4GA1UECwwHUm9vdCBDQTEL
MAkGA1UEAwwCQ0ExHTAbBgkqhkiG9w0BCQEWDkNBQGV4YW1wbGUuY29tMB4XDTIx
MDMxODEyNTQxOFoXDTI1MDMxODEyNTQxOFowcjELMAkGA1UEBhMCUEwxGzAZBgNV
BAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQMA4GA1UECwwHcmV2b2tlZDEQMA4GA1UE
AwwHcmV2b2tlZDEiMCAGCSqGSIb3DQEJARYTcmV2b2tlZEBleGFtcGxlLmNvbTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOZFiyZkmA1XgVhbjKSTMa/w
Qt4MATQCC6XoBdFGjsWyYJJVMu62Ifx6+t7TgDz4rVlf1rgwupVeJ9IUEfL8nEC0
VZPLkqN659I4Hs1SEE8cemClGkxDVOs8voO/KYourjKVOZA6rt3vNHI/8Uh1a6eY
wo9mZ/tdya3QsrUmZHIj8Vs3KT92QPTNxyrQlkaVRuHaTFluyEBI3VNiq9e/VGVJ
hikNiXqspuyt85LU6S2xj3/HVrVyxmXuSbp5urqe7XTL9/SBRFyAB11gmvyCpCwz
AD4uOaqyTPa3E2G8a4UWEU/yTHminzNpnMFMYQQnwK7KqQZvtEDFctoswL8JTDcC
AwEAAaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQU3bD2NyKFlGcdzmf9tbQyiZ7s
B7YwHwYDVR0jBBgwFoAUF36fHLAOahK03W/5Q99MEBHAiAowDQYJKoZIhvcNAQEL
BQADggEBAIbPe0ttoLFmo43XFMeD3460yaGtf3EBj2hGHbwhgHppSteyJ++zymJ7
1A5OqcLWm9DrTtQp6VkhLHYLL54uYrL+0QcR9GBJlhfqTbOTlzdkHDC3/8u9xmgS
+qlI4EUGtzeaj2dTU+8IvihFx4wk+QhMeafr8pouVwt+VdmlW6XbZt5+QiZtVwYT
d3hwLSuHb+g1Trt4ryWbNGia/SrTmFfH54jJ8+2WrxEDcv6TAqqGm0L224vImcbA
EoMJIC8Wi0p+lnGyVtyvghyTYgct7asTQgsoNNyB6PL12DKIrIwecchY/KF5nz12
b6CaxuIkQiLOqlqUxwqxdg4xRnlFdqA=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA5kWLJmSYDVeBWFuMpJMxr/BC3gwBNAILpegF0UaOxbJgklUy
7rYh/Hr63tOAPPitWV/WuDC6lV4n0hQR8vycQLRVk8uSo3rn0jgezVIQTxx6YKUa
TENU6zy+g78pii6uMpU5kDqu3e80cj/xSHVrp5jCj2Zn+13JrdCytSZkciPxWzcp
P3ZA9M3HKtCWRpVG4dpMWW7IQEjdU2Kr179UZUmGKQ2Jeqym7K3zktTpLbGPf8dW
tXLGZe5Junm6up7tdMv39IFEXIAHXWCa/IKkLDMAPi45qrJM9rcTYbxrhRYRT/JM
eaKfM2mcwUxhBCfArsqpBm+0QMVy2izAvwlMNwIDAQABAoIBAEkrxgjAJFTw/mfu
R2WwZDSM+yKF3AgDsmHYtaiHbCzD/s3hBts1wtzw0zDlMjWtq5/fxWIoEdIO5kZq
HD4DKT+iTiM1p/YMwwdYz+jcb9RDr1twe0fKiXxqg/tnTjLbnHz0UCNVkmVxck/v
o6MrtLa/4usgVmBYsBJsY60OcxKVYOeF1yI/ODQCFw9RjglE+HybfTg2cGiR0ggA
wPmJq6N2CvTJwzjWDuKI5mGJY0xDXwnvvDbcYpgmHNF+6AgMxW5dbpgSoUQvXRCJ
8MTN/hwfDC48UDvQAoRPf/RFK3UX/VRbemzvjYGpqqkDW5hS/CY7y4sgFHwZ0T1R
fzbuzHECgYEA+kgbWRLatN68IgnM37A0hIgWbF1PDtqh/e7gnYRPghniDzj9WFi/
3/9WwfKCKFzjl68nh9W/FFcN9FyXxHjFoKe7Rg5PTWHtQCWQnOB11o1uvcv0gPNv
OnXm8x1O/OM49A+YLo7xUfvSPEqx79GVIoMQHbGTpuovr/Brq8SzSj8CgYEA64hm
BHedWUbbHOGsgL8g/7KOou36ndYUflR0xIDdDd1JwoEfhWSil71W4zd3ruJy721p
MFZIym2rq8dJF9FCq0IVSwBTwPpxU3s9MvjlLAD5CqhO6KT3lve8BhxdAx189DBT
DRUqNZZnioVz8hFvqcwXKW6B2fnnrVyozAB4UAkCgYBY9k56P+BrkAxxUOh4zkos
na7Sv+v9DKut9j3y33ffd9HJtWkgARPazAkLkWbAcBwZ65FykACGe1cjd9IebQta
SqSfhzCbAebx+ShJCuP36nflkNyNBXqQ3h3EZrOP4jh5UB241uhiSs90zNwosWeA
R/PvihJAr1daA2xSNu2/wwKBgF6VgdJdbpTBfZBVl/6Dwm6sd9c6FiB4LfalV9bp
oNvGd65iSBQ7W4fwAwpv5eIXEezQVSOSIt0XuY7cEqA76rf3a7GYygl/CS9rGCJ2
DSHkqh37hOSsCrlXduxFS5zKpLkzBscELtUiNyZLfUpCckMPsGV0+TRdxQm7YhW6
QpZxAoGBAIjBjRZ2sSxdcSMihOVVbgcfvJMCOsPgc155FZBtEtO0JSC+QgGhB2z9
XRNu00G97TrKcU68kLdi0rse8Gcb4DN+J0t7eRSsyFmdVE+39V630GIpNLGIslrd
lHSepln2sJfSmT4tGjjOG1V/7b4jt/Uo8v7wPQH8YmZLMYO89TW1
-----END RSA PRIVATE KEY-----

Просмотреть файл

@ -1,2 +0,0 @@
test1:6UoHxibiMes9DaN8P0aDsM0tRbEBCflRoDaTVYefMHc26BFX7I
test2:1xIL8YDbX2sva8QjG734JzSOJVkWhG6HTEp4v82hiJFvfxa1f4

Двоичные данные
tests/certs/server_cert.p12

Двоичный файл не отображается.

Просмотреть файл

@ -1,49 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDoDCCAoigAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UEBhMCUEwx
GzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEQMA4GA1UECwwHUm9vdCBDQTEL
MAkGA1UEAwwCQ0ExHTAbBgkqhkiG9w0BCQEWDkNBQGV4YW1wbGUuY29tMB4XDTIx
MDMxODEyNTQxOFoXDTI1MDMxODEyNTQxOFowbzELMAkGA1UEBhMCUEwxGzAZBgNV
BAoMElN0dW5uZWwgRGV2ZWxvcGVyczEPMA0GA1UECwwGc2VydmVyMQ8wDQYDVQQD
DAZzZXJ2ZXIxITAfBgkqhkiG9w0BCQEWEnNlcnZlckBleGFtcGxlLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNK+CxahWSi4zH4SQgMJjPjiiI+
zG6JTpibWV9Lxuc21b2XRlx9I8xOITsDb3JiKacO6Lg+hWg+EymuyFAE/h5ASmNZ
e9pCEmsvCM8XGYyGw18cxOoNK8v+DzAR4XySF6BOcaeaFnInTcbYUnhK0YDSn0P6
lyv8Ol76xR/C+y4AvuyoYCjVOzvxY2g3HdjlyA7RwVS9ekYgS5nd0s/qdO91gQ+4
imb67HW76bF5LmiCAfZ0XKqHFyvHO5D57QifLq3Kwe6IorTrTSFH/fWre/A/JIji
Bt63dGSlxCnfNzQIJYJjJYdU7tz7cKMnpp0avxSCeFZYw8RsAr1L8JunLtsCAwEA
AaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQU7L61jETM7BttdLW3uOPJuRqs9uUw
HwYDVR0jBBgwFoAUF36fHLAOahK03W/5Q99MEBHAiAowDQYJKoZIhvcNAQELBQAD
ggEBAFfZkSmuYMjMfEBzBUudunL2vOeQUsQcH6KROsYaq+lN09aazMKBX8j+VMTL
6ZSlVxeM5BCXdD3GvpFb+R4ED8EcrRWKbAiqUJz1tAyjLRyHW2GWqfFpOn5yNonK
vsUtZSL+v87V26PGuRs5dQizGkstS2gKx3zFqaKwWdCQE5ldDwT+kDkghvALoGXw
IuFt7+QbZjLQvQ/YdCUXjBVdzICVO5WgEePAZ4IO8r20jrda2aP5OFVmUcc+iA8P
Rn6jCOfdnNyBDWwm+oEf1WecYxTr0Ly0d3QcOxpAUeQTgT6tZawpllGLkwfrUZFV
09YKu45BurR5WZzok/9zyflPv80=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAs0r4LFqFZKLjMfhJCAwmM+OKIj7MbolOmJtZX0vG5zbVvZdG
XH0jzE4hOwNvcmIppw7ouD6FaD4TKa7IUAT+HkBKY1l72kISay8IzxcZjIbDXxzE
6g0ry/4PMBHhfJIXoE5xp5oWcidNxthSeErRgNKfQ/qXK/w6XvrFH8L7LgC+7Khg
KNU7O/FjaDcd2OXIDtHBVL16RiBLmd3Sz+p073WBD7iKZvrsdbvpsXkuaIIB9nRc
qocXK8c7kPntCJ8urcrB7oiitOtNIUf99at78D8kiOIG3rd0ZKXEKd83NAglgmMl
h1Tu3PtwoyemnRq/FIJ4VljDxGwCvUvwm6cu2wIDAQABAoIBAB6SbwTpHovNdp4j
rxhPMghxCTHTsXo7sYo2GyQzwKPWZtXgQKAuunbw75und05yzJVu5mHcT1U6GHxo
EEIMx+QSpFySepr53zglmgPt9W5P4GqMdktOmaQ8GwzgT6m1I5AzMBAbJy6p4wpA
Arf+UgD8aSnnRfW7GZzud8R1s+zg7Jc4Xi+2UOvSojw8RHcF8GTmiGrhLAD616Cb
Yg5sAO2RhNXJwGP3B2kHJEjE8yN1xoOXf2SVjgNtlD1AriQ3TLNQmR8Ecoq7cCVh
wYy3DZdIttqAcjL7IvSUnE8zHmQi+gtaHhVol3Z8KDObwj+b0mYgqqVYYRYf2hFP
YM156MkCgYEA27eq4L1RIbx4oxOc3XMyiem8Je6ciOvw0kj9r0lwlL/cfn5WgpeM
bpbP7a//kfbipQ/FbAyo3FIVCVJN5CgHlRKdHo9IM0x/1U9mpRnhoGF06PooOFwX
skbi6FoRkewcGm1GGEEHJksNCdtVYVzGePcLgGfJEX5zuusfqixd/J8CgYEA0OZk
k18K2r+9Vlwa3ZB17j6VPqJFtpbN5MSzFf2weyW2yBN3MZQcysukr8q95x2NFSq4
fjX68XPgzKCnDfcfszQbaoXFOL6fxTslYuGvXmEUuiqn1J3yKSoG6/GJklR3pGZp
R9bLNZDc/5WJ4jXbxrNOZzJ1+8Bkod6l0ule6EUCgYAscsmE0Ye6NXCKPQt82TMe
J0TCv7S3FlQPlmiLr2WxEec/R7uki5gDP0stIG+pTbKoBbrAkwcOGyTaT+YmA9sU
00Epz36hshYiRv/S4pt8YHrQLts4G5lHnYOF0cLALG27AuQtP+p8Wq52kgKBwcz8
561R+qz4dwZeh/ZN7M/OrQKBgQC6MS/hvquhD5dFmvCDHRhP0k4Ztm7mcIFxbvSk
HCqpiJLiv57UfMww4NOXr+AVV9yAykQIkjpp7Tunh2V+aA5EHqR1DGgdzKIBHFeV
S8yQFX1w9UYDlwfZMtFaiT1yRIEi8fjShBs5UjX4RCPSkOijsPuntW09h1zqfdVV
KJZj9QKBgBgSZFAG7WO/bbOYoB95bxSRLyg111OI0nVkWhkHgj1h5n+Lp4n6HGeQ
+R4j4tH0oEzQh7fVhfbtA3cs4/met1K5sNm8fPUFNHEyHNu90sbpTeLnIOzSNjX0
J44ybnlrZii1DLw0sAP+XmMdKRZ9FS5+krC4yo/uUrdoNTpQ4z0W
-----END RSA PRIVATE KEY-----

Просмотреть файл

@ -1,53 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC23fBHFVaHSAtS
UwzLFCyaq36QXoWqqq0nrZdZpjiu6J6I4w/ulVUHTBWchhKEY+71r000Z3H7ZU7W
BoQ7QMmW5LAl2xvYcQjBzPdRRIqT32Jjn6WvEzCATZhL6Ja0OPFo5JmO5ns8RXzf
V05odEtZ2hGyVJoFdpupZs1IWDL6A0eJ66uBC/MX6F4uhGI+5CJAbyf7SPJMHOKH
EvDrTbRb7g9eF7lkybU5jVqnsTyg72W3Etui4H1t3RHADTzvFIvir+xgsyHGAYQQ
WCpc24tQ3eOoFG8P1Xt+Y0Drw8nL0EbJUTvvlGIW+lTGqKsi80h/kbIiPkjphQiE
ia/3rnBtAgMBAAECggEBAK/xA3BxAEqyr2nqzAFMDMpXvDMNLpARHP5zD47K1fi7
iWTtCnQjq6aUtqpdeM12FQC/RInqCYm2ZE6aAHm+EPckWrJhiP4La0CDg2TmjGpP
4Cs3/EJhNSYNAj3ur6kArIyefXw3F1TbCpUcPC1VzvXJUYOB0Jr3DjfD2DkF2y4d
fzF3K0kc20dwWeUnPKm/ffN3MS7VBwf+pyUcwAKU/Oq6WWOSWGJxzMSPhFObvF5o
ZkT7Q5rPBHdtWOey+oWdcKEBfh4FC/kZst8R5LscZ59vN0ZSFDEL+xNqNXdTKsB3
5X7spCFmoDWEiaUkHxsW/OA+uIip1ehw/6QMmYsMbuECgYEA3SOyOeD1ojWpQiI6
wuMrE6ldD/jk6aaXS9GC1N0uriguAaAI/NNXL89zEMkENrsqcgOBU9qAMbGu6bZ7
4LKZra1aRju0MNBhraI/g5gPsjrtooY3hfg0Sn7/Ei/24Uip22K3nYqQp35PqqxC
nbPvwRrwSqpCdpAoFBLgsbmwP8kCgYEA07G3t6Rdo7e6arxhELyIHZRh5cV9nbYm
CpTCTFSlhB5XTXBy3PrFDxw1FrbHTJKQ0tOVQ19PcBT9BHrsCdAWbpk7r2UiXk4x
hl92DST0oZlbCEAPM/xTaAdSxRmGmxtYxWojyWGSncQeA9l9OLpi5rg/KqD5uGm6
qHplar3bZYUCgYEAutRyujWWMVJWyrnynT6h4T2gk2L7u290uaireT3ZN2hY3iSg
E0JWkd0ZYOAEAF2G0camV/rtfY6ZsXjsFf2umq4v69B7PxZ+v9yo/nvVHwZsSHhO
po/5VcsPowUE9naWkvRHHwG3jtrHYfGhYm1oLOSeiOZpupO2WKdOULkJ8AkCgYEA
z2eSGMFX4Pw0DzkLXItqTJjBJY5NWURJlxpSFtjj5UKYxE1ErE6g3QIE3YEsWFBM
xdH4rq5ltOlLT6VjNuYB5FALEvfiKUUw7nb+wTgQ2XbXooionIU97nEmXed5YuPz
IE+ySi5nqFyqD5l5PygVl/iyIoDeyRgFgeWREXh7yMUCgYAg702QxrhdMVN1dwDL
BUMdvUbQ2Ad+AhKxTqn9XBDdMQdWkdR//0+emB+9zfscBgNGMU1SU1hlOM8E6Obd
nFol+2hAS5w4q/U/KIsZNY00dcZm/aYG/EjPDYSOo1R8dMF9UAx+5An6iSg8U5Wz
8TN3/NjT/FC7biSt+/P3QlnUew==
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEQTCCAymgAwIBAgIUB/R3pMEt+vuJcu2Gd035OJy7blEwDQYJKoZIhvcNAQEL
BQAwgacxCzAJBgNVBAYTAlBMMRkwFwYDVQQIDBBNYXpvdmlhIFByb3ZpbmNlMQ8w
DQYDVQQHDAZXYXJzYXcxGzAZBgNVBAoMElN0dW5uZWwgRGV2ZWxvcGVyczEXMBUG
A1UECwwOUHJvdmlzaW9uYWwgQ0ExEjAQBgNVBAMMCWxvY2FsaG9zdDEiMCAGCSqG
SIb3DQEJARYTc3R1bm5lbEBleGFtcGxlLmNvbTAeFw0yMTAzMTgxMjU0MTdaFw0y
NTAzMTgxMjU0MTdaMIGnMQswCQYDVQQGEwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQ
cm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3MRswGQYDVQQKDBJTdHVubmVsIERldmVs
b3BlcnMxFzAVBgNVBAsMDlByb3Zpc2lvbmFsIENBMRIwEAYDVQQDDAlsb2NhbGhv
c3QxIjAgBgkqhkiG9w0BCQEWE3N0dW5uZWxAZXhhbXBsZS5jb20wggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC23fBHFVaHSAtSUwzLFCyaq36QXoWqqq0n
rZdZpjiu6J6I4w/ulVUHTBWchhKEY+71r000Z3H7ZU7WBoQ7QMmW5LAl2xvYcQjB
zPdRRIqT32Jjn6WvEzCATZhL6Ja0OPFo5JmO5ns8RXzfV05odEtZ2hGyVJoFdpup
Zs1IWDL6A0eJ66uBC/MX6F4uhGI+5CJAbyf7SPJMHOKHEvDrTbRb7g9eF7lkybU5
jVqnsTyg72W3Etui4H1t3RHADTzvFIvir+xgsyHGAYQQWCpc24tQ3eOoFG8P1Xt+
Y0Drw8nL0EbJUTvvlGIW+lTGqKsi80h/kbIiPkjphQiEia/3rnBtAgMBAAGjYzBh
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJSgbfs9SkZg/XEeUj6nDyGCHkXn
MB8GA1UdIwQYMBaAFJSgbfs9SkZg/XEeUj6nDyGCHkXnMA4GA1UdDwEB/wQEAwIB
hjANBgkqhkiG9w0BAQsFAAOCAQEAnYdyJUeOS3XgKQ1Yz/wuJQPrhoN67fSSjdy6
jmeXFV7wbs0rgrsiWy/Lg6YTHqNzDQUC6/cvTcrh2KxMwbNcgAJd4VxwyKw4mMwu
P4htwmE1wSXfrMdckQZ50QnJ6sdf+9fY/xmYtSj0+KVEkIXIgjf25brxcnj5znxD
kSWeZt5FCo4/zwcsYLTd22q0k5ynl6LaaVUVCP3C/f0hlHFUJXAKl4kRF4ZwH1is
mLLpIZYPjaqla1Au8c512rRP8Txx02n2TPYD4PQmyzvmXWLa0Fi3d37DjHPe3kS+
ihMrfXvmT4DtErI32t6gvdiJpnmMWdRk66GTA/Hkeg2i7dSgZQ==
-----END CERTIFICATE-----

4
tests/error.py Executable file
Просмотреть файл

@ -0,0 +1,4 @@
"""An error occured."""
if __name__ == '__main__':
print("Wrong_connection!")

Просмотреть файл

@ -1,3 +0,0 @@
#!/bin/sh
printf "%-35s\t%s\n" "test $1" "success"

Просмотреть файл

@ -1,3 +0,0 @@
#!/bin/sh
cat >> "$1"

Просмотреть файл

@ -1,3 +0,0 @@
#!/bin/sh
echo "$@" > "$1"

Просмотреть файл

@ -1,2 +0,0 @@
GET / HTTP/1.0

Просмотреть файл

@ -1,115 +0,0 @@
#!/bin/sh
result=0
count=0
fail=0
skip=0
result_path=$(pwd)
cd $(dirname "$0")
script_path=$(pwd)
cd "${result_path}"
result_path="${result_path}/logs"
autodetection() {
result=0
if [ -n "$(command -v ncat)" ]
then # ncat
mynetcat="ncat"
elif [ -n "$(command -v nc)" ]
then # nc
mynetcat="nc"
else # netcat is required
printf "%s\n" "ncat / nc not found in \$PATH"
result=1
fi
if uname -r | grep -q Microsoft && test -f /mnt/c/Windows/System32/netstat.exe && ! /mnt/c/Windows/System32/netstat.exe -a -n 2>&1 | grep -q -e "usage" -e "invalid" -e "illegal" -e "command not found"
then
mynetstat="/mnt/c/Windows/System32/netstat.exe"
elif [ -n "$(command -v netstat)" ] && ! netstat -a -n 2>&1 | grep -q -e "usage" -e "invalid" -e "illegal" -e "command not found"
then
mynetstat="netstat"
elif [ -n "$(command -v ss)" ] && ! ss -a -n -l 2>&1 | grep -q -e "usage" -e "invalid" -e "illegal" -e "command not found"
then
mynetstat="ss"
elif [ -n "$(command -v lsof)" ] && ! lsof -i -n -P 2>&1 | grep -q -e "usage" -e "invalid" -e "illegal" -e "command not found"
then
mynetstat="lsof"
else # netstat / ss / lsof is required
printf "%s\n" "netstat / ss / lsof not found in \$PATH or some option error"
result=1
fi
if [ -n "$(command -v stdbuf)" ]
then
mybuffer="stdbuf"
elif [ -n "$(command -v unbuffer)" ]
then
mybuffer="unbuffer"
else
mybuffer=""
fi
if [ -n "$(command -v python3)" ]
then
mypython=python3
elif [ -n "$(command -v python)" ] && python -V | grep -q "Python 3"
then
mypython=python
else
mypython=""
fi
return $result
}
if autodetection
then
rm -rf "${result_path}"
mkdir "${result_path}"
cd "${result_path}"
date > "results.log"
../../src/stunnel -version 2>> "results.log"
if [ -n "$(command -v fips-mode-setup)" ]
then
printf "\n" >> "results.log"
fips-mode-setup --check 1>> "results.log"
fi
printf "\n%s\n" "Testing..." >> "results.log"
head -n5 "results.log"
if ! grep -q "solaris" "results.log"
then
for plik in ${script_path}/recipes/*
do
/bin/sh $plik "$mynetcat" "$mynetstat" "$mybuffer" "$mypython"
state=$?
if [ "$state" -eq 0 ]
then # $state=0
count=$((count + 1))
elif [ "$state" -eq 125 ]
then # $state=125
skip=$((skip + 1))
else # $state=1
fail=$((fail + 1))
result=1
fi
done
if [ $count -eq 0 ]
then # no test was done
result=1
fi
printf "%s\n" "summary: success $count, skip $skip, fail $fail"
printf "%s\n" "summary: success $count, skip $skip, fail $fail" >> "results.log"
printf "%s\n" "./make_test finished"
cd ..
else # skip make test for solaris
printf "%s\n" "./make_test skipped"
printf "%s\n" "./make_test skipped" >> "results.log"
#result=125
fi
else # netcat not found
printf "%s\n" "./make_test skipped"
#result=125
fi
exit $result

1692
tests/maketest.py Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

140
tests/plugin_collection.py Normal file
Просмотреть файл

@ -0,0 +1,140 @@
"""A plugin structure"""
import dataclasses
import inspect
import os
import pkgutil
@dataclasses.dataclass(frozen=True)
class LogEvent():
"""The base class for an event."""
etype: str
level: int
log: str
class Plugin():
"""Base class that each plugin must inherit from. Within this class
you must define the methods that all of your plugins must implement
"""
# pylint: disable=too-few-public-methods
def __init__(self):
self.description = 'UNKNOWN'
async def perform_operation(self, cfg, logger):
"""The method that we expect all plugins to implement. This is the
method that our framework will call
"""
raise NotImplementedError
class PluginCollection():
"""Upon creation, this class will read the plugins package for modules
that contain a class definition that is inheriting from the Plugin class
"""
def __init__(self, cfg, logger, plugin_package):
"""Constructor that initiates the reading of all available plugins
when an instance of the PluginCollection object is created
"""
self.plugin_package = plugin_package
self.cfg = cfg
self.logger = logger
self.plugins = []
self.seen_paths = []
def __await__(self):
return self.async_init().__await__()
async def async_init(self):
"""Constructor that initiates the reading of all available plugins
when an instance of the PluginCollection object is created
"""
await self.reload_plugins()
await self.apply_all_plugins()
async def reload_plugins(self):
"""Reset the list of all plugins and initiate the walk over the main
provided plugin package to load all available plugins
"""
await self.cfg.mainq.put(
LogEvent(
etype="log",
level=10,
log=f'[plugins] Looking for plugins under package {self.plugin_package}'
)
)
await self.walk_package(self.plugin_package)
async def apply_all_plugins(self):
"""Apply all of the plugins
"""
await self.cfg.mainq.put(
LogEvent(
etype="log",
level=10,
log='[plugins] ----- Applying all plugins -----'
)
)
for plugin in self.plugins:
await self.cfg.mainq.put(LogEvent(etype="log", level=20, log=""))
await self.cfg.mainq.put(
LogEvent(
etype="log",
level=20,
log=f'[plugins] >>>>> Applying \'{plugin.description}\' <<<<<'
)
)
await plugin.perform_operation(self.cfg, self.logger)
async def walk_package(self, package):
"""Recursively walk the supplied package to retrieve all plugins
"""
imported_package = __import__(package, fromlist=['blah'])
for _, pluginname, ispkg in pkgutil.iter_modules(
imported_package.__path__, imported_package.__name__ + '.'
):
if not ispkg:
plugin_module = __import__(pluginname, fromlist=['blah'])
clsmembers = inspect.getmembers(plugin_module, inspect.isclass)
for (_, cls) in clsmembers:
# Only add classes that are a sub class of Plugin, but NOT Plugin itself
if issubclass(cls, Plugin) & (cls is not Plugin):
await self.cfg.mainq.put(
LogEvent(
etype="log",
level=10,
log=f'[plugins] Found plugin class: {cls.__module__}.{cls.__name__}'
)
)
self.plugins.append(cls())
# Now that we have looked at all the modules in the current package, start looking
# recursively for additional modules in sub packages
all_current_paths = []
if isinstance(imported_package.__path__, str):
all_current_paths.append(imported_package.__path__)
else:
all_current_paths.extend(imported_package.__path__)
for pkg_path in all_current_paths:
if pkg_path not in self.seen_paths:
self.seen_paths.append(pkg_path)
# Get all sub directory of the current package path directory
child_pkgs = [
p for p in os.listdir(pkg_path)
if os.path.isdir(os.path.join(pkg_path, p))
]
# For each sub directory, apply the walk_package method recursively
for child_pkg in child_pkgs:
await self.walk_package(package + '.' + child_pkg)

Двоичные данные
tests/plugins/__pycache__/p01_client_cert.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p02_require_cert.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p03_verify_peer.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p04_verify_chain.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p05_verify_crl.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p06_psk_secrets.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p07_p12cert.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p08_ipv6.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p09_bind.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p10_fips.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p11_fips_cipher.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p12_sni.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p13_resume.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p14_resume_ticket.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p15_resume_secret.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p16_redirect.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p17_redirect_proxy.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p18_redirect_resume.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p19_reload.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p20_failover.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p21_include.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p22_inetd.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p23_exec_conn.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p24_delay.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p25_wrong_client.cpython-39.pyc Normal file

Двоичный файл не отображается.

Двоичные данные
tests/plugins/__pycache__/p26_wrong_server.cpython-39.pyc Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,139 @@
"""stunnel client tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel client tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_server = True
self.params.services = ['client']
class CertTest(StunnelTest):
""" Checking if the cert option ensures a client certificate.
The success is expected because the client presents a certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '011. Test \"cert\" option'
self.params.context = 'cert_required'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[0]}
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
class FailureCertTest(StunnelTest):
""" Checking if the cert option ensures a client certificate.
The failure is expected because the client does not present any certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '012. Test no \"cert\" option'
self.params.context = 'cert_required'
self.events.count = 1
self.events.success = [
"Client received unexpected message",
"Connection reset by peer"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
#"Connection reset by peer",
#"Connection lost",
#"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[0]}
;client does not present any certificate
;cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
class StunnelClientTest(Plugin):
"""Stunnel client tests
HTTP client --> stunnel client --> HTTPS server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Existing certificate'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = CertTest(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureCertTest(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,133 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class RequireCertTest(StunnelTest):
"""Checking if the requireCert option requires a client certificate.
The success is expected because the client presents any but incorrect certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '021. Test \"requireCert\" option'
self.params.context = 'load_wrong_cert'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
requireCert = yes
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailureRequireCertTest(StunnelTest):
"""Checking if the requireCert option requires a client certificate.
The failure is expected because the client does not present any certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '022. Failure test \"requireCert\" option'
self.events.count = 1
self.events.success = [
"peer did not return a certificate"
]
self.events.failure = [
#"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
#"Connection reset by peer",
#"Connection lost",
#"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
requireCert = yes
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelServerTest(Plugin):
"""Stunnel server tests:
HTTPS client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Require certificate'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = RequireCertTest(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureRequireCertTest(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,138 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class VerifyPeer(StunnelTest):
"""Checking if the verifyPeer option verifies the peer certificate.
The peer certificate is stored in the file specified with CAfile.
The success is expected because the client presents the valid certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '031. Test \"verifyPeer\" option'
self.params.context = 'load_correct_cert'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailureVerifyPeer(StunnelTest):
"""Checking if the verifyPeer option verifies the peer certificate.
The valid peer certificate is stored in the file specified with CAfile.
The failure is expected because the client presents an incorrect certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '032. Failure test \"verifyPeer\" option'
self.params.context = 'load_wrong_cert'
self.events.count = 1
self.events.success = [
"certificate verify failed"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
#"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
#"Connection reset by peer",
#"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelServerTest(Plugin):
"""Stunnel server tests:
HTTPS client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Verify peer'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = VerifyPeer(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureVerifyPeer(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,138 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class VerifyChain(StunnelTest):
"""Checking if the verifyChain option verifies the peer certificate starting from the root CA.
The self-signed root CA certificate is stored in the file specified with CAfile.
The success is expected because python client presents the valid certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '041. Test \"verifyChain\" option'
self.params.context = 'load_correct_cert'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyChain = yes
CAfile = {cfg.certdir}/CACert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailureVerifyChain(StunnelTest):
"""Checking if the verifyChain option verifies the peer certificate starting from the root CA.
The self-signed root CA certificate is stored in the file specified with CAfile.
The failure is expected because python client presents an incorrect certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '042. Failure test \"verifyChain\" option'
self.params.context = 'load_wrong_cert'
self.events.count = 1
self.events.success = [
"certificate verify failed"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
#"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
#"Connection reset by peer",
#"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyChain = yes
CAfile = {cfg.certdir}/CACert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelServerTest(Plugin):
"""Stunnel server tests:
HTTPS client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Verify chain'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = VerifyChain(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureVerifyChain(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,144 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class VerifyCRL(StunnelTest):
"""Checking if the CRL is verified.
The verifyChain option verifies the peer certificate starting from the root CA.
The self-signed root CA certificate is stored in the file specified with CAfile.
Certificate Revocation Lists file is stored in the file specified with CRLfile.
The success is expected because python client presents the valid certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '051. CRL file with valid certificate'
self.params.context = 'load_correct_cert'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyChain = yes
CAfile = {cfg.certdir}/CACert.pem
CRLfile = {cfg.certdir}/CACertCRL.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailureVerifyCRL(StunnelTest):
"""Checking if the CRL is verified.
The verifyChain option verifies the peer certificate starting from the root CA.
The self-signed root CA certificate is stored in the file specified with CAfile.
Certificate Revocation Lists file is stored in the file specified with CRLfile.
The failure is expected because the python client presents the revoked certificate.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '052. CRL file with revoked certificate'
self.params.context = 'load_revoked_cert'
self.events.count = 1
self.events.success = [
"certificate verify failed"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
#"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
#"Connection reset by peer",
#"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyChain = yes
CAfile = {cfg.certdir}/CACert.pem
CRLfile = {cfg.certdir}/CACertCRL.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelServerTest(Plugin):
"""Stunnel server tests:
HTTPS client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Verify CRL file'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = VerifyCRL(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureVerifyCRL(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,176 @@
"""stunnel client-server tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.services = ['server', 'client']
class PSKSecrets(StunnelTest):
"""Checking if the PSK authentication works properly.
PSK identities and corresponding keys are stored in files specified with PSKsecrets.
The success is expected because the client presents the valid PSK.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '061. Test \"PSKsecrets\" option'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
PSKsecrets = {cfg.certdir}/psk1.txt
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
requireCert = yes
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
PSKsecrets = {cfg.certdir}/secrets.txt
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailurePSKSecrets(StunnelTest):
"""Checking if the PSK authentication works properly.
PSK identities and corresponding keys are stored in files specified with PSKsecrets.
The failure is expected because the client presented an incorrect key.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '062. Failure test \"PSKsecrets\" option'
self.events.count = 1
self.events.success = [
"binder does not verify"
]
self.events.failure = [
#"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
#"Connection reset by peer",
#"Connection lost",
#"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
PSKsecrets = {cfg.certdir}/psk2.txt
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
requireCert = yes
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
PSKsecrets = {cfg.certdir}/secrets.txt
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelClientServerTest(Plugin):
"""Stunnel client-server tests
HTTP client --> stunnel client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'PSK authentication'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = PSKSecrets(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailurePSKSecrets(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,81 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class Certp12Test(StunnelTest):
"""Checking if the file containing certificates used by stunnel to authenticate
itself against the remote client may be in the P12 format.
The success is expected because the server presents the valid certificate in the P12 format.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '071. Test PKCS#12 certificate'
self.params.context = 'load_verify_locations"'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.p12
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelServerTest(Plugin):
"""Stunnel server tests:
HTTPS client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Existing PKCS#12 certificate'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = Certp12Test(cfg, logger)
await stunnel.test_stunnel(cfg)

98
tests/plugins/p08_ipv6.py Normal file
Просмотреть файл

@ -0,0 +1,98 @@
"""stunnel client-server tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.services = ['server', 'client']
class IPv6Test(StunnelTest):
""" Checking if IPv6 is supported.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '081. Test IPv6 support'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = ::1:{ports[1]}
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = ::1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelClientTest(Plugin):
"""Stunnel client-server tests
HTTP client --> stunnel client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'IPv6 support'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = IPv6Test(cfg, logger)
await stunnel.test_stunnel(cfg)

82
tests/plugins/p09_bind.py Normal file
Просмотреть файл

@ -0,0 +1,82 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class BindingTest(StunnelTest):
"""Checking if the service does't refuse to start if binding fails for some addresses:ports.
Sample log expected:
LOG5[ui]: Binding service [server] to 127.0.0.1:43293: Address already in use (98)
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '091. Binding server'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:{port}
accept = 127.0.0.1:0
accept = 127.0.0.1:{port}
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelServerTest(Plugin):
"""Stunnel server tests:
HTTPS client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Binding service'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = BindingTest(cfg, logger)
await stunnel.test_stunnel(cfg)

108
tests/plugins/p10_fips.py Normal file
Просмотреть файл

@ -0,0 +1,108 @@
"""stunnel client-server tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.services = ['server', 'client']
class FIPSTest(StunnelTest):
""" Checking FIPS mode.
The success is expected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '101. Test FIPS mode'
self.events.skip = [
"FIPS provider not available",
"fips mode not supported",
r"FIPS PROVIDER.*could not load the shared library"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
fips = yes
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
fips = yes
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelClientServerTest(Plugin):
"""Stunnel client-server tests
HTTP client --> stunnel client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'FIPS mode'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = FIPSTest(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,214 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
ExpectedConfigurationFailure
)
class StunnelTest(ExpectedConfigurationFailure):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class FailureCipherFIPS(StunnelTest):
"""Checking FIPS mode.
The cipher "CAMELLIA256-SHA" (TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256)
is unavailable if FIPS is enabled.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '111. Failure FIPS mode with unavailable cipher'
self.events.skip = [
"FIPS provider not available",
"fips mode not supported",
r"FIPS PROVIDER.*could not load the shared library"
]
self.events.count = 1
self.events.success = [
"no cipher match"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
#"Something went wrong: stunnel 'server' failed",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
fips = yes
ciphers = CAMELLIA256-SHA
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailureCiphersuitesFIPS(StunnelTest):
"""Checking FIPS mode.
The ciphersuite "TLS_CHACHA20_POLY1305_SHA256" is unavailable if FIPS is enabled.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '112. Failure FIPS mode with unavailable ciphersuite'
self.events.skip = [
"FIPS provider not available",
"fips mode not supported",
r"FIPS PROVIDER.*could not load the shared library"
]
self.events.count = 1
self.events.success = [
"disabled for FIPS",
"no ciphers available"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
fips = yes
ciphersuites = TLS_CHACHA20_POLY1305_SHA256
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailureEllipticCurveFIPS(StunnelTest):
""" Checking FIPS mode.
The elliptic curve "sect163r1" is unavailable if FIPS is enabled.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '113. Failure FIPS mode with unavailable elliptic curve'
self.events.skip = [
"FIPS provider not available",
"fips mode not supported",
r"FIPS PROVIDER.*could not load the shared library"
]
self.events.count = 1
self.events.success = [
"no suitable key share",
"Invalid groups list in 'curves'"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
fips = yes
curves = sect163r1
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelServerTest(Plugin):
"""Stunnel server tests:
HTTPS client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'FIPS mode cipher'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = FailureCipherFIPS(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureCiphersuitesFIPS(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureEllipticCurveFIPS(cfg, logger)
await stunnel.test_stunnel(cfg)

196
tests/plugins/p12_sni.py Normal file
Просмотреть файл

@ -0,0 +1,196 @@
"""stunnel client-server tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.services = ['server_virtual', 'client']
class SNITest(StunnelTest):
"""Use the service as a slave service (a name-based virtual server)
for Server Name Indication TLS extension.
SERVICE_NAME (server_virtual) specifies the master service that
accepts client connections with the accept option.
SERVER_NAME_PATTERN (*.mydomain.com) specifies the host name to be redirected.
The success is expected because the client presents the sni pattern (sni.mydomain.com)
corresponding with SERVER_NAME_PATTERN (*.mydomain.com).
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '121. Test \"sni\" option'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
sni = sni.mydomain.com
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
cert = {cfg.certdir}/server_cert.pem
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
[sni]
connect = 127.0.0.1:{port}
sni = server_virtual:*.mydomain.com
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class FailureSNITest(StunnelTest):
"""Use the service as a slave service (a name-based virtual server)
for Server Name Indication TLS extension.
SERVICE_NAME (server_virtual) specifies the master service that
accepts client connections with the accept option.
SERVER_NAME_PATTERN sni.mydomain.com) specifies the host name to be redirected.
The success is expected because the client doesn't present any sni pattern.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '122. Failure test \"sni\" option'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
;the client doesn't present any sni pattern
;sni = sni.mydomain.com
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
[sni]
sni = server_virtual:*.mydomain.com
cert = {cfg.certdir}/server_cert.pem
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelClientServerTest(Plugin):
"""Stunnel client-server tests
HTTP client --> stunnel client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Server Name Indication'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = SNITest(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = FailureSNITest(cfg, logger)
await stunnel.test_stunnel(cfg)

351
tests/plugins/p13_resume.py Normal file
Просмотреть файл

@ -0,0 +1,351 @@
"""stunnel client-server tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.services = ['server', 'client']
self.params.conn_num = 3
class ResumePSK(StunnelTest):
"""Checking if the PSK authentication works properly when the session is resumed.
We expect exactly 2 "TLS accepted: previous session reused" to be logged
by the [server] service because the client presents the valid PSK.
PSK identities and corresponding keys are stored in files specified with PSKsecrets.
This resumption of the session does not work for the FORK threading model.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '131. Resume session with PSK authentication'
self.events.skip = [
"FORK"
]
self.events.count = 2
self.events.success = [
"TLS accepted: previous session reused"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
#"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
PSKsecrets = {cfg.certdir}/psk1.txt
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
PSKsecrets = {cfg.certdir}/secrets.txt
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class ResumeCacheTLSv12(StunnelTest):
"""Checking the cache session resumption.
We expect exactly 2 "TLS accepted: previous session reused" to be
logged by the [server] service.
"options = NO_TICKET" turns off ticket support in TLSv1.2 and older.
In TLSv1.3, "options = NO_TICKET" switches from using stateful tickets to
stateless tickets (traditional cache with session id sent in tickets).
https://github.com/openssl/openssl/issues/10280
Session cache resumption does not work with the FORK threading model.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '132. Cache session resumption with TLSv1.2'
self.events.skip = [
"FORK"
]
self.events.count = 2
self.events.success = [
"TLS accepted: previous session reused"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
#"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
sslVersionMax = TLSv1.2
options = NO_TICKET
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class SessionResume(StunnelTest):
"""Enable the 'sessionResume' service-level option to allow session resumption.
This resumption of the session does not work for the FORK threading model.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '133. Test enabled \"sessionResume\" option'
self.events.skip = [
"FORK"
]
self.events.count = 2
self.events.success = [
"TLS accepted: previous session reused"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
#"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
sessionResume = yes
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class NoSessionResume(StunnelTest):
"""Disable the 'sessionResume' service-level option to disallow session resumption.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '134. Test disabled \"sessionResume\" option'
self.events.count = 3
self.events.success = [
"TLS accepted: new session negotiated"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
client = yes
accept = 127.0.0.1:0
connect = 127.0.0.1:{ports[1]}
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
sessionResume = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelClientServerTest(Plugin):
"""Stunnel client-server tests
HTTP client --> stunnel client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Resume session'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = ResumePSK(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = ResumeCacheTLSv12(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = SessionResume(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = NoSessionResume(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,209 @@
"""stunnel client-server tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
ClientConnectExec
)
class StunnelTest(ClientConnectExec):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path):
super().__init__(cfg, logger, path)
self.params.services = ['server', 'client']
self.params.conn_num = 3
self.events.count = 2
class ResumeTicketTLSv12(StunnelTest):
"""Checking the stateless session ticket resumption (RFC 4507bis) with TLSv1.2.
We expect exactly 2 "TLS accepted: previous session reused" to be logged by the
[server] service, because [client] connected 3 times (1 new session, 2 reused sessions).
The following options are used to disable session cache:
- The "sessionCacheSize = 1" option sets the internal session cache size.
- "options = -NO_TICKET" (it is the default with OpenSSL 1.1.1 or later)
Stateless session ticket resumption also works with the FORK threading model.
"""
def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path):
super().__init__(cfg, logger, path)
self.params.description = '141. Stateless session ticket resumption with TLSv1.2'
self.events.count = 2
self.events.success = [
"TLS accepted: previous session reused"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
#"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
self.path = path
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
retry = yes
[{service}]
client = yes
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/reader.py {self.path}
connect = 127.0.0.1:{ports[1]}
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
sslVersionMax = TLSv1.2
sessionCacheSize = 1
options = -NO_TICKET
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class ResumeTicketTLSv13(StunnelTest):
"""Checking the stateless session ticket resumption (RFC 4507bis) with TLS 1.3.
We expect exactly 2 "TLS accepted: previous session reused" to be logged by the
[server] service, because [client] connected 3 times (1 new session, 2 reused sessions).
The following options are used to disable session cache:
- The "sessionCacheSize = 1" option sets the internal session cache size.
- "options = -NO_TICKET" (it is the default with OpenSSL 1.1.1 or later).
Stateless session ticket resumption also works with the FORK threading model.
"""
def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path):
super().__init__(cfg, logger, path)
self.params.description = '142. Stateless session ticket resumption with TLSv1.3'
self.events.count = 2
self.events.success = [
"TLS accepted: previous session reused"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
#"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
self.path = path
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
retry = yes
[{service}]
client = yes
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/reader.py {self.path}
connect = 127.0.0.1:{ports[1]}
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
sslVersion = TLSv1.3
sessionCacheSize = 1
options = -NO_TICKET
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelClientServerTest(Plugin):
"""Stunnel client-server tests
HTTP client --> stunnel client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Resume session'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
path = os.path.join(cfg.tempd, 'unix.sock')
stunnel = ResumeTicketTLSv12(cfg, logger, path)
await stunnel.test_stunnel(cfg)
stunnel = ResumeTicketTLSv13(cfg, logger, path)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,145 @@
"""stunnel client-server tests"""
import logging
import os
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
ServerReopen
)
class StunnelTest(ServerReopen):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path):
super().__init__(cfg, logger, path)
self.params.services = ['server', 'client']
self.params.conn_num = 4
self.events.count = 1
class ResumeTicketSecret(StunnelTest):
"""Checking if the reloaded server resume the session with secret keys for
the session ticket processing.
We expect exactly 2 "TLS accepted: previous session reused" to be logged by the
[server] service, because the server holds keys for the session ticket processing.
The ticket session resumption also works for the FORK model.
"""
def __init__(self, cfg: Config, logger: logging.Logger, path:pathlib.Path):
super().__init__(cfg, logger, path)
self.params.description = '151. Session resumption with secret keys'
self.events.count = 3
self.events.success = [
"TLS accepted: previous session reused"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
#"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
self.path = path
async def prepare_client_cfgfile(
self, cfg: Config, ports: list, service: str
) -> (pathlib.Path, pathlib.Path):
"""Create a configuration file for a stunnel client."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
retry = yes
[{service}]
client = yes
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/reader.py {self.path}
connect = 127.0.0.1:{ports[1]}
cert = {cfg.certdir}/client_cert.pem
"""
cfgfile = cfg.tempd / "stunnel_client.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile, os.devnull
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
options = -NO_TICKET
ticketKeySecret = 6c:42:72:46:57:23:3a:3d:4b:54:2d:7b:55:4b:6e:8f:32:5c:21:6a:2e:6e:47:31:57:20:2f:75:26:7b:4d:25
ticketMacSecret = 3f:3c:77:53:32:48:79:76:75:7a:50:33:70:65:47:27:32:79:73:7e:73:2c:21:6c:3a:6f:30:28:4c:5c:27:1f
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
async def prepare_additional_server_cfgfile(
self, cfg: Config, ports: list, lport: int
) -> pathlib.Path:
"""Create a configuration file for new stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_new_server.pid
foreground = yes
debug = debug
syslog = no
ticketKeySecret = 6c:42:72:46:57:23:3a:3d:4b:54:2d:7b:55:4b:6e:8f:32:5c:21:6a:2e:6e:47:31:57:20:2f:75:26:7b:4d:25
ticketMacSecret = 3f:3c:77:53:32:48:79:76:75:7a:50:33:70:65:47:27:32:79:73:7e:73:2c:21:6c:3a:6f:30:28:4c:5c:27:1f
[server]
accept = 127.0.0.1:{ports[1]}
connect = 127.0.0.1:{lport}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class StunnelClientServerTest(Plugin):
"""Stunnel client-server tests
HTTP client --> stunnel client --> stunnel server --> HTTP server
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Resume session'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
path = os.path.join(cfg.tempd, 'unix.sock')
stunnel = ResumeTicketSecret(cfg, logger, path)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,354 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class RedirectWrongPeerCert(StunnelTest):
"""Redirect stunnel server test.
The client presents the *wrong* certificate so the connection is redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '161. Redirect connection (wrong peer certificate)'
self.params.context = 'load_wrong_cert'
self.events.count = 1
self.events.success = [
"Redirecting connection"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
#"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
redirect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class RedirectNoPeerCert(StunnelTest):
"""Redirect stunnel server test.
The client does not present any certificate so the connection is redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '162. Redirect connection (no peer certificate)'
self.events.count = 1
self.events.success = [
"Redirecting connection"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
#"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
redirect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class NoRedirectCorrectPeerCert(StunnelTest):
"""No redirect stunnel server test.
The client presents the *correct* certificate and the connection is not redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '163. Not redirected connection (valid peer certificate)'
self.params.context = 'load_correct_cert'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
redirect = 127.0.0.1:0
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class RedirectWrongChainCert(StunnelTest):
"""Redirect stunnel server test.
The client does not present any certificate so the connection is redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '164. Redirect connection (wrong chain)'
self.events.count = 1
self.events.success = [
"Redirecting connection"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
#"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
redirect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyChain = yes
CAfile = {cfg.certdir}/CACert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class RedirectNoChainCert(StunnelTest):
"""No redirect stunnel server test.
The client does not present any certificate so the connection is redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '165. Redirect connection (no chain)'
self.events.count = 1
self.events.success = [
"Redirecting connection"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
#"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
redirect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyChain = yes
CAfile = {cfg.certdir}/CACert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class NoRedirectCorrectChainCert(StunnelTest):
"""No redirect stunnel server test.
The client presents the *correct* certificate and the connection is not redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '166. Not redirected connection (valid chain)'
self.params.context = 'load_correct_cert'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
redirect = 127.0.0.1:0
cert = {cfg.certdir}/server_cert.pem
verifyChain = yes
CAfile = {cfg.certdir}/CACert.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class RedirectStunnelTest(Plugin):
"""Stunnel redirect server tests
HTTPS client --> stunnel server --> HTTP server or "Wrong_connection!"
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Redirect connection'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = RedirectWrongPeerCert(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = RedirectNoPeerCert(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = NoRedirectCorrectPeerCert(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = RedirectWrongChainCert(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = RedirectNoChainCert(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = NoRedirectCorrectChainCert(cfg, logger)
await stunnel.test_stunnel(cfg)

Просмотреть файл

@ -0,0 +1,200 @@
"""stunnel server tests"""
import logging
import pathlib
from plugin_collection import Plugin
from maketest import (
Config,
StunnelAcceptConnect
)
class StunnelTest(StunnelAcceptConnect):
"""Base class for stunnel client-server tests."""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.ssl_client = True
self.params.services = ['server']
class RedirectProxyWrongPeerCert(StunnelTest):
"""Redirect stunnel server test.
The client presents the *wrong* certificate so the connection is redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '171. Redirect proxy connection (wrong peer certificate)'
self.params.context = 'load_wrong_cert'
self.events.count = 1
self.events.success = [
"Redirecting connection"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
#"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
protocol = proxy
[{service}]
accept = 127.0.0.1:0
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
redirect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class RedirectProxyNoPeerCert(StunnelTest):
"""Redirect stunnel server test.
The client does not present any certificate so the connection is redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '172. Redirect proxy connection (no peer certificate)'
self.events.count = 1
self.events.success = [
"Redirecting connection"
]
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
#"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
protocol = proxy
[{service}]
accept = 127.0.0.1:0
exec = {cfg.pythondir}
execArgs = python3 {cfg.scriptdir}/error.py
redirect = 127.0.0.1:{port}
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class NoRedirectProxyCorrectPeerCert(StunnelTest):
"""No redirect stunnel server test.
The client presents the *correct* certificate and the connection is not redirected.
"""
def __init__(self, cfg: Config, logger: logging.Logger):
super().__init__(cfg, logger)
self.params.description = '173. Not redirected proxy connection (valid peer certificate)'
self.params.context = 'load_correct_cert'
self.events.failure = [
"peer did not return a certificate",
"bad certificate",
"certificate verify failed",
"unsupported protocol",
"TLS accepted: previous session reused",
"Redirecting connection",
"Connection reset by peer",
"Connection lost",
"Client received unexpected message",
"Server received unexpected message",
"Something went wrong",
"INTERNAL ERROR"
]
async def prepare_server_cfgfile(
self, cfg: Config, port: int, service: str
) -> pathlib.Path:
"""Create a configuration file for a stunnel server."""
contents = f"""
pid = {cfg.tempd}/stunnel_{service}.pid
foreground = yes
debug = debug
syslog = no
protocol = proxy
[{service}]
accept = 127.0.0.1:0
connect = 127.0.0.1:{port}
redirect = 127.0.0.1:0
cert = {cfg.certdir}/server_cert.pem
verifyPeer = yes
CAfile = {cfg.certdir}/PeerCerts.pem
"""
cfgfile = cfg.tempd / "stunnel_server.conf"
cfgfile.write_text(contents, encoding="UTF-8")
return cfgfile
class RedirectStunnelTest(Plugin):
"""Stunnel redirect server tests
HTTPS client --> stunnel server --> HTTP server or "Wrong_connection!"
"""
# pylint: disable=too-few-public-methods
def __init__(self):
super().__init__()
self.description = 'Redirect PROXY connection'
async def perform_operation(self, cfg: Config, logger: logging.Logger) -> None:
"""Run tests"""
stunnel = RedirectProxyWrongPeerCert(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = RedirectProxyNoPeerCert(cfg, logger)
await stunnel.test_stunnel(cfg)
stunnel = NoRedirectProxyCorrectPeerCert(cfg, logger)
await stunnel.test_stunnel(cfg)

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше