From: Nicolas Thill Date: Thu, 13 May 2010 00:47:17 +0000 (+0000) Subject: [packages] stunnel: update to 4.33 (closes: #7296) X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;hb=37db891ba27d6c3372702d91419d46e8ef6a128c [packages] stunnel: update to 4.33 (closes: #7296) SVN-Revision: 21439 --- diff --git a/net/stunnel/Makefile b/net/stunnel/Makefile index 12b7f7ced3..59acf97663 100644 --- a/net/stunnel/Makefile +++ b/net/stunnel/Makefile @@ -1,11 +1,17 @@ +# +# Copyright (C) 2006-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# include $(TOPDIR)/rules.mk PKG_NAME:=stunnel -PKG_VERSION:=4.29 -PKG_RELEASE:=4 +PKG_VERSION:=4.33 +PKG_RELEASE:=1 -PKG_MD5SUM:=14dc3f8412947f0548975cbce74d6863 +PKG_MD5SUM:=559a864066d8cc4afd8a97682c90d41c PKG_SOURCE_URL:=http://www.stunnel.org/download/stunnel/src/ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz diff --git a/net/stunnel/patches/100-cross-compile.patch b/net/stunnel/patches/100-cross-compile.patch index 52052a02e0..6d7648c4a6 100644 --- a/net/stunnel/patches/100-cross-compile.patch +++ b/net/stunnel/patches/100-cross-compile.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -21536,56 +21536,56 @@ _ACEOF +@@ -21552,56 +21552,56 @@ _ACEOF fi rm -f conftest* @@ -100,7 +100,7 @@ { echo "$as_me:$LINENO: **************************************** entropy" >&5 -@@ -24033,8 +24033,8 @@ _ACEOF +@@ -24049,8 +24049,8 @@ _ACEOF # Add SSL includes and libraries diff --git a/net/stunnel/patches/101-no-comp.patch b/net/stunnel/patches/101-no-comp.patch index 640bd89482..9fbe22c9e9 100644 --- a/net/stunnel/patches/101-no-comp.patch +++ b/net/stunnel/patches/101-no-comp.patch @@ -1,27 +1,28 @@ --- a/src/ssl.c +++ b/src/ssl.c -@@ -63,13 +63,16 @@ void ssl_init(void) { /* init SSL before - } - - void ssl_configure(void) { /* configure global SSL settings */ -+#ifndef OPENSSL_NO_COMP - if(options.compression!=COMP_NONE) - init_compression(); +@@ -72,14 +72,17 @@ int ssl_configure(void) { /* configure g + s_log(LOG_NOTICE, "FIPS mode %s", + global_options.option.fips ? "enabled" : "disabled"); + #endif /* USE_FIPS */ ++#ifndef OPENSSL_NO_COMP + if(global_options.compression!=COMP_NONE && !init_compression()) + return 0; +#endif if(!init_prng()) - s_log(LOG_DEBUG, "PRNG seeded successfully"); + return 0; + s_log(LOG_DEBUG, "PRNG seeded successfully"); + return 1; /* SUCCESS */ } - static void init_compression(void) { +#ifndef OPENSSL_NO_COMP + static int init_compression(void) { int id=0; COMP_METHOD *cm=NULL; - char *name="unknown"; -@@ -98,6 +101,7 @@ static void init_compression(void) { - die(1); - } +@@ -111,6 +114,7 @@ static int init_compression(void) { s_log(LOG_INFO, "Compression enabled using %s method", name); -+#endif + return 1; } ++#endif static int init_prng(void) { + int totbytes=0; diff --git a/net/stunnel/patches/102-no-ssl2.patch b/net/stunnel/patches/102-no-ssl2.patch index 9ebd4243a0..e94184b04e 100644 --- a/net/stunnel/patches/102-no-ssl2.patch +++ b/net/stunnel/patches/102-no-ssl2.patch @@ -1,6 +1,6 @@ --- a/src/options.c +++ b/src/options.c -@@ -1198,8 +1198,10 @@ static char *service_options(CMD cmd, LO +@@ -1234,8 +1234,10 @@ static char *parse_service_option(CMD cm section->client_method=(SSL_METHOD *)SSLv23_client_method(); section->server_method=(SSL_METHOD *)SSLv23_server_method(); } else if(!strcasecmp(arg, "SSLv2")) { diff --git a/net/stunnel/patches/103-no-zlib-link.patch b/net/stunnel/patches/103-no-zlib-link.patch index 6e2a45651d..f627c53c85 100644 --- a/net/stunnel/patches/103-no-zlib-link.patch +++ b/net/stunnel/patches/103-no-zlib-link.patch @@ -1,7 +1,7 @@ Avoid linking with zlib, which is a dependency of openssl, not ours. --- a/configure +++ b/configure -@@ -23001,7 +23001,7 @@ if test $ac_cv_lib_z_inflateEnd = yes; t +@@ -23017,7 +23017,7 @@ if test $ac_cv_lib_z_inflateEnd = yes; t #define HAVE_LIBZ 1 _ACEOF diff --git a/net/stunnel/patches/104-fix-paths.patch b/net/stunnel/patches/104-fix-paths.patch index 3c9966794b..aad310b94e 100644 --- a/net/stunnel/patches/104-fix-paths.patch +++ b/net/stunnel/patches/104-fix-paths.patch @@ -1,41 +1,42 @@ ## Do several path fixups, removing unneeded @prefix@s --- a/tools/stunnel.conf-sample.in +++ b/tools/stunnel.conf-sample.in -@@ -3,14 +3,14 @@ - ; Please make sure you understand them (especially the effect of the chroot jail) +@@ -4,15 +4,15 @@ + ; please read the manual and make sure you understand them - ; Certificate/key is needed in server mode and optional in client mode + ; certificate/key is needed in server mode and optional in client mode -cert = @prefix@/etc/stunnel/mail.pem -;key = @prefix@/etc/stunnel/mail.pem +cert = @sysconfdir@/stunnel/stunnel.pem +;key = @sysconfdir@/stunnel/stunnel.pem - ; Protocol version (all, SSLv2, SSLv3, TLSv1) + ; protocol version (all, SSLv2, SSLv3, TLSv1) sslVersion = SSLv3 - ; Some security enhancements for UNIX systems - comment them out on Win32 + ; security enhancements for UNIX systems - comment them out on Win32 + ; for chroot a copy of some devices and files is needed within the jail -chroot = @prefix@/var/lib/stunnel/ +chroot = @localstatedir@ setuid = nobody setgid = @DEFAULT_GROUP@ ; PID is created inside the chroot jail -@@ -30,16 +30,16 @@ socket = r:TCP_NODELAY=1 +@@ -33,16 +33,16 @@ socket = r:TCP_NODELAY=1 ; CApath is located inside chroot jail ;CApath = /certs - ; It's often easier to use CAfile + ; it's often easier to use CAfile -;CAfile = @prefix@/etc/stunnel/certs.pem +;CAfile = @sysconfdir@/stunnel/certs.pem - ; Don't forget to c_rehash CRLpath + ; don't forget to c_rehash CRLpath ; CRLpath is located inside chroot jail ;CRLpath = /crls - ; Alternatively you can use CRLfile + ; alternatively CRLfile can be used -;CRLfile = @prefix@/etc/stunnel/crls.pem +;CRLfile = @sysconfdir@/stunnel/crls.pem - ; Some debugging stuff useful for troubleshooting + ; debugging stuff (may useful for troubleshooting) ;debug = 7 -;output = stunnel.log +;output = @localstatedir@/log/stunnel.log - ; Use it for client mode + ; SSL client mode ;client = yes diff --git a/net/stunnel/patches/105-stunnel-conf.patch b/net/stunnel/patches/105-stunnel-conf.patch index 3f213cee83..c22e0b441f 100644 --- a/net/stunnel/patches/105-stunnel-conf.patch +++ b/net/stunnel/patches/105-stunnel-conf.patch @@ -1,17 +1,17 @@ --- a/tools/stunnel.conf-sample.in +++ b/tools/stunnel.conf-sample.in -@@ -7,7 +7,7 @@ cert = @sysconfdir@/stunnel/stunnel.pem +@@ -8,7 +8,7 @@ cert = @sysconfdir@/stunnel/stunnel.pem ;key = @sysconfdir@/stunnel/stunnel.pem - ; Protocol version (all, SSLv2, SSLv3, TLSv1) + ; protocol version (all, SSLv2, SSLv3, TLSv1) -sslVersion = SSLv3 +sslVersion = all - ; Some security enhancements for UNIX systems - comment them out on Win32 - chroot = @localstatedir@ -@@ -46,21 +46,26 @@ socket = r:TCP_NODELAY=1 + ; security enhancements for UNIX systems - comment them out on Win32 + ; for chroot a copy of some devices and files is needed within the jail +@@ -49,21 +49,26 @@ socket = r:TCP_NODELAY=1 - ; Service-level configuration + ; service-level configuration -[pop3s] -accept = 995 diff --git a/net/stunnel/patches/106-stunnel-xforwardedfor.patch b/net/stunnel/patches/106-stunnel-xforwardedfor.patch index 2c0f1076d2..497ff6d53d 100644 --- a/net/stunnel/patches/106-stunnel-xforwardedfor.patch +++ b/net/stunnel/patches/106-stunnel-xforwardedfor.patch @@ -1,6 +1,6 @@ --- a/doc/stunnel.8 +++ b/doc/stunnel.8 -@@ -497,7 +497,10 @@ time to keep an idle connection +@@ -504,7 +504,10 @@ time to keep an idle connection .IP "\fBtransparent\fR = yes | no (Unix only)" 4 .IX Item "transparent = yes | no (Unix only)" transparent proxy mode @@ -12,738 +12,6 @@ Re-write address to appear as if wrapped daemon is connecting from the \s-1SSL\s0 client machine instead of the machine running \fBstunnel\fR. .Sp ---- /dev/null -+++ b/doc/stunnel.8.orig -@@ -0,0 +1,729 @@ -+.\" Automatically generated by Pod::Man 2.1801 (Pod::Simple 3.05) -+.\" -+.\" Standard preamble: -+.\" ======================================================================== -+.de Sp \" Vertical space (when we can't use .PP) -+.if t .sp .5v -+.if n .sp -+.. -+.de Vb \" Begin verbatim text -+.ft CW -+.nf -+.ne \\$1 -+.. -+.de Ve \" End verbatim text -+.ft R -+.fi -+.. -+.\" Set up some character translations and predefined strings. \*(-- will -+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -+.\" double quote, and \*(R" will give a right double quote. \*(C+ will -+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -+.\" nothing in troff, for use with C<>. -+.tr \(*W- -+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -+.ie n \{\ -+. ds -- \(*W- -+. ds PI pi -+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -+. ds L" "" -+. ds R" "" -+. ds C` "" -+. ds C' "" -+'br\} -+.el\{\ -+. ds -- \|\(em\| -+. ds PI \(*p -+. ds L" `` -+. ds R" '' -+'br\} -+.\" -+.\" Escape single quotes in literal strings from groff's Unicode transform. -+.ie \n(.g .ds Aq \(aq -+.el .ds Aq ' -+.\" -+.\" If the F register is turned on, we'll generate index entries on stderr for -+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -+.\" entries marked with X<> in POD. Of course, you'll have to process the -+.\" output yourself in some meaningful fashion. -+.ie \nF \{\ -+. de IX -+. tm Index:\\$1\t\\n%\t"\\$2" -+.. -+. nr % 0 -+. rr F -+.\} -+.el \{\ -+. de IX -+.. -+.\} -+.\" ======================================================================== -+.\" -+.IX Title "STUNNEL 8" -+.TH STUNNEL 8 "2009.11.20" "4.29" "stunnel" -+.\" For nroff, turn off justification. Always turn off hyphenation; it makes -+.\" way too many mistakes in technical documents. -+.if n .ad l -+.nh -+.SH "NAME" -+stunnel \- universal SSL tunnel -+.SH "SYNOPSIS" -+.IX Header "SYNOPSIS" -+.IP "\fBUnix:\fR" 4 -+.IX Item "Unix:" -+\&\fBstunnel\fR [] | \-fd n | \-help | \-version | \-sockets -+.IP "\fB\s-1WIN32:\s0\fR" 4 -+.IX Item "WIN32:" -+\&\fBstunnel\fR [ [\-install | \-uninstall | \-start | \-stop] -+ [\-quiet] [] ] | \-help | \-version | \-sockets -+.SH "DESCRIPTION" -+.IX Header "DESCRIPTION" -+The \fBstunnel\fR program is designed to work as \fI\s-1SSL\s0\fR encryption wrapper -+between remote clients and local (\fIinetd\fR\-startable) or remote -+servers. The concept is that having non-SSL aware daemons running on -+your system you can easily set them up to communicate with clients over -+secure \s-1SSL\s0 channels. -+.PP -+\&\fBstunnel\fR can be used to add \s-1SSL\s0 functionality to commonly used \fIInetd\fR -+daemons like \s-1POP\-2\s0, \s-1POP\-3\s0, and \s-1IMAP\s0 servers, to standalone daemons like -+\&\s-1NNTP\s0, \s-1SMTP\s0 and \s-1HTTP\s0, and in tunneling \s-1PPP\s0 over network sockets without -+changes to the source code. -+.PP -+This product includes cryptographic software written by -+Eric Young (eay@cryptsoft.com) -+.SH "OPTIONS" -+.IX Header "OPTIONS" -+.IP "<\fBfilename\fR>" 4 -+.IX Item "" -+Use specified configuration file -+.IP "\fB\-fd n\fR (Unix only)" 4 -+.IX Item "-fd n (Unix only)" -+Read the config file from specified file descriptor -+.IP "\fB\-help\fR" 4 -+.IX Item "-help" -+Print \fBstunnel\fR help menu -+.IP "\fB\-version\fR" 4 -+.IX Item "-version" -+Print \fBstunnel\fR version and compile time defaults -+.IP "\fB\-sockets\fR" 4 -+.IX Item "-sockets" -+Print default socket options -+.IP "\fB\-install\fR (\s-1NT/2000/XP\s0 only)" 4 -+.IX Item "-install (NT/2000/XP only)" -+Install \s-1NT\s0 Service -+.IP "\fB\-uninstall\fR (\s-1NT/2000/XP\s0 only)" 4 -+.IX Item "-uninstall (NT/2000/XP only)" -+Uninstall \s-1NT\s0 Service -+.IP "\fB\-start\fR (\s-1NT/2000/XP\s0 only)" 4 -+.IX Item "-start (NT/2000/XP only)" -+Start \s-1NT\s0 Service -+.IP "\fB\-stop\fR (\s-1NT/2000/XP\s0 only)" 4 -+.IX Item "-stop (NT/2000/XP only)" -+Stop \s-1NT\s0 Service -+.IP "\fB\-quiet\fR (\s-1NT/2000/XP\s0 only)" 4 -+.IX Item "-quiet (NT/2000/XP only)" -+Don't display a message box when successfully installed or uninstalled \s-1NT\s0 service -+.SH "CONFIGURATION FILE" -+.IX Header "CONFIGURATION FILE" -+Each line of the configuration file can be either: -+.IP "\(bu" 4 -+an empty line (ignored) -+.IP "\(bu" 4 -+a comment starting with ';' (ignored) -+.IP "\(bu" 4 -+an 'option_name = option_value' pair -+.IP "\(bu" 4 -+\&'[service_name]' indicating a start of a service definition -+.SS "\s-1GLOBAL\s0 \s-1OPTIONS\s0" -+.IX Subsection "GLOBAL OPTIONS" -+.IP "\fBchroot\fR = directory (Unix only)" 4 -+.IX Item "chroot = directory (Unix only)" -+directory to chroot \fBstunnel\fR process -+.Sp -+\&\fBchroot\fR keeps \fBstunnel\fR in chrooted jail. \fICApath\fR, \fICRLpath\fR, \fIpid\fR -+and \fIexec\fR are located inside the jail and the patches have to be relative -+to the directory specified with \fBchroot\fR. -+.Sp -+To have libwrap (\s-1TCP\s0 Wrappers) control effective in a chrooted environment -+you also have to copy its configuration files (/etc/hosts.allow and -+/etc/hosts.deny) there. -+.IP "\fBcompression\fR = zlib | rle" 4 -+.IX Item "compression = zlib | rle" -+select data compression algorithm -+.Sp -+default: no compression -+.Sp -+zlib compression of OpenSSL 0.9.8 or above is not backward compatible with -+OpenSSL 0.9.7. -+.Sp -+rle compression is currently not implemented by the OpenSSL library. -+.IP "\fBdebug\fR = [facility.]level" 4 -+.IX Item "debug = [facility.]level" -+debugging level -+.Sp -+Level is a one of the syslog level names or numbers -+emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), -+info (6), or debug (7). All logs for the specified level and -+all levels numerically less than it will be shown. Use \fBdebug = debug\fR or -+\&\fBdebug = 7\fR for greatest debugging output. The default is notice (5). -+.Sp -+The syslog facility 'daemon' will be used unless a facility name is supplied. -+(Facilities are not supported on Win32.) -+.Sp -+Case is ignored for both facilities and levels. -+.IP "\fB\s-1EGD\s0\fR = egd path (Unix only)" 4 -+.IX Item "EGD = egd path (Unix only)" -+path to Entropy Gathering Daemon socket -+.Sp -+Entropy Gathering Daemon socket to use to feed OpenSSL random number -+generator. (Available only if compiled with OpenSSL 0.9.5a or higher) -+.IP "\fBengine\fR = auto | " 4 -+.IX Item "engine = auto | " -+select hardware engine -+.Sp -+default: software-only cryptography -+.Sp -+There's an example in '\s-1EXAMPLES\s0' section. -+.IP "\fBengineCtrl\fR = command[:parameter]" 4 -+.IX Item "engineCtrl = command[:parameter]" -+control hardware engine -+.Sp -+Special commands \*(L"\s-1LOAD\s0\*(R" and \*(L"\s-1INIT\s0\*(R" can be used to load and initialize the -+engine cryptogaphic module. -+.IP "\fBfips\fR = yes | no" 4 -+.IX Item "fips = yes | no" -+Enable or disable \s-1FIPS\s0 140\-2 mode. -+.Sp -+This option allows to disable entering \s-1FIPS\s0 mode if stunnel was compiled with -+\&\s-1FIPS\s0 140\-2 support. -+.Sp -+default: yes -+.IP "\fBforeground\fR = yes | no (Unix only)" 4 -+.IX Item "foreground = yes | no (Unix only)" -+foreground mode -+.Sp -+Stay in foreground (don't fork) and log to stderr -+instead of via syslog (unless \fBoutput\fR is specified). -+.Sp -+default: background in daemon mode -+.IP "\fBoutput\fR = file" 4 -+.IX Item "output = file" -+append log messages to a file instead of using syslog -+.Sp -+/dev/stdout device can be used to redirect log messages to the standard -+output (for example to log them with daemontools splogger). -+.IP "\fBpid\fR = file (Unix only)" 4 -+.IX Item "pid = file (Unix only)" -+pid file location -+.Sp -+If the argument is empty, then no pid file will be created. -+.Sp -+\&\fIpid\fR path is relative to \fIchroot\fR directory if specified. -+.IP "\fBRNDbytes\fR = bytes" 4 -+.IX Item "RNDbytes = bytes" -+bytes to read from random seed files -+.Sp -+Number of bytes of data read from random seed files. With \s-1SSL\s0 versions -+less than 0.9.5a, also determines how many bytes of data are considered -+sufficient to seed the \s-1PRNG\s0. More recent OpenSSL versions have a builtin -+function to determine when sufficient randomness is available. -+.IP "\fBRNDfile\fR = file" 4 -+.IX Item "RNDfile = file" -+path to file with random seed data -+.Sp -+The \s-1SSL\s0 library will use data from this file first to seed the random -+number generator. -+.IP "\fBRNDoverwrite\fR = yes | no" 4 -+.IX Item "RNDoverwrite = yes | no" -+overwrite the random seed files with new random data -+.Sp -+default: yes -+.IP "\fBservice\fR = servicename" 4 -+.IX Item "service = servicename" -+use specified string as the service name -+.Sp -+\&\fBOn Unix:\fR \fIinetd\fR mode service name for \s-1TCP\s0 Wrapper library. -+.Sp -+\&\fBOn \s-1NT/2000/XP:\s0\fR \s-1NT\s0 service name in the Control Panel. -+.Sp -+default: stunnel -+.IP "\fBsetgid\fR = groupname (Unix only)" 4 -+.IX Item "setgid = groupname (Unix only)" -+\&\fIsetgid()\fR to groupname in daemon mode and clears all other groups -+.IP "\fBsetuid\fR = username (Unix only)" 4 -+.IX Item "setuid = username (Unix only)" -+\&\fIsetuid()\fR to username in daemon mode -+.IP "\fBsocket\fR = a|l|r:option=value[:value]" 4 -+.IX Item "socket = a|l|r:option=value[:value]" -+Set an option on accept/local/remote socket -+.Sp -+The values for linger option are l_onof:l_linger. -+The values for time are tv_sec:tv_usec. -+.Sp -+Examples: -+.Sp -+.Vb 11 -+\& socket = l:SO_LINGER=1:60 -+\& set one minute timeout for closing local socket -+\& socket = r:TCP_NODELAY=1 -+\& turn off the Nagle algorithm for remote sockets -+\& socket = r:SO_OOBINLINE=1 -+\& place out\-of\-band data directly into the -+\& receive data stream for remote sockets -+\& socket = a:SO_REUSEADDR=0 -+\& disable address reuse (enabled by default) -+\& socket = a:SO_BINDTODEVICE=lo -+\& only accept connections on loopback interface -+.Ve -+.IP "\fBsyslog\fR = yes | no (Unix only)" 4 -+.IX Item "syslog = yes | no (Unix only)" -+enable logging via syslog -+.Sp -+default: yes -+.IP "\fBtaskbar\fR = yes | no (\s-1WIN32\s0 only)" 4 -+.IX Item "taskbar = yes | no (WIN32 only)" -+enable the taskbar icon -+.Sp -+default: yes -+.SS "SERVICE-LEVEL \s-1OPTIONS\s0" -+.IX Subsection "SERVICE-LEVEL OPTIONS" -+Each configuration section begins with service name in square brackets. -+The service name is used for libwrap (\s-1TCP\s0 Wrappers) access control and lets -+you distinguish \fBstunnel\fR services in your log files. -+.PP -+Note that if you wish to run \fBstunnel\fR in \fIinetd\fR mode (where it -+is provided a network socket by a server such as \fIinetd\fR, \fIxinetd\fR, -+or \fItcpserver\fR) then you should read the section entitled \fI\s-1INETD\s0 \s-1MODE\s0\fR -+below. -+.IP "\fBaccept\fR = [host:]port" 4 -+.IX Item "accept = [host:]port" -+accept connections on specified host:port -+.Sp -+If no host specified, defaults to all \s-1IP\s0 addresses for the local host. -+.IP "\fBCApath\fR = directory" 4 -+.IX Item "CApath = directory" -+Certificate Authority directory -+.Sp -+This is the directory in which \fBstunnel\fR will look for certificates when using -+the \fIverify\fR. Note that the certificates in this directory should be named -+\&\s-1XXXXXXXX\s0.0 where \s-1XXXXXXXX\s0 is the hash value of the \s-1DER\s0 encoded subject of the -+cert (the first 4 bytes of the \s-1MD5\s0 hash in least significant byte order). -+.Sp -+\&\fICApath\fR path is relative to \fIchroot\fR directory if specified. -+.IP "\fBCAfile\fR = certfile" 4 -+.IX Item "CAfile = certfile" -+Certificate Authority file -+.Sp -+This file contains multiple \s-1CA\s0 certificates, used with the \fIverify\fR. -+.IP "\fBcert\fR = pemfile" 4 -+.IX Item "cert = pemfile" -+certificate chain \s-1PEM\s0 file name -+.Sp -+A \s-1PEM\s0 is always needed in server mode. -+Specifying this flag in client mode will use this certificate chain -+as a client side certificate chain. Using client side certs is optional. -+The certificates must be in \s-1PEM\s0 format and must be sorted starting with the -+certificate to the highest level (root \s-1CA\s0). -+.IP "\fBciphers\fR = cipherlist" 4 -+.IX Item "ciphers = cipherlist" -+Select permitted \s-1SSL\s0 ciphers -+.Sp -+A colon delimited list of the ciphers to allow in the \s-1SSL\s0 connection. -+For example \s-1DES\-CBC3\-SHA:IDEA\-CBC\-MD5\s0 -+.IP "\fBclient\fR = yes | no" 4 -+.IX Item "client = yes | no" -+client mode (remote service uses \s-1SSL\s0) -+.Sp -+default: no (server mode) -+.IP "\fBconnect\fR = [host:]port" 4 -+.IX Item "connect = [host:]port" -+connect to a remote host:port -+.Sp -+If no host is specified, the host defaults to localhost. -+.Sp -+Multiple \fBconnect\fR options are allowed in a single service section. -+.Sp -+If host resolves to multiple addresses and/or if multiple \fBconnect\fR -+options are specified, then the remote address is chosen using a -+round-robin algorithm. -+.IP "\fBCRLpath\fR = directory" 4 -+.IX Item "CRLpath = directory" -+Certificate Revocation Lists directory -+.Sp -+This is the directory in which \fBstunnel\fR will look for CRLs when -+using the \fIverify\fR. Note that the CRLs in this directory should -+be named \s-1XXXXXXXX\s0.0 where \s-1XXXXXXXX\s0 is the hash value of the \s-1CRL\s0. -+.Sp -+\&\fICRLpath\fR path is relative to \fIchroot\fR directory if specified. -+.IP "\fBCRLfile\fR = certfile" 4 -+.IX Item "CRLfile = certfile" -+Certificate Revocation Lists file -+.Sp -+This file contains multiple CRLs, used with the \fIverify\fR. -+.IP "\fBdelay\fR = yes | no" 4 -+.IX Item "delay = yes | no" -+delay \s-1DNS\s0 lookup for 'connect' option -+.IP "\fBengineNum\fR = engine number" 4 -+.IX Item "engineNum = engine number" -+select engine number to read private key -+.Sp -+The engines are numbered starting from 1. -+.IP "\fBexec\fR = executable_path (Unix only)" 4 -+.IX Item "exec = executable_path (Unix only)" -+execute local inetd-type program -+.Sp -+\&\fIexec\fR path is relative to \fIchroot\fR directory if specified. -+.ie n .IP "\fBexecargs\fR = $0 $1 $2 ... (Unix only)" 4 -+.el .IP "\fBexecargs\fR = \f(CW$0\fR \f(CW$1\fR \f(CW$2\fR ... (Unix only)" 4 -+.IX Item "execargs = $0 $1 $2 ... (Unix only)" -+arguments for \fIexec\fR including program name ($0) -+.Sp -+Quoting is currently not supported. -+Arguments are separated with arbitrary number of whitespaces. -+.IP "\fBfailover\fR = rr | prio" 4 -+.IX Item "failover = rr | prio" -+Failover strategy for multiple \*(L"connect\*(R" targets. -+.Sp -+.Vb 2 -+\& rr (round robin) \- fair load distribution -+\& prio (priority) \- use the order specified in config file -+.Ve -+.Sp -+default: rr -+.IP "\fBident\fR = username" 4 -+.IX Item "ident = username" -+use \s-1IDENT\s0 (\s-1RFC\s0 1413) username checking -+.IP "\fBkey\fR = keyfile" 4 -+.IX Item "key = keyfile" -+private key for certificate specified with \fIcert\fR option -+.Sp -+Private key is needed to authenticate certificate owner. -+Since this file should be kept secret it should only be readable -+to its owner. On Unix systems you can use the following command: -+.Sp -+.Vb 1 -+\& chmod 600 keyfile -+.Ve -+.Sp -+default: value of \fIcert\fR option -+.IP "\fBlocal\fR = host" 4 -+.IX Item "local = host" -+\&\s-1IP\s0 of the outgoing interface is used as source for remote connections. -+Use this option to bind a static local \s-1IP\s0 address, instead. -+.IP "\fB\s-1OCSP\s0\fR = url" 4 -+.IX Item "OCSP = url" -+select \s-1OCSP\s0 server for certificate verification -+.IP "\fBOCSPflag\fR = flag" 4 -+.IX Item "OCSPflag = flag" -+specify \s-1OCSP\s0 server flag -+.Sp -+Several \fIOCSPflag\fR can be used to specify multiple flags. -+.Sp -+currently supported flags: \s-1NOCERTS\s0, \s-1NOINTERN\s0 \s-1NOSIGS\s0, \s-1NOCHAIN\s0, \s-1NOVERIFY\s0, -+\&\s-1NOEXPLICIT\s0, \s-1NOCASIGN\s0, \s-1NODELEGATED\s0, \s-1NOCHECKS\s0, \s-1TRUSTOTHER\s0, \s-1RESPID_KEY\s0, \s-1NOTIME\s0 -+.IP "\fBoptions\fR = SSL_options" 4 -+.IX Item "options = SSL_options" -+OpenSSL library options -+.Sp -+The parameter is the OpenSSL option name as described in the -+\&\fI\fISSL_CTX_set_options\fI\|(3ssl)\fR manual, but without \fI\s-1SSL_OP_\s0\fR prefix. -+Several \fIoptions\fR can be used to specify multiple options. -+.Sp -+For example for compatibility with erroneous Eudora \s-1SSL\s0 implementation -+the following option can be used: -+.Sp -+.Vb 1 -+\& options = DONT_INSERT_EMPTY_FRAGMENTS -+.Ve -+.IP "\fBprotocol\fR = proto" 4 -+.IX Item "protocol = proto" -+application protocol to negotiate \s-1SSL\s0 -+.Sp -+currently supported: cifs, connect, imap, nntp, pop3, smtp, pgsql -+.IP "\fBprotocolAuthentication\fR = auth_type" 4 -+.IX Item "protocolAuthentication = auth_type" -+authentication type for protocol negotiations -+.Sp -+currently supported: basic, \s-1NTLM\s0 -+.Sp -+Currently authentication type only applies to 'connect' protocol. -+.Sp -+default: basic -+.IP "\fBprotocolHost\fR = host:port" 4 -+.IX Item "protocolHost = host:port" -+destination address for protocol negotiations -+.IP "\fBprotocolPassword\fR = password" 4 -+.IX Item "protocolPassword = password" -+password for protocol negotiations -+.IP "\fBprotocolUsername\fR = username" 4 -+.IX Item "protocolUsername = username" -+username for protocol negotiations -+.IP "\fBpty\fR = yes | no (Unix only)" 4 -+.IX Item "pty = yes | no (Unix only)" -+allocate pseudo terminal for 'exec' option -+.IP "\fBretry\fR = yes | no (Unix only)" 4 -+.IX Item "retry = yes | no (Unix only)" -+reconnect a connect+exec section after it's disconnected -+.Sp -+default: no -+.IP "\fBsession\fR = timeout" 4 -+.IX Item "session = timeout" -+session cache timeout -+.IP "\fBsessiond\fR = host:port" 4 -+.IX Item "sessiond = host:port" -+address of sessiond \s-1SSL\s0 cache server -+.IP "\fBsslVersion\fR = version" 4 -+.IX Item "sslVersion = version" -+select version of \s-1SSL\s0 protocol -+.Sp -+Allowed options: all, SSLv2, SSLv3, TLSv1 -+.IP "\fBstack\fR = bytes (except for \s-1FORK\s0 model)" 4 -+.IX Item "stack = bytes (except for FORK model)" -+thread stack size -+.IP "\fBTIMEOUTbusy\fR = seconds" 4 -+.IX Item "TIMEOUTbusy = seconds" -+time to wait for expected data -+.IP "\fBTIMEOUTclose\fR = seconds" 4 -+.IX Item "TIMEOUTclose = seconds" -+time to wait for close_notify (set to 0 for buggy \s-1MSIE\s0) -+.IP "\fBTIMEOUTconnect\fR = seconds" 4 -+.IX Item "TIMEOUTconnect = seconds" -+time to wait to connect a remote host -+.IP "\fBTIMEOUTidle\fR = seconds" 4 -+.IX Item "TIMEOUTidle = seconds" -+time to keep an idle connection -+.IP "\fBtransparent\fR = yes | no (Unix only)" 4 -+.IX Item "transparent = yes | no (Unix only)" -+transparent proxy mode -+.Sp -+Re-write address to appear as if wrapped daemon is connecting -+from the \s-1SSL\s0 client machine instead of the machine running \fBstunnel\fR. -+.Sp -+This option is currently available in: -+.Sp -+.Vb 3 -+\& remote mode (I option) on Linux >=2.6.28 -+\& remote mode (I option) 2.2.x -+\& local mode (I option) -+.Ve -+.Sp -+\&\fBRemote mode\fR (either 2.2.x and >=2.6.28) requires stunnel to be executed as -+root. \fBsetuid\fR option will also break this functionality. -+.Sp -+\&\fBLinux >=2.6.28\fR requires the following setup for iptables and routing -+(possibly in /etc/rc.local or equivalent file): -+.Sp -+.Vb 6 -+\& iptables \-t mangle \-N DIVERT -+\& iptables \-t mangle \-A PREROUTING \-p tcp \-m socket \-j DIVERT -+\& iptables \-t mangle \-A DIVERT \-j MARK \-\-set\-mark 1 -+\& iptables \-t mangle \-A DIVERT \-j ACCEPT -+\& ip rule add fwmark 1 lookup 100 -+\& ip route add local 0.0.0.0/0 dev lo table 100 -+.Ve -+.Sp -+\&\fBLinux 2.2.x\fR requires kernel to be compiled with \fItransparent proxy\fR option. -+Connected service must be installed on a separate host. -+Routing towards the clients has to go through the stunnel box. -+.Sp -+\&\fBLocal mode\fR works by LD_PRELOADing env.so shared library. -+.IP "\fBverify\fR = level" 4 -+.IX Item "verify = level" -+verify peer certificate -+.Sp -+.Vb 4 -+\& level 1 \- verify peer certificate if present -+\& level 2 \- verify peer certificate -+\& level 3 \- verify peer with locally installed certificate -+\& default \- no verify -+.Ve -+.Sp -+It is important to understand, that this option was solely designed for access -+control and not for authorization. Specifically for level 2 every non-revoked -+certificate is accepted regardless of its Common Name. For this reason a -+dedicated \s-1CA\s0 should be used with level 2, and not a generic \s-1CA\s0 commonly used -+for webservers. Level 3 is preferred for point-to-point connections. -+.SH "RETURN VALUE" -+.IX Header "RETURN VALUE" -+\&\fBstunnel\fR returns zero on success, non-zero on error. -+.SH "EXAMPLES" -+.IX Header "EXAMPLES" -+In order to provide \s-1SSL\s0 encapsulation to your local \fIimapd\fR service, use -+.PP -+.Vb 4 -+\& [imapd] -+\& accept = 993 -+\& exec = /usr/sbin/imapd -+\& execargs = imapd -+.Ve -+.PP -+If you want to provide tunneling to your \fIpppd\fR daemon on port 2020, -+use something like -+.PP -+.Vb 5 -+\& [vpn] -+\& accept = 2020 -+\& exec = /usr/sbin/pppd -+\& execargs = pppd local -+\& pty = yes -+.Ve -+.PP -+If you want to use \fBstunnel\fR in \fIinetd\fR mode to launch your imapd -+process, you'd use this \fIstunnel.conf\fR. -+Note there must be no \fI[service_name]\fR section. -+.PP -+.Vb 2 -+\& exec = /usr/sbin/imapd -+\& execargs = imapd -+.Ve -+.PP -+Here is an example of advanced engine configuration to read private key from an -+OpenSC engine -+.PP -+.Vb 7 -+\& engine=dynamic -+\& engineCtrl=SO_PATH:/usr/lib/opensc/engine_pkcs11.so -+\& engineCtrl=ID:pkcs11 -+\& engineCtrl=LIST_ADD:1 -+\& engineCtrl=LOAD -+\& engineCtrl=MODULE_PATH:/usr/lib/pkcs11/opensc\-pkcs11.so -+\& engineCtrl=INIT -+\& -+\& [service] -+\& engineNum=1 -+\& key=id_45 -+.Ve -+.SH "FILES" -+.IX Header "FILES" -+.IP "\fIstunnel.conf\fR" 4 -+.IX Item "stunnel.conf" -+\&\fBstunnel\fR configuration file -+.IP "\fIstunnel.pem\fR" 4 -+.IX Item "stunnel.pem" -+\&\fBstunnel\fR certificate and private key -+.SH "BUGS" -+.IX Header "BUGS" -+Option \fIexecargs\fR does not support quoting. -+.SH "RESTRICTIONS" -+.IX Header "RESTRICTIONS" -+\&\fBstunnel\fR cannot be used for the \s-1FTP\s0 daemon because of the nature -+of the \s-1FTP\s0 protocol which utilizes multiple ports for data transfers. -+There are available \s-1SSL\s0 enabled versions of \s-1FTP\s0 and telnet daemons, however. -+.SH "NOTES" -+.IX Header "NOTES" -+.SS "\s-1INETD\s0 \s-1MODE\s0" -+.IX Subsection "INETD MODE" -+The most common use of \fBstunnel\fR is to listen on a network -+port and establish communication with either a new port -+via the connect option, or a new program via the \fIexec\fR option. -+However there is a special case when you wish to have -+some other program accept incoming connections and -+launch \fBstunnel\fR, for example with \fIinetd\fR, \fIxinetd\fR, -+or \fItcpserver\fR. -+.PP -+For example, if you have the following line in \fIinetd.conf\fR: -+.PP -+.Vb 1 -+\& imaps stream tcp nowait root /usr/bin/stunnel stunnel /etc/stunnel/imaps.conf -+.Ve -+.PP -+In these cases, the \fIinetd\fR\-style program is responsible -+for binding a network socket (\fIimaps\fR above) and handing -+it to \fBstunnel\fR when a connection is received. -+Thus you do not want \fBstunnel\fR to have any \fIaccept\fR option. -+All the \fIService Level Options\fR should be placed in the -+global options section, and no \fI[service_name]\fR section -+will be present. See the \fI\s-1EXAMPLES\s0\fR section for example -+configurations. -+.SS "\s-1CERTIFICATES\s0" -+.IX Subsection "CERTIFICATES" -+Each \s-1SSL\s0 enabled daemon needs to present a valid X.509 certificate -+to the peer. It also needs a private key to decrypt the incoming -+data. The easiest way to obtain a certificate and a key is to -+generate them with the free \fIOpenSSL\fR package. You can find more -+information on certificates generation on pages listed below. -+.PP -+The order of contents of the \fI.pem\fR file is important. It should contain the -+unencrypted private key first, then a signed certificate (not certificate -+request). There should be also empty lines after certificate and private key. -+Plaintext certificate information appended on the top of generated certificate -+should be discarded. So the file should look like this: -+.PP -+.Vb 8 -+\& \-\-\-\-\-BEGIN RSA PRIVATE KEY\-\-\-\-\- -+\& [encoded key] -+\& \-\-\-\-\-END RSA PRIVATE KEY\-\-\-\-\- -+\& [empty line] -+\& \-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\- -+\& [encoded certificate] -+\& \-\-\-\-\-END CERTIFICATE\-\-\-\-\- -+\& [empty line] -+.Ve -+.SS "\s-1RANDOMNESS\s0" -+.IX Subsection "RANDOMNESS" -+\&\fBstunnel\fR needs to seed the \s-1PRNG\s0 (pseudo random number generator) in -+order for \s-1SSL\s0 to use good randomness. The following sources are loaded -+in order until sufficient random data has been gathered: -+.IP "\(bu" 4 -+The file specified with the \fIRNDfile\fR flag. -+.IP "\(bu" 4 -+The file specified by the \s-1RANDFILE\s0 environment variable, if set. -+.IP "\(bu" 4 -+The file .rnd in your home directory, if \s-1RANDFILE\s0 not set. -+.IP "\(bu" 4 -+The file specified with '\-\-with\-random' at compile time. -+.IP "\(bu" 4 -+The contents of the screen if running on Windows. -+.IP "\(bu" 4 -+The egd socket specified with the \fI\s-1EGD\s0\fR flag. -+.IP "\(bu" 4 -+The egd socket specified with '\-\-with\-egd\-sock' at compile time. -+.IP "\(bu" 4 -+The /dev/urandom device. -+.PP -+With recent (>=OpenSSL 0.9.5a) version of \s-1SSL\s0 it will stop loading -+random data automatically when sufficient entropy has been gathered. -+With previous versions it will continue to gather from all the above -+sources since no \s-1SSL\s0 function exists to tell when enough data is available. -+.PP -+Note that on Windows machines that do not have console user interaction -+(mouse movements, creating windows, etc) the screen contents are not -+variable enough to be sufficient, and you should provide a random file -+for use with the \fIRNDfile\fR flag. -+.PP -+Note that the file specified with the \fIRNDfile\fR flag should contain -+random data \*(-- that means it should contain different information -+each time \fBstunnel\fR is run. This is handled automatically -+unless the \fIRNDoverwrite\fR flag is used. If you wish to update this file -+manually, the \fIopenssl rand\fR command in recent versions of OpenSSL, -+would be useful. -+.PP -+One important note \*(-- if /dev/urandom is available, OpenSSL has a habit of -+seeding the \s-1PRNG\s0 with it even when checking the random state, so on -+systems with /dev/urandom you're likely to use it even though it's listed -+at the very bottom of the list above. This isn't \fBstunnel's\fR behaviour, it's -+OpenSSLs. -+.SH "SEE ALSO" -+.IX Header "SEE ALSO" -+.IP "\fItcpd\fR\|(8)" 4 -+.IX Item "tcpd" -+access control facility for internet services -+.IP "\fIinetd\fR\|(8)" 4 -+.IX Item "inetd" -+internet 'super\-server' -+.IP "\fIhttp://stunnel.mirt.net/\fR" 4 -+.IX Item "http://stunnel.mirt.net/" -+\&\fBstunnel\fR homepage -+.IP "\fIhttp://www.stunnel.org/\fR" 4 -+.IX Item "http://www.stunnel.org/" -+\&\fBstunnel\fR Frequently Asked Questions -+.IP "\fIhttp://www.openssl.org/\fR" 4 -+.IX Item "http://www.openssl.org/" -+OpenSSL project website -+.SH "AUTHOR" -+.IX Header "AUTHOR" -+.IP "Michal Trojnara" 4 -+.IX Item "Michal Trojnara" -+<\fIMichal.Trojnara@mirt.net\fR> --- a/doc/stunnel.fr.8 +++ b/doc/stunnel.fr.8 @@ -445,6 +445,10 @@ Cette option permet de relier une adress @@ -759,7 +27,7 @@ Alloue un pseudo-terminal pour l'option «\ exec\ » --- a/src/client.c +++ b/src/client.c -@@ -90,6 +90,12 @@ CLI *alloc_client_session(LOCAL_OPTIONS +@@ -86,6 +86,12 @@ CLI *alloc_client_session(SERVICE_OPTION return NULL; } c->opt=opt; @@ -772,7 +40,7 @@ c->local_rfd.fd=rfd; c->local_wfd.fd=wfd; return c; -@@ -382,6 +388,29 @@ static void init_ssl(CLI *c) { +@@ -376,6 +382,29 @@ static void init_ssl(CLI *c) { } } @@ -802,7 +70,7 @@ /****************************** some defines for transfer() */ /* is socket/SSL open for read/write? */ #define sock_rd (c->sock_rfd->rd) -@@ -416,13 +445,16 @@ static void transfer(CLI *c) { +@@ -410,13 +439,16 @@ static void transfer(CLI *c) { check_SSL_pending=0; SSL_read_wants_read= @@ -821,7 +89,7 @@ s_poll_add(&c->fds, c->sock_rfd->fd, 1, 0); if(SSL_read_wants_read || SSL_write_wants_read || -@@ -521,7 +553,8 @@ static void transfer(CLI *c) { +@@ -515,7 +547,8 @@ static void transfer(CLI *c) { break; default: memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num); @@ -831,7 +99,7 @@ check_SSL_pending=1; /* check for data buffered by SSL */ c->ssl_ptr-=num; c->sock_bytes+=num; -@@ -581,7 +614,8 @@ static void transfer(CLI *c) { +@@ -577,7 +610,8 @@ static void transfer(CLI *c) { /****************************** read from socket */ if(sock_rd && sock_can_rd) { num=readsocket(c->sock_rfd->fd, @@ -841,7 +109,7 @@ switch(num) { case -1: parse_socket_error(c, "readsocket"); -@@ -601,10 +635,73 @@ static void transfer(CLI *c) { +@@ -597,10 +631,73 @@ static void transfer(CLI *c) { (SSL_read_wants_write && ssl_can_wr) || (check_SSL_pending && SSL_pending(c->ssl))) { SSL_read_wants_write=0; @@ -916,1051 +184,6 @@ watchdog=0; /* reset watchdog */ break; case SSL_ERROR_WANT_WRITE: ---- /dev/null -+++ b/src/client.c.orig -@@ -0,0 +1,1042 @@ -+/* -+ * stunnel Universal SSL tunnel -+ * Copyright (C) 1998-2009 Michal Trojnara -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ * See the GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, see . -+ * -+ * Linking stunnel statically or dynamically with other modules is making -+ * a combined work based on stunnel. Thus, the terms and conditions of -+ * the GNU General Public License cover the whole combination. -+ * -+ * In addition, as a special exception, the copyright holder of stunnel -+ * gives you permission to combine stunnel with free software programs or -+ * libraries that are released under the GNU LGPL and with code included -+ * in the standard release of OpenSSL under the OpenSSL License (or -+ * modified versions of such code, with unchanged license). You may copy -+ * and distribute such a system following the terms of the GNU GPL for -+ * stunnel and the licenses of the other code concerned. -+ * -+ * Note that people who make modified versions of stunnel are not obligated -+ * to grant this special exception for their modified versions; it is their -+ * choice whether to do so. The GNU General Public License gives permission -+ * to release a modified version without this exception; this exception -+ * also makes it possible to release a modified version which carries -+ * forward this exception. -+ */ -+ -+/* Undefine if you have problems with make_sockets() */ -+#define INET_SOCKET_PAIR -+ -+#include "common.h" -+#include "prototypes.h" -+ -+#ifndef SHUT_RD -+#define SHUT_RD 0 -+#endif -+#ifndef SHUT_WR -+#define SHUT_WR 1 -+#endif -+#ifndef SHUT_RDWR -+#define SHUT_RDWR 2 -+#endif -+ -+#if SSLEAY_VERSION_NUMBER >= 0x0922 -+static char *sid_ctx="stunnel SID"; -+ /* const allowed here */ -+#endif -+ -+static void do_client(CLI *); -+static void run_client(CLI *); -+static void init_local(CLI *); -+static void init_remote(CLI *); -+static void init_ssl(CLI *); -+static void transfer(CLI *); -+static void parse_socket_error(CLI *, const char *); -+ -+static void print_cipher(CLI *); -+static void auth_user(CLI *); -+static int connect_local(CLI *); -+#ifndef USE_WIN32 -+static void make_sockets(CLI *, int [2]); -+#endif -+static int connect_remote(CLI *); -+static void local_bind(CLI *c); -+static void print_bound_address(CLI *); -+static void reset(int, char *); -+ -+int max_clients; -+#ifndef USE_WIN32 -+int max_fds; -+#endif -+ -+/* Allocate local data structure for the new thread */ -+CLI *alloc_client_session(LOCAL_OPTIONS *opt, int rfd, int wfd) { -+ CLI *c; -+ -+ c=calloc(1, sizeof(CLI)); -+ if(!c) { -+ s_log(LOG_ERR, "Memory allocation failed"); -+ return NULL; -+ } -+ c->opt=opt; -+ c->local_rfd.fd=rfd; -+ c->local_wfd.fd=wfd; -+ return c; -+} -+ -+void *client(void *arg) { -+ CLI *c=arg; -+ -+#ifdef DEBUG_STACK_SIZE -+ stack_info(1); /* initialize */ -+#endif -+ s_log(LOG_DEBUG, "%s started", c->opt->servname); -+#ifndef USE_WIN32 -+ if(c->opt->option.remote && c->opt->option.program) { -+ /* connect and exec options specified together */ -+ /* -> spawn a local program instead of stdio */ -+ while((c->local_rfd.fd=c->local_wfd.fd=connect_local(c))>=0) { -+ run_client(c); -+ if(!c->opt->option.retry) -+ break; -+ sleep(1); /* FIXME: not a good idea in ucontext threading */ -+ } -+ } else -+#endif -+ { -+ if(alloc_fd(c->local_rfd.fd)) -+ return NULL; -+ if(c->local_wfd.fd!=c->local_rfd.fd) -+ if(alloc_fd(c->local_wfd.fd)) -+ return NULL; -+ run_client(c); -+ } -+ free(c); -+#ifdef DEBUG_STACK_SIZE -+ stack_info(0); /* display computed value */ -+#endif -+#if defined(USE_WIN32) && !defined(_WIN32_WCE) -+ _endthread(); -+#endif -+#ifdef USE_UCONTEXT -+ s_log(LOG_DEBUG, "Context %ld closed", ready_head->id); -+ s_poll_wait(NULL, 0, 0); /* wait on poll() */ -+ s_log(LOG_ERR, "INTERNAL ERROR: failed to drop context"); -+#endif -+ return NULL; -+} -+ -+static void run_client(CLI *c) { -+ int error; -+ -+ c->remote_fd.fd=-1; -+ c->fd=-1; -+ c->ssl=NULL; -+ c->sock_bytes=c->ssl_bytes=0; -+ -+ error=setjmp(c->err); -+ if(!error) -+ do_client(c); -+ -+ s_log(LOG_NOTICE, -+ "Connection %s: %d bytes sent to SSL, %d bytes sent to socket", -+ error==1 ? "reset" : "closed", c->ssl_bytes, c->sock_bytes); -+ -+ /* Cleanup IDENT socket */ -+ if(c->fd>=0) -+ closesocket(c->fd); -+ -+ /* Cleanup SSL */ -+ if(c->ssl) { /* SSL initialized */ -+ SSL_set_shutdown(c->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); -+ SSL_free(c->ssl); -+ ERR_remove_state(0); -+ } -+ -+ /* Cleanup remote socket */ -+ if(c->remote_fd.fd>=0) { /* Remote socket initialized */ -+ if(error==1 && c->remote_fd.is_socket) -+ reset(c->remote_fd.fd, "linger (remote)"); -+ closesocket(c->remote_fd.fd); -+ } -+ -+ /* Cleanup local socket */ -+ if(c->local_rfd.fd>=0) { /* Local socket initialized */ -+ if(c->local_rfd.fd==c->local_wfd.fd) { -+ if(error==1 && c->local_rfd.is_socket) -+ reset(c->local_rfd.fd, "linger (local)"); -+ closesocket(c->local_rfd.fd); -+ } else { /* STDIO */ -+ if(error==1 && c->local_rfd.is_socket) -+ reset(c->local_rfd.fd, "linger (local_rfd)"); -+ if(error==1 && c->local_wfd.is_socket) -+ reset(c->local_wfd.fd, "linger (local_wfd)"); -+ } -+ } -+#ifdef USE_FORK -+ if(!c->opt->option.remote) /* 'exec' specified */ -+ child_status(); /* null SIGCHLD handler was used */ -+#else -+ enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */ -+ s_log(LOG_DEBUG, "%s finished (%d left)", c->opt->servname, -+ --num_clients); -+ leave_critical_section(CRIT_CLIENTS); -+#endif -+} -+ -+static void do_client(CLI *c) { -+ init_local(c); -+ if(!c->opt->option.client && !c->opt->protocol) { -+ /* Server mode and no protocol negotiation needed */ -+ init_ssl(c); -+ init_remote(c); -+ } else { -+ init_remote(c); -+ negotiate(c); -+ init_ssl(c); -+ } -+ transfer(c); -+} -+ -+static void init_local(CLI *c) { -+ SOCKADDR_UNION addr; -+ socklen_t addrlen; -+ -+ addrlen=sizeof addr; -+ if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)<0) { -+ strcpy(c->accepted_address, "NOT A SOCKET"); -+ c->local_rfd.is_socket=0; -+ c->local_wfd.is_socket=0; /* TODO: It's not always true */ -+#ifdef USE_WIN32 -+ if(get_last_socket_error()!=ENOTSOCK) { -+#else -+ if(c->opt->option.transparent || get_last_socket_error()!=ENOTSOCK) { -+#endif -+ sockerror("getpeerbyname"); -+ longjmp(c->err, 1); -+ } -+ /* Ignore ENOTSOCK error so 'local' doesn't have to be a socket */ -+ } else { /* success */ -+ /* copy addr to c->peer_addr */ -+ memcpy(&c->peer_addr.addr[0], &addr, sizeof addr); -+ c->peer_addr.num=1; -+ s_ntop(c->accepted_address, &c->peer_addr.addr[0]); -+ c->local_rfd.is_socket=1; -+ c->local_wfd.is_socket=1; /* TODO: It's not always true */ -+ /* It's a socket: lets setup options */ -+ if(set_socket_options(c->local_rfd.fd, 1)<0) -+ longjmp(c->err, 1); -+#ifdef USE_LIBWRAP -+ auth_libwrap(c); -+#endif /* USE_LIBWRAP */ -+ auth_user(c); -+ s_log(LOG_NOTICE, "%s accepted connection from %s", -+ c->opt->servname, c->accepted_address); -+ } -+} -+ -+static void init_remote(CLI *c) { -+ /* create connection to host/service */ -+ if(c->opt->source_addr.num) -+ memcpy(&c->bind_addr, &c->opt->source_addr, sizeof(SOCKADDR_LIST)); -+#ifndef USE_WIN32 -+ else if(c->opt->option.transparent) -+ memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST)); -+#endif -+ else { -+ c->bind_addr.num=0; /* don't bind connecting socket */ -+ } -+ -+ /* setup c->remote_fd, now */ -+ if(c->opt->option.remote) { -+ c->remote_fd.fd=connect_remote(c); -+ } else /* NOT in remote mode */ -+ c->remote_fd.fd=connect_local(c); -+ c->remote_fd.is_socket=1; /* Always! */ -+#ifndef USE_WIN32 -+ if(c->remote_fd.fd>=max_fds) { -+ s_log(LOG_ERR, "Remote file descriptor out of range (%d>=%d)", -+ c->remote_fd.fd, max_fds); -+ longjmp(c->err, 1); -+ } -+#endif -+ s_log(LOG_DEBUG, "Remote FD=%d initialized", c->remote_fd.fd); -+ if(set_socket_options(c->remote_fd.fd, 2)<0) -+ longjmp(c->err, 1); -+} -+ -+static void init_ssl(CLI *c) { -+ int i, err; -+ SSL_SESSION *old_session; -+ -+ if(!(c->ssl=SSL_new(c->opt->ctx))) { -+ sslerror("SSL_new"); -+ longjmp(c->err, 1); -+ } -+ SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */ -+#if SSLEAY_VERSION_NUMBER >= 0x0922 -+ SSL_set_session_id_context(c->ssl, (unsigned char *)sid_ctx, -+ strlen(sid_ctx)); -+#endif -+ if(c->opt->option.client) { -+ if(c->opt->session) { -+ enter_critical_section(CRIT_SESSION); -+ SSL_set_session(c->ssl, c->opt->session); -+ leave_critical_section(CRIT_SESSION); -+ } -+ SSL_set_fd(c->ssl, c->remote_fd.fd); -+ SSL_set_connect_state(c->ssl); -+ } else { -+ if(c->local_rfd.fd==c->local_wfd.fd) -+ SSL_set_fd(c->ssl, c->local_rfd.fd); -+ else { -+ /* Does it make sence to have SSL on STDIN/STDOUT? */ -+ SSL_set_rfd(c->ssl, c->local_rfd.fd); -+ SSL_set_wfd(c->ssl, c->local_wfd.fd); -+ } -+ SSL_set_accept_state(c->ssl); -+ } -+ -+ /* Setup some values for transfer() function */ -+ if(c->opt->option.client) { -+ c->sock_rfd=&(c->local_rfd); -+ c->sock_wfd=&(c->local_wfd); -+ c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); -+ } else { -+ c->sock_rfd=c->sock_wfd=&(c->remote_fd); -+ c->ssl_rfd=&(c->local_rfd); -+ c->ssl_wfd=&(c->local_wfd); -+ } -+ -+ while(1) { -+ /* crude workaround for random MT-safety problems in OpenSSL */ -+ /* performance penalty is not huge, as it's a non-blocking code */ -+ enter_critical_section(CRIT_SSL); -+ if(c->opt->option.client) -+ i=SSL_connect(c->ssl); -+ else -+ i=SSL_accept(c->ssl); -+ leave_critical_section(CRIT_SSL); -+ err=SSL_get_error(c->ssl, i); -+ if(err==SSL_ERROR_NONE) -+ break; /* ok -> done */ -+ if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) { -+ s_poll_init(&c->fds); -+ s_poll_add(&c->fds, c->ssl_rfd->fd, -+ err==SSL_ERROR_WANT_READ, -+ err==SSL_ERROR_WANT_WRITE); -+ switch(s_poll_wait(&c->fds, c->opt->timeout_busy, 0)) { -+ case -1: -+ sockerror("init_ssl: s_poll_wait"); -+ longjmp(c->err, 1); -+ case 0: -+ s_log(LOG_INFO, "init_ssl: s_poll_wait timeout"); -+ longjmp(c->err, 1); -+ case 1: -+ break; /* OK */ -+ default: -+ s_log(LOG_ERR, "init_ssl: s_poll_wait unknown result"); -+ longjmp(c->err, 1); -+ } -+ continue; /* ok -> retry */ -+ } -+ if(err==SSL_ERROR_SYSCALL) { -+ switch(get_last_socket_error()) { -+ case EINTR: -+ case EAGAIN: -+ continue; -+ } -+ } -+ if(c->opt->option.client) -+ sslerror("SSL_connect"); -+ else -+ sslerror("SSL_accept"); -+ longjmp(c->err, 1); -+ } -+ if(SSL_session_reused(c->ssl)) { -+ s_log(LOG_INFO, "SSL %s: previous session reused", -+ c->opt->option.client ? "connected" : "accepted"); -+ } else { /* a new session was negotiated */ -+ if(c->opt->option.client) { -+ s_log(LOG_INFO, "SSL connected: new session negotiated"); -+ enter_critical_section(CRIT_SESSION); -+ old_session=c->opt->session; -+ c->opt->session=SSL_get1_session(c->ssl); /* store it */ -+ if(old_session) -+ SSL_SESSION_free(old_session); /* release the old one */ -+ leave_critical_section(CRIT_SESSION); -+ } else -+ s_log(LOG_INFO, "SSL accepted: new session negotiated"); -+ print_cipher(c); -+ } -+} -+ -+/****************************** some defines for transfer() */ -+/* is socket/SSL open for read/write? */ -+#define sock_rd (c->sock_rfd->rd) -+#define sock_wr (c->sock_wfd->wr) -+#define ssl_rd (c->ssl_rfd->rd) -+#define ssl_wr (c->ssl_wfd->wr) -+/* NOTE: above defines are related to the logical data stream, -+ * not the underlying file descriptors */ -+ -+/* is socket/SSL ready for read/write? */ -+#define sock_can_rd (s_poll_canread(&c->fds, c->sock_rfd->fd)) -+#define sock_can_wr (s_poll_canwrite(&c->fds, c->sock_wfd->fd)) -+#define ssl_can_rd (s_poll_canread(&c->fds, c->ssl_rfd->fd)) -+#define ssl_can_wr (s_poll_canwrite(&c->fds, c->ssl_wfd->fd)) -+ -+/****************************** transfer data */ -+static void transfer(CLI *c) { -+ int watchdog=0; /* a counter to detect an infinite loop */ -+ int error; -+ socklen_t optlen; -+ int num, err, check_SSL_pending; -+ int SSL_shutdown_wants_read=0, SSL_shutdown_wants_write=0; -+ int SSL_write_wants_read=0, SSL_write_wants_write=0; -+ int SSL_read_wants_read=0, SSL_read_wants_write=0; -+ -+ c->sock_ptr=c->ssl_ptr=0; -+ sock_rd=sock_wr=ssl_rd=ssl_wr=1; -+ -+ do { /* main loop */ -+ /* set flag to try and read any buffered SSL data -+ * if we made room in the buffer by writing to the socket */ -+ check_SSL_pending=0; -+ -+ SSL_read_wants_read= -+ ssl_rd && c->ssl_ptrsock_ptr && !SSL_write_wants_read; -+ -+ /****************************** setup c->fds structure */ -+ s_poll_init(&c->fds); /* initialize the structure */ -+ if(sock_rd && c->sock_ptrfds, c->sock_rfd->fd, 1, 0); -+ if(SSL_read_wants_read || -+ SSL_write_wants_read || -+ SSL_shutdown_wants_read) -+ s_poll_add(&c->fds, c->ssl_rfd->fd, 1, 0); -+ if(sock_wr && c->ssl_ptr) -+ s_poll_add(&c->fds, c->sock_wfd->fd, 0, 1); -+ if(SSL_read_wants_write || -+ SSL_write_wants_write || -+ SSL_shutdown_wants_write) -+ s_poll_add(&c->fds, c->ssl_wfd->fd, 0, 1); -+ -+ /****************************** wait for an event */ -+ err=s_poll_wait(&c->fds, (sock_rd && ssl_rd) /* both peers open */ || -+ c->ssl_ptr /* data buffered to write to socket */ || -+ c->sock_ptr /* data buffered to write to SSL */ ? -+ c->opt->timeout_idle : c->opt->timeout_close, 0); -+ switch(err) { -+ case -1: -+ sockerror("transfer: s_poll_wait"); -+ longjmp(c->err, 1); -+ case 0: /* timeout */ -+ if((sock_rd && ssl_rd) || c->ssl_ptr || c->sock_ptr) { -+ s_log(LOG_INFO, "s_poll_wait timeout: connection reset"); -+ longjmp(c->err, 1); -+ } else { /* already closing connection */ -+ s_log(LOG_INFO, "s_poll_wait timeout: connection close"); -+ return; /* OK */ -+ } -+ } -+ if(!(sock_can_rd || sock_can_wr || ssl_can_rd || ssl_can_wr)) { -+ s_log(LOG_ERR, "INTERNAL ERROR: " -+ "s_poll_wait returned %d, but no descriptor is ready", err); -+ longjmp(c->err, 1); -+ } -+ if(!sock_rd && sock_can_rd) { -+ optlen=sizeof error; -+ if(getsockopt(c->sock_rfd->fd, SOL_SOCKET, SO_ERROR, -+ (void *)&error, &optlen)) -+ error=get_last_socket_error(); /* failed -> ask why */ -+ if(error) { /* really an error? */ -+ s_log(LOG_ERR, "Closed socket ready to read: %s (%d)", -+ my_strerror(error), error); -+ longjmp(c->err, 1); -+ } -+ if(c->ssl_ptr) { /* anything left to write */ -+ s_log(LOG_ERR, "Closed socket ready to read - reset"); -+ longjmp(c->err, 1); -+ } -+ s_log(LOG_INFO, "Closed socket ready to read - write close"); -+ sock_wr=0; /* no further write allowed */ -+ shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */ -+ } -+ -+ /****************************** send SSL close_notify message */ -+ if(SSL_shutdown_wants_read || SSL_shutdown_wants_write) { -+ SSL_shutdown_wants_read=SSL_shutdown_wants_write=0; -+ num=SSL_shutdown(c->ssl); /* send close_notify */ -+ if(num<0) /* -1 - not completed */ -+ err=SSL_get_error(c->ssl, num); -+ else /* 0 or 1 - success */ -+ err=SSL_ERROR_NONE; -+ switch(err) { -+ case SSL_ERROR_NONE: /* the shutdown was successfully completed */ -+ s_log(LOG_INFO, "SSL_shutdown successfully sent close_notify"); -+ break; -+ case SSL_ERROR_WANT_WRITE: -+ s_log(LOG_DEBUG, "SSL_shutdown returned WANT_WRITE: retrying"); -+ SSL_shutdown_wants_write=1; -+ break; -+ case SSL_ERROR_WANT_READ: -+ s_log(LOG_DEBUG, "SSL_shutdown returned WANT_READ: retrying"); -+ SSL_shutdown_wants_read=1; -+ break; -+ case SSL_ERROR_SYSCALL: /* socket error */ -+ parse_socket_error(c, "SSL_shutdown"); -+ break; -+ case SSL_ERROR_SSL: /* SSL error */ -+ sslerror("SSL_shutdown"); -+ longjmp(c->err, 1); -+ default: -+ s_log(LOG_ERR, "SSL_shutdown/SSL_get_error returned %d", err); -+ longjmp(c->err, 1); -+ } -+ } -+ -+ /****************************** write to socket */ -+ if(sock_wr && sock_can_wr) { -+ num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr); -+ switch(num) { -+ case -1: /* error */ -+ parse_socket_error(c, "writesocket"); -+ break; -+ case 0: -+ s_log(LOG_DEBUG, "No data written to the socket: retrying"); -+ break; -+ default: -+ memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num); -+ if(c->ssl_ptr==BUFFSIZE) /* buffer was previously full */ -+ check_SSL_pending=1; /* check for data buffered by SSL */ -+ c->ssl_ptr-=num; -+ c->sock_bytes+=num; -+ watchdog=0; /* reset watchdog */ -+ } -+ } -+ -+ /****************************** write to SSL */ -+ if((SSL_write_wants_read && ssl_can_rd) || -+ (SSL_write_wants_write && ssl_can_wr)) { -+ SSL_write_wants_read=0; -+ num=SSL_write(c->ssl, c->sock_buff, c->sock_ptr); -+ switch(err=SSL_get_error(c->ssl, num)) { -+ case SSL_ERROR_NONE: -+ memmove(c->sock_buff, c->sock_buff+num, c->sock_ptr-num); -+ c->sock_ptr-=num; -+ c->ssl_bytes+=num; -+ watchdog=0; /* reset watchdog */ -+ break; -+ case SSL_ERROR_WANT_WRITE: /* nothing unexpected */ -+ break; -+ case SSL_ERROR_WANT_READ: -+ s_log(LOG_DEBUG, "SSL_write returned WANT_READ: retrying"); -+ SSL_write_wants_read=1; -+ break; -+ case SSL_ERROR_WANT_X509_LOOKUP: -+ s_log(LOG_DEBUG, -+ "SSL_write returned WANT_X509_LOOKUP: retrying"); -+ break; -+ case SSL_ERROR_SYSCALL: /* socket error */ -+ if(!num) { /* EOF */ -+ if(c->sock_ptr) { -+ s_log(LOG_ERR, -+ "SSL socket closed on SSL_write " -+ "with %d byte(s) in buffer", -+ c->sock_ptr); -+ longjmp(c->err, 1); /* reset the socket */ -+ } -+ s_log(LOG_DEBUG, "SSL socket closed on SSL_write"); -+ ssl_rd=ssl_wr=0; /* buggy or SSLv2 peer: no close_notify */ -+ } else -+ parse_socket_error(c, "SSL_write"); -+ break; -+ case SSL_ERROR_ZERO_RETURN: /* close_notify received */ -+ s_log(LOG_DEBUG, "SSL closed on SSL_write"); -+ ssl_rd=0; -+ break; -+ case SSL_ERROR_SSL: -+ sslerror("SSL_write"); -+ longjmp(c->err, 1); -+ default: -+ s_log(LOG_ERR, "SSL_write/SSL_get_error returned %d", err); -+ longjmp(c->err, 1); -+ } -+ } -+ -+ /****************************** read from socket */ -+ if(sock_rd && sock_can_rd) { -+ num=readsocket(c->sock_rfd->fd, -+ c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr); -+ switch(num) { -+ case -1: -+ parse_socket_error(c, "readsocket"); -+ break; -+ case 0: /* close */ -+ s_log(LOG_DEBUG, "Socket closed on read"); -+ sock_rd=0; -+ break; -+ default: -+ c->sock_ptr+=num; -+ watchdog=0; /* reset watchdog */ -+ } -+ } -+ -+ /****************************** read from SSL */ -+ if((SSL_read_wants_read && ssl_can_rd) || -+ (SSL_read_wants_write && ssl_can_wr) || -+ (check_SSL_pending && SSL_pending(c->ssl))) { -+ SSL_read_wants_write=0; -+ num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr); -+ switch(err=SSL_get_error(c->ssl, num)) { -+ case SSL_ERROR_NONE: -+ c->ssl_ptr+=num; -+ watchdog=0; /* reset watchdog */ -+ break; -+ case SSL_ERROR_WANT_WRITE: -+ s_log(LOG_DEBUG, "SSL_read returned WANT_WRITE: retrying"); -+ SSL_read_wants_write=1; -+ break; -+ case SSL_ERROR_WANT_READ: /* nothing unexpected */ -+ break; -+ case SSL_ERROR_WANT_X509_LOOKUP: -+ s_log(LOG_DEBUG, -+ "SSL_read returned WANT_X509_LOOKUP: retrying"); -+ break; -+ case SSL_ERROR_SYSCALL: -+ if(!num) { /* EOF */ -+ if(c->sock_ptr) { -+ s_log(LOG_ERR, -+ "SSL socket closed on SSL_read " -+ "with %d byte(s) in buffer", -+ c->sock_ptr); -+ longjmp(c->err, 1); /* reset the socket */ -+ } -+ s_log(LOG_DEBUG, "SSL socket closed on SSL_read"); -+ ssl_rd=ssl_wr=0; /* buggy or SSLv2 peer: no close_notify */ -+ } else -+ parse_socket_error(c, "SSL_read"); -+ break; -+ case SSL_ERROR_ZERO_RETURN: /* close_notify received */ -+ s_log(LOG_DEBUG, "SSL closed on SSL_read"); -+ ssl_rd=0; -+ break; -+ case SSL_ERROR_SSL: -+ sslerror("SSL_read"); -+ longjmp(c->err, 1); -+ default: -+ s_log(LOG_ERR, "SSL_read/SSL_get_error returned %d", err); -+ longjmp(c->err, 1); -+ } -+ } -+ -+ /****************************** check write shutdown conditions */ -+ if(sock_wr && !ssl_rd && !c->ssl_ptr) { -+ s_log(LOG_DEBUG, "Socket write shutdown"); -+ sock_wr=0; /* no further write allowed */ -+ shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */ -+ } -+ if(ssl_wr && !sock_rd && !c->sock_ptr) { -+ s_log(LOG_DEBUG, "SSL write shutdown"); -+ ssl_wr=0; /* no further write allowed */ -+ if(strcmp(SSL_get_version(c->ssl), "SSLv2")) { /* SSLv3, TLSv1 */ -+ SSL_shutdown_wants_write=1; /* initiate close_notify */ -+ } else { /* no alerts in SSLv2 including close_notify alert */ -+ shutdown(c->sock_rfd->fd, SHUT_RD); /* notify the kernel */ -+ shutdown(c->sock_wfd->fd, SHUT_WR); /* send TCP FIN */ -+ SSL_set_shutdown(c->ssl, /* notify the OpenSSL library */ -+ SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); -+ ssl_rd=0; /* no further read allowed */ -+ } -+ } -+ -+ /****************************** check watchdog */ -+ if(++watchdog>100) { /* loop executes without transferring any data */ -+ s_log(LOG_ERR, -+ "transfer() loop executes not transferring any data"); -+ s_log(LOG_ERR, -+ "please report the problem to Michal.Trojnara@mirt.net"); -+ s_log(LOG_ERR, "socket open: rd=%s wr=%s, ssl open: rd=%s wr=%s", -+ sock_rd ? "yes" : "no", sock_wr ? "yes" : "no", -+ ssl_rd ? "yes" : "no", ssl_wr ? "yes" : "no"); -+ s_log(LOG_ERR, "socket ready: rd=%s wr=%s, ssl ready: rd=%s wr=%s", -+ sock_can_rd ? "yes" : "no", sock_can_wr ? "yes" : "no", -+ ssl_can_rd ? "yes" : "no", ssl_can_wr ? "yes" : "no"); -+ s_log(LOG_ERR, -+ "wants: SSL_read rd=%s wr=%s, " -+ "SSL_write rd=%s wr=%s, " -+ "SSL_shutdown rd=%s wr=%s", -+ SSL_read_wants_read ? "yes" : "no", -+ SSL_read_wants_write ? "yes" : "no", -+ SSL_write_wants_read ? "yes" : "no", -+ SSL_write_wants_write ? "yes" : "no", -+ SSL_shutdown_wants_read ? "yes" : "no", -+ SSL_shutdown_wants_write ? "yes" : "no"); -+ s_log(LOG_ERR, "socket input buffer: %d byte(s), " -+ "ssl input buffer: %d byte(s)", c->sock_ptr, c->ssl_ptr); -+ s_log(LOG_ERR, "check_SSL_pending=%d", check_SSL_pending); -+ longjmp(c->err, 1); -+ } -+ -+ } while(sock_wr || ssl_wr || -+ SSL_shutdown_wants_read || SSL_shutdown_wants_write); -+} -+ -+static void parse_socket_error(CLI *c, const char *text) { -+ switch(get_last_socket_error()) { -+ case EINTR: -+ s_log(LOG_DEBUG, "%s interrupted by a signal: retrying", text); -+ return; -+ case EWOULDBLOCK: -+ s_log(LOG_NOTICE, "%s would block: retrying", text); -+ sleep(1); /* Microsoft bug KB177346 */ -+ return; -+#if EAGAIN!=EWOULDBLOCK -+ case EAGAIN: -+ s_log(LOG_DEBUG, "%s temporary lack of resources: retrying", text); -+ return; -+#endif -+ default: -+ sockerror(text); -+ longjmp(c->err, 1); -+ } -+} -+ -+static void print_cipher(CLI *c) { /* print negotiated cipher */ -+#if SSLEAY_VERSION_NUMBER <= 0x0800 -+ s_log(LOG_INFO, "%s opened with SSLv%d, cipher %s", -+ c->opt->servname, ssl->session->ssl_version, SSL_get_cipher(c->ssl)); -+#else -+ SSL_CIPHER *cipher; -+ char buf[STRLEN], *i, *j; -+ -+ cipher=(SSL_CIPHER *)SSL_get_current_cipher(c->ssl); -+ SSL_CIPHER_description(cipher, buf, STRLEN); -+ i=j=buf; -+ do { -+ switch(*i) { -+ case ' ': -+ *j++=' '; -+ while(i[1]==' ') -+ ++i; -+ break; -+ case '\n': -+ break; -+ default: -+ *j++=*i; -+ } -+ } while(*i++); -+ s_log(LOG_INFO, "Negotiated ciphers: %s", buf); -+#endif -+} -+ -+static void auth_user(CLI *c) { -+#ifndef _WIN32_WCE -+ struct servent *s_ent; /* structure for getservbyname */ -+#endif -+ SOCKADDR_UNION ident; /* IDENT socket name */ -+ char name[STRLEN]; -+ -+ if(!c->opt->username) -+ return; /* -u option not specified */ -+ if((c->fd= -+ socket(c->peer_addr.addr[0].sa.sa_family, SOCK_STREAM, 0))<0) { -+ sockerror("socket (auth_user)"); -+ longjmp(c->err, 1); -+ } -+ if(alloc_fd(c->fd)) -+ longjmp(c->err, 1); -+ memcpy(&ident, &c->peer_addr.addr[0], sizeof ident); -+#ifndef _WIN32_WCE -+ s_ent=getservbyname("auth", "tcp"); -+ if(s_ent) { -+ ident.in.sin_port=s_ent->s_port; -+ } else -+#endif -+ { -+ s_log(LOG_WARNING, "Unknown service 'auth': using default 113"); -+ ident.in.sin_port=htons(113); -+ } -+ if(connect_blocking(c, &ident, addr_len(ident))) -+ longjmp(c->err, 1); -+ s_log(LOG_DEBUG, "IDENT server connected"); -+ fdprintf(c, c->fd, "%u , %u", -+ ntohs(c->peer_addr.addr[0].in.sin_port), -+ ntohs(c->opt->local_addr.addr[0].in.sin_port)); -+ if(fdscanf(c, c->fd, "%*[^:]: USERID :%*[^:]:%s", name)!=1) { -+ s_log(LOG_ERR, "Incorrect data from IDENT server"); -+ longjmp(c->err, 1); -+ } -+ closesocket(c->fd); -+ c->fd=-1; /* avoid double close on cleanup */ -+ if(strcmp(name, c->opt->username)) { -+ safestring(name); -+ s_log(LOG_WARNING, "Connection from %s REFUSED by IDENT (user %s)", -+ c->accepted_address, name); -+ longjmp(c->err, 1); -+ } -+ s_log(LOG_INFO, "IDENT authentication passed"); -+} -+ -+static int connect_local(CLI *c) { /* spawn local process */ -+#if defined (USE_WIN32) || defined (__vms) -+ s_log(LOG_ERR, "LOCAL MODE NOT SUPPORTED ON WIN32 and OpenVMS PLATFORM"); -+ longjmp(c->err, 1); -+ return -1; /* some C compilers require a return value */ -+#else /* USE_WIN32, __vms */ -+ char env[3][STRLEN], name[STRLEN], *portname; -+ int fd[2], pid; -+ X509 *peer; -+#ifdef HAVE_PTHREAD_SIGMASK -+ sigset_t newmask; -+#endif -+ -+ if (c->opt->option.pty) { -+ char tty[STRLEN]; -+ -+ if(pty_allocate(fd, fd+1, tty, STRLEN)) -+ longjmp(c->err, 1); -+ s_log(LOG_DEBUG, "%s allocated", tty); -+ } else -+ make_sockets(c, fd); -+ pid=fork(); -+ c->pid=(unsigned long)pid; -+ switch(pid) { -+ case -1: /* error */ -+ closesocket(fd[0]); -+ closesocket(fd[1]); -+ ioerror("fork"); -+ longjmp(c->err, 1); -+ case 0: /* child */ -+ closesocket(fd[0]); -+ dup2(fd[1], 0); -+ dup2(fd[1], 1); -+ if(!options.option.foreground) -+ dup2(fd[1], 2); -+ closesocket(fd[1]); -+ safecopy(env[0], "REMOTE_HOST="); -+ safeconcat(env[0], c->accepted_address); -+ portname=strrchr(env[0], ':'); -+ if(portname) /* strip the port name */ -+ *portname='\0'; -+ putenv(env[0]); -+ if(c->opt->option.transparent) { -+ putenv("LD_PRELOAD=" LIBDIR "/libstunnel.so"); -+ /* For Tru64 _RLD_LIST is used instead */ -+ putenv("_RLD_LIST=" LIBDIR "/libstunnel.so:DEFAULT"); -+ } -+ if(c->ssl) { -+ peer=SSL_get_peer_certificate(c->ssl); -+ if(peer) { -+ safecopy(env[1], "SSL_CLIENT_DN="); -+ X509_NAME_oneline(X509_get_subject_name(peer), name, STRLEN); -+ safestring(name); -+ safeconcat(env[1], name); -+ putenv(env[1]); -+ safecopy(env[2], "SSL_CLIENT_I_DN="); -+ X509_NAME_oneline(X509_get_issuer_name(peer), name, STRLEN); -+ safestring(name); -+ safeconcat(env[2], name); -+ putenv(env[2]); -+ X509_free(peer); -+ } -+ } -+#ifdef HAVE_PTHREAD_SIGMASK -+ sigemptyset(&newmask); -+ sigprocmask(SIG_SETMASK, &newmask, NULL); -+#endif -+ execvp(c->opt->execname, c->opt->execargs); -+ ioerror(c->opt->execname); /* execv failed */ -+ _exit(1); -+ default: -+ break; -+ } -+ /* parent */ -+ s_log(LOG_INFO, "Local mode child started (PID=%lu)", c->pid); -+ closesocket(fd[1]); -+#ifdef FD_CLOEXEC -+ fcntl(fd[0], F_SETFD, FD_CLOEXEC); -+#endif -+ return fd[0]; -+#endif /* USE_WIN32,__vms */ -+} -+ -+#ifndef USE_WIN32 -+ -+static void make_sockets(CLI *c, int fd[2]) { /* make a pair of connected sockets */ -+#ifdef INET_SOCKET_PAIR -+ SOCKADDR_UNION addr; -+ socklen_t addrlen; -+ int s; /* temporary socket awaiting for connection */ -+ -+ if((s=socket(AF_INET, SOCK_STREAM, 0))<0) { -+ sockerror("socket#1"); -+ longjmp(c->err, 1); -+ } -+ if((fd[1]=socket(AF_INET, SOCK_STREAM, 0))<0) { -+ sockerror("socket#2"); -+ longjmp(c->err, 1); -+ } -+ addrlen=sizeof addr; -+ memset(&addr, 0, addrlen); -+ addr.in.sin_family=AF_INET; -+ addr.in.sin_addr.s_addr=htonl(INADDR_LOOPBACK); -+ addr.in.sin_port=htons(0); /* dynamic port allocation */ -+ if(bind(s, &addr.sa, addrlen)) -+ log_error(LOG_DEBUG, get_last_socket_error(), "bind#1"); -+ if(bind(fd[1], &addr.sa, addrlen)) -+ log_error(LOG_DEBUG, get_last_socket_error(), "bind#2"); -+ if(listen(s, 5)) { -+ sockerror("listen"); -+ longjmp(c->err, 1); -+ } -+ if(getsockname(s, &addr.sa, &addrlen)) { -+ sockerror("getsockname"); -+ longjmp(c->err, 1); -+ } -+ if(connect(fd[1], &addr.sa, addrlen)) { -+ sockerror("connect"); -+ longjmp(c->err, 1); -+ } -+ if((fd[0]=accept(s, &addr.sa, &addrlen))<0) { -+ sockerror("accept"); -+ longjmp(c->err, 1); -+ } -+ closesocket(s); /* don't care about the result */ -+#else -+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) { -+ sockerror("socketpair"); -+ longjmp(c->err, 1); -+ } -+#endif -+} -+#endif -+ -+static int connect_remote(CLI *c) { /* connect to remote host */ -+ SOCKADDR_UNION addr; -+ SOCKADDR_LIST resolved_list, *address_list; -+ int fd, ind_try, ind_cur; -+ -+ /* setup address_list */ -+ if(c->opt->option.delayed_lookup) { -+ resolved_list.num=0; -+ if(!name2addrlist(&resolved_list, -+ c->opt->remote_address, DEFAULT_LOOPBACK)) { -+ s_log(LOG_ERR, "No host resolved"); -+ longjmp(c->err, 1); -+ } -+ address_list=&resolved_list; -+ } else /* use pre-resolved addresses */ -+ address_list=&c->opt->remote_addr; -+ -+ /* try to connect each host from the list */ -+ for(ind_try=0; ind_trynum; ind_try++) { -+ if(c->opt->failover==FAILOVER_RR) { -+ ind_cur=address_list->cur; -+ /* the race condition here can be safely ignored */ -+ address_list->cur=(ind_cur+1)%address_list->num; -+ } else { /* FAILOVER_PRIO */ -+ ind_cur=ind_try; /* ignore address_list->cur */ -+ } -+ memcpy(&addr, address_list->addr+ind_cur, sizeof addr); -+ -+ if((c->fd=socket(addr.sa.sa_family, SOCK_STREAM, 0))<0) { -+ sockerror("remote socket"); -+ longjmp(c->err, 1); -+ } -+ if(alloc_fd(c->fd)) -+ longjmp(c->err, 1); -+ -+ if(c->bind_addr.num) /* explicit local bind or transparent proxy */ -+ local_bind(c); -+ -+ if(connect_blocking(c, &addr, addr_len(addr))) { -+ closesocket(c->fd); -+ c->fd=-1; -+ continue; /* next IP */ -+ } -+ print_bound_address(c); -+ fd=c->fd; -+ c->fd=-1; -+ return fd; /* success! */ -+ } -+ longjmp(c->err, 1); -+ return -1; /* some C compilers require a return value */ -+} -+ -+static void local_bind(CLI *c) { -+ SOCKADDR_UNION addr; -+ -+#ifdef IP_TRANSPARENT -+ int on=1; -+ if(setsockopt(c->fd, SOL_IP, IP_TRANSPARENT, &on, sizeof on)) -+ sockerror("setsockopt IP_TRANSPARENT"); -+ /* ignore the error to retain Linux 2.2 compatibility */ -+ /* the error will be handled by bind(), anyway */ -+#endif /* IP_TRANSPARENT */ -+ -+ memcpy(&addr, &c->bind_addr.addr[0], sizeof addr); -+ if(ntohs(addr.in.sin_port)>=1024) { /* security check */ -+ if(!bind(c->fd, &addr.sa, addr_len(addr))) { -+ s_log(LOG_INFO, "local_bind succeeded on the original port"); -+ return; /* success */ -+ } -+ if(get_last_socket_error()!=EADDRINUSE -+#ifndef USE_WIN32 -+ || !c->opt->option.transparent -+#endif /* USE_WIN32 */ -+ ) { -+ sockerror("local_bind (original port)"); -+ longjmp(c->err, 1); -+ } -+ } -+ -+ addr.in.sin_port=htons(0); /* retry with ephemeral port */ -+ if(!bind(c->fd, &addr.sa, addr_len(addr))) { -+ s_log(LOG_INFO, "local_bind succeeded on an ephemeral port"); -+ return; /* success */ -+ } -+ sockerror("local_bind (ephemeral port)"); -+ longjmp(c->err, 1); -+} -+ -+static void print_bound_address(CLI *c) { -+ char txt[IPLEN]; -+ SOCKADDR_UNION addr; -+ socklen_t addrlen=sizeof addr; -+ -+ memset(&addr, 0, addrlen); -+ if(getsockname(c->fd, (struct sockaddr *)&addr, &addrlen)) { -+ sockerror("getsockname"); -+ } else { -+ s_ntop(txt, &addr); -+ s_log(LOG_NOTICE,"%s connected remote server from %s", -+ c->opt->servname, txt); -+ } -+} -+ -+static void reset(int fd, char *txt) { -+ /* Set lingering on a socket if needed*/ -+ struct linger l; -+ -+ l.l_onoff=1; -+ l.l_linger=0; -+ if(setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&l, sizeof l)) -+ log_error(LOG_DEBUG, get_last_socket_error(), txt); -+} -+ -+/* End of client.c */ --- a/src/common.h +++ b/src/common.h @@ -53,6 +53,9 @@ @@ -1968,446 +191,14 @@ #define BUFFSIZE 16384 +/* maximum space reserved for header insertion in BUFFSIZE */ -+#define BUFF_RESERVED 1024 ++#define BUFF_RESERVED 1024 + - /* Length of strings (including the terminating '\0' character) */ - /* It can't be lower than 256 bytes or NTLM authentication will break */ + /* length of strings (including the terminating '\0' character) */ + /* it can't be lower than 256 bytes or NTLM authentication will break */ #define STRLEN 256 ---- /dev/null -+++ b/src/common.h.orig -@@ -0,0 +1,429 @@ -+/* -+ * stunnel Universal SSL tunnel -+ * Copyright (C) 1998-2009 Michal Trojnara -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ * See the GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, see . -+ * -+ * Linking stunnel statically or dynamically with other modules is making -+ * a combined work based on stunnel. Thus, the terms and conditions of -+ * the GNU General Public License cover the whole combination. -+ * -+ * In addition, as a special exception, the copyright holder of stunnel -+ * gives you permission to combine stunnel with free software programs or -+ * libraries that are released under the GNU LGPL and with code included -+ * in the standard release of OpenSSL under the OpenSSL License (or -+ * modified versions of such code, with unchanged license). You may copy -+ * and distribute such a system following the terms of the GNU GPL for -+ * stunnel and the licenses of the other code concerned. -+ * -+ * Note that people who make modified versions of stunnel are not obligated -+ * to grant this special exception for their modified versions; it is their -+ * choice whether to do so. The GNU General Public License gives permission -+ * to release a modified version without this exception; this exception -+ * also makes it possible to release a modified version which carries -+ * forward this exception. -+ */ -+ -+#ifndef COMMON_H -+#define COMMON_H -+ -+#ifndef VERSION -+#define VERSION "unknown" -+#endif -+ -+/**************************************** Common constants */ -+ -+#define LIBWRAP_CLIENTS 5 -+ -+/* CPU stack size */ -+#define DEFAULT_STACK_SIZE 65536 -+/* #define DEBUG_STACK_SIZE */ -+ -+/* I/O buffer size */ -+#define BUFFSIZE 16384 -+ -+/* Length of strings (including the terminating '\0' character) */ -+/* It can't be lower than 256 bytes or NTLM authentication will break */ -+#define STRLEN 256 -+ -+/* IP address and TCP port textual representation length */ -+#define IPLEN 128 -+ -+/* How many bytes of random input to read from files for PRNG */ -+/* OpenSSL likes at least 128 bits, so 64 bytes seems plenty. */ -+#define RANDOM_BYTES 64 -+ -+/* For FormatGuard */ -+/* #define __NO_FORMATGUARD_ */ -+ -+/**************************************** Platform */ -+ -+#ifdef USE_WIN32 -+#define USE_IPv6 -+/* #define USE_FIPS */ -+#endif -+ -+#ifdef _WIN32_WCE -+#define USE_WIN32 -+typedef int socklen_t; -+#define EINTR WSAEINTR -+#define EMFILE WSAEMFILE -+#endif -+ -+#ifdef USE_WIN32 -+#define HAVE_OPENSSL -+#define HAVE_OSSL_ENGINE_H -+/* prevent including wincrypt.h, as it defines it's own OCSP_RESPONSE */ -+#define __WINCRYPT_H__ -+#endif -+ -+/**************************************** Generic headers */ -+ -+#ifdef __vms -+#include -+#endif /* __vms */ -+ -+/* For nsr-tandem-nsk architecture */ -+#ifdef __TANDEM -+#include -+#endif -+ -+/* threads model */ -+#ifdef USE_UCONTEXT -+#define __MAKECONTEXT_V2_SOURCE -+#include -+#endif -+ -+#ifdef USE_PTHREAD -+#define THREADS -+#define _REENTRANT -+#define _THREAD_SAFE -+#include -+#endif -+ -+/* TCP wrapper */ -+#if HAVE_TCPD_H && HAVE_LIBWRAP -+#define USE_LIBWRAP -+#endif -+ -+/* Must be included before sys/stat.h for Ultrix */ -+#include /* u_short, u_long */ -+/* General headers */ -+#include -+/* Must be included before sys/stat.h for Ultrix */ -+#ifndef _WIN32_WCE -+#include -+#endif -+#include -+#include /* va_ */ -+#include -+#include /* isalnum */ -+#include -+#include /* stat */ -+#include -+ -+/**************************************** WIN32 headers */ -+ -+#ifdef USE_WIN32 -+ -+#ifndef HOST -+#ifdef __MINGW32__ -+#define HOST "x86-pc-mingw32-gnu" -+#else -+#ifdef _MSC_VER -+#define _QUOTEME(x) #x -+#define QUOTEME(x) _QUOTEME(x) -+#define HOST "x86-pc-msvc-" ## QUOTEME(_MSC_VER) -+#else -+#define HOST "x86-pc-unknown" -+#endif -+#endif -+#endif -+ -+typedef unsigned char u8; -+typedef unsigned short u16; -+typedef unsigned long u32; -+ -+#define HAVE_SNPRINTF -+#define snprintf _snprintf -+#define HAVE_VSNPRINTF -+#define vsnprintf _vsnprintf -+#define strcasecmp _stricmp -+#define strncasecmp _strnicmp -+#define sleep(c) Sleep(1000*(c)) -+ -+#define get_last_socket_error() WSAGetLastError() -+#define get_last_error() GetLastError() -+#define readsocket(s,b,n) recv((s),(b),(n),0) -+#define writesocket(s,b,n) send((s),(b),(n),0) -+ -+/* #define FD_SETSIZE 4096 */ -+/* #define Win32_Winsock */ -+#define __USE_W32_SOCKETS -+ -+/* Winsock2 header for IPv6 definitions */ -+#ifdef _WIN32_WCE -+#include -+#else -+#include -+#include -+#endif -+#include -+ -+#define ECONNRESET WSAECONNRESET -+#define ENOTSOCK WSAENOTSOCK -+#define ENOPROTOOPT WSAENOPROTOOPT -+#define EINPROGRESS WSAEINPROGRESS -+#define EWOULDBLOCK WSAEWOULDBLOCK -+#define EISCONN WSAEISCONN -+#define EADDRINUSE WSAEADDRINUSE -+ -+#ifdef EINVAL -+#undef EINVAL -+#endif -+#define EINVAL WSAEINVAL -+ -+#include /* _beginthread */ -+#include -+ -+#define NO_IDEA -+#define OPENSSL_NO_IDEA -+ -+/**************************************** non-WIN32 headers */ -+ -+#else /* USE_WIN32 */ -+ -+#if SIZEOF_UNSIGNED_CHAR == 1 -+typedef unsigned char u8; -+#endif -+ -+#if SIZEOF_UNSIGNED_SHORT == 2 -+typedef unsigned short u16; -+#else -+typedef unsigned int u16; -+#endif -+ -+#if SIZEOF_UNSIGNED_INT == 4 -+typedef unsigned int u32; -+#else -+typedef unsigned long u32; -+#endif -+ -+#ifdef __INNOTEK_LIBC__ -+# define get_last_socket_error() sock_errno() -+# define get_last_error() errno -+# define readsocket(s,b,n) recv((s),(b),(n),0) -+# define writesocket(s,b,n) send((s),(b),(n),0) -+# define closesocket(s) close(s) -+# define ioctlsocket(a,b,c) so_ioctl((a),(b),(c)) -+#else -+#define get_last_socket_error() errno -+#define get_last_error() errno -+#define readsocket(s,b,n) read((s),(b),(n)) -+#define writesocket(s,b,n) write((s),(b),(n)) -+#define closesocket(s) close(s) -+#define ioctlsocket(a,b,c) ioctl((a),(b),(c)) -+#endif -+ /* OpenVMS compatibility */ -+#ifdef __vms -+#define libdir "__NA__" -+#define PIDFILE "SYS$LOGIN:STUNNEL.PID" -+#ifdef __alpha -+#define HOST "alpha-openvms" -+#else -+#define HOST "vax-openvms" -+#endif -+#include -+#include -+#else /* __vms */ -+#include -+#endif /* __vms */ -+ -+ /* Unix-specific headers */ -+#include /* signal */ -+#include /* wait */ -+#ifdef HAVE_SYS_RESOURCE_H -+#include /* getrlimit */ -+#endif -+#ifdef HAVE_UNISTD_H -+#include /* getpid, fork, execvp, exit */ -+#endif -+#ifdef HAVE_STROPTS_H -+#include -+#endif -+#ifdef HAVE_SYS_SELECT_H -+#include /* for aix */ -+#endif -+ -+#ifndef BROKEN_POLL -+#ifdef HAVE_POLL_H -+#include -+#define USE_POLL -+#else /* HAVE_POLL_H */ -+#ifdef HAVE_SYS_POLL_H -+#include -+#define USE_POLL -+#endif /* HAVE_SYS_POLL_H */ -+#endif /* HAVE_POLL_H */ -+#endif /* BROKEN_POLL */ -+ -+#ifdef HAVE_SYS_FILIO_H -+#include /* for FIONBIO */ -+#endif -+#include -+#ifdef HAVE_GRP_H -+#include -+#endif -+#ifdef __BEOS__ -+#include -+#endif -+#include -+ -+#include /* struct sockaddr_in */ -+#include /* getpeername */ -+#include /* inet_ntoa */ -+#include /* select */ -+#include /* ioctl */ -+#include -+#include -+#ifndef INADDR_ANY -+#define INADDR_ANY (u32)0x00000000 -+#endif -+#ifndef INADDR_LOOPBACK -+#define INADDR_LOOPBACK (u32)0x7F000001 -+#endif -+ -+#if defined(HAVE_WAITPID) -+/* For SYSV systems */ -+#define wait_for_pid(a, b, c) waitpid((a), (b), (c)) -+#define HAVE_WAIT_FOR_PID 1 -+#elif defined(HAVE_WAIT4) -+/* For BSD systems */ -+#define wait_for_pid(a, b, c) wait4((a), (b), (c), NULL) -+#define HAVE_WAIT_FOR_PID 1 -+#endif -+ -+/* SunOS 4 */ -+#if defined(sun) && !defined(__svr4__) && !defined(__SVR4) -+#define atexit(a) on_exit((a), NULL) -+extern int sys_nerr; -+extern char *sys_errlist[]; -+#define strerror(num) ((num)==0 ? "No error" : \ -+ ((num)>=sys_nerr ? "Unknown error" : sys_errlist[num])) -+#endif /* SunOS 4 */ -+ -+/* AIX does not have SOL_TCP defined */ -+#ifndef SOL_TCP -+#define SOL_TCP SOL_SOCKET -+#endif /* SOL_TCP */ -+ -+/* Linux */ -+#ifdef __linux__ -+#ifndef IP_TRANSPARENT -+/* old kernel headers without IP_TRANSPARENT definition */ -+#define IP_TRANSPARENT 19 -+#endif /* IP_TRANSPARENT */ -+#endif /* __linux__ */ -+ -+#endif /* USE_WIN32 */ -+ -+/**************************************** OpenSSL headers */ -+ -+#ifdef HAVE_OPENSSL -+ -+#define OPENSSL_THREAD_DEFINES -+#include -+#if !defined(OPENSSL_THREADS) && defined(USE_PTHREAD) -+#error OpenSSL library compiled without thread support -+#endif /* !OPENSSL_THREADS && USE_PTHREAD */ -+ -+#include -+#include -+#include -+#include /* for CRYPTO_* and SSLeay_version */ -+#include -+#include -+#include -+ -+#ifdef HAVE_OSSL_ENGINE_H -+#include -+#endif /* HAVE_OSSL_ENGINE_H */ -+ -+#if SSLEAY_VERSION_NUMBER >= 0x00907000L -+#include -+#endif /* OpenSSL-0.9.7 */ -+ -+#ifdef USE_FIPS -+#include -+#include -+#endif /* USE_FIPS */ -+ -+#else /* HAVE_OPENSSL */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#endif /* HAVE_OPENSSL */ -+ -+/**************************************** Other defines */ -+ -+/* Safe copy for strings declarated as char[STRLEN] */ -+#define safecopy(dst, src) \ -+ (dst[STRLEN-1]='\0', strncpy((dst), (src), STRLEN-1)) -+#define safeconcat(dst, src) \ -+ (dst[STRLEN-1]='\0', strncat((dst), (src), STRLEN-strlen(dst)-1)) -+/* change all non-printable characters to '.' */ -+#define safestring(s) \ -+ do {unsigned char *p; for(p=(unsigned char *)(s); *p; p++) \ -+ if(!isprint((int)*p)) *p='.';} while(0) -+/* change all unsafe characters to '.' */ -+#define safename(s) \ -+ do {unsigned char *p; for(p=(s); *p; p++) \ -+ if(!isalnum((int)*p)) *p='.';} while(0) -+ -+/* Some definitions for IPv6 support */ -+#if defined(USE_IPv6) -+#define addr_len(x) ((x).sa.sa_family==AF_INET ? \ -+ sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) -+#else -+#define addr_len(x) (sizeof(struct sockaddr_in)) -+#endif -+ -+/* Always use IPv4 defaults! */ -+#define DEFAULT_LOOPBACK "127.0.0.1" -+#define DEFAULT_ANY "0.0.0.0" -+#if 0 -+#define DEFAULT_LOOPBACK "::1" -+#define DEFAULT_ANY "::" -+#endif -+ -+#if defined (USE_WIN32) || defined (__vms) -+#define LOG_EMERG 0 -+#define LOG_ALERT 1 -+#define LOG_CRIT 2 -+#define LOG_ERR 3 -+#define LOG_WARNING 4 -+#define LOG_NOTICE 5 -+#define LOG_INFO 6 -+#define LOG_DEBUG 7 -+#endif /* defined (USE_WIN32) || defined (__vms) */ -+#define LOG_RAW -1 -+ -+#endif /* defined COMMON_H */ -+ -+/* End of common.h */ --- a/src/options.c +++ b/src/options.c -@@ -781,6 +781,28 @@ static char *service_options(CMD cmd, LO +@@ -792,6 +792,28 @@ static char *parse_service_option(CMD cm } #endif @@ -2434,2494 +225,24 @@ + } + /* exec */ - #ifndef USE_WIN32 switch(cmd) { ---- /dev/null -+++ b/src/options.c.orig -@@ -0,0 +1,1994 @@ -+/* -+ * stunnel Universal SSL tunnel -+ * Copyright (C) 1998-2009 Michal Trojnara -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ * See the GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, see . -+ * -+ * Linking stunnel statically or dynamically with other modules is making -+ * a combined work based on stunnel. Thus, the terms and conditions of -+ * the GNU General Public License cover the whole combination. -+ * -+ * In addition, as a special exception, the copyright holder of stunnel -+ * gives you permission to combine stunnel with free software programs or -+ * libraries that are released under the GNU LGPL and with code included -+ * in the standard release of OpenSSL under the OpenSSL License (or -+ * modified versions of such code, with unchanged license). You may copy -+ * and distribute such a system following the terms of the GNU GPL for -+ * stunnel and the licenses of the other code concerned. -+ * -+ * Note that people who make modified versions of stunnel are not obligated -+ * to grant this special exception for their modified versions; it is their -+ * choice whether to do so. The GNU General Public License gives permission -+ * to release a modified version without this exception; this exception -+ * also makes it possible to release a modified version which carries -+ * forward this exception. -+ */ -+ -+#include "common.h" -+#include "prototypes.h" -+ -+#if defined(_WIN32_WCE) && !defined(CONFDIR) -+#define CONFDIR "\\stunnel" -+#endif -+ -+#ifdef USE_WIN32 -+#define CONFSEPARATOR "\\" -+#else -+#define CONFSEPARATOR "/" -+#endif -+ -+#define CONFLINELEN (16*1024) -+ -+static void section_validate(char *, int, LOCAL_OPTIONS *, int); -+static void config_error(char *, int, char *); -+static char *stralloc(char *); -+#ifndef USE_WIN32 -+static char **argalloc(char *); -+#endif -+ -+static int parse_debug_level(char *); -+static int parse_ssl_option(char *); -+static int print_socket_options(void); -+static void print_option(char *, int, OPT_UNION *); -+static int parse_socket_option(char *); -+static char *parse_ocsp_url(LOCAL_OPTIONS *, char *); -+static unsigned long parse_ocsp_flag(char *); -+ -+GLOBAL_OPTIONS options; -+LOCAL_OPTIONS local_options; -+ -+typedef enum { -+ CMD_INIT, /* initialize */ -+ CMD_EXEC, -+ CMD_DEFAULT, -+ CMD_HELP -+} CMD; -+ -+static char *option_not_found= -+ "Specified option name is not valid here"; -+ -+static char *global_options(CMD cmd, char *opt, char *arg) { -+ char *tmpstr; -+#ifndef USE_WIN32 -+ struct group *gr; -+ struct passwd *pw; -+#endif -+ -+ if(cmd==CMD_DEFAULT || cmd==CMD_HELP) { -+ s_log(LOG_RAW, "Global options"); -+ } -+ -+ /* chroot */ -+#ifdef HAVE_CHROOT -+ switch(cmd) { -+ case CMD_INIT: -+ options.chroot_dir=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "chroot")) -+ break; -+ options.chroot_dir=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = directory to chroot stunnel process", "chroot"); -+ break; -+ } -+#endif /* HAVE_CHROOT */ -+ -+ /* compression */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.compression=COMP_NONE; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "compression")) -+ break; -+ if(!strcasecmp(arg, "zlib")) -+ options.compression=COMP_ZLIB; -+ else if(!strcasecmp(arg, "rle")) -+ options.compression=COMP_RLE; -+ else -+ return "Compression type should be either 'zlib' or 'rle'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = zlib|rle compression type", -+ "compression"); -+ break; -+ } -+ -+ /* debug */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.debug_level=5; -+#if !defined (USE_WIN32) && !defined (__vms) -+ options.facility=LOG_DAEMON; -+#endif -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "debug")) -+ break; -+ if(!parse_debug_level(arg)) -+ return "Illegal debug argument"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %d", "debug", options.debug_level); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = [facility].level (e.g. daemon.info)", "debug"); -+ break; -+ } -+ -+ /* EGD is only supported when compiled with OpenSSL 0.9.5a or later */ -+#if SSLEAY_VERSION_NUMBER >= 0x0090581fL -+ switch(cmd) { -+ case CMD_INIT: -+ options.egd_sock=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "EGD")) -+ break; -+ options.egd_sock=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+#ifdef EGD_SOCKET -+ s_log(LOG_RAW, "%-15s = %s", "EGD", EGD_SOCKET); -+#endif -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = path to Entropy Gathering Daemon socket", "EGD"); -+ break; -+ } -+#endif /* OpenSSL 0.9.5a */ -+ -+#ifdef HAVE_OSSL_ENGINE_H -+ /* engine */ -+ switch(cmd) { -+ case CMD_INIT: -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "engine")) -+ break; -+ open_engine(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = auto|engine_id", -+ "engine"); -+ break; -+ } -+ -+ /* engineCtrl */ -+ switch(cmd) { -+ case CMD_INIT: -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "engineCtrl")) -+ break; -+ tmpstr=strchr(arg, ':'); -+ if(tmpstr) -+ *tmpstr++='\0'; -+ ctrl_engine(arg, tmpstr); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = cmd[:arg]", -+ "engineCtrl"); -+ break; -+ } -+#endif -+ -+ /* fips */ -+#ifdef USE_FIPS -+ switch(cmd) { -+ case CMD_INIT: -+ options.option.fips=1; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "fips")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ options.option.fips=1; -+ else if(!strcasecmp(arg, "no")) -+ options.option.fips=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no FIPS 140-2 mode", -+ "fips"); -+ break; -+ } -+#endif /* USE_FIPS */ -+ -+ /* foreground */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ options.option.foreground=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "foreground")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ options.option.foreground=1; -+ else if(!strcasecmp(arg, "no")) -+ options.option.foreground=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no foreground mode (don't fork, log to stderr)", -+ "foreground"); -+ break; -+ } -+#endif -+ -+ /* output */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.output_file=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "output")) -+ break; -+ options.output_file=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = file to append log messages", "output"); -+ break; -+ } -+ -+ /* pid */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ options.pidfile=PIDFILE; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "pid")) -+ break; -+ if(arg[0]) /* is argument not empty? */ -+ options.pidfile=stralloc(arg); -+ else -+ options.pidfile=NULL; /* empty -> do not create a pid file */ -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %s", "pid", PIDFILE); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = pid file (empty to disable creating)", "pid"); -+ break; -+ } -+#endif -+ -+ /* RNDbytes */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.random_bytes=RANDOM_BYTES; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "RNDbytes")) -+ break; -+ options.random_bytes=atoi(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %d", "RNDbytes", RANDOM_BYTES); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = bytes to read from random seed files", "RNDbytes"); -+ break; -+ } -+ -+ /* RNDfile */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.rand_file=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "RNDfile")) -+ break; -+ options.rand_file=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+#ifdef RANDOM_FILE -+ s_log(LOG_RAW, "%-15s = %s", "RNDfile", RANDOM_FILE); -+#endif -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = path to file with random seed data", "RNDfile"); -+ break; -+ } -+ -+ /* RNDoverwrite */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.option.rand_write=1; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "RNDoverwrite")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ options.option.rand_write=1; -+ else if(!strcasecmp(arg, "no")) -+ options.option.rand_write=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = yes", "RNDoverwrite"); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no overwrite seed datafiles with new random data", -+ "RNDoverwrite"); -+ break; -+ } -+ -+ /* service */ -+ switch(cmd) { -+ case CMD_INIT: -+ local_options.servname=stralloc("stunnel"); -+#if defined(USE_WIN32) && !defined(_WIN32_WCE) -+ options.win32_service="stunnel"; -+#endif -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "service")) -+ break; -+ local_options.servname=stralloc(arg); -+#if defined(USE_WIN32) && !defined(_WIN32_WCE) -+ options.win32_service=stralloc(arg); -+#endif -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+#if defined(USE_WIN32) && !defined(_WIN32_WCE) -+ s_log(LOG_RAW, "%-15s = %s", "service", options.win32_service); -+#endif -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = service name", "service"); -+ break; -+ } -+ -+#ifndef USE_WIN32 -+ /* setgid */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.gid=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "setgid")) -+ break; -+ gr=getgrnam(arg); -+ if(gr) -+ options.gid=gr->gr_gid; -+ else if(atoi(arg)) /* numerical? */ -+ options.gid=atoi(arg); -+ else -+ return "Illegal GID"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = groupname for setgid()", "setgid"); -+ break; -+ } -+#endif -+ -+#ifndef USE_WIN32 -+ /* setuid */ -+ switch(cmd) { -+ case CMD_INIT: -+ options.uid=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "setuid")) -+ break; -+ pw=getpwnam(arg); -+ if(pw) -+ options.uid=pw->pw_uid; -+ else if(atoi(arg)) /* numerical? */ -+ options.uid=atoi(arg); -+ else -+ return "Illegal UID"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = username for setuid()", "setuid"); -+ break; -+ } -+#endif -+ -+ /* socket */ -+ switch(cmd) { -+ case CMD_INIT: -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "socket")) -+ break; -+ if(!parse_socket_option(arg)) -+ return "Illegal socket option"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = a|l|r:option=value[:value]", "socket"); -+ s_log(LOG_RAW, "%18sset an option on accept/local/remote socket", ""); -+ break; -+ } -+ -+ /* syslog */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ options.option.syslog=1; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "syslog")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ options.option.syslog=1; -+ else if(!strcasecmp(arg, "no")) -+ options.option.syslog=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no send logging messages to syslog", -+ "syslog"); -+ break; -+ } -+#endif -+ -+ /* taskbar */ -+#ifdef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ options.option.taskbar=1; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "taskbar")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ options.option.taskbar=1; -+ else if(!strcasecmp(arg, "no")) -+ options.option.taskbar=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = yes", "taskbar"); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no enable the taskbar icon", "taskbar"); -+ break; -+ } -+#endif -+ -+ if(cmd==CMD_EXEC) -+ return option_not_found; -+ return NULL; /* OK */ -+} -+ -+static char *service_options(CMD cmd, LOCAL_OPTIONS *section, -+ char *opt, char *arg) { -+ int tmpnum; -+ -+ if(cmd==CMD_DEFAULT || cmd==CMD_HELP) { -+ s_log(LOG_RAW, " "); -+ s_log(LOG_RAW, "Service-level options"); -+ } -+ -+ /* accept */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.accept=0; -+ memset(§ion->local_addr, 0, sizeof(SOCKADDR_LIST)); -+ section->local_addr.addr[0].in.sin_family=AF_INET; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "accept")) -+ break; -+ section->option.accept=1; -+ if(!name2addrlist(§ion->local_addr, arg, DEFAULT_ANY)) -+ return "Failed to resolve accepting address"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = [host:]port accept connections on specified host:port", -+ "accept"); -+ break; -+ } -+ -+ /* CApath */ -+ switch(cmd) { -+ case CMD_INIT: -+#if 0 -+ section->ca_dir=(char *)X509_get_default_cert_dir(); -+#endif -+ section->ca_dir=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "CApath")) -+ break; -+ if(arg[0]) /* not empty */ -+ section->ca_dir=stralloc(arg); -+ else -+ section->ca_dir=NULL; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+#if 0 -+ s_log(LOG_RAW, "%-15s = %s", "CApath", -+ section->ca_dir ? section->ca_dir : "(none)"); -+#endif -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = CA certificate directory for 'verify' option", -+ "CApath"); -+ break; -+ } -+ -+ /* CAfile */ -+ switch(cmd) { -+ case CMD_INIT: -+#if 0 -+ section->ca_file=(char *)X509_get_default_certfile(); -+#endif -+ section->ca_file=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "CAfile")) -+ break; -+ if(arg[0]) /* not empty */ -+ section->ca_file=stralloc(arg); -+ else -+ section->ca_file=NULL; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+#if 0 -+ s_log(LOG_RAW, "%-15s = %s", "CAfile", -+ section->ca_file ? section->ca_file : "(none)"); -+#endif -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = CA certificate file for 'verify' option", -+ "CAfile"); -+ break; -+ } -+ -+ /* cert */ -+ switch(cmd) { -+ case CMD_INIT: -+#ifdef CONFDIR -+ section->cert=CONFDIR CONFSEPARATOR "stunnel.pem"; -+#else -+ section->cert="stunnel.pem"; -+#endif -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "cert")) -+ break; -+ section->cert=stralloc(arg); -+ section->option.cert=1; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %s", "cert", section->cert); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = certificate chain", "cert"); -+ break; -+ } -+ -+ /* ciphers */ -+#ifdef USE_FIPS -+#define STUNNEL_DEFAULT_CIPHER_LIST "FIPS" -+#else -+#define STUNNEL_DEFAULT_CIPHER_LIST SSL_DEFAULT_CIPHER_LIST -+#endif /* USE_FIPS */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->cipher_list=STUNNEL_DEFAULT_CIPHER_LIST; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "ciphers")) -+ break; -+ section->cipher_list=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %s", "ciphers", STUNNEL_DEFAULT_CIPHER_LIST); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = list of permitted SSL ciphers", "ciphers"); -+ break; -+ } -+ -+ /* client */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.client=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "client")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ section->option.client=1; -+ else if(!strcasecmp(arg, "no")) -+ section->option.client=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no client mode (remote service uses SSL)", -+ "client"); -+ break; -+ } -+ -+ /* connect */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.remote=0; -+ section->remote_address=NULL; -+ section->remote_addr.num=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "connect")) -+ break; -+ section->option.remote=1; -+ section->remote_address=stralloc(arg); -+ if(!section->option.delayed_lookup && -+ !name2addrlist(§ion->remote_addr, arg, DEFAULT_LOOPBACK)) { -+ s_log(LOG_RAW, "Cannot resolve '%s' - delaying DNS lookup", arg); -+ section->option.delayed_lookup=1; -+ } -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = [host:]port connect remote host:port", -+ "connect"); -+ break; -+ } -+ -+ /* CRLpath */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->crl_dir=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "CRLpath")) -+ break; -+ if(arg[0]) /* not empty */ -+ section->crl_dir=stralloc(arg); -+ else -+ section->crl_dir=NULL; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = CRL directory", "CRLpath"); -+ break; -+ } -+ -+ /* CRLfile */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->crl_file=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "CRLfile")) -+ break; -+ if(arg[0]) /* not empty */ -+ section->crl_file=stralloc(arg); -+ else -+ section->crl_file=NULL; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = CRL file", "CRLfile"); -+ break; -+ } -+ -+ /* delay */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.delayed_lookup=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "delay")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ section->option.delayed_lookup=1; -+ else if(!strcasecmp(arg, "no")) -+ section->option.delayed_lookup=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no delay DNS lookup for 'connect' option", -+ "delay"); -+ break; -+ } -+ -+#ifdef HAVE_OSSL_ENGINE_H -+ /* engineNum */ -+ switch(cmd) { -+ case CMD_INIT: -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "engineNum")) -+ break; -+ section->engine=get_engine(atoi(arg)); -+ if(!section->engine) -+ return "Illegal engine number"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = number of engine to read the key from", -+ "engineNum"); -+ break; -+ } -+#endif -+ -+ /* exec */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.program=0; -+ section->execname=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "exec")) -+ break; -+ section->option.program=1; -+ section->execname=stralloc(arg); -+ if(!section->execargs) { -+ section->execargs=calloc(2, sizeof(char *)); -+ section->execargs[0]=section->execname; -+ section->execargs[1]=NULL; /* to show that it's null-terminated */ -+ } -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = file execute local inetd-type program", -+ "exec"); -+ break; -+ } -+#endif -+ -+ /* execargs */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ section->execargs=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "execargs")) -+ break; -+ section->execargs=argalloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = arguments for 'exec' (including $0)", -+ "execargs"); -+ break; -+ } -+#endif -+ -+ /* failover */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->failover=FAILOVER_RR; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "failover")) -+ break; -+ if(!strcasecmp(arg, "rr")) -+ section->failover=FAILOVER_RR; -+ else if(!strcasecmp(arg, "prio")) -+ section->failover=FAILOVER_PRIO; -+ else -+ return "Argument should be either 'rr' or 'prio'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = rr|prio chose failover strategy", -+ "failover"); -+ break; -+ } -+ -+ /* ident */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->username=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "ident")) -+ break; -+ section->username=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = username for IDENT (RFC 1413) checking", "ident"); -+ break; -+ } -+ -+ /* key */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->key=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "key")) -+ break; -+ section->key=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %s", "key", section->cert); /* set in stunnel.c */ -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = certificate private key", "key"); -+ break; -+ } -+ -+ /* local */ -+ switch(cmd) { -+ case CMD_INIT: -+ memset(§ion->source_addr, 0, sizeof(SOCKADDR_LIST)); -+ section->source_addr.addr[0].in.sin_family=AF_INET; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "local")) -+ break; -+ if(!hostport2addrlist(§ion->source_addr, arg, "0")) -+ return "Failed to resolve local address"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = IP address to be used as source for remote" -+ " connections", "local"); -+ break; -+ } -+ -+#if SSLEAY_VERSION_NUMBER >= 0x00907000L -+ /* OCSP */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.ocsp=0; -+ memset(§ion->ocsp_addr, 0, sizeof(SOCKADDR_LIST)); -+ section->ocsp_addr.addr[0].in.sin_family=AF_INET; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "ocsp")) -+ break; -+ section->option.ocsp=1; -+ return parse_ocsp_url(section, arg); -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = OCSP server URL", "ocsp"); -+ break; -+ } -+ -+ /* OCSPflag */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->ocsp_flags=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "OCSPflag")) -+ break; -+ tmpnum=parse_ocsp_flag(arg); -+ if(!tmpnum) -+ return "Illegal OCSP flag"; -+ section->ocsp_flags|=tmpnum; -+ return NULL; -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = OCSP server flags", "OCSPflag"); -+ break; -+ } -+#endif /* OpenSSL-0.9.7 */ -+ -+ /* options */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->ssl_options=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "options")) -+ break; -+ tmpnum=parse_ssl_option(arg); -+ if(!tmpnum) -+ return "Illegal SSL option"; -+ section->ssl_options|=tmpnum; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = SSL option", "options"); -+ s_log(LOG_RAW, "%18sset an SSL option", ""); -+ break; -+ } -+ -+ /* protocol */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->protocol=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "protocol")) -+ break; -+ section->protocol=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = protocol to negotiate before SSL initialization", -+ "protocol"); -+ s_log(LOG_RAW, "%18scurrently supported: cifs, connect, nntp, pop3, smtp", ""); -+ break; -+ } -+ -+ /* protocolAuthentication */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->protocol_authentication="basic"; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "protocolAuthentication")) -+ break; -+ section->protocol_authentication=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = authentication type for protocol negotiations", -+ "protocolAuthentication"); -+ break; -+ } -+ -+ /* protocolHost */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->protocol_host=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "protocolHost")) -+ break; -+ section->protocol_host=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = host:port for protocol negotiations", -+ "protocolHost"); -+ break; -+ } -+ -+ /* protocolPassword */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->protocol_password=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "protocolPassword")) -+ break; -+ section->protocol_password=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = password for protocol negotiations", -+ "protocolPassword"); -+ break; -+ } -+ -+ /* protocolUsername */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->protocol_username=NULL; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "protocolUsername")) -+ break; -+ section->protocol_username=stralloc(arg); -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = username for protocol negotiations", -+ "protocolUsername"); -+ break; -+ } -+ -+ /* pty */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.pty=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "pty")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ section->option.pty=1; -+ else if(!strcasecmp(arg, "no")) -+ section->option.pty=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no allocate pseudo terminal for 'exec' option", -+ "pty"); -+ break; -+ } -+#endif -+ -+ /* retry */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.retry=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "retry")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ section->option.retry=1; -+ else if(!strcasecmp(arg, "no")) -+ section->option.retry=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no retry connect+exec section", -+ "retry"); -+ break; -+ } -+#endif -+ -+ /* session */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->session_timeout=300; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "session")) -+ break; -+ if(atoi(arg)>0) -+ section->session_timeout=atoi(arg); -+ else -+ return "Illegal session timeout"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %ld seconds", "session", section->session_timeout); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = session cache timeout (in seconds)", "session"); -+ break; -+ } -+ -+ /* sessiond */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.sessiond=0; -+ memset(§ion->sessiond_addr, 0, sizeof(SOCKADDR_LIST)); -+ section->sessiond_addr.addr[0].in.sin_family=AF_INET; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "sessiond")) -+ break; -+ section->option.sessiond=1; -+#ifdef SSL_OP_NO_TICKET -+ /* disable RFC4507 support introduced in OpenSSL 0.9.8f */ -+ /* this prevents session callbacks from beeing executed */ -+ section->ssl_options|=SSL_OP_NO_TICKET; -+#endif -+ if(!name2addrlist(§ion->sessiond_addr, arg, DEFAULT_LOOPBACK)) -+ return "Failed to resolve sessiond server address"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = [host:]port use sessiond at host:port", -+ "sessiond"); -+ break; -+ } -+ -+#ifndef USE_FORK -+ /* stack */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->stack_size=DEFAULT_STACK_SIZE; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "stack")) -+ break; -+ if(atoi(arg)>0) -+ section->stack_size=atoi(arg); -+ else -+ return "Illegal thread stack size"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %d bytes", "stack", section->stack_size); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = thread stack size (in bytes)", "stack"); -+ break; -+ } -+#endif -+ -+ /* sslVersion */ -+ switch(cmd) { -+ case CMD_INIT: -+#ifdef USE_FIPS -+ section->client_method=(SSL_METHOD *)TLSv1_client_method(); -+ section->server_method=(SSL_METHOD *)TLSv1_server_method(); -+#else -+ section->client_method=(SSL_METHOD *)SSLv3_client_method(); -+ section->server_method=(SSL_METHOD *)SSLv23_server_method(); -+#endif -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "sslVersion")) -+ break; -+ if(!strcasecmp(arg, "all")) { -+ section->client_method=(SSL_METHOD *)SSLv23_client_method(); -+ section->server_method=(SSL_METHOD *)SSLv23_server_method(); -+ } else if(!strcasecmp(arg, "SSLv2")) { -+ section->client_method=(SSL_METHOD *)SSLv2_client_method(); -+ section->server_method=(SSL_METHOD *)SSLv2_server_method(); -+ } else if(!strcasecmp(arg, "SSLv3")) { -+ section->client_method=(SSL_METHOD *)SSLv3_client_method(); -+ section->server_method=(SSL_METHOD *)SSLv3_server_method(); -+ } else if(!strcasecmp(arg, "TLSv1")) { -+ section->client_method=(SSL_METHOD *)TLSv1_client_method(); -+ section->server_method=(SSL_METHOD *)TLSv1_server_method(); -+ } else -+ return "Incorrect version of SSL protocol"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+#ifdef USE_FIPS -+ s_log(LOG_RAW, "%-15s = TLSv1", "sslVersion"); -+#else -+ s_log(LOG_RAW, "%-15s = SSLv3 for client, all for server", "sslVersion"); -+#endif -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = all|SSLv2|SSLv3|TLSv1 SSL method", "sslVersion"); -+ break; -+ } -+ -+ /* TIMEOUTbusy */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->timeout_busy=300; /* 5 minutes */ -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "TIMEOUTbusy")) -+ break; -+ if(atoi(arg)>0) -+ section->timeout_busy=atoi(arg); -+ else -+ return "Illegal busy timeout"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %d seconds", "TIMEOUTbusy", section->timeout_busy); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = seconds to wait for expected data", "TIMEOUTbusy"); -+ break; -+ } -+ -+ /* TIMEOUTclose */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->timeout_close=60; /* 1 minute */ -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "TIMEOUTclose")) -+ break; -+ if(atoi(arg)>0 || !strcmp(arg, "0")) -+ section->timeout_close=atoi(arg); -+ else -+ return "Illegal close timeout"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %d seconds", "TIMEOUTclose", section->timeout_close); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = seconds to wait for close_notify" -+ " (set to 0 for buggy MSIE)", "TIMEOUTclose"); -+ break; -+ } -+ -+ /* TIMEOUTconnect */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->timeout_connect=10; /* 10 seconds */ -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "TIMEOUTconnect")) -+ break; -+ if(atoi(arg)>0 || !strcmp(arg, "0")) -+ section->timeout_connect=atoi(arg); -+ else -+ return "Illegal connect timeout"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %d seconds", "TIMEOUTconnect", -+ section->timeout_connect); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = seconds to connect remote host", "TIMEOUTconnect"); -+ break; -+ } -+ -+ /* TIMEOUTidle */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->timeout_idle=43200; /* 12 hours */ -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "TIMEOUTidle")) -+ break; -+ if(atoi(arg)>0) -+ section->timeout_idle=atoi(arg); -+ else -+ return "Illegal idle timeout"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = %d seconds", "TIMEOUTidle", section->timeout_idle); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = seconds to keep an idle connection", "TIMEOUTidle"); -+ break; -+ } -+ -+ /* transparent */ -+#ifndef USE_WIN32 -+ switch(cmd) { -+ case CMD_INIT: -+ section->option.transparent=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "transparent")) -+ break; -+ if(!strcasecmp(arg, "yes")) -+ section->option.transparent=1; -+ else if(!strcasecmp(arg, "no")) -+ section->option.transparent=0; -+ else -+ return "Argument should be either 'yes' or 'no'"; -+ return NULL; /* OK */ -+ case CMD_DEFAULT: -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = yes|no transparent proxy mode", -+ "transparent"); -+ break; -+ } -+#endif -+ -+ /* verify */ -+ switch(cmd) { -+ case CMD_INIT: -+ section->verify_level=-1; -+ section->verify_use_only_my=0; -+ break; -+ case CMD_EXEC: -+ if(strcasecmp(opt, "verify")) -+ break; -+ section->verify_level=SSL_VERIFY_NONE; -+ switch(atoi(arg)) { -+ case 3: -+ section->verify_use_only_my=1; -+ case 2: -+ section->verify_level|=SSL_VERIFY_FAIL_IF_NO_PEER_CERT; -+ case 1: -+ section->verify_level|=SSL_VERIFY_PEER; -+ case 0: -+ return NULL; /* OK */ -+ default: -+ return "Bad verify level"; -+ } -+ case CMD_DEFAULT: -+ s_log(LOG_RAW, "%-15s = none", "verify"); -+ break; -+ case CMD_HELP: -+ s_log(LOG_RAW, "%-15s = level of peer certificate verification", "verify"); -+ s_log(LOG_RAW, "%18slevel 1 - verify peer certificate if present", ""); -+ s_log(LOG_RAW, "%18slevel 2 - require valid peer certificate always", ""); -+ s_log(LOG_RAW, "%18slevel 3 - verify peer with locally installed certificate", -+ ""); -+ break; -+ } -+ -+ if(cmd==CMD_EXEC) -+ return option_not_found; -+ return NULL; /* OK */ -+} -+ -+static void syntax(char *confname) { -+ s_log(LOG_RAW, " "); -+ s_log(LOG_RAW, "Syntax:"); -+ s_log(LOG_RAW, "stunnel " -+#ifdef USE_WIN32 -+#ifndef _WIN32_WCE -+ "[ [-install | -uninstall] " -+#endif -+ "[-quiet] " -+#endif -+ "[] ] " -+#ifndef USE_WIN32 -+ "-fd " -+#endif -+ "| -help | -version | -sockets"); -+ s_log(LOG_RAW, " - use specified config file instead of %s", -+ confname); -+#ifdef USE_WIN32 -+#ifndef _WIN32_WCE -+ s_log(LOG_RAW, " -install - install NT service"); -+ s_log(LOG_RAW, " -uninstall - uninstall NT service"); -+#endif -+ s_log(LOG_RAW, " -quiet - don't display a message box on success"); -+#else -+ s_log(LOG_RAW, " -fd - read the config file from a file descriptor"); -+#endif -+ s_log(LOG_RAW, " -help - get config file help"); -+ s_log(LOG_RAW, " -version - display version and defaults"); -+ s_log(LOG_RAW, " -sockets - display default socket options"); -+ die(1); -+} -+ -+void parse_config(char *name, char *parameter) { -+#ifdef CONFDIR -+ char *default_config_file=CONFDIR CONFSEPARATOR "stunnel.conf"; -+#else -+ char *default_config_file="stunnel.conf"; -+#endif -+ DISK_FILE *df; -+ char confline[CONFLINELEN], *arg, *opt, *errstr, *filename; -+ int line_number, i; -+#ifdef MAX_FD -+ int sections=0; -+#endif -+ LOCAL_OPTIONS *section, *new_section; -+ -+ memset(&options, 0, sizeof(GLOBAL_OPTIONS)); /* reset global options */ -+ -+ memset(&local_options, 0, sizeof(LOCAL_OPTIONS)); /* reset local options */ -+ local_options.next=NULL; -+ section=&local_options; -+ -+ global_options(CMD_INIT, NULL, NULL); -+ service_options(CMD_INIT, section, NULL, NULL); -+ if(!name) -+ name=default_config_file; -+ if(!strcasecmp(name, "-help")) { -+ global_options(CMD_HELP, NULL, NULL); -+ service_options(CMD_HELP, section, NULL, NULL); -+ die(1); -+ } -+ if(!strcasecmp(name, "-version")) { -+ stunnel_info(1); -+ s_log(LOG_RAW, " "); -+ global_options(CMD_DEFAULT, NULL, NULL); -+ service_options(CMD_DEFAULT, section, NULL, NULL); -+ die(1); -+ } -+ if(!strcasecmp(name, "-sockets")) { -+ print_socket_options(); -+ die(1); -+ } -+#ifndef USE_WIN32 -+ if(!strcasecmp(name, "-fd")) { -+ if(!parameter) { -+ s_log(LOG_RAW, "No file descriptor specified"); -+ syntax(default_config_file); -+ } -+ for(arg=parameter, i=0; *arg; ++arg) { -+ if(*arg<'0' || *arg>'9') { -+ s_log(LOG_RAW, "Invalid file descriptor %s", parameter); -+ syntax(default_config_file); -+ } -+ i=10*i+*arg-'0'; -+ } -+ df=file_fdopen(i); -+ if(!df) { -+ s_log(LOG_RAW, "Invalid file descriptor %s", parameter); -+ syntax(default_config_file); -+ } -+ filename="descriptor"; -+ } else -+#endif -+ { -+ df=file_open(name, 0); -+ if(!df) -+ syntax(default_config_file); -+ filename=name; -+ } -+ line_number=0; -+ while(file_getline(df, confline, CONFLINELEN)) { -+ ++line_number; -+ opt=confline; -+ while(isspace((unsigned char)*opt)) -+ ++opt; /* remove initial whitespaces */ -+ for(i=strlen(opt)-1; i>=0 && isspace((unsigned char)opt[i]); --i) -+ opt[i]='\0'; /* remove trailing whitespaces */ -+ if(opt[0]=='\0' || opt[0]=='#' || opt[0]==';') /* empty or comment */ -+ continue; -+ if(opt[0]=='[' && opt[strlen(opt)-1]==']') { /* new section */ -+ section_validate(filename, line_number, section, 0); -+ ++opt; -+ opt[strlen(opt)-1]='\0'; -+ new_section=calloc(1, sizeof(LOCAL_OPTIONS)); -+ if(!new_section) { -+ s_log(LOG_RAW, "Fatal memory allocation error"); -+ die(2); -+ } -+ memcpy(new_section, &local_options, sizeof(LOCAL_OPTIONS)); -+ new_section->servname=stralloc(opt); -+ new_section->session=NULL; -+ new_section->next=NULL; -+ section->next=new_section; -+ section=new_section; -+#ifdef MAX_FD -+ if(++sections>MAX_FD) -+ config_error(filename, line_number, "Too many sections"); -+#endif -+ continue; -+ } -+ arg=strchr(confline, '='); -+ if(!arg) -+ config_error(filename, line_number, "No '=' found"); -+ *arg++='\0'; /* split into option name and argument value */ -+ for(i=strlen(opt)-1; i>=0 && isspace((unsigned char)opt[i]); --i) -+ opt[i]='\0'; /* remove trailing whitespaces */ -+ while(isspace((unsigned char)*arg)) -+ ++arg; /* remove initial whitespaces */ -+ errstr=service_options(CMD_EXEC, section, opt, arg); -+ if(section==&local_options && errstr==option_not_found) -+ errstr=global_options(CMD_EXEC, opt, arg); -+ config_error(filename, line_number, errstr); -+ } -+ section_validate(filename, line_number, section, 1); -+ file_close(df); -+ if(!local_options.next) { /* inetd mode */ -+ if (section->option.accept) { -+ s_log(LOG_RAW, "accept option is not allowed in inetd mode"); -+ s_log(LOG_RAW, "remove accept option or define a [section]"); -+ die(1); -+ } -+ if (!section->option.remote && !section->execname) { -+ s_log(LOG_RAW, "inetd mode must define a remote host or an executable"); -+ die(1); -+ } -+ } -+} -+ -+static void section_validate(char *filename, int line_number, -+ LOCAL_OPTIONS *section, int final) { -+ if(section==&local_options) { /* global options just configured */ -+#ifdef HAVE_OSSL_ENGINE_H -+ close_engine(); -+#endif -+ ssl_configure(); /* configure global SSL settings */ -+ if(!final) /* no need to validate defaults */ -+ return; -+ } -+ if(!section->option.client) -+ section->option.cert=1; /* Server always needs a certificate */ -+ context_init(section); /* initialize SSL context */ -+ -+ if(section==&local_options) { /* inetd mode */ -+ if(section->option.accept) -+ config_error(filename, line_number, -+ "accept is not allowed in inetd mode"); -+ /* TODO: some additional checks could be useful -+ if((unsigned int)section->option.program + -+ (unsigned int)section->option.remote != 1) -+ config_error(filename, line_number, -+ "Single endpoint is required in inetd mode"); -+ */ -+ return; -+ } -+ -+ /* standalone mode */ -+#ifdef USE_WIN32 -+ if(!section->option.accept || !section->option.remote) -+#else -+ if((unsigned int)section->option.accept + -+ (unsigned int)section->option.program + -+ (unsigned int)section->option.remote != 2) -+#endif -+ config_error(filename, line_number, -+ "Each service section must define exactly two endpoints"); -+ return; /* All tests passed -- continue program execution */ -+} -+ -+static void config_error(char *name, int num, char *str) { -+ if(!str) /* NULL -> no error */ -+ return; -+ s_log(LOG_RAW, "file %s line %d: %s", name, num, str); -+ die(1); -+} -+ -+static char *stralloc(char *str) { /* Allocate static string */ -+ char *retval; -+ -+ retval=calloc(strlen(str)+1, 1); -+ if(!retval) { -+ s_log(LOG_RAW, "Fatal memory allocation error"); -+ die(2); -+ } -+ strcpy(retval, str); -+ return retval; -+} -+ -+#ifndef USE_WIN32 -+static char **argalloc(char *str) { /* Allocate 'exec' argumets */ -+ int max_arg, i; -+ char *ptr, **retval; -+ -+ max_arg=strlen(str)/2+1; -+ ptr=stralloc(str); -+ retval=calloc(max_arg+1, sizeof(char *)); -+ if(!retval) { -+ s_log(LOG_RAW, "Fatal memory allocation error"); -+ die(2); -+ } -+ i=0; -+ while(*ptr && iname; ++fl) { -+ if(!strcasecmp(fl->name, string)) { -+ options.facility = fl->value; -+ break; -+ } -+ } -+ if(options.facility==-1) -+ return 0; /* FAILED */ -+ string=strtok(NULL, "."); /* set to the remainder */ -+ } -+#endif /* USE_WIN32, __vms */ -+ -+ /* Time to check the syslog level */ -+ if(string && strlen(string)==1 && *string>='0' && *string<='7') { -+ options.debug_level=*string-'0'; -+ return 1; /* OK */ -+ } -+ options.debug_level=8; /* illegal level */ -+ for(fl=levels; fl->name; ++fl) { -+ if(!strcasecmp(fl->name, string)) { -+ options.debug_level=fl->value; -+ break; -+ } -+ } -+ if (options.debug_level==8) -+ return 0; /* FAILED */ -+ return 1; /* OK */ -+} -+ -+/* Parse out SSL options stuff */ -+ -+static int parse_ssl_option(char *arg) { -+ struct { -+ char *name; -+ long value; -+ } ssl_opts[] = { -+ {"MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG}, -+ {"NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG}, -+ {"NETSCAPE_REUSE_CIPHER_CHANGE_BUG", -+ SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG}, -+ {"SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG}, -+ {"MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER}, -+ {"MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING}, -+ {"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}, -+ {"DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS}, -+#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}, -+#endif -+#ifdef SSL_OP_NO_TICKET -+ {"NO_TICKET", SSL_OP_NO_TICKET}, -+#endif -+ {"NO_SESSION_RESUMPTION_ON_RENEGOTIATION", -+ SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION}, -+#ifdef SSL_OP_NO_COMPRESSION -+ {"NO_COMPRESSION", SSL_OP_NO_COMPRESSION}, -+#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}, -+ {"CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE}, -+ {"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}, -+ {"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}, -+ {"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}, -+#endif -+ {"ALL", SSL_OP_ALL}, -+ {NULL, 0} -+ }, *option; -+ -+ for(option=ssl_opts; option->name; ++option) -+ if(!strcasecmp(option->name, arg)) -+ return option->value; -+ return 0; /* FAILED */ -+} -+ -+/* Parse out the socket options stuff */ -+ -+static int on=1; -+ -+#define DEF_VALS {NULL, NULL, NULL} -+#define DEF_ACCEPT {(void *)&on, NULL, NULL} -+ -+SOCK_OPT sock_opts[] = { -+ {"SO_DEBUG", SOL_SOCKET, SO_DEBUG, TYPE_FLAG, DEF_VALS}, -+ {"SO_DONTROUTE", SOL_SOCKET, SO_DONTROUTE, TYPE_FLAG, DEF_VALS}, -+ {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, TYPE_FLAG, DEF_VALS}, -+ {"SO_LINGER", SOL_SOCKET, SO_LINGER, TYPE_LINGER, DEF_VALS}, -+ {"SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE, TYPE_FLAG, DEF_VALS}, -+ {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, TYPE_INT, DEF_VALS}, -+ {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, TYPE_INT, DEF_VALS}, -+#ifdef SO_RCVLOWAT -+ {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, TYPE_INT, DEF_VALS}, -+#endif -+#ifdef SO_SNDLOWAT -+ {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, TYPE_INT, DEF_VALS}, -+#endif -+#ifdef SO_RCVTIMEO -+ {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, TYPE_TIMEVAL, DEF_VALS}, -+#endif -+#ifdef SO_SNDTIMEO -+ {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, TYPE_TIMEVAL, DEF_VALS}, -+#endif -+ {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, TYPE_FLAG, DEF_ACCEPT}, -+#ifdef SO_BINDTODEVICE -+ {"SO_BINDTODEVICE", SOL_SOCKET, SO_BINDTODEVICE, TYPE_STRING, DEF_VALS}, -+#endif -+#ifdef TCP_KEEPCNT -+ {"TCP_KEEPCNT", SOL_TCP, TCP_KEEPCNT, TYPE_INT, DEF_VALS}, -+#endif -+#ifdef TCP_KEEPIDLE -+ {"TCP_KEEPIDLE", SOL_TCP, TCP_KEEPIDLE, TYPE_INT, DEF_VALS}, -+#endif -+#ifdef TCP_KEEPINTVL -+ {"TCP_KEEPINTVL", SOL_TCP, TCP_KEEPINTVL, TYPE_INT, DEF_VALS}, -+#endif -+#ifdef IP_TOS -+ {"IP_TOS", IPPROTO_IP, IP_TOS, TYPE_INT, DEF_VALS}, -+#endif -+#ifdef IP_TTL -+ {"IP_TTL", IPPROTO_IP, IP_TTL, TYPE_INT, DEF_VALS}, -+#endif -+#ifdef IP_MAXSEG -+ {"TCP_MAXSEG", IPPROTO_TCP, TCP_MAXSEG, TYPE_INT, DEF_VALS}, -+#endif -+ {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, TYPE_FLAG, DEF_VALS}, -+ {NULL, 0, 0, TYPE_NONE, DEF_VALS} -+}; -+ -+static int print_socket_options(void) { -+ int fd; -+ socklen_t optlen; -+ SOCK_OPT *ptr; -+ OPT_UNION val; -+ char line[STRLEN]; -+ -+ fd=socket(AF_INET, SOCK_STREAM, 0); -+ -+ s_log(LOG_RAW, "Socket option defaults:"); -+ s_log(LOG_RAW, " %-16s%-10s%-10s%-10s%-10s", -+ "Option", "Accept", "Local", "Remote", "OS default"); -+ for(ptr=sock_opts; ptr->opt_str; ++ptr) { -+ /* display option name */ -+ sprintf(line, " %-16s", ptr->opt_str); -+ /* display stunnel default values */ -+ print_option(line, ptr->opt_type, ptr->opt_val[0]); -+ print_option(line, ptr->opt_type, ptr->opt_val[1]); -+ print_option(line, ptr->opt_type, ptr->opt_val[2]); -+ /* display OS default value */ -+ optlen=sizeof val; -+ if(getsockopt(fd, ptr->opt_level, -+ ptr->opt_name, (void *)&val, &optlen)) { -+ if(get_last_socket_error()!=ENOPROTOOPT) { -+ s_log(LOG_RAW, "%s", line); /* dump the name and assigned values */ -+ sockerror("getsockopt"); -+ return 0; /* FAILED */ -+ } -+ safeconcat(line, " -- "); /* write-only value */ -+ } else -+ print_option(line, ptr->opt_type, &val); -+ s_log(LOG_RAW, "%s", line); -+ } -+ return 1; /* OK */ -+} -+ -+static void print_option(char *line, int type, OPT_UNION *val) { -+ char text[STRLEN]; -+ -+ if(!val) { -+ safecopy(text, " -- "); -+ } else { -+ switch(type) { -+ case TYPE_FLAG: -+ case TYPE_INT: -+ sprintf(text, "%10d", val->i_val); -+ break; -+ case TYPE_LINGER: -+ sprintf(text, "%d:%-8d", -+ val->linger_val.l_onoff, val->linger_val.l_linger); -+ break; -+ case TYPE_TIMEVAL: -+ sprintf(text, "%6d:%-3d", -+ (int)val->timeval_val.tv_sec, (int)val->timeval_val.tv_usec); -+ break; -+ case TYPE_STRING: -+ sprintf(text, "%10s", val->c_val); -+ break; -+ default: -+ safecopy(text, " Ooops? "); /* Internal error? */ -+ } -+ } -+ safeconcat(line, text); -+} -+ -+static int parse_socket_option(char *arg) { -+ int socket_type; /* 0-accept, 1-local, 2-remote */ -+ char *opt_val_str, *opt_val2_str; -+ SOCK_OPT *ptr; -+ -+ if(arg[1]!=':') -+ return 0; /* FAILED */ -+ switch(arg[0]) { -+ case 'a': -+ socket_type=0; break; -+ case 'l': -+ socket_type=1; break; -+ case 'r': -+ socket_type=2; break; -+ default: -+ return 0; /* FAILED */ -+ } -+ arg+=2; -+ opt_val_str=strchr(arg, '='); -+ if(!opt_val_str) /* No '='? */ -+ return 0; /* FAILED */ -+ *opt_val_str++='\0'; -+ ptr=sock_opts; -+ for(;;) { -+ if(!ptr->opt_str) -+ return 0; /* FAILED */ -+ if(!strcmp(arg, ptr->opt_str)) -+ break; /* option name found */ -+ ++ptr; -+ } -+ ptr->opt_val[socket_type]=calloc(1, sizeof(OPT_UNION)); -+ switch(ptr->opt_type) { -+ case TYPE_FLAG: -+ case TYPE_INT: -+ ptr->opt_val[socket_type]->i_val=atoi(opt_val_str); -+ return 1; /* OK */ -+ case TYPE_LINGER: -+ opt_val2_str=strchr(opt_val_str, ':'); -+ if(opt_val2_str) { -+ *opt_val2_str++='\0'; -+ ptr->opt_val[socket_type]->linger_val.l_linger=atoi(opt_val2_str); -+ } else { -+ ptr->opt_val[socket_type]->linger_val.l_linger=0; -+ } -+ ptr->opt_val[socket_type]->linger_val.l_onoff=atoi(opt_val_str); -+ return 1; /* OK */ -+ case TYPE_TIMEVAL: -+ opt_val2_str=strchr(opt_val_str, ':'); -+ if(opt_val2_str) { -+ *opt_val2_str++='\0'; -+ ptr->opt_val[socket_type]->timeval_val.tv_usec=atoi(opt_val2_str); -+ } else { -+ ptr->opt_val[socket_type]->timeval_val.tv_usec=0; -+ } -+ ptr->opt_val[socket_type]->timeval_val.tv_sec=atoi(opt_val_str); -+ return 1; /* OK */ -+ case TYPE_STRING: -+ if(strlen(opt_val_str)+1>sizeof(OPT_UNION)) -+ return 0; /* FAILED */ -+ strcpy(ptr->opt_val[socket_type]->c_val, opt_val_str); -+ return 1; /* OK */ -+ default: -+ ; /* ANSI C compiler needs it */ -+ } -+ return 0; /* FAILED */ -+} -+ -+/* Parse out OCSP URL */ -+ -+static char *parse_ocsp_url(LOCAL_OPTIONS *section, char *arg) { -+ char *host, *port, *path; -+ int ssl; -+ -+ if(!OCSP_parse_url(arg, &host, &port, &path, &ssl)) -+ return "Failed to parse OCSP URL"; -+ if(ssl) -+ return "SSL not supported for OCSP" -+ " - additional stunnel service needs to be defined"; -+ if(!hostport2addrlist(§ion->ocsp_addr, host, port)) -+ return "Failed to resolve OCSP server address"; -+ section->ocsp_path=stralloc(path); -+ if(host) -+ OPENSSL_free(host); -+ if(port) -+ OPENSSL_free(port); -+ if(path) -+ OPENSSL_free(path); -+ return NULL; /* OK! */ -+} -+ -+/* Parse out OCSP flags stuff */ -+ -+static unsigned long parse_ocsp_flag(char *arg) { -+ struct { -+ char *name; -+ unsigned long value; -+ } ocsp_opts[] = { -+ {"NOCERTS", OCSP_NOCERTS}, -+ {"NOINTERN", OCSP_NOINTERN}, -+ {"NOSIGS", OCSP_NOSIGS}, -+ {"NOCHAIN", OCSP_NOCHAIN}, -+ {"NOVERIFY", OCSP_NOVERIFY}, -+ {"NOEXPLICIT", OCSP_NOEXPLICIT}, -+ {"NOCASIGN", OCSP_NOCASIGN}, -+ {"NODELEGATED", OCSP_NODELEGATED}, -+ {"NOCHECKS", OCSP_NOCHECKS}, -+ {"TRUSTOTHER", OCSP_TRUSTOTHER}, -+ {"RESPID_KEY", OCSP_RESPID_KEY}, -+ {"NOTIME", OCSP_NOTIME}, -+ {NULL, 0} -+ }, *option; -+ -+ for(option=ocsp_opts; option->name; ++option) -+ if(!strcasecmp(option->name, arg)) -+ return option->value; -+ return 0; /* FAILED */ -+} -+ -+/* End of options.c */ + case CMD_INIT: --- a/src/prototypes.h +++ b/src/prototypes.h -@@ -231,6 +231,7 @@ typedef struct local_options { +@@ -177,6 +177,7 @@ typedef struct service_options_struct { unsigned int remote:1; unsigned int retry:1; /* loop remote+program */ unsigned int sessiond:1; -+ unsigned int xforwardedfor:1; - #ifndef USE_WIN32 ++ unsigned int xforwardedfor:1; unsigned int program:1; + #ifndef USE_WIN32 unsigned int pty:1; -@@ -334,6 +335,8 @@ typedef struct { - FD *ssl_rfd, *ssl_wfd; /* Read and write SSL descriptors */ - int sock_bytes, ssl_bytes; /* Bytes written to socket and ssl */ - s_poll_set fds; /* File descriptors */ -+ int buffsize; /* current buffer size, may be lower than BUFFSIZE */ -+ int crlf_seen; /* the number of successive CRLF seen */ +@@ -351,6 +352,8 @@ typedef struct { + FD *ssl_rfd, *ssl_wfd; /* read and write SSL descriptors */ + int sock_bytes, ssl_bytes; /* bytes written to socket and ssl */ + s_poll_set fds; /* file descriptors */ ++ int buffsize; /* current buffer size, may be lower than BUFFSIZE */ ++ int crlf_seen; /* the number of successive CRLF seen */ } CLI; - extern int max_clients; ---- /dev/null -+++ b/src/prototypes.h.orig -@@ -0,0 +1,470 @@ -+/* -+ * stunnel Universal SSL tunnel -+ * Copyright (C) 1998-2009 Michal Trojnara -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -+ * See the GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, see . -+ * -+ * Linking stunnel statically or dynamically with other modules is making -+ * a combined work based on stunnel. Thus, the terms and conditions of -+ * the GNU General Public License cover the whole combination. -+ * -+ * In addition, as a special exception, the copyright holder of stunnel -+ * gives you permission to combine stunnel with free software programs or -+ * libraries that are released under the GNU LGPL and with code included -+ * in the standard release of OpenSSL under the OpenSSL License (or -+ * modified versions of such code, with unchanged license). You may copy -+ * and distribute such a system following the terms of the GNU GPL for -+ * stunnel and the licenses of the other code concerned. -+ * -+ * Note that people who make modified versions of stunnel are not obligated -+ * to grant this special exception for their modified versions; it is their -+ * choice whether to do so. The GNU General Public License gives permission -+ * to release a modified version without this exception; this exception -+ * also makes it possible to release a modified version which carries -+ * forward this exception. -+ */ -+ -+#ifndef PROTOTYPES_H -+#define PROTOTYPES_H -+ -+#include "common.h" -+ -+/**************************************** Network data structure */ -+ -+#define MAX_HOSTS 16 -+ -+typedef union sockaddr_union { -+ struct sockaddr sa; -+ struct sockaddr_in in; -+#if defined(USE_IPv6) -+ struct sockaddr_in6 in6; -+#endif -+} SOCKADDR_UNION; -+ -+typedef struct sockaddr_list { /* list of addresses */ -+ SOCKADDR_UNION addr[MAX_HOSTS]; /* the list of addresses */ -+ u16 cur; /* current address for round-robin */ -+ u16 num; /* how many addresses are used */ -+} SOCKADDR_LIST; -+ -+#ifdef __INNOTEK_LIBC__ -+#define socklen_t __socklen_t -+#define strcasecmp stricmp -+#define strncasecmp strnicmp -+#define NI_NUMERICHOST 1 -+#define NI_NUMERICSERV 2 -+#endif -+ -+ -+/**************************************** Prototypes for stunnel.c */ -+ -+extern volatile int num_clients; -+ -+void main_initialize(char *, char *); -+void main_execute(void); -+#if !defined (USE_WIN32) && !defined (__vms) && !defined(USE_OS2) -+void drop_privileges(void); -+#endif -+void stunnel_info(int); -+void die(int); -+ -+/**************************************** Prototypes for log.c */ -+ -+void log_open(void); -+void log_close(void); -+void log_flush(void); -+void s_log(int, const char *, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format (printf, 2, 3))); -+#else -+ ; -+#endif -+void ioerror(const char *); -+void sockerror(const char *); -+void log_error(int, int, const char *); -+char *my_strerror(int); -+ -+/**************************************** Prototypes for pty.c */ -+/* Based on Public Domain code by Tatu Ylonen */ -+ -+int pty_allocate(int *, int *, char *, int); -+#if 0 -+void pty_release(char *); -+void pty_make_controlling_tty(int *, char *); -+#endif -+ -+/**************************************** Prototypes for ssl.c */ -+ -+typedef enum { -+ COMP_NONE, COMP_ZLIB, COMP_RLE -+} COMP_TYPE; -+ -+extern int cli_index, opt_index;; -+ -+void ssl_init(void); -+void ssl_configure(void); -+#ifdef HAVE_OSSL_ENGINE_H -+void open_engine(const char *); -+void ctrl_engine(const char *, const char *); -+void close_engine(void); -+ENGINE *get_engine(int); -+#endif -+ -+/**************************************** Prototypes for options.c */ -+ -+typedef struct { -+ /* some data for SSL initialization in ssl.c */ -+ COMP_TYPE compression; /* compression type */ -+ char *egd_sock; /* entropy gathering daemon socket */ -+ char *rand_file; /* file with random data */ -+ int random_bytes; /* how many random bytes to read */ -+ -+ /* some global data for stunnel.c */ -+#ifndef USE_WIN32 -+#ifdef HAVE_CHROOT -+ char *chroot_dir; -+#endif -+ unsigned long dpid; -+ char *pidfile; -+ int uid, gid; -+#endif -+ -+ /* Win32 specific data for gui.c */ -+#if defined(USE_WIN32) && !defined(_WIN32_WCE) -+ char *win32_service; -+#endif -+ -+ /* logging-support data for log.c */ -+ int debug_level; /* debug level for logging */ -+#ifndef USE_WIN32 -+ int facility; /* debug facility for syslog */ -+#endif -+ char *output_file; -+ -+ /* on/off switches */ -+ struct { -+ unsigned int rand_write:1; /* overwrite rand_file */ -+#ifdef USE_WIN32 -+ unsigned int taskbar:1; /* enable the taskbar icon */ -+#else /* !USE_WIN32 */ -+ unsigned int foreground:1; -+ unsigned int syslog:1; -+#endif -+#ifdef USE_FIPS -+ unsigned int fips:1; /* enable FIPS 140-2 mode */ -+#endif -+ } option; -+} GLOBAL_OPTIONS; -+ -+extern GLOBAL_OPTIONS options; -+ -+typedef struct local_options { -+ SSL_CTX *ctx; /* SSL context */ -+ X509_STORE *revocation_store; /* cert store for CRL checking */ -+#ifdef HAVE_OSSL_ENGINE_H -+ ENGINE *engine; /* engine to read the private key */ -+#endif -+ struct local_options *next; /* next node in the services list */ -+ char *servname; /* service name for logging & permission checking */ -+ SSL_SESSION *session; /* jecently used session */ -+ char local_address[IPLEN]; /* dotted-decimal address to bind */ -+#ifndef USE_FORK -+ int stack_size; /* stack size for this thread */ -+#endif -+ -+ /* service-specific data for ctx.c */ -+ char *ca_dir; /* directory for hashed certs */ -+ char *ca_file; /* file containing bunches of certs */ -+ char *crl_dir; /* directory for hashed CRLs */ -+ char *crl_file; /* file containing bunches of CRLs */ -+ char *cipher_list; -+ char *cert; /* cert filename */ -+ char *key; /* pem (priv key/cert) filename */ -+ long session_timeout; -+ int verify_level; -+ int verify_use_only_my; -+ long ssl_options; -+#if SSLEAY_VERSION_NUMBER >= 0x00907000L -+ SOCKADDR_LIST ocsp_addr; -+ char *ocsp_path; -+ unsigned long ocsp_flags; -+#endif /* OpenSSL-0.9.7 */ -+ SSL_METHOD *client_method, *server_method; -+ SOCKADDR_LIST sessiond_addr; -+ -+ /* service-specific data for client.c */ -+ int fd; /* file descriptor accepting connections for this service */ -+ char *execname, **execargs; /* program name and arguments for local mode */ -+ SOCKADDR_LIST local_addr, remote_addr, source_addr; -+ char *username; -+ char *remote_address; -+ int timeout_busy; /* maximum waiting for data time */ -+ int timeout_close; /* maximum close_notify time */ -+ int timeout_connect; /* maximum connect() time */ -+ int timeout_idle; /* maximum idle connection time */ -+ enum {FAILOVER_RR, FAILOVER_PRIO} failover; /* failover strategy */ -+ -+ /* protocol name for protocol.c */ -+ char *protocol; -+ char *protocol_host; -+ char *protocol_username; -+ char *protocol_password; -+ char *protocol_authentication; -+ -+ /* on/off switches */ -+ struct { -+ unsigned int cert:1; -+ unsigned int client:1; -+ unsigned int delayed_lookup:1; -+ unsigned int accept:1; -+ unsigned int remote:1; -+ unsigned int retry:1; /* loop remote+program */ -+ unsigned int sessiond:1; -+#ifndef USE_WIN32 -+ unsigned int program:1; -+ unsigned int pty:1; -+ unsigned int transparent:1; -+#endif -+#if SSLEAY_VERSION_NUMBER >= 0x00907000L -+ unsigned int ocsp:1; -+#endif -+ } option; -+} LOCAL_OPTIONS; -+ -+extern LOCAL_OPTIONS local_options; -+ -+typedef enum { -+ TYPE_NONE, TYPE_FLAG, TYPE_INT, TYPE_LINGER, TYPE_TIMEVAL, TYPE_STRING -+} VAL_TYPE; -+ -+typedef union { -+ int i_val; -+ long l_val; -+ char c_val[16]; -+ struct linger linger_val; -+ struct timeval timeval_val; -+} OPT_UNION; -+ -+typedef struct { -+ char *opt_str; -+ int opt_level; -+ int opt_name; -+ VAL_TYPE opt_type; -+ OPT_UNION *opt_val[3]; -+} SOCK_OPT; -+ -+void parse_config(char *, char *); -+ -+/**************************************** Prototypes for ctx.c */ -+ -+void context_init(LOCAL_OPTIONS *); -+void sslerror(char *); -+ -+/**************************************** Prototypes for verify.c */ -+ -+void verify_init(LOCAL_OPTIONS *); -+ -+/**************************************** Prototypes for network.c */ -+ -+#ifdef USE_POLL -+#define MAX_FD 256 -+#endif -+ -+typedef struct { -+#ifdef USE_POLL -+ struct pollfd ufds[MAX_FD]; -+ unsigned int nfds; -+#else -+ fd_set irfds, iwfds, orfds, owfds; -+ int max; -+#endif -+} s_poll_set; -+ -+void s_poll_init(s_poll_set *); -+void s_poll_add(s_poll_set *, int, int, int); -+int s_poll_canread(s_poll_set *, int); -+int s_poll_canwrite(s_poll_set *, int); -+int s_poll_wait(s_poll_set *, int, int); -+ -+#ifndef USE_WIN32 -+int signal_pipe_init(void); -+void child_status(void); /* dead libwrap or 'exec' process detected */ -+#endif -+int set_socket_options(int, int); -+int alloc_fd(int); -+void setnonblock(int, unsigned long); -+ -+/**************************************** Prototypes for client.c */ -+ -+typedef struct { -+ int fd; /* File descriptor */ -+ int rd; /* Open for read */ -+ int wr; /* Open for write */ -+ int is_socket; /* File descriptor is a socket */ -+} FD; -+ -+typedef struct { -+ LOCAL_OPTIONS *opt; -+ char accepted_address[IPLEN]; /* text */ -+ SOCKADDR_LIST peer_addr; /* Peer address */ -+ FD local_rfd, local_wfd; /* Read and write local descriptors */ -+ FD remote_fd; /* Remote file descriptor */ -+ SSL *ssl; /* SSL Connection */ -+ SOCKADDR_LIST bind_addr; -+ /* IP for explicit local bind or transparent proxy */ -+ unsigned long pid; /* PID of local process */ -+ int fd; /* Temporary file descriptor */ -+ jmp_buf err; -+ -+ char sock_buff[BUFFSIZE]; /* Socket read buffer */ -+ char ssl_buff[BUFFSIZE]; /* SSL read buffer */ -+ int sock_ptr, ssl_ptr; /* Index of first unused byte in buffer */ -+ FD *sock_rfd, *sock_wfd; /* Read and write socket descriptors */ -+ FD *ssl_rfd, *ssl_wfd; /* Read and write SSL descriptors */ -+ int sock_bytes, ssl_bytes; /* Bytes written to socket and ssl */ -+ s_poll_set fds; /* File descriptors */ -+} CLI; -+ -+extern int max_clients; -+#ifndef USE_WIN32 -+extern int max_fds; -+#endif -+ -+CLI *alloc_client_session(LOCAL_OPTIONS *, int, int); -+void *client(void *); -+ -+/**************************************** Prototypes for network.c */ -+ -+int connect_blocking(CLI *, SOCKADDR_UNION *, socklen_t); -+void write_blocking(CLI *, int fd, void *, int); -+void read_blocking(CLI *, int fd, void *, int); -+void fdputline(CLI *, int, const char *); -+void fdgetline(CLI *, int, char *); -+/* descriptor versions of fprintf/fscanf */ -+int fdprintf(CLI *, int, const char *, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format (printf, 3, 4))); -+#else -+ ; -+#endif -+int fdscanf(CLI *, int, const char *, char *) -+#ifdef __GNUC__ -+ __attribute__ ((format (scanf, 3, 0))); -+#else -+ ; -+#endif -+ -+/**************************************** Prototype for protocol.c */ -+ -+void negotiate(CLI *c); -+ -+/**************************************** Prototypes for resolver.c */ -+ -+int name2addrlist(SOCKADDR_LIST *, char *, char *); -+int hostport2addrlist(SOCKADDR_LIST *, char *, char *); -+char *s_ntop(char *, SOCKADDR_UNION *); -+ -+/**************************************** Prototypes for sthreads.c */ -+ -+typedef enum { -+ CRIT_KEYGEN, CRIT_INET, CRIT_CLIENTS, CRIT_WIN_LOG, CRIT_SESSION, -+ CRIT_LIBWRAP, CRIT_SSL, CRIT_SECTIONS -+} SECTION_CODE; -+ -+void enter_critical_section(SECTION_CODE); -+void leave_critical_section(SECTION_CODE); -+void sthreads_init(void); -+unsigned long stunnel_process_id(void); -+unsigned long stunnel_thread_id(void); -+int create_client(int, int, CLI *, void *(*)(void *)); -+#ifdef USE_UCONTEXT -+typedef struct CONTEXT_STRUCTURE { -+ char *stack; /* CPU stack for this thread */ -+ unsigned long id; -+ ucontext_t ctx; -+ s_poll_set *fds; -+ int ready; /* number of ready file descriptors */ -+ time_t finish; /* when to finish poll() for this context */ -+ struct CONTEXT_STRUCTURE *next; /* next context on a list */ -+} CONTEXT; -+extern CONTEXT *ready_head, *ready_tail; -+extern CONTEXT *waiting_head, *waiting_tail; -+#endif -+#ifdef _WIN32_WCE -+int _beginthread(void (*)(void *), int, void *); -+void _endthread(void); -+#endif -+#ifdef DEBUG_STACK_SIZE -+void stack_info(int); -+#endif -+ -+/**************************************** Prototypes for gui.c */ -+ -+typedef struct { -+ LOCAL_OPTIONS *section; -+ char pass[PEM_BUFSIZE]; -+} UI_DATA; -+ -+#ifdef USE_WIN32 -+void win_log(char *); -+void exit_win32(int); -+int passwd_cb(char *, int, int, void *); -+#ifdef HAVE_OSSL_ENGINE_H -+int pin_cb(UI *, UI_STRING *); -+#endif -+ -+#ifndef _WIN32_WCE -+typedef int (CALLBACK * GETADDRINFO) (const char *, -+ const char *, const struct addrinfo *, struct addrinfo **); -+typedef void (CALLBACK * FREEADDRINFO) (struct addrinfo FAR *); -+typedef int (CALLBACK * GETNAMEINFO) (const struct sockaddr *, socklen_t, -+ char *, size_t, char *, size_t, int); -+extern GETADDRINFO s_getaddrinfo; -+extern FREEADDRINFO s_freeaddrinfo; -+extern GETNAMEINFO s_getnameinfo; -+#endif /* ! _WIN32_WCE */ -+#endif /* USE_WIN32 */ -+ -+/**************************************** Prototypes for file.c */ -+ -+typedef struct disk_file { -+#ifdef USE_WIN32 -+ HANDLE fh; -+#else -+ int fd; -+#endif -+ /* the inteface is prepared to easily implement buffering if needed */ -+} DISK_FILE; -+ -+#ifndef USE_WIN32 -+DISK_FILE *file_fdopen(int); -+#endif -+DISK_FILE *file_open(char *, int); -+void file_close(DISK_FILE *); -+int file_getline(DISK_FILE *, char *, int); -+int file_putline(DISK_FILE *, char *); -+ -+#ifdef USE_WIN32 -+LPTSTR str2tstr(const LPSTR); -+LPSTR tstr2str(const LPTSTR); -+#endif -+ -+/**************************************** Prototypes for libwrap.c */ -+ -+void libwrap_init(int); -+void auth_libwrap(CLI *); -+ -+#endif /* defined PROTOTYPES_H */ -+ -+/* End of prototypes.h */ + extern int max_fds, max_clients;