1#!/usr/bin/env perl 2#*************************************************************************** 3# _ _ ____ _ 4# Project ___| | | | _ \| | 5# / __| | | | |_) | | 6# | (__| |_| | _ <| |___ 7# \___|\___/|_| \_\_____| 8# 9# Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. 10# 11# This software is licensed as described in the file COPYING, which 12# you should have received as part of this distribution. The terms 13# are also available at http://curl.haxx.se/docs/copyright.html. 14# 15# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16# copies of the Software, and permit persons to whom the Software is 17# furnished to do so, under the terms of the COPYING file. 18# 19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20# KIND, either express or implied. 21# 22#*************************************************************************** 23 24# This is the HTTPS, FTPS, POP3S, IMAPS, SMTPS, server used for curl test 25# harness. Actually just a layer that runs stunnel properly using the 26# non-secure test harness servers. 27 28BEGIN { 29 @INC=(@INC, $ENV{'srcdir'}, '.'); 30} 31 32use strict; 33use warnings; 34use Cwd; 35 36use serverhelp qw( 37 server_pidfilename 38 server_logfilename 39 ); 40 41my $stunnel = "stunnel"; 42 43my $verbose=0; # set to 1 for debugging 44 45my $accept_port = 8991; # just our default, weird enough 46my $target_port = 8999; # default test http-server port 47 48my $stuncert; 49 50my $ver_major; 51my $ver_minor; 52my $stunnel_version; 53my $socketopt; 54my $cmd; 55 56my $pidfile; # stunnel pid file 57my $logfile; # stunnel log file 58my $loglevel = 5; # stunnel log level 59my $ipvnum = 4; # default IP version of stunneled server 60my $idnum = 1; # dafault stunneled server instance number 61my $proto = 'https'; # default secure server protocol 62my $conffile; # stunnel configuration file 63my $certfile; # certificate chain PEM file 64 65#*************************************************************************** 66# stunnel requires full path specification for several files. 67# 68my $path = getcwd(); 69my $srcdir = $path; 70my $logdir = $path .'/log'; 71 72#*************************************************************************** 73# Signal handler to remove our stunnel 4.00 and newer configuration file. 74# 75sub exit_signal_handler { 76 my $signame = shift; 77 local $!; # preserve errno 78 local $?; # preserve exit status 79 unlink($conffile) if($conffile && (-f $conffile)); 80 exit; 81} 82 83#*************************************************************************** 84# Process command line options 85# 86while(@ARGV) { 87 if($ARGV[0] eq '--verbose') { 88 $verbose = 1; 89 } 90 elsif($ARGV[0] eq '--proto') { 91 if($ARGV[1]) { 92 $proto = $ARGV[1]; 93 shift @ARGV; 94 } 95 } 96 elsif($ARGV[0] eq '--accept') { 97 if($ARGV[1]) { 98 if($ARGV[1] =~ /^(\d+)$/) { 99 $accept_port = $1; 100 shift @ARGV; 101 } 102 } 103 } 104 elsif($ARGV[0] eq '--connect') { 105 if($ARGV[1]) { 106 if($ARGV[1] =~ /^(\d+)$/) { 107 $target_port = $1; 108 shift @ARGV; 109 } 110 } 111 } 112 elsif($ARGV[0] eq '--stunnel') { 113 if($ARGV[1]) { 114 $stunnel = $ARGV[1]; 115 shift @ARGV; 116 } 117 } 118 elsif($ARGV[0] eq '--srcdir') { 119 if($ARGV[1]) { 120 $srcdir = $ARGV[1]; 121 shift @ARGV; 122 } 123 } 124 elsif($ARGV[0] eq '--certfile') { 125 if($ARGV[1]) { 126 $stuncert = $ARGV[1]; 127 shift @ARGV; 128 } 129 } 130 elsif($ARGV[0] eq '--id') { 131 if($ARGV[1]) { 132 if($ARGV[1] =~ /^(\d+)$/) { 133 $idnum = $1 if($1 > 0); 134 shift @ARGV; 135 } 136 } 137 } 138 elsif($ARGV[0] eq '--ipv4') { 139 $ipvnum = 4; 140 } 141 elsif($ARGV[0] eq '--ipv6') { 142 $ipvnum = 6; 143 } 144 elsif($ARGV[0] eq '--pidfile') { 145 if($ARGV[1]) { 146 $pidfile = "$path/". $ARGV[1]; 147 shift @ARGV; 148 } 149 } 150 elsif($ARGV[0] eq '--logfile') { 151 if($ARGV[1]) { 152 $logfile = "$path/". $ARGV[1]; 153 shift @ARGV; 154 } 155 } 156 else { 157 print STDERR "\nWarning: secureserver.pl unknown parameter: $ARGV[0]\n"; 158 } 159 shift @ARGV; 160} 161 162#*************************************************************************** 163# Initialize command line option dependant variables 164# 165if(!$pidfile) { 166 $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum); 167} 168if(!$logfile) { 169 $logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum); 170} 171 172$conffile = "$path/stunnel.conf"; 173 174$certfile = "$srcdir/". ($stuncert?"certs/$stuncert":"stunnel.pem"); 175 176my $ssltext = uc($proto) ." SSL/TLS:"; 177 178#*************************************************************************** 179# Find out version info for the given stunnel binary 180# 181foreach my $veropt (('-version', '-V')) { 182 foreach my $verstr (qx($stunnel $veropt 2>&1)) { 183 if($verstr =~ /^stunnel (\d+)\.(\d+) on /) { 184 $ver_major = $1; 185 $ver_minor = $2; 186 last; 187 } 188 } 189 last if($ver_major); 190} 191if((!$ver_major) || (!$ver_minor)) { 192 if(-x "$stunnel" && ! -d "$stunnel") { 193 print "$ssltext Unknown stunnel version\n"; 194 } 195 else { 196 print "$ssltext No stunnel\n"; 197 } 198 exit 1; 199} 200$stunnel_version = (100*$ver_major) + $ver_minor; 201 202#*************************************************************************** 203# Verify minimmum stunnel required version 204# 205if($stunnel_version < 310) { 206 print "$ssltext Unsupported stunnel version $ver_major.$ver_minor\n"; 207 exit 1; 208} 209 210#*************************************************************************** 211# Build command to execute for stunnel 3.X versions 212# 213if($stunnel_version < 400) { 214 if($stunnel_version >= 319) { 215 $socketopt = "-O a:SO_REUSEADDR=1"; 216 } 217 $cmd = "$stunnel -p $certfile -P $pidfile "; 218 $cmd .= "-d $accept_port -r $target_port -f -D $loglevel "; 219 $cmd .= ($socketopt) ? "$socketopt " : ""; 220 $cmd .= ">$logfile 2>&1"; 221 if($verbose) { 222 print uc($proto) ." server (stunnel $ver_major.$ver_minor)\n"; 223 print "cmd: $cmd\n"; 224 print "pem cert file: $certfile\n"; 225 print "pid file: $pidfile\n"; 226 print "log file: $logfile\n"; 227 print "log level: $loglevel\n"; 228 print "listen on port: $accept_port\n"; 229 print "connect to port: $target_port\n"; 230 } 231} 232 233#*************************************************************************** 234# Build command to execute for stunnel 4.00 and newer 235# 236if($stunnel_version >= 400) { 237 $socketopt = "a:SO_REUSEADDR=1"; 238 $cmd = "$stunnel $conffile "; 239 $cmd .= ">$logfile 2>&1"; 240 # setup signal handler 241 $SIG{INT} = \&exit_signal_handler; 242 $SIG{TERM} = \&exit_signal_handler; 243 # stunnel configuration file 244 if(open(STUNCONF, ">$conffile")) { 245 print STUNCONF " 246 CApath = $path 247 cert = $certfile 248 pid = $pidfile 249 debug = $loglevel 250 output = $logfile 251 socket = $socketopt 252 foreground = yes 253 254 [curltest] 255 accept = $accept_port 256 connect = $target_port 257 "; 258 if(!close(STUNCONF)) { 259 print "$ssltext Error closing file $conffile\n"; 260 exit 1; 261 } 262 } 263 else { 264 print "$ssltext Error writing file $conffile\n"; 265 exit 1; 266 } 267 if($verbose) { 268 print uc($proto) ." server (stunnel $ver_major.$ver_minor)\n"; 269 print "cmd: $cmd\n"; 270 print "CApath = $path\n"; 271 print "cert = $certfile\n"; 272 print "pid = $pidfile\n"; 273 print "debug = $loglevel\n"; 274 print "output = $logfile\n"; 275 print "socket = $socketopt\n"; 276 print "foreground = yes\n"; 277 print "\n"; 278 print "[curltest]\n"; 279 print "accept = $accept_port\n"; 280 print "connect = $target_port\n"; 281 } 282} 283 284#*************************************************************************** 285# Set file permissions on certificate pem file. 286# 287chmod(0600, $certfile) if(-f $certfile); 288 289#*************************************************************************** 290# Run stunnel. 291# 292my $rc = system($cmd); 293 294$rc >>= 8; 295 296unlink($conffile) if($conffile && -f $conffile); 297 298exit $rc; 299