1#!/usr/bin/env perl 2#*************************************************************************** 3# _ _ ____ _ 4# Project ___| | | | _ \| | 5# / __| | | | |_) | | 6# | (__| |_| | _ <| |___ 7# \___|\___/|_| \_\_____| 8# 9# Copyright (C) 1998 - 2016, 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 https://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# Experimental hooks are available to run tests remotely on machines that 25# are able to run curl but are unable to run the test harness. 26# The following sections need to be modified: 27# 28# $HOSTIP, $HOST6IP - Set to the address of the host running the test suite 29# $CLIENTIP, $CLIENT6IP - Set to the address of the host running curl 30# runclient, runclientoutput - Modify to copy all the files in the log/ 31# directory to the system running curl, run the given command remotely 32# and save the return code or returned stdout (respectively), then 33# copy all the files from the remote system's log/ directory back to 34# the host running the test suite. This can be done a few ways, such 35# as using scp & ssh, rsync & telnet, or using a NFS shared directory 36# and ssh. 37# 38# 'make && make test' needs to be done on both machines before making the 39# above changes and running runtests.pl manually. In the shared NFS case, 40# the contents of the tests/server/ directory must be from the host 41# running the test suite, while the rest must be from the host running curl. 42# 43# Note that even with these changes a number of tests will still fail (mainly 44# to do with cookies, those that set environment variables, or those that 45# do more than touch the file system in a <precheck> or <postcheck> 46# section). These can be added to the $TESTCASES line below, 47# e.g. $TESTCASES="!8 !31 !63 !cookies..." 48# 49# Finally, to properly support -g and -n, checktestcmd needs to change 50# to check the remote system's PATH, and the places in the code where 51# the curl binary is read directly to determine its type also need to be 52# fixed. As long as the -g option is never given, and the -n is always 53# given, this won't be a problem. 54 55 56# These should be the only variables that might be needed to get edited: 57 58BEGIN { 59 push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'}); 60 push(@INC, "."); 61 # run time statistics needs Time::HiRes 62 eval { 63 no warnings "all"; 64 require Time::HiRes; 65 import Time::HiRes qw( time ); 66 } 67} 68 69use strict; 70use warnings; 71use Cwd; 72 73# Subs imported from serverhelp module 74use serverhelp qw( 75 serverfactors 76 servername_id 77 servername_str 78 servername_canon 79 server_pidfilename 80 server_logfilename 81 ); 82 83# Variables and subs imported from sshhelp module 84use sshhelp qw( 85 $sshdexe 86 $sshexe 87 $sftpexe 88 $sshconfig 89 $sftpconfig 90 $sshdlog 91 $sshlog 92 $sftplog 93 $sftpcmds 94 display_sshdconfig 95 display_sshconfig 96 display_sftpconfig 97 display_sshdlog 98 display_sshlog 99 display_sftplog 100 exe_ext 101 find_sshd 102 find_ssh 103 find_sftp 104 find_httptlssrv 105 sshversioninfo 106 ); 107 108use pathhelp; 109 110require "getpart.pm"; # array functions 111require "valgrind.pm"; # valgrind report parser 112require "ftp.pm"; 113 114my $HOSTIP="127.0.0.1"; # address on which the test server listens 115my $HOST6IP="[::1]"; # address on which the test server listens 116my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections 117my $CLIENT6IP="[::1]"; # address which curl uses for incoming connections 118 119my $base = 8990; # base port number 120 121my $HTTPPORT; # HTTP server port 122my $HTTP6PORT; # HTTP IPv6 server port 123my $HTTPSPORT; # HTTPS (stunnel) server port 124my $FTPPORT; # FTP server port 125my $FTP2PORT; # FTP server 2 port 126my $FTPSPORT; # FTPS (stunnel) server port 127my $FTP6PORT; # FTP IPv6 server port 128my $TFTPPORT; # TFTP 129my $TFTP6PORT; # TFTP 130my $SSHPORT; # SCP/SFTP 131my $SOCKSPORT; # SOCKS4/5 port 132my $POP3PORT; # POP3 133my $POP36PORT; # POP3 IPv6 server port 134my $IMAPPORT; # IMAP 135my $IMAP6PORT; # IMAP IPv6 server port 136my $SMTPPORT; # SMTP 137my $SMTP6PORT; # SMTP IPv6 server port 138my $RTSPPORT; # RTSP 139my $RTSP6PORT; # RTSP IPv6 server port 140my $GOPHERPORT; # Gopher 141my $GOPHER6PORT; # Gopher IPv6 server port 142my $HTTPTLSPORT; # HTTP TLS (non-stunnel) server port 143my $HTTPTLS6PORT; # HTTP TLS (non-stunnel) IPv6 server port 144my $HTTPPROXYPORT; # HTTP proxy port, when using CONNECT 145my $HTTPPIPEPORT; # HTTP pipelining port 146my $HTTPUNIXPATH; # HTTP server Unix domain socket path 147my $HTTP2PORT; # HTTP/2 server port 148 149my $srcdir = $ENV{'srcdir'} || '.'; 150my $CURL="../src/curl".exe_ext(); # what curl executable to run on the tests 151my $VCURL=$CURL; # what curl binary to use to verify the servers with 152 # VCURL is handy to set to the system one when the one you 153 # just built hangs or crashes and thus prevent verification 154my $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging 155my $LOGDIR="log"; 156my $TESTDIR="$srcdir/data"; 157my $LIBDIR="./libtest"; 158my $UNITDIR="./unit"; 159# TODO: change this to use server_inputfilename() 160my $SERVERIN="$LOGDIR/server.input"; # what curl sent the server 161my $SERVER2IN="$LOGDIR/server2.input"; # what curl sent the second server 162my $PROXYIN="$LOGDIR/proxy.input"; # what curl sent the proxy 163my $CURLLOG="$LOGDIR/curl.log"; # all command lines run 164my $FTPDCMD="$LOGDIR/ftpserver.cmd"; # copy ftp server instructions here 165my $SERVERLOGS_LOCK="$LOGDIR/serverlogs.lock"; # server logs advisor read lock 166my $CURLCONFIG="../curl-config"; # curl-config from current build 167 168# Normally, all test cases should be run, but at times it is handy to 169# simply run a particular one: 170my $TESTCASES="all"; 171 172# To run specific test cases, set them like: 173# $TESTCASES="1 2 3 7 8"; 174 175####################################################################### 176# No variables below this point should need to be modified 177# 178 179# invoke perl like this: 180my $perl="perl -I$srcdir"; 181my $server_response_maxtime=13; 182 183my $debug_build=0; # built debug enabled (--enable-debug) 184my $has_memory_tracking=0; # built with memory tracking (--enable-curldebug) 185my $libtool; 186 187# name of the file that the memory debugging creates: 188my $memdump="$LOGDIR/memdump"; 189 190# the path to the script that analyzes the memory debug output file: 191my $memanalyze="$perl $srcdir/memanalyze.pl"; 192 193my $pwd = getcwd(); # current working directory 194 195my $start; 196my $ftpchecktime=1; # time it took to verify our test FTP server 197 198my $stunnel = checkcmd("stunnel4") || checkcmd("tstunnel") || checkcmd("stunnel"); 199my $valgrind = checktestcmd("valgrind"); 200my $valgrind_logfile="--logfile"; 201my $valgrind_tool; 202my $gdb = checktestcmd("gdb"); 203my $httptlssrv = find_httptlssrv(); 204 205my $has_ssl; # set if libcurl is built with SSL support 206my $has_largefile; # set if libcurl is built with large file support 207my $has_idn; # set if libcurl is built with IDN support 208my $http_ipv6; # set if HTTP server has IPv6 support 209my $http_unix; # set if HTTP server has Unix sockets support 210my $ftp_ipv6; # set if FTP server has IPv6 support 211my $tftp_ipv6; # set if TFTP server has IPv6 support 212my $gopher_ipv6; # set if Gopher server has IPv6 support 213my $has_ipv6; # set if libcurl is built with IPv6 support 214my $has_unix; # set if libcurl is built with Unix sockets support 215my $has_libz; # set if libcurl is built with libz support 216my $has_getrlimit; # set if system has getrlimit() 217my $has_ntlm; # set if libcurl is built with NTLM support 218my $has_ntlm_wb; # set if libcurl is built with NTLM delegation to winbind 219my $has_sspi; # set if libcurl is built with Windows SSPI 220my $has_gssapi; # set if libcurl is built with a GSS-API library 221my $has_kerberos; # set if libcurl is built with Kerberos support 222my $has_spnego; # set if libcurl is built with SPNEGO support 223my $has_charconv; # set if libcurl is built with CharConv support 224my $has_tls_srp; # set if libcurl is built with TLS-SRP support 225my $has_metalink; # set if curl is built with Metalink support 226my $has_http2; # set if libcurl is built with HTTP2 support 227my $has_crypto; # set if libcurl is built with cryptographic support 228my $has_cares; # set if built with c-ares 229my $has_threadedres;# set if built with threaded resolver 230my $has_psl; # set if libcurl is built with PSL support 231 232# this version is decided by the particular nghttp2 library that is being used 233my $h2cver = "h2c"; 234 235my $has_openssl; # built with a lib using an OpenSSL-like API 236my $has_gnutls; # built with GnuTLS 237my $has_nss; # built with NSS 238my $has_yassl; # built with yassl 239my $has_polarssl; # built with polarssl 240my $has_axtls; # built with axTLS 241my $has_winssl; # built with WinSSL (Secure Channel aka Schannel) 242my $has_darwinssl; # built with DarwinSSL (Secure Transport) 243my $has_boringssl; # built with BoringSSL 244my $has_libressl; # built with libressl 245my $has_mbedtls; # built with mbedTLS 246 247my $has_sslpinning; # built with a TLS backend that supports pinning 248 249my $has_shared = "unknown"; # built shared 250 251my $resolver; # name of the resolver backend (for human presentation) 252my $ssllib; # name of the SSL library we use (for human presentation) 253 254my $has_textaware; # set if running on a system that has a text mode concept 255 # on files. Windows for example 256 257my @protocols; # array of lowercase supported protocol servers 258 259my $skipped=0; # number of tests skipped; reported in main loop 260my %skipped; # skipped{reason}=counter, reasons for skip 261my @teststat; # teststat[testnum]=reason, reasons for skip 262my %disabled_keywords; # key words of tests to skip 263my %enabled_keywords; # key words of tests to run 264my %disabled; # disabled test cases 265 266my $sshdid; # for socks server, ssh daemon version id 267my $sshdvernum; # for socks server, ssh daemon version number 268my $sshdverstr; # for socks server, ssh daemon version string 269my $sshderror; # for socks server, ssh daemon version error 270 271my $defserverlogslocktimeout = 20; # timeout to await server logs lock removal 272my $defpostcommanddelay = 0; # delay between command and postcheck sections 273 274my $timestats; # time stamping and stats generation 275my $fullstats; # show time stats for every single test 276my %timeprepini; # timestamp for each test preparation start 277my %timesrvrini; # timestamp for each test required servers verification start 278my %timesrvrend; # timestamp for each test required servers verification end 279my %timetoolini; # timestamp for each test command run starting 280my %timetoolend; # timestamp for each test command run stopping 281my %timesrvrlog; # timestamp for each test server logs lock removal 282my %timevrfyend; # timestamp for each test result verification end 283 284my $testnumcheck; # test number, set in singletest sub. 285my %oldenv; 286 287####################################################################### 288# variables that command line options may set 289# 290 291my $short; 292my $automakestyle; 293my $verbose; 294my $debugprotocol; 295my $anyway; 296my $gdbthis; # run test case with gdb debugger 297my $gdbxwin; # use windowed gdb when using gdb 298my $keepoutfiles; # keep stdout and stderr files after tests 299my $listonly; # only list the tests 300my $postmortem; # display detailed info about failed tests 301my $run_event_based; # run curl with --test-event to test the event API 302 303my %run; # running server 304my %doesntrun; # servers that don't work, identified by pidfile 305my %serverpidfile;# all server pid file names, identified by server id 306my %runcert; # cert file currently in use by an ssl running server 307 308# torture test variables 309my $torture; 310my $tortnum; 311my $tortalloc; 312 313####################################################################### 314# logmsg is our general message logging subroutine. 315# 316sub logmsg { 317 for(@_) { 318 print "$_"; 319 } 320} 321 322# get the name of the current user 323my $USER = $ENV{USER}; # Linux 324if (!$USER) { 325 $USER = $ENV{USERNAME}; # Windows 326 if (!$USER) { 327 $USER = $ENV{LOGNAME}; # Some Unix (I think) 328 } 329} 330 331# enable memory debugging if curl is compiled with it 332$ENV{'CURL_MEMDEBUG'} = $memdump; 333$ENV{'CURL_ENTROPY'}="12345678"; 334$ENV{'CURL_FORCETIME'}=1; # for debug NTLM magic 335$ENV{'HOME'}=$pwd; 336 337sub catch_zap { 338 my $signame = shift; 339 logmsg "runtests.pl received SIG$signame, exiting\n"; 340 stopservers($verbose); 341 die "Somebody sent me a SIG$signame"; 342} 343$SIG{INT} = \&catch_zap; 344$SIG{TERM} = \&catch_zap; 345 346########################################################################## 347# Clear all possible '*_proxy' environment variables for various protocols 348# to prevent them to interfere with our testing! 349 350my $protocol; 351foreach $protocol (('ftp', 'http', 'ftps', 'https', 'no', 'all')) { 352 my $proxy = "${protocol}_proxy"; 353 # clear lowercase version 354 delete $ENV{$proxy} if($ENV{$proxy}); 355 # clear uppercase version 356 delete $ENV{uc($proxy)} if($ENV{uc($proxy)}); 357} 358 359# make sure we don't get affected by other variables that control our 360# behaviour 361 362delete $ENV{'SSL_CERT_DIR'} if($ENV{'SSL_CERT_DIR'}); 363delete $ENV{'SSL_CERT_PATH'} if($ENV{'SSL_CERT_PATH'}); 364delete $ENV{'CURL_CA_BUNDLE'} if($ENV{'CURL_CA_BUNDLE'}); 365 366####################################################################### 367# Load serverpidfile hash with pidfile names for all possible servers. 368# 369sub init_serverpidfile_hash { 370 for my $proto (('ftp', 'http', 'imap', 'pop3', 'smtp', 'http/2')) { 371 for my $ssl (('', 's')) { 372 for my $ipvnum ((4, 6)) { 373 for my $idnum ((1, 2, 3)) { 374 my $serv = servername_id("$proto$ssl", $ipvnum, $idnum); 375 my $pidf = server_pidfilename("$proto$ssl", $ipvnum, $idnum); 376 $serverpidfile{$serv} = $pidf; 377 } 378 } 379 } 380 } 381 for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'gopher', 'httptls')) { 382 for my $ipvnum ((4, 6)) { 383 for my $idnum ((1, 2)) { 384 my $serv = servername_id($proto, $ipvnum, $idnum); 385 my $pidf = server_pidfilename($proto, $ipvnum, $idnum); 386 $serverpidfile{$serv} = $pidf; 387 } 388 } 389 } 390 for my $proto (('http', 'imap', 'pop3', 'smtp', 'http/2')) { 391 for my $ssl (('', 's')) { 392 my $serv = servername_id("$proto$ssl", "unix", 1); 393 my $pidf = server_pidfilename("$proto$ssl", "unix", 1); 394 $serverpidfile{$serv} = $pidf; 395 } 396 } 397} 398 399####################################################################### 400# Check if a given child process has just died. Reaps it if so. 401# 402sub checkdied { 403 use POSIX ":sys_wait_h"; 404 my $pid = $_[0]; 405 if((not defined $pid) || $pid <= 0) { 406 return 0; 407 } 408 my $rc = waitpid($pid, &WNOHANG); 409 return ($rc == $pid)?1:0; 410} 411 412####################################################################### 413# Start a new thread/process and run the given command line in there. 414# Return the pids (yes plural) of the new child process to the parent. 415# 416sub startnew { 417 my ($cmd, $pidfile, $timeout, $fake)=@_; 418 419 logmsg "startnew: $cmd\n" if ($verbose); 420 421 my $child = fork(); 422 my $pid2 = 0; 423 424 if(not defined $child) { 425 logmsg "startnew: fork() failure detected\n"; 426 return (-1,-1); 427 } 428 429 if(0 == $child) { 430 # Here we are the child. Run the given command. 431 432 # Put an "exec" in front of the command so that the child process 433 # keeps this child's process ID. 434 exec("exec $cmd") || die "Can't exec() $cmd: $!"; 435 436 # exec() should never return back here to this process. We protect 437 # ourselves by calling die() just in case something goes really bad. 438 die "error: exec() has returned"; 439 } 440 441 # Ugly hack but ssh client and gnutls-serv don't support pid files 442 if ($fake) { 443 if(open(OUT, ">$pidfile")) { 444 print OUT $child . "\n"; 445 close(OUT); 446 logmsg "startnew: $pidfile faked with pid=$child\n" if($verbose); 447 } 448 else { 449 logmsg "startnew: failed to write fake $pidfile with pid=$child\n"; 450 } 451 # could/should do a while connect fails sleep a bit and loop 452 sleep $timeout; 453 if (checkdied($child)) { 454 logmsg "startnew: child process has failed to start\n" if($verbose); 455 return (-1,-1); 456 } 457 } 458 459 my $count = $timeout; 460 while($count--) { 461 if(-f $pidfile && -s $pidfile && open(PID, "<$pidfile")) { 462 $pid2 = 0 + <PID>; 463 close(PID); 464 if(($pid2 > 0) && pidexists($pid2)) { 465 # if $pid2 is valid, then make sure this pid is alive, as 466 # otherwise it is just likely to be the _previous_ pidfile or 467 # similar! 468 last; 469 } 470 # invalidate $pid2 if not actually alive 471 $pid2 = 0; 472 } 473 if (checkdied($child)) { 474 logmsg "startnew: child process has died, server might start up\n" 475 if($verbose); 476 # We can't just abort waiting for the server with a 477 # return (-1,-1); 478 # because the server might have forked and could still start 479 # up normally. Instead, just reduce the amount of time we remain 480 # waiting. 481 $count >>= 2; 482 } 483 sleep(1); 484 } 485 486 # Return two PIDs, the one for the child process we spawned and the one 487 # reported by the server itself (in case it forked again on its own). 488 # Both (potentially) need to be killed at the end of the test. 489 return ($child, $pid2); 490} 491 492 493####################################################################### 494# Check for a command in the PATH of the test server. 495# 496sub checkcmd { 497 my ($cmd)=@_; 498 my @paths=(split(":", $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin", 499 "/sbin", "/usr/bin", "/usr/local/bin", 500 "./libtest/.libs", "./libtest"); 501 for(@paths) { 502 if( -x "$_/$cmd" && ! -d "$_/$cmd") { 503 # executable bit but not a directory! 504 return "$_/$cmd"; 505 } 506 } 507} 508 509####################################################################### 510# Get the list of tests that the tests/data/Makefile.am knows about! 511# 512my $disttests; 513sub get_disttests { 514 my @dist = `cd data && make show`; 515 $disttests = join("", @dist); 516} 517 518####################################################################### 519# Check for a command in the PATH of the machine running curl. 520# 521sub checktestcmd { 522 my ($cmd)=@_; 523 return checkcmd($cmd); 524} 525 526####################################################################### 527# Run the application under test and return its return code 528# 529sub runclient { 530 my ($cmd)=@_; 531 my $ret = system($cmd); 532 print "CMD ($ret): $cmd\n" if($verbose && !$torture); 533 return $ret; 534 535# This is one way to test curl on a remote machine 536# my $out = system("ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'"); 537# sleep 2; # time to allow the NFS server to be updated 538# return $out; 539} 540 541####################################################################### 542# Run the application under test and return its stdout 543# 544sub runclientoutput { 545 my ($cmd)=@_; 546 return `$cmd`; 547 548# This is one way to test curl on a remote machine 549# my @out = `ssh $CLIENTIP cd \'$pwd\' \\; \'$cmd\'`; 550# sleep 2; # time to allow the NFS server to be updated 551# return @out; 552 } 553 554####################################################################### 555# Memory allocation test and failure torture testing. 556# 557sub torture { 558 my $testcmd = shift; 559 my $gdbline = shift; 560 561 # remove memdump first to be sure we get a new nice and clean one 562 unlink($memdump); 563 564 # First get URL from test server, ignore the output/result 565 runclient($testcmd); 566 567 logmsg " CMD: $testcmd\n" if($verbose); 568 569 # memanalyze -v is our friend, get the number of allocations made 570 my $count=0; 571 my @out = `$memanalyze -v $memdump`; 572 for(@out) { 573 if(/^Allocations: (\d+)/) { 574 $count = $1; 575 last; 576 } 577 } 578 if(!$count) { 579 logmsg " found no allocs to make fail\n"; 580 return 0; 581 } 582 583 logmsg " $count allocations to make fail\n"; 584 585 for ( 1 .. $count ) { 586 my $limit = $_; 587 my $fail; 588 my $dumped_core; 589 590 if($tortalloc && ($tortalloc != $limit)) { 591 next; 592 } 593 594 if($verbose) { 595 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = 596 localtime(time()); 597 my $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec); 598 logmsg "Fail alloc no: $limit at $now\r"; 599 } 600 601 # make the memory allocation function number $limit return failure 602 $ENV{'CURL_MEMLIMIT'} = $limit; 603 604 # remove memdump first to be sure we get a new nice and clean one 605 unlink($memdump); 606 607 logmsg "*** Alloc number $limit is now set to fail ***\n" if($gdbthis); 608 609 my $ret = 0; 610 if($gdbthis) { 611 runclient($gdbline); 612 } 613 else { 614 $ret = runclient($testcmd); 615 } 616 #logmsg "$_ Returned " . ($ret >> 8) . "\n"; 617 618 # Now clear the variable again 619 delete $ENV{'CURL_MEMLIMIT'} if($ENV{'CURL_MEMLIMIT'}); 620 621 if(-r "core") { 622 # there's core file present now! 623 logmsg " core dumped\n"; 624 $dumped_core = 1; 625 $fail = 2; 626 } 627 628 # verify that it returns a proper error code, doesn't leak memory 629 # and doesn't core dump 630 if(($ret & 255) || ($ret >> 8) >= 128) { 631 logmsg " system() returned $ret\n"; 632 $fail=1; 633 } 634 else { 635 my @memdata=`$memanalyze $memdump`; 636 my $leak=0; 637 for(@memdata) { 638 if($_ ne "") { 639 # well it could be other memory problems as well, but 640 # we call it leak for short here 641 $leak=1; 642 } 643 } 644 if($leak) { 645 logmsg "** MEMORY FAILURE\n"; 646 logmsg @memdata; 647 logmsg `$memanalyze -l $memdump`; 648 $fail = 1; 649 } 650 } 651 if($fail) { 652 logmsg " Failed on alloc number $limit in test.\n", 653 " invoke with \"-t$limit\" to repeat this single case.\n"; 654 stopservers($verbose); 655 return 1; 656 } 657 } 658 659 logmsg "torture OK\n"; 660 return 0; 661} 662 663####################################################################### 664# Stop a test server along with pids which aren't in the %run hash yet. 665# This also stops all servers which are relative to the given one. 666# 667sub stopserver { 668 my ($server, $pidlist) = @_; 669 # 670 # kill sockfilter processes for pingpong relative server 671 # 672 if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) { 673 my $proto = $1; 674 my $idnum = ($2 && ($2 > 1)) ? $2 : 1; 675 my $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4; 676 killsockfilters($proto, $ipvnum, $idnum, $verbose); 677 } 678 # 679 # All servers relative to the given one must be stopped also 680 # 681 my @killservers; 682 if($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)s((\d*)(-ipv6|-unix|))$/) { 683 # given a stunnel based ssl server, also kill non-ssl underlying one 684 push @killservers, "${1}${2}"; 685 } 686 elsif($server =~ /^(ftp|http|imap|pop3|smtp|httppipe)((\d*)(-ipv6|-unix|))$/) { 687 # given a non-ssl server, also kill stunnel based ssl piggybacking one 688 push @killservers, "${1}s${2}"; 689 } 690 elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) { 691 # given a socks server, also kill ssh underlying one 692 push @killservers, "ssh${2}"; 693 } 694 elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) { 695 # given a ssh server, also kill socks piggybacking one 696 push @killservers, "socks${2}"; 697 } 698 push @killservers, $server; 699 # 700 # kill given pids and server relative ones clearing them in %run hash 701 # 702 foreach my $server (@killservers) { 703 if($run{$server}) { 704 # we must prepend a space since $pidlist may already contain a pid 705 $pidlist .= " $run{$server}"; 706 $run{$server} = 0; 707 } 708 $runcert{$server} = 0 if($runcert{$server}); 709 } 710 killpid($verbose, $pidlist); 711 # 712 # cleanup server pid files 713 # 714 foreach my $server (@killservers) { 715 my $pidfile = $serverpidfile{$server}; 716 my $pid = processexists($pidfile); 717 if($pid > 0) { 718 logmsg "Warning: $server server unexpectedly alive\n"; 719 killpid($verbose, $pid); 720 } 721 unlink($pidfile) if(-f $pidfile); 722 } 723} 724 725####################################################################### 726# Verify that the server that runs on $ip, $port is our server. This also 727# implies that we can speak with it, as there might be occasions when the 728# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't 729# assign requested address") 730# 731sub verifyhttp { 732 my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_; 733 my $server = servername_id($proto, $ipvnum, $idnum); 734 my $pid = 0; 735 my $bonus=""; 736 # $port_or_path contains a path for Unix sockets, sws ignores the port 737 my $port = ($ipvnum eq "unix") ? 80 : $port_or_path; 738 739 my $verifyout = "$LOGDIR/". 740 servername_canon($proto, $ipvnum, $idnum) .'_verify.out'; 741 unlink($verifyout) if(-f $verifyout); 742 743 my $verifylog = "$LOGDIR/". 744 servername_canon($proto, $ipvnum, $idnum) .'_verify.log'; 745 unlink($verifylog) if(-f $verifylog); 746 747 if($proto eq "gopher") { 748 # gopher is funny 749 $bonus="1/"; 750 } 751 752 my $flags = "--max-time $server_response_maxtime "; 753 $flags .= "--output $verifyout "; 754 $flags .= "--silent "; 755 $flags .= "--verbose "; 756 $flags .= "--globoff "; 757 $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix"; 758 $flags .= "-1 " if($has_axtls); 759 $flags .= "--insecure " if($proto eq 'https'); 760 $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\""; 761 762 my $cmd = "$VCURL $flags 2>$verifylog"; 763 764 # verify if our/any server is running on this port 765 logmsg "RUN: $cmd\n" if($verbose); 766 my $res = runclient($cmd); 767 768 $res >>= 8; # rotate the result 769 if($res & 128) { 770 logmsg "RUN: curl command died with a coredump\n"; 771 return -1; 772 } 773 774 if($res && $verbose) { 775 logmsg "RUN: curl command returned $res\n"; 776 if(open(FILE, "<$verifylog")) { 777 while(my $string = <FILE>) { 778 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/); 779 } 780 close(FILE); 781 } 782 } 783 784 my $data; 785 if(open(FILE, "<$verifyout")) { 786 while(my $string = <FILE>) { 787 $data = $string; 788 last; # only want first line 789 } 790 close(FILE); 791 } 792 793 if($data && ($data =~ /WE ROOLZ: (\d+)/)) { 794 $pid = 0+$1; 795 } 796 elsif($res == 6) { 797 # curl: (6) Couldn't resolve host '::1' 798 logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n"; 799 return -1; 800 } 801 elsif($data || ($res && ($res != 7))) { 802 logmsg "RUN: Unknown server on our $server port: $port ($res)\n"; 803 return -1; 804 } 805 return $pid; 806} 807 808####################################################################### 809# Verify that the server that runs on $ip, $port is our server. This also 810# implies that we can speak with it, as there might be occasions when the 811# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't 812# assign requested address") 813# 814sub verifyftp { 815 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 816 my $server = servername_id($proto, $ipvnum, $idnum); 817 my $pid = 0; 818 my $time=time(); 819 my $extra=""; 820 821 my $verifylog = "$LOGDIR/". 822 servername_canon($proto, $ipvnum, $idnum) .'_verify.log'; 823 unlink($verifylog) if(-f $verifylog); 824 825 if($proto eq "ftps") { 826 $extra .= "--insecure --ftp-ssl-control "; 827 } 828 829 my $flags = "--max-time $server_response_maxtime "; 830 $flags .= "--silent "; 831 $flags .= "--verbose "; 832 $flags .= "--globoff "; 833 $flags .= $extra; 834 $flags .= "\"$proto://$ip:$port/verifiedserver\""; 835 836 my $cmd = "$VCURL $flags 2>$verifylog"; 837 838 # check if this is our server running on this port: 839 logmsg "RUN: $cmd\n" if($verbose); 840 my @data = runclientoutput($cmd); 841 842 my $res = $? >> 8; # rotate the result 843 if($res & 128) { 844 logmsg "RUN: curl command died with a coredump\n"; 845 return -1; 846 } 847 848 foreach my $line (@data) { 849 if($line =~ /WE ROOLZ: (\d+)/) { 850 # this is our test server with a known pid! 851 $pid = 0+$1; 852 last; 853 } 854 } 855 if($pid <= 0 && @data && $data[0]) { 856 # this is not a known server 857 logmsg "RUN: Unknown server on our $server port: $port\n"; 858 return 0; 859 } 860 # we can/should use the time it took to verify the FTP server as a measure 861 # on how fast/slow this host/FTP is. 862 my $took = int(0.5+time()-$time); 863 864 if($verbose) { 865 logmsg "RUN: Verifying our test $server server took $took seconds\n"; 866 } 867 $ftpchecktime = $took>=1?$took:1; # make sure it never is below 1 868 869 return $pid; 870} 871 872####################################################################### 873# Verify that the server that runs on $ip, $port is our server. This also 874# implies that we can speak with it, as there might be occasions when the 875# server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't 876# assign requested address") 877# 878sub verifyrtsp { 879 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 880 my $server = servername_id($proto, $ipvnum, $idnum); 881 my $pid = 0; 882 883 my $verifyout = "$LOGDIR/". 884 servername_canon($proto, $ipvnum, $idnum) .'_verify.out'; 885 unlink($verifyout) if(-f $verifyout); 886 887 my $verifylog = "$LOGDIR/". 888 servername_canon($proto, $ipvnum, $idnum) .'_verify.log'; 889 unlink($verifylog) if(-f $verifylog); 890 891 my $flags = "--max-time $server_response_maxtime "; 892 $flags .= "--output $verifyout "; 893 $flags .= "--silent "; 894 $flags .= "--verbose "; 895 $flags .= "--globoff "; 896 # currently verification is done using http 897 $flags .= "\"http://$ip:$port/verifiedserver\""; 898 899 my $cmd = "$VCURL $flags 2>$verifylog"; 900 901 # verify if our/any server is running on this port 902 logmsg "RUN: $cmd\n" if($verbose); 903 my $res = runclient($cmd); 904 905 $res >>= 8; # rotate the result 906 if($res & 128) { 907 logmsg "RUN: curl command died with a coredump\n"; 908 return -1; 909 } 910 911 if($res && $verbose) { 912 logmsg "RUN: curl command returned $res\n"; 913 if(open(FILE, "<$verifylog")) { 914 while(my $string = <FILE>) { 915 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/); 916 } 917 close(FILE); 918 } 919 } 920 921 my $data; 922 if(open(FILE, "<$verifyout")) { 923 while(my $string = <FILE>) { 924 $data = $string; 925 last; # only want first line 926 } 927 close(FILE); 928 } 929 930 if($data && ($data =~ /RTSP_SERVER WE ROOLZ: (\d+)/)) { 931 $pid = 0+$1; 932 } 933 elsif($res == 6) { 934 # curl: (6) Couldn't resolve host '::1' 935 logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n"; 936 return -1; 937 } 938 elsif($data || ($res != 7)) { 939 logmsg "RUN: Unknown server on our $server port: $port\n"; 940 return -1; 941 } 942 return $pid; 943} 944 945####################################################################### 946# Verify that the ssh server has written out its pidfile, recovering 947# the pid from the file and returning it if a process with that pid is 948# actually alive. 949# 950sub verifyssh { 951 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 952 my $server = servername_id($proto, $ipvnum, $idnum); 953 my $pidfile = server_pidfilename($proto, $ipvnum, $idnum); 954 my $pid = 0; 955 if(open(FILE, "<$pidfile")) { 956 $pid=0+<FILE>; 957 close(FILE); 958 } 959 if($pid > 0) { 960 # if we have a pid it is actually our ssh server, 961 # since runsshserver() unlinks previous pidfile 962 if(!pidexists($pid)) { 963 logmsg "RUN: SSH server has died after starting up\n"; 964 checkdied($pid); 965 unlink($pidfile); 966 $pid = -1; 967 } 968 } 969 return $pid; 970} 971 972####################################################################### 973# Verify that we can connect to the sftp server, properly authenticate 974# with generated config and key files and run a simple remote pwd. 975# 976sub verifysftp { 977 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 978 my $server = servername_id($proto, $ipvnum, $idnum); 979 my $verified = 0; 980 # Find out sftp client canonical file name 981 my $sftp = find_sftp(); 982 if(!$sftp) { 983 logmsg "RUN: SFTP server cannot find $sftpexe\n"; 984 return -1; 985 } 986 # Find out ssh client canonical file name 987 my $ssh = find_ssh(); 988 if(!$ssh) { 989 logmsg "RUN: SFTP server cannot find $sshexe\n"; 990 return -1; 991 } 992 # Connect to sftp server, authenticate and run a remote pwd 993 # command using our generated configuration and key files 994 my $cmd = "\"$sftp\" -b $sftpcmds -F $sftpconfig -S \"$ssh\" $ip > $sftplog 2>&1"; 995 my $res = runclient($cmd); 996 # Search for pwd command response in log file 997 if(open(SFTPLOGFILE, "<$sftplog")) { 998 while(<SFTPLOGFILE>) { 999 if(/^Remote working directory: /) { 1000 $verified = 1; 1001 last; 1002 } 1003 } 1004 close(SFTPLOGFILE); 1005 } 1006 return $verified; 1007} 1008 1009####################################################################### 1010# Verify that the non-stunnel HTTP TLS extensions capable server that runs 1011# on $ip, $port is our server. This also implies that we can speak with it, 1012# as there might be occasions when the server runs fine but we cannot talk 1013# to it ("Failed to connect to ::1: Can't assign requested address") 1014# 1015sub verifyhttptls { 1016 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 1017 my $server = servername_id($proto, $ipvnum, $idnum); 1018 my $pidfile = server_pidfilename($proto, $ipvnum, $idnum); 1019 my $pid = 0; 1020 1021 my $verifyout = "$LOGDIR/". 1022 servername_canon($proto, $ipvnum, $idnum) .'_verify.out'; 1023 unlink($verifyout) if(-f $verifyout); 1024 1025 my $verifylog = "$LOGDIR/". 1026 servername_canon($proto, $ipvnum, $idnum) .'_verify.log'; 1027 unlink($verifylog) if(-f $verifylog); 1028 1029 my $flags = "--max-time $server_response_maxtime "; 1030 $flags .= "--output $verifyout "; 1031 $flags .= "--verbose "; 1032 $flags .= "--globoff "; 1033 $flags .= "--insecure "; 1034 $flags .= "--tlsauthtype SRP "; 1035 $flags .= "--tlsuser jsmith "; 1036 $flags .= "--tlspassword abc "; 1037 $flags .= "\"https://$ip:$port/verifiedserver\""; 1038 1039 my $cmd = "$VCURL $flags 2>$verifylog"; 1040 1041 # verify if our/any server is running on this port 1042 logmsg "RUN: $cmd\n" if($verbose); 1043 my $res = runclient($cmd); 1044 1045 $res >>= 8; # rotate the result 1046 if($res & 128) { 1047 logmsg "RUN: curl command died with a coredump\n"; 1048 return -1; 1049 } 1050 1051 if($res && $verbose) { 1052 logmsg "RUN: curl command returned $res\n"; 1053 if(open(FILE, "<$verifylog")) { 1054 while(my $string = <FILE>) { 1055 logmsg "RUN: $string" if($string !~ /^([ \t]*)$/); 1056 } 1057 close(FILE); 1058 } 1059 } 1060 1061 my $data; 1062 if(open(FILE, "<$verifyout")) { 1063 while(my $string = <FILE>) { 1064 $data .= $string; 1065 } 1066 close(FILE); 1067 } 1068 1069 if($data && ($data =~ /(GNUTLS|GnuTLS)/) && open(FILE, "<$pidfile")) { 1070 $pid=0+<FILE>; 1071 close(FILE); 1072 if($pid > 0) { 1073 # if we have a pid it is actually our httptls server, 1074 # since runhttptlsserver() unlinks previous pidfile 1075 if(!pidexists($pid)) { 1076 logmsg "RUN: $server server has died after starting up\n"; 1077 checkdied($pid); 1078 unlink($pidfile); 1079 $pid = -1; 1080 } 1081 } 1082 return $pid; 1083 } 1084 elsif($res == 6) { 1085 # curl: (6) Couldn't resolve host '::1' 1086 logmsg "RUN: failed to resolve host (https://$ip:$port/verifiedserver)\n"; 1087 return -1; 1088 } 1089 elsif($data || ($res && ($res != 7))) { 1090 logmsg "RUN: Unknown server on our $server port: $port ($res)\n"; 1091 return -1; 1092 } 1093 return $pid; 1094} 1095 1096####################################################################### 1097# STUB for verifying socks 1098# 1099sub verifysocks { 1100 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 1101 my $server = servername_id($proto, $ipvnum, $idnum); 1102 my $pidfile = server_pidfilename($proto, $ipvnum, $idnum); 1103 my $pid = 0; 1104 if(open(FILE, "<$pidfile")) { 1105 $pid=0+<FILE>; 1106 close(FILE); 1107 } 1108 if($pid > 0) { 1109 # if we have a pid it is actually our socks server, 1110 # since runsocksserver() unlinks previous pidfile 1111 if(!pidexists($pid)) { 1112 logmsg "RUN: SOCKS server has died after starting up\n"; 1113 checkdied($pid); 1114 unlink($pidfile); 1115 $pid = -1; 1116 } 1117 } 1118 return $pid; 1119} 1120 1121####################################################################### 1122# Verify that the server that runs on $ip, $port is our server. 1123# Retry over several seconds before giving up. The ssh server in 1124# particular can take a long time to start if it needs to generate 1125# keys on a slow or loaded host. 1126# 1127# Just for convenience, test harness uses 'https' and 'httptls' literals 1128# as values for 'proto' variable in order to differentiate different 1129# servers. 'https' literal is used for stunnel based https test servers, 1130# and 'httptls' is used for non-stunnel https test servers. 1131# 1132 1133my %protofunc = ('http' => \&verifyhttp, 1134 'https' => \&verifyhttp, 1135 'rtsp' => \&verifyrtsp, 1136 'ftp' => \&verifyftp, 1137 'pop3' => \&verifyftp, 1138 'imap' => \&verifyftp, 1139 'smtp' => \&verifyftp, 1140 'httppipe' => \&verifyhttp, 1141 'ftps' => \&verifyftp, 1142 'tftp' => \&verifyftp, 1143 'ssh' => \&verifyssh, 1144 'socks' => \&verifysocks, 1145 'gopher' => \&verifyhttp, 1146 'httptls' => \&verifyhttptls); 1147 1148sub verifyserver { 1149 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 1150 1151 my $count = 30; # try for this many seconds 1152 my $pid; 1153 1154 while($count--) { 1155 my $fun = $protofunc{$proto}; 1156 1157 $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port); 1158 1159 if($pid > 0) { 1160 last; 1161 } 1162 elsif($pid < 0) { 1163 # a real failure, stop trying and bail out 1164 return 0; 1165 } 1166 sleep(1); 1167 } 1168 return $pid; 1169} 1170 1171####################################################################### 1172# Single shot server responsiveness test. This should only be used 1173# to verify that a server present in %run hash is still functional 1174# 1175sub responsiveserver { 1176 my ($proto, $ipvnum, $idnum, $ip, $port) = @_; 1177 my $prev_verbose = $verbose; 1178 1179 $verbose = 0; 1180 my $fun = $protofunc{$proto}; 1181 my $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port); 1182 $verbose = $prev_verbose; 1183 1184 if($pid > 0) { 1185 return 1; # responsive 1186 } 1187 1188 my $srvrname = servername_str($proto, $ipvnum, $idnum); 1189 logmsg " server precheck FAILED (unresponsive $srvrname server)\n"; 1190 return 0; 1191} 1192 1193####################################################################### 1194# start the http2 server 1195# 1196sub runhttp2server { 1197 my ($verbose, $port) = @_; 1198 my $server; 1199 my $srvrname; 1200 my $pidfile; 1201 my $logfile; 1202 my $flags = ""; 1203 my $proto="http/2"; 1204 my $ipvnum = 4; 1205 my $idnum = 0; 1206 my $exe = "$perl $srcdir/http2-server.pl"; 1207 my $verbose_flag = "--verbose "; 1208 1209 $server = servername_id($proto, $ipvnum, $idnum); 1210 1211 $pidfile = $serverpidfile{$server}; 1212 1213 # don't retry if the server doesn't work 1214 if ($doesntrun{$pidfile}) { 1215 return (0,0); 1216 } 1217 1218 my $pid = processexists($pidfile); 1219 if($pid > 0) { 1220 stopserver($server, "$pid"); 1221 } 1222 unlink($pidfile) if(-f $pidfile); 1223 1224 $srvrname = servername_str($proto, $ipvnum, $idnum); 1225 1226 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1227 1228 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1229 $flags .= "--port $HTTP2PORT "; 1230 $flags .= $verbose_flag if($debugprotocol); 1231 1232 my $cmd = "$exe $flags"; 1233 my ($http2pid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1234 1235 if($http2pid <= 0 || !pidexists($http2pid)) { 1236 # it is NOT alive 1237 logmsg "RUN: failed to start the $srvrname server\n"; 1238 stopserver($server, "$pid2"); 1239 $doesntrun{$pidfile} = 1; 1240 return (0,0); 1241 } 1242 1243 if($verbose) { 1244 logmsg "RUN: $srvrname server is now running PID $http2pid\n"; 1245 } 1246 1247 return ($http2pid, $pid2); 1248} 1249 1250####################################################################### 1251# start the http server 1252# 1253sub runhttpserver { 1254 my ($proto, $verbose, $alt, $port_or_path) = @_; 1255 my $ip = $HOSTIP; 1256 my $ipvnum = 4; 1257 my $idnum = 1; 1258 my $server; 1259 my $srvrname; 1260 my $pidfile; 1261 my $logfile; 1262 my $flags = ""; 1263 my $exe = "$perl $srcdir/httpserver.pl"; 1264 my $verbose_flag = "--verbose "; 1265 1266 if($alt eq "ipv6") { 1267 # if IPv6, use a different setup 1268 $ipvnum = 6; 1269 $ip = $HOST6IP; 1270 } 1271 elsif($alt eq "proxy") { 1272 # basically the same, but another ID 1273 $idnum = 2; 1274 } 1275 elsif($alt eq "pipe") { 1276 # basically the same, but another ID 1277 $idnum = 3; 1278 $exe = "python $srcdir/http_pipe.py"; 1279 $verbose_flag .= "1 "; 1280 } 1281 elsif($alt eq "unix") { 1282 # IP (protocol) is mutually exclusive with Unix sockets 1283 $ipvnum = "unix"; 1284 } 1285 1286 $server = servername_id($proto, $ipvnum, $idnum); 1287 1288 $pidfile = $serverpidfile{$server}; 1289 1290 # don't retry if the server doesn't work 1291 if ($doesntrun{$pidfile}) { 1292 return (0,0); 1293 } 1294 1295 my $pid = processexists($pidfile); 1296 if($pid > 0) { 1297 stopserver($server, "$pid"); 1298 } 1299 unlink($pidfile) if(-f $pidfile); 1300 1301 $srvrname = servername_str($proto, $ipvnum, $idnum); 1302 1303 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1304 1305 $flags .= "--gopher " if($proto eq "gopher"); 1306 $flags .= "--connect $HOSTIP " if($alt eq "proxy"); 1307 $flags .= $verbose_flag if($debugprotocol); 1308 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1309 $flags .= "--id $idnum " if($idnum > 1); 1310 if($ipvnum eq "unix") { 1311 $flags .= "--unix-socket '$port_or_path' "; 1312 } else { 1313 $flags .= "--ipv$ipvnum --port $port_or_path "; 1314 } 1315 $flags .= "--srcdir \"$srcdir\""; 1316 1317 my $cmd = "$exe $flags"; 1318 my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1319 1320 if($httppid <= 0 || !pidexists($httppid)) { 1321 # it is NOT alive 1322 logmsg "RUN: failed to start the $srvrname server\n"; 1323 stopserver($server, "$pid2"); 1324 displaylogs($testnumcheck); 1325 $doesntrun{$pidfile} = 1; 1326 return (0,0); 1327 } 1328 1329 # Server is up. Verify that we can speak to it. 1330 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path); 1331 if(!$pid3) { 1332 logmsg "RUN: $srvrname server failed verification\n"; 1333 # failed to talk to it properly. Kill the server and return failure 1334 stopserver($server, "$httppid $pid2"); 1335 displaylogs($testnumcheck); 1336 $doesntrun{$pidfile} = 1; 1337 return (0,0); 1338 } 1339 $pid2 = $pid3; 1340 1341 if($verbose) { 1342 logmsg "RUN: $srvrname server is now running PID $httppid\n"; 1343 } 1344 1345 sleep(1); 1346 1347 return ($httppid, $pid2); 1348} 1349 1350####################################################################### 1351# start the http server 1352# 1353sub runhttp_pipeserver { 1354 my ($proto, $verbose, $alt, $port) = @_; 1355 my $ip = $HOSTIP; 1356 my $ipvnum = 4; 1357 my $idnum = 1; 1358 my $server; 1359 my $srvrname; 1360 my $pidfile; 1361 my $logfile; 1362 my $flags = ""; 1363 1364 if($alt eq "ipv6") { 1365 # No IPv6 1366 } 1367 1368 $server = servername_id($proto, $ipvnum, $idnum); 1369 1370 $pidfile = $serverpidfile{$server}; 1371 1372 # don't retry if the server doesn't work 1373 if ($doesntrun{$pidfile}) { 1374 return (0,0); 1375 } 1376 1377 my $pid = processexists($pidfile); 1378 if($pid > 0) { 1379 stopserver($server, "$pid"); 1380 } 1381 unlink($pidfile) if(-f $pidfile); 1382 1383 $srvrname = servername_str($proto, $ipvnum, $idnum); 1384 1385 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1386 1387 $flags .= "--verbose 1 " if($debugprotocol); 1388 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1389 $flags .= "--id $idnum " if($idnum > 1); 1390 $flags .= "--port $port --srcdir \"$srcdir\""; 1391 1392 my $cmd = "$srcdir/http_pipe.py $flags"; 1393 my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1394 1395 if($httppid <= 0 || !pidexists($httppid)) { 1396 # it is NOT alive 1397 logmsg "RUN: failed to start the $srvrname server\n"; 1398 stopserver($server, "$pid2"); 1399 displaylogs($testnumcheck); 1400 $doesntrun{$pidfile} = 1; 1401 return (0,0); 1402 } 1403 1404 # Server is up. Verify that we can speak to it. 1405 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); 1406 if(!$pid3) { 1407 logmsg "RUN: $srvrname server failed verification\n"; 1408 # failed to talk to it properly. Kill the server and return failure 1409 stopserver($server, "$httppid $pid2"); 1410 displaylogs($testnumcheck); 1411 $doesntrun{$pidfile} = 1; 1412 return (0,0); 1413 } 1414 $pid2 = $pid3; 1415 1416 if($verbose) { 1417 logmsg "RUN: $srvrname server is now running PID $httppid\n"; 1418 } 1419 1420 sleep(1); 1421 1422 return ($httppid, $pid2); 1423} 1424 1425####################################################################### 1426# start the https stunnel based server 1427# 1428sub runhttpsserver { 1429 my ($verbose, $ipv6, $certfile) = @_; 1430 my $proto = 'https'; 1431 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP"; 1432 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4; 1433 my $idnum = 1; 1434 my $server; 1435 my $srvrname; 1436 my $pidfile; 1437 my $logfile; 1438 my $flags = ""; 1439 1440 if(!$stunnel) { 1441 return (0,0); 1442 } 1443 1444 $server = servername_id($proto, $ipvnum, $idnum); 1445 1446 $pidfile = $serverpidfile{$server}; 1447 1448 # don't retry if the server doesn't work 1449 if ($doesntrun{$pidfile}) { 1450 return (0,0); 1451 } 1452 1453 my $pid = processexists($pidfile); 1454 if($pid > 0) { 1455 stopserver($server, "$pid"); 1456 } 1457 unlink($pidfile) if(-f $pidfile); 1458 1459 $srvrname = servername_str($proto, $ipvnum, $idnum); 1460 1461 $certfile = 'stunnel.pem' unless($certfile); 1462 1463 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1464 1465 $flags .= "--verbose " if($debugprotocol); 1466 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1467 $flags .= "--id $idnum " if($idnum > 1); 1468 $flags .= "--ipv$ipvnum --proto $proto "; 1469 $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem'); 1470 $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" "; 1471 $flags .= "--connect $HTTPPORT --accept $HTTPSPORT"; 1472 1473 my $cmd = "$perl $srcdir/secureserver.pl $flags"; 1474 my ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1475 1476 if($httpspid <= 0 || !pidexists($httpspid)) { 1477 # it is NOT alive 1478 logmsg "RUN: failed to start the $srvrname server\n"; 1479 stopserver($server, "$pid2"); 1480 displaylogs($testnumcheck); 1481 $doesntrun{$pidfile} = 1; 1482 return(0,0); 1483 } 1484 1485 # Server is up. Verify that we can speak to it. 1486 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $HTTPSPORT); 1487 if(!$pid3) { 1488 logmsg "RUN: $srvrname server failed verification\n"; 1489 # failed to talk to it properly. Kill the server and return failure 1490 stopserver($server, "$httpspid $pid2"); 1491 displaylogs($testnumcheck); 1492 $doesntrun{$pidfile} = 1; 1493 return (0,0); 1494 } 1495 # Here pid3 is actually the pid returned by the unsecure-http server. 1496 1497 $runcert{$server} = $certfile; 1498 1499 if($verbose) { 1500 logmsg "RUN: $srvrname server is now running PID $httpspid\n"; 1501 } 1502 1503 sleep(1); 1504 1505 return ($httpspid, $pid2); 1506} 1507 1508####################################################################### 1509# start the non-stunnel HTTP TLS extensions capable server 1510# 1511sub runhttptlsserver { 1512 my ($verbose, $ipv6) = @_; 1513 my $proto = "httptls"; 1514 my $port = ($ipv6 && ($ipv6 =~ /6$/)) ? $HTTPTLS6PORT : $HTTPTLSPORT; 1515 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP"; 1516 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4; 1517 my $idnum = 1; 1518 my $server; 1519 my $srvrname; 1520 my $pidfile; 1521 my $logfile; 1522 my $flags = ""; 1523 1524 if(!$httptlssrv) { 1525 return (0,0); 1526 } 1527 1528 $server = servername_id($proto, $ipvnum, $idnum); 1529 1530 $pidfile = $serverpidfile{$server}; 1531 1532 # don't retry if the server doesn't work 1533 if ($doesntrun{$pidfile}) { 1534 return (0,0); 1535 } 1536 1537 my $pid = processexists($pidfile); 1538 if($pid > 0) { 1539 stopserver($server, "$pid"); 1540 } 1541 unlink($pidfile) if(-f $pidfile); 1542 1543 $srvrname = servername_str($proto, $ipvnum, $idnum); 1544 1545 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1546 1547 $flags .= "--http "; 1548 $flags .= "--debug 1 " if($debugprotocol); 1549 $flags .= "--port $port "; 1550 $flags .= "--priority NORMAL:+SRP "; 1551 $flags .= "--srppasswd $srcdir/certs/srp-verifier-db "; 1552 $flags .= "--srppasswdconf $srcdir/certs/srp-verifier-conf"; 1553 1554 my $cmd = "$httptlssrv $flags > $logfile 2>&1"; 1555 my ($httptlspid, $pid2) = startnew($cmd, $pidfile, 10, 1); # fake pidfile 1556 1557 if($httptlspid <= 0 || !pidexists($httptlspid)) { 1558 # it is NOT alive 1559 logmsg "RUN: failed to start the $srvrname server\n"; 1560 stopserver($server, "$pid2"); 1561 displaylogs($testnumcheck); 1562 $doesntrun{$pidfile} = 1; 1563 return (0,0); 1564 } 1565 1566 # Server is up. Verify that we can speak to it. PID is from fake pidfile 1567 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); 1568 if(!$pid3) { 1569 logmsg "RUN: $srvrname server failed verification\n"; 1570 # failed to talk to it properly. Kill the server and return failure 1571 stopserver($server, "$httptlspid $pid2"); 1572 displaylogs($testnumcheck); 1573 $doesntrun{$pidfile} = 1; 1574 return (0,0); 1575 } 1576 $pid2 = $pid3; 1577 1578 if($verbose) { 1579 logmsg "RUN: $srvrname server is now running PID $httptlspid\n"; 1580 } 1581 1582 sleep(1); 1583 1584 return ($httptlspid, $pid2); 1585} 1586 1587####################################################################### 1588# start the pingpong server (FTP, POP3, IMAP, SMTP) 1589# 1590sub runpingpongserver { 1591 my ($proto, $id, $verbose, $ipv6) = @_; 1592 my $port; 1593 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP"; 1594 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4; 1595 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1; 1596 my $server; 1597 my $srvrname; 1598 my $pidfile; 1599 my $logfile; 1600 my $flags = ""; 1601 1602 if($proto eq "ftp") { 1603 $port = ($idnum>1)?$FTP2PORT:$FTPPORT; 1604 1605 if($ipvnum==6) { 1606 # if IPv6, use a different setup 1607 $port = $FTP6PORT; 1608 } 1609 } 1610 elsif($proto eq "pop3") { 1611 $port = ($ipvnum==6) ? $POP36PORT : $POP3PORT; 1612 } 1613 elsif($proto eq "imap") { 1614 $port = ($ipvnum==6) ? $IMAP6PORT : $IMAPPORT; 1615 } 1616 elsif($proto eq "smtp") { 1617 $port = ($ipvnum==6) ? $SMTP6PORT : $SMTPPORT; 1618 } 1619 else { 1620 print STDERR "Unsupported protocol $proto!!\n"; 1621 return 0; 1622 } 1623 1624 $server = servername_id($proto, $ipvnum, $idnum); 1625 1626 $pidfile = $serverpidfile{$server}; 1627 1628 # don't retry if the server doesn't work 1629 if ($doesntrun{$pidfile}) { 1630 return (0,0); 1631 } 1632 1633 my $pid = processexists($pidfile); 1634 if($pid > 0) { 1635 stopserver($server, "$pid"); 1636 } 1637 unlink($pidfile) if(-f $pidfile); 1638 1639 $srvrname = servername_str($proto, $ipvnum, $idnum); 1640 1641 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1642 1643 $flags .= "--verbose " if($debugprotocol); 1644 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1645 $flags .= "--srcdir \"$srcdir\" --proto $proto "; 1646 $flags .= "--id $idnum " if($idnum > 1); 1647 $flags .= "--ipv$ipvnum --port $port --addr \"$ip\""; 1648 1649 my $cmd = "$perl $srcdir/ftpserver.pl $flags"; 1650 my ($ftppid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1651 1652 if($ftppid <= 0 || !pidexists($ftppid)) { 1653 # it is NOT alive 1654 logmsg "RUN: failed to start the $srvrname server\n"; 1655 stopserver($server, "$pid2"); 1656 displaylogs($testnumcheck); 1657 $doesntrun{$pidfile} = 1; 1658 return (0,0); 1659 } 1660 1661 # Server is up. Verify that we can speak to it. 1662 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); 1663 if(!$pid3) { 1664 logmsg "RUN: $srvrname server failed verification\n"; 1665 # failed to talk to it properly. Kill the server and return failure 1666 stopserver($server, "$ftppid $pid2"); 1667 displaylogs($testnumcheck); 1668 $doesntrun{$pidfile} = 1; 1669 return (0,0); 1670 } 1671 1672 $pid2 = $pid3; 1673 1674 if($verbose) { 1675 logmsg "RUN: $srvrname server is now running PID $ftppid\n"; 1676 } 1677 1678 sleep(1); 1679 1680 return ($pid2, $ftppid); 1681} 1682 1683####################################################################### 1684# start the ftps server (or rather, tunnel) 1685# 1686sub runftpsserver { 1687 my ($verbose, $ipv6, $certfile) = @_; 1688 my $proto = 'ftps'; 1689 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP"; 1690 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4; 1691 my $idnum = 1; 1692 my $server; 1693 my $srvrname; 1694 my $pidfile; 1695 my $logfile; 1696 my $flags = ""; 1697 1698 if(!$stunnel) { 1699 return (0,0); 1700 } 1701 1702 $server = servername_id($proto, $ipvnum, $idnum); 1703 1704 $pidfile = $serverpidfile{$server}; 1705 1706 # don't retry if the server doesn't work 1707 if ($doesntrun{$pidfile}) { 1708 return (0,0); 1709 } 1710 1711 my $pid = processexists($pidfile); 1712 if($pid > 0) { 1713 stopserver($server, "$pid"); 1714 } 1715 unlink($pidfile) if(-f $pidfile); 1716 1717 $srvrname = servername_str($proto, $ipvnum, $idnum); 1718 1719 $certfile = 'stunnel.pem' unless($certfile); 1720 1721 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1722 1723 $flags .= "--verbose " if($debugprotocol); 1724 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1725 $flags .= "--id $idnum " if($idnum > 1); 1726 $flags .= "--ipv$ipvnum --proto $proto "; 1727 $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem'); 1728 $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" "; 1729 $flags .= "--connect $FTPPORT --accept $FTPSPORT"; 1730 1731 my $cmd = "$perl $srcdir/secureserver.pl $flags"; 1732 my ($ftpspid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1733 1734 if($ftpspid <= 0 || !pidexists($ftpspid)) { 1735 # it is NOT alive 1736 logmsg "RUN: failed to start the $srvrname server\n"; 1737 stopserver($server, "$pid2"); 1738 displaylogs($testnumcheck); 1739 $doesntrun{$pidfile} = 1; 1740 return(0,0); 1741 } 1742 1743 # Server is up. Verify that we can speak to it. 1744 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $FTPSPORT); 1745 if(!$pid3) { 1746 logmsg "RUN: $srvrname server failed verification\n"; 1747 # failed to talk to it properly. Kill the server and return failure 1748 stopserver($server, "$ftpspid $pid2"); 1749 displaylogs($testnumcheck); 1750 $doesntrun{$pidfile} = 1; 1751 return (0,0); 1752 } 1753 # Here pid3 is actually the pid returned by the unsecure-ftp server. 1754 1755 $runcert{$server} = $certfile; 1756 1757 if($verbose) { 1758 logmsg "RUN: $srvrname server is now running PID $ftpspid\n"; 1759 } 1760 1761 sleep(1); 1762 1763 return ($ftpspid, $pid2); 1764} 1765 1766####################################################################### 1767# start the tftp server 1768# 1769sub runtftpserver { 1770 my ($id, $verbose, $ipv6) = @_; 1771 my $port = $TFTPPORT; 1772 my $ip = $HOSTIP; 1773 my $proto = 'tftp'; 1774 my $ipvnum = 4; 1775 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1; 1776 my $server; 1777 my $srvrname; 1778 my $pidfile; 1779 my $logfile; 1780 my $flags = ""; 1781 1782 if($ipv6) { 1783 # if IPv6, use a different setup 1784 $ipvnum = 6; 1785 $port = $TFTP6PORT; 1786 $ip = $HOST6IP; 1787 } 1788 1789 $server = servername_id($proto, $ipvnum, $idnum); 1790 1791 $pidfile = $serverpidfile{$server}; 1792 1793 # don't retry if the server doesn't work 1794 if ($doesntrun{$pidfile}) { 1795 return (0,0); 1796 } 1797 1798 my $pid = processexists($pidfile); 1799 if($pid > 0) { 1800 stopserver($server, "$pid"); 1801 } 1802 unlink($pidfile) if(-f $pidfile); 1803 1804 $srvrname = servername_str($proto, $ipvnum, $idnum); 1805 1806 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1807 1808 $flags .= "--verbose " if($debugprotocol); 1809 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1810 $flags .= "--id $idnum " if($idnum > 1); 1811 $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; 1812 1813 my $cmd = "$perl $srcdir/tftpserver.pl $flags"; 1814 my ($tftppid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1815 1816 if($tftppid <= 0 || !pidexists($tftppid)) { 1817 # it is NOT alive 1818 logmsg "RUN: failed to start the $srvrname server\n"; 1819 stopserver($server, "$pid2"); 1820 displaylogs($testnumcheck); 1821 $doesntrun{$pidfile} = 1; 1822 return (0,0); 1823 } 1824 1825 # Server is up. Verify that we can speak to it. 1826 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); 1827 if(!$pid3) { 1828 logmsg "RUN: $srvrname server failed verification\n"; 1829 # failed to talk to it properly. Kill the server and return failure 1830 stopserver($server, "$tftppid $pid2"); 1831 displaylogs($testnumcheck); 1832 $doesntrun{$pidfile} = 1; 1833 return (0,0); 1834 } 1835 $pid2 = $pid3; 1836 1837 if($verbose) { 1838 logmsg "RUN: $srvrname server is now running PID $tftppid\n"; 1839 } 1840 1841 sleep(1); 1842 1843 return ($pid2, $tftppid); 1844} 1845 1846 1847####################################################################### 1848# start the rtsp server 1849# 1850sub runrtspserver { 1851 my ($verbose, $ipv6) = @_; 1852 my $port = $RTSPPORT; 1853 my $ip = $HOSTIP; 1854 my $proto = 'rtsp'; 1855 my $ipvnum = 4; 1856 my $idnum = 1; 1857 my $server; 1858 my $srvrname; 1859 my $pidfile; 1860 my $logfile; 1861 my $flags = ""; 1862 1863 if($ipv6) { 1864 # if IPv6, use a different setup 1865 $ipvnum = 6; 1866 $port = $RTSP6PORT; 1867 $ip = $HOST6IP; 1868 } 1869 1870 $server = servername_id($proto, $ipvnum, $idnum); 1871 1872 $pidfile = $serverpidfile{$server}; 1873 1874 # don't retry if the server doesn't work 1875 if ($doesntrun{$pidfile}) { 1876 return (0,0); 1877 } 1878 1879 my $pid = processexists($pidfile); 1880 if($pid > 0) { 1881 stopserver($server, "$pid"); 1882 } 1883 unlink($pidfile) if(-f $pidfile); 1884 1885 $srvrname = servername_str($proto, $ipvnum, $idnum); 1886 1887 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1888 1889 $flags .= "--verbose " if($debugprotocol); 1890 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; 1891 $flags .= "--id $idnum " if($idnum > 1); 1892 $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; 1893 1894 my $cmd = "$perl $srcdir/rtspserver.pl $flags"; 1895 my ($rtsppid, $pid2) = startnew($cmd, $pidfile, 15, 0); 1896 1897 if($rtsppid <= 0 || !pidexists($rtsppid)) { 1898 # it is NOT alive 1899 logmsg "RUN: failed to start the $srvrname server\n"; 1900 stopserver($server, "$pid2"); 1901 displaylogs($testnumcheck); 1902 $doesntrun{$pidfile} = 1; 1903 return (0,0); 1904 } 1905 1906 # Server is up. Verify that we can speak to it. 1907 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); 1908 if(!$pid3) { 1909 logmsg "RUN: $srvrname server failed verification\n"; 1910 # failed to talk to it properly. Kill the server and return failure 1911 stopserver($server, "$rtsppid $pid2"); 1912 displaylogs($testnumcheck); 1913 $doesntrun{$pidfile} = 1; 1914 return (0,0); 1915 } 1916 $pid2 = $pid3; 1917 1918 if($verbose) { 1919 logmsg "RUN: $srvrname server is now running PID $rtsppid\n"; 1920 } 1921 1922 sleep(1); 1923 1924 return ($rtsppid, $pid2); 1925} 1926 1927 1928####################################################################### 1929# Start the ssh (scp/sftp) server 1930# 1931sub runsshserver { 1932 my ($id, $verbose, $ipv6) = @_; 1933 my $ip=$HOSTIP; 1934 my $port = $SSHPORT; 1935 my $socksport = $SOCKSPORT; 1936 my $proto = 'ssh'; 1937 my $ipvnum = 4; 1938 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1; 1939 my $server; 1940 my $srvrname; 1941 my $pidfile; 1942 my $logfile; 1943 my $flags = ""; 1944 1945 $server = servername_id($proto, $ipvnum, $idnum); 1946 1947 $pidfile = $serverpidfile{$server}; 1948 1949 # don't retry if the server doesn't work 1950 if ($doesntrun{$pidfile}) { 1951 return (0,0); 1952 } 1953 1954 my $pid = processexists($pidfile); 1955 if($pid > 0) { 1956 stopserver($server, "$pid"); 1957 } 1958 unlink($pidfile) if(-f $pidfile); 1959 1960 $srvrname = servername_str($proto, $ipvnum, $idnum); 1961 1962 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 1963 1964 $flags .= "--verbose " if($verbose); 1965 $flags .= "--debugprotocol " if($debugprotocol); 1966 $flags .= "--pidfile \"$pidfile\" "; 1967 $flags .= "--id $idnum " if($idnum > 1); 1968 $flags .= "--ipv$ipvnum --addr \"$ip\" "; 1969 $flags .= "--sshport $port --socksport $socksport "; 1970 $flags .= "--user \"$USER\""; 1971 1972 my $cmd = "$perl $srcdir/sshserver.pl $flags"; 1973 my ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0); 1974 1975 # on loaded systems sshserver start up can take longer than the timeout 1976 # passed to startnew, when this happens startnew completes without being 1977 # able to read the pidfile and consequently returns a zero pid2 above. 1978 1979 if($sshpid <= 0 || !pidexists($sshpid)) { 1980 # it is NOT alive 1981 logmsg "RUN: failed to start the $srvrname server\n"; 1982 stopserver($server, "$pid2"); 1983 $doesntrun{$pidfile} = 1; 1984 return (0,0); 1985 } 1986 1987 # ssh server verification allows some extra time for the server to start up 1988 # and gives us the opportunity of recovering the pid from the pidfile, when 1989 # this verification succeeds the recovered pid is assigned to pid2. 1990 1991 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); 1992 if(!$pid3) { 1993 logmsg "RUN: $srvrname server failed verification\n"; 1994 # failed to fetch server pid. Kill the server and return failure 1995 stopserver($server, "$sshpid $pid2"); 1996 $doesntrun{$pidfile} = 1; 1997 return (0,0); 1998 } 1999 $pid2 = $pid3; 2000 2001 # once it is known that the ssh server is alive, sftp server verification 2002 # is performed actually connecting to it, authenticating and performing a 2003 # very simple remote command. This verification is tried only one time. 2004 2005 $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum); 2006 $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum); 2007 2008 if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) { 2009 logmsg "RUN: SFTP server failed verification\n"; 2010 # failed to talk to it properly. Kill the server and return failure 2011 display_sftplog(); 2012 display_sftpconfig(); 2013 display_sshdlog(); 2014 display_sshdconfig(); 2015 stopserver($server, "$sshpid $pid2"); 2016 $doesntrun{$pidfile} = 1; 2017 return (0,0); 2018 } 2019 2020 if($verbose) { 2021 logmsg "RUN: $srvrname server is now running PID $pid2\n"; 2022 } 2023 2024 return ($pid2, $sshpid); 2025} 2026 2027####################################################################### 2028# Start the socks server 2029# 2030sub runsocksserver { 2031 my ($id, $verbose, $ipv6) = @_; 2032 my $ip=$HOSTIP; 2033 my $port = $SOCKSPORT; 2034 my $proto = 'socks'; 2035 my $ipvnum = 4; 2036 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1; 2037 my $server; 2038 my $srvrname; 2039 my $pidfile; 2040 my $logfile; 2041 my $flags = ""; 2042 2043 $server = servername_id($proto, $ipvnum, $idnum); 2044 2045 $pidfile = $serverpidfile{$server}; 2046 2047 # don't retry if the server doesn't work 2048 if ($doesntrun{$pidfile}) { 2049 return (0,0); 2050 } 2051 2052 my $pid = processexists($pidfile); 2053 if($pid > 0) { 2054 stopserver($server, "$pid"); 2055 } 2056 unlink($pidfile) if(-f $pidfile); 2057 2058 $srvrname = servername_str($proto, $ipvnum, $idnum); 2059 2060 $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); 2061 2062 # The ssh server must be already running 2063 if(!$run{'ssh'}) { 2064 logmsg "RUN: SOCKS server cannot find running SSH server\n"; 2065 $doesntrun{$pidfile} = 1; 2066 return (0,0); 2067 } 2068 2069 # Find out ssh daemon canonical file name 2070 my $sshd = find_sshd(); 2071 if(!$sshd) { 2072 logmsg "RUN: SOCKS server cannot find $sshdexe\n"; 2073 $doesntrun{$pidfile} = 1; 2074 return (0,0); 2075 } 2076 2077 # Find out ssh daemon version info 2078 ($sshdid, $sshdvernum, $sshdverstr, $sshderror) = sshversioninfo($sshd); 2079 if(!$sshdid) { 2080 # Not an OpenSSH or SunSSH ssh daemon 2081 logmsg "$sshderror\n" if($verbose); 2082 logmsg "SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later\n"; 2083 $doesntrun{$pidfile} = 1; 2084 return (0,0); 2085 } 2086 logmsg "ssh server found $sshd is $sshdverstr\n" if($verbose); 2087 2088 # Find out ssh client canonical file name 2089 my $ssh = find_ssh(); 2090 if(!$ssh) { 2091 logmsg "RUN: SOCKS server cannot find $sshexe\n"; 2092 $doesntrun{$pidfile} = 1; 2093 return (0,0); 2094 } 2095 2096 # Find out ssh client version info 2097 my ($sshid, $sshvernum, $sshverstr, $ssherror) = sshversioninfo($ssh); 2098 if(!$sshid) { 2099 # Not an OpenSSH or SunSSH ssh client 2100 logmsg "$ssherror\n" if($verbose); 2101 logmsg "SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later\n"; 2102 $doesntrun{$pidfile} = 1; 2103 return (0,0); 2104 } 2105 2106 # Verify minimum ssh client version 2107 if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) || 2108 (($sshid =~ /SunSSH/) && ($sshvernum < 100))) { 2109 logmsg "ssh client found $ssh is $sshverstr\n"; 2110 logmsg "SCP, SFTP and SOCKS tests require OpenSSH 2.9.9 or later\n"; 2111 $doesntrun{$pidfile} = 1; 2112 return (0,0); 2113 } 2114 logmsg "ssh client found $ssh is $sshverstr\n" if($verbose); 2115 2116 # Verify if ssh client and ssh daemon versions match 2117 if(($sshdid ne $sshid) || ($sshdvernum != $sshvernum)) { 2118 # Our test harness might work with slightly mismatched versions 2119 logmsg "Warning: version mismatch: sshd $sshdverstr - ssh $sshverstr\n" 2120 if($verbose); 2121 } 2122 2123 # Config file options for ssh client are previously set from sshserver.pl 2124 if(! -e $sshconfig) { 2125 logmsg "RUN: SOCKS server cannot find $sshconfig\n"; 2126 $doesntrun{$pidfile} = 1; 2127 return (0,0); 2128 } 2129 2130 $sshlog = server_logfilename($LOGDIR, 'socks', $ipvnum, $idnum); 2131 2132 # start our socks server 2133 my $cmd="\"$ssh\" -N -F $sshconfig $ip > $sshlog 2>&1"; 2134 my ($sshpid, $pid2) = startnew($cmd, $pidfile, 30, 1); # fake pidfile 2135 2136 if($sshpid <= 0 || !pidexists($sshpid)) { 2137 # it is NOT alive 2138 logmsg "RUN: failed to start the $srvrname server\n"; 2139 display_sshlog(); 2140 display_sshconfig(); 2141 display_sshdlog(); 2142 display_sshdconfig(); 2143 stopserver($server, "$pid2"); 2144 $doesntrun{$pidfile} = 1; 2145 return (0,0); 2146 } 2147 2148 # Ugly hack but ssh doesn't support pid files. PID is from fake pidfile. 2149 my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); 2150 if(!$pid3) { 2151 logmsg "RUN: $srvrname server failed verification\n"; 2152 # failed to talk to it properly. Kill the server and return failure 2153 stopserver($server, "$sshpid $pid2"); 2154 $doesntrun{$pidfile} = 1; 2155 return (0,0); 2156 } 2157 $pid2 = $pid3; 2158 2159 if($verbose) { 2160 logmsg "RUN: $srvrname server is now running PID $pid2\n"; 2161 } 2162 2163 return ($pid2, $sshpid); 2164} 2165 2166####################################################################### 2167# Single shot http and gopher server responsiveness test. This should only 2168# be used to verify that a server present in %run hash is still functional 2169# 2170sub responsive_http_server { 2171 my ($proto, $verbose, $alt, $port_or_path) = @_; 2172 my $ip = $HOSTIP; 2173 my $ipvnum = 4; 2174 my $idnum = 1; 2175 2176 if($alt eq "ipv6") { 2177 # if IPv6, use a different setup 2178 $ipvnum = 6; 2179 $ip = $HOST6IP; 2180 } 2181 elsif($alt eq "proxy") { 2182 $idnum = 2; 2183 } 2184 elsif($alt eq "unix") { 2185 # IP (protocol) is mutually exclusive with Unix sockets 2186 $ipvnum = "unix"; 2187 } 2188 2189 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path); 2190} 2191 2192####################################################################### 2193# Single shot pingpong server responsiveness test. This should only be 2194# used to verify that a server present in %run hash is still functional 2195# 2196sub responsive_pingpong_server { 2197 my ($proto, $id, $verbose, $ipv6) = @_; 2198 my $port; 2199 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP"; 2200 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4; 2201 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1; 2202 2203 if($proto eq "ftp") { 2204 $port = ($idnum>1)?$FTP2PORT:$FTPPORT; 2205 2206 if($ipvnum==6) { 2207 # if IPv6, use a different setup 2208 $port = $FTP6PORT; 2209 } 2210 } 2211 elsif($proto eq "pop3") { 2212 $port = ($ipvnum==6) ? $POP36PORT : $POP3PORT; 2213 } 2214 elsif($proto eq "imap") { 2215 $port = ($ipvnum==6) ? $IMAP6PORT : $IMAPPORT; 2216 } 2217 elsif($proto eq "smtp") { 2218 $port = ($ipvnum==6) ? $SMTP6PORT : $SMTPPORT; 2219 } 2220 else { 2221 print STDERR "Unsupported protocol $proto!!\n"; 2222 return 0; 2223 } 2224 2225 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port); 2226} 2227 2228####################################################################### 2229# Single shot rtsp server responsiveness test. This should only be 2230# used to verify that a server present in %run hash is still functional 2231# 2232sub responsive_rtsp_server { 2233 my ($verbose, $ipv6) = @_; 2234 my $port = $RTSPPORT; 2235 my $ip = $HOSTIP; 2236 my $proto = 'rtsp'; 2237 my $ipvnum = 4; 2238 my $idnum = 1; 2239 2240 if($ipv6) { 2241 # if IPv6, use a different setup 2242 $ipvnum = 6; 2243 $port = $RTSP6PORT; 2244 $ip = $HOST6IP; 2245 } 2246 2247 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port); 2248} 2249 2250####################################################################### 2251# Single shot tftp server responsiveness test. This should only be 2252# used to verify that a server present in %run hash is still functional 2253# 2254sub responsive_tftp_server { 2255 my ($id, $verbose, $ipv6) = @_; 2256 my $port = $TFTPPORT; 2257 my $ip = $HOSTIP; 2258 my $proto = 'tftp'; 2259 my $ipvnum = 4; 2260 my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1; 2261 2262 if($ipv6) { 2263 # if IPv6, use a different setup 2264 $ipvnum = 6; 2265 $port = $TFTP6PORT; 2266 $ip = $HOST6IP; 2267 } 2268 2269 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port); 2270} 2271 2272####################################################################### 2273# Single shot non-stunnel HTTP TLS extensions capable server 2274# responsiveness test. This should only be used to verify that a 2275# server present in %run hash is still functional 2276# 2277sub responsive_httptls_server { 2278 my ($verbose, $ipv6) = @_; 2279 my $proto = "httptls"; 2280 my $port = ($ipv6 && ($ipv6 =~ /6$/)) ? $HTTPTLS6PORT : $HTTPTLSPORT; 2281 my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP"; 2282 my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4; 2283 my $idnum = 1; 2284 2285 return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port); 2286} 2287 2288####################################################################### 2289# Remove all files in the specified directory 2290# 2291sub cleardir { 2292 my $dir = $_[0]; 2293 my $count; 2294 my $file; 2295 2296 # Get all files 2297 opendir(DIR, $dir) || 2298 return 0; # can't open dir 2299 while($file = readdir(DIR)) { 2300 if($file !~ /^\./) { 2301 unlink("$dir/$file"); 2302 $count++; 2303 } 2304 } 2305 closedir DIR; 2306 return $count; 2307} 2308 2309####################################################################### 2310# compare test results with the expected output, we might filter off 2311# some pattern that is allowed to differ, output test results 2312# 2313sub compare { 2314 my ($testnum, $testname, $subject, $firstref, $secondref)=@_; 2315 2316 my $result = compareparts($firstref, $secondref); 2317 2318 if($result) { 2319 # timestamp test result verification end 2320 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 2321 2322 if(!$short) { 2323 logmsg "\n $testnum: $subject FAILED:\n"; 2324 logmsg showdiff($LOGDIR, $firstref, $secondref); 2325 } 2326 elsif(!$automakestyle) { 2327 logmsg "FAILED\n"; 2328 } 2329 else { 2330 # automakestyle 2331 logmsg "FAIL: $testnum - $testname - $subject\n"; 2332 } 2333 } 2334 return $result; 2335} 2336 2337####################################################################### 2338# display information about curl and the host the test suite runs on 2339# 2340sub checksystem { 2341 2342 unlink($memdump); # remove this if there was one left 2343 2344 my $feat; 2345 my $curl; 2346 my $libcurl; 2347 my $versretval; 2348 my $versnoexec; 2349 my @version=(); 2350 2351 my $curlverout="$LOGDIR/curlverout.log"; 2352 my $curlvererr="$LOGDIR/curlvererr.log"; 2353 my $versioncmd="$CURL --version 1>$curlverout 2>$curlvererr"; 2354 2355 unlink($curlverout); 2356 unlink($curlvererr); 2357 2358 $versretval = runclient($versioncmd); 2359 $versnoexec = $!; 2360 2361 open(VERSOUT, "<$curlverout"); 2362 @version = <VERSOUT>; 2363 close(VERSOUT); 2364 2365 $resolver="stock"; 2366 for(@version) { 2367 chomp; 2368 2369 if($_ =~ /^curl/) { 2370 $curl = $_; 2371 $curl =~ s/^(.*)(libcurl.*)/$1/g; 2372 2373 $libcurl = $2; 2374 if($curl =~ /win32|mingw(32|64)/) { 2375 # This is a Windows MinGW build or native build, we need to use 2376 # Win32-style path. 2377 $pwd = pathhelp::sys_native_current_path(); 2378 } 2379 if ($libcurl =~ /winssl/i) { 2380 $has_winssl=1; 2381 $ssllib="WinSSL"; 2382 } 2383 elsif ($libcurl =~ /openssl/i) { 2384 $has_openssl=1; 2385 $has_sslpinning=1; 2386 $ssllib="OpenSSL"; 2387 } 2388 elsif ($libcurl =~ /gnutls/i) { 2389 $has_gnutls=1; 2390 $has_sslpinning=1; 2391 $ssllib="GnuTLS"; 2392 } 2393 elsif ($libcurl =~ /nss/i) { 2394 $has_nss=1; 2395 $has_sslpinning=1; 2396 $ssllib="NSS"; 2397 } 2398 elsif ($libcurl =~ /(yassl|wolfssl)/i) { 2399 $has_yassl=1; 2400 $has_sslpinning=1; 2401 $ssllib="yassl"; 2402 } 2403 elsif ($libcurl =~ /polarssl/i) { 2404 $has_polarssl=1; 2405 $has_sslpinning=1; 2406 $ssllib="polarssl"; 2407 } 2408 elsif ($libcurl =~ /axtls/i) { 2409 $has_axtls=1; 2410 $ssllib="axTLS"; 2411 } 2412 elsif ($libcurl =~ /securetransport/i) { 2413 $has_darwinssl=1; 2414 $ssllib="DarwinSSL"; 2415 } 2416 elsif ($libcurl =~ /BoringSSL/i) { 2417 $has_boringssl=1; 2418 $has_sslpinning=1; 2419 $ssllib="BoringSSL"; 2420 } 2421 elsif ($libcurl =~ /libressl/i) { 2422 $has_libressl=1; 2423 $has_sslpinning=1; 2424 $ssllib="libressl"; 2425 } 2426 elsif ($libcurl =~ /mbedTLS/i) { 2427 $has_mbedtls=1; 2428 $has_sslpinning=1; 2429 $ssllib="mbedTLS"; 2430 } 2431 if ($libcurl =~ /ares/i) { 2432 $has_cares=1; 2433 $resolver="c-ares"; 2434 } 2435 } 2436 elsif($_ =~ /^Protocols: (.*)/i) { 2437 # these are the protocols compiled in to this libcurl 2438 @protocols = split(' ', lc($1)); 2439 2440 # Generate a "proto-ipv6" version of each protocol to match the 2441 # IPv6 <server> name and a "proto-unix" to match the variant which 2442 # uses Unix domain sockets. This works even if support isn't 2443 # compiled in because the <features> test will fail. 2444 push @protocols, map(("$_-ipv6", "$_-unix"), @protocols); 2445 2446 # 'http-proxy' is used in test cases to do CONNECT through 2447 push @protocols, 'http-proxy'; 2448 2449 # 'http-pipe' is the special server for testing pipelining 2450 push @protocols, 'http-pipe'; 2451 2452 # 'none' is used in test cases to mean no server 2453 push @protocols, 'none'; 2454 } 2455 elsif($_ =~ /^Features: (.*)/i) { 2456 $feat = $1; 2457 if($feat =~ /TrackMemory/i) { 2458 # built with memory tracking support (--enable-curldebug) 2459 $has_memory_tracking = 1; 2460 } 2461 if($feat =~ /debug/i) { 2462 # curl was built with --enable-debug 2463 $debug_build = 1; 2464 } 2465 if($feat =~ /SSL/i) { 2466 # ssl enabled 2467 $has_ssl=1; 2468 } 2469 if($feat =~ /Largefile/i) { 2470 # large file support 2471 $has_largefile=1; 2472 } 2473 if($feat =~ /IDN/i) { 2474 # IDN support 2475 $has_idn=1; 2476 } 2477 if($feat =~ /IPv6/i) { 2478 $has_ipv6 = 1; 2479 } 2480 if($feat =~ /UnixSockets/i) { 2481 $has_unix = 1; 2482 } 2483 if($feat =~ /libz/i) { 2484 $has_libz = 1; 2485 } 2486 if($feat =~ /NTLM/i) { 2487 # NTLM enabled 2488 $has_ntlm=1; 2489 2490 # Use this as a proxy for any cryptographic authentication 2491 $has_crypto=1; 2492 } 2493 if($feat =~ /NTLM_WB/i) { 2494 # NTLM delegation to winbind daemon ntlm_auth helper enabled 2495 $has_ntlm_wb=1; 2496 } 2497 if($feat =~ /SSPI/i) { 2498 # SSPI enabled 2499 $has_sspi=1; 2500 } 2501 if($feat =~ /GSS-API/i) { 2502 # GSS-API enabled 2503 $has_gssapi=1; 2504 } 2505 if($feat =~ /Kerberos/i) { 2506 # Kerberos enabled 2507 $has_kerberos=1; 2508 2509 # Use this as a proxy for any cryptographic authentication 2510 $has_crypto=1; 2511 } 2512 if($feat =~ /SPNEGO/i) { 2513 # SPNEGO enabled 2514 $has_spnego=1; 2515 2516 # Use this as a proxy for any cryptographic authentication 2517 $has_crypto=1; 2518 } 2519 if($feat =~ /CharConv/i) { 2520 # CharConv enabled 2521 $has_charconv=1; 2522 } 2523 if($feat =~ /TLS-SRP/i) { 2524 # TLS-SRP enabled 2525 $has_tls_srp=1; 2526 } 2527 if($feat =~ /Metalink/i) { 2528 # Metalink enabled 2529 $has_metalink=1; 2530 } 2531 if($feat =~ /PSL/i) { 2532 # PSL enabled 2533 $has_psl=1; 2534 } 2535 if($feat =~ /AsynchDNS/i) { 2536 if(!$has_cares) { 2537 # this means threaded resolver 2538 $has_threadedres=1; 2539 $resolver="threaded"; 2540 } 2541 } 2542 if($feat =~ /HTTP2/) { 2543 # http2 enabled 2544 $has_http2=1; 2545 2546 push @protocols, 'http/2'; 2547 } 2548 } 2549 # 2550 # Test harness currently uses a non-stunnel server in order to 2551 # run HTTP TLS-SRP tests required when curl is built with https 2552 # protocol support and TLS-SRP feature enabled. For convenience 2553 # 'httptls' may be included in the test harness protocols array 2554 # to differentiate this from classic stunnel based 'https' test 2555 # harness server. 2556 # 2557 if($has_tls_srp) { 2558 my $add_httptls; 2559 for(@protocols) { 2560 if($_ =~ /^https(-ipv6|)$/) { 2561 $add_httptls=1; 2562 last; 2563 } 2564 } 2565 if($add_httptls && (! grep /^httptls$/, @protocols)) { 2566 push @protocols, 'httptls'; 2567 push @protocols, 'httptls-ipv6'; 2568 } 2569 } 2570 } 2571 if(!$curl) { 2572 logmsg "unable to get curl's version, further details are:\n"; 2573 logmsg "issued command: \n"; 2574 logmsg "$versioncmd \n"; 2575 if ($versretval == -1) { 2576 logmsg "command failed with: \n"; 2577 logmsg "$versnoexec \n"; 2578 } 2579 elsif ($versretval & 127) { 2580 logmsg sprintf("command died with signal %d, and %s coredump.\n", 2581 ($versretval & 127), ($versretval & 128)?"a":"no"); 2582 } 2583 else { 2584 logmsg sprintf("command exited with value %d \n", $versretval >> 8); 2585 } 2586 logmsg "contents of $curlverout: \n"; 2587 displaylogcontent("$curlverout"); 2588 logmsg "contents of $curlvererr: \n"; 2589 displaylogcontent("$curlvererr"); 2590 die "couldn't get curl's version"; 2591 } 2592 2593 if(-r "../lib/curl_config.h") { 2594 open(CONF, "<../lib/curl_config.h"); 2595 while(<CONF>) { 2596 if($_ =~ /^\#define HAVE_GETRLIMIT/) { 2597 $has_getrlimit = 1; 2598 } 2599 } 2600 close(CONF); 2601 } 2602 2603 if($has_ipv6) { 2604 # client has IPv6 support 2605 2606 # check if the HTTP server has it! 2607 my @sws = `server/sws --version`; 2608 if($sws[0] =~ /IPv6/) { 2609 # HTTP server has IPv6 support! 2610 $http_ipv6 = 1; 2611 $gopher_ipv6 = 1; 2612 } 2613 2614 # check if the FTP server has it! 2615 @sws = `server/sockfilt --version`; 2616 if($sws[0] =~ /IPv6/) { 2617 # FTP server has IPv6 support! 2618 $ftp_ipv6 = 1; 2619 } 2620 } 2621 2622 if($has_unix) { 2623 # client has Unix sockets support, check whether the HTTP server has it 2624 my @sws = `server/sws --version`; 2625 $http_unix = 1 if($sws[0] =~ /unix/); 2626 } 2627 2628 if(!$has_memory_tracking && $torture) { 2629 die "can't run torture tests since curl was built without ". 2630 "TrackMemory feature (--enable-curldebug)"; 2631 } 2632 2633 $has_shared = `sh $CURLCONFIG --built-shared`; 2634 chomp $has_shared; 2635 2636 my $hostname=join(' ', runclientoutput("hostname")); 2637 my $hosttype=join(' ', runclientoutput("uname -a")); 2638 2639 logmsg ("********* System characteristics ******** \n", 2640 "* $curl\n", 2641 "* $libcurl\n", 2642 "* Features: $feat\n", 2643 "* Host: $hostname", 2644 "* System: $hosttype"); 2645 2646 if($has_memory_tracking && $has_threadedres) { 2647 $has_memory_tracking = 0; 2648 logmsg("*\n", 2649 "*** DISABLES memory tracking when using threaded resolver\n", 2650 "*\n"); 2651 } 2652 2653 logmsg sprintf("* Servers: %s", $stunnel?"SSL ":""); 2654 logmsg sprintf("%s", $http_ipv6?"HTTP-IPv6 ":""); 2655 logmsg sprintf("%s", $http_unix?"HTTP-unix ":""); 2656 logmsg sprintf("%s\n", $ftp_ipv6?"FTP-IPv6 ":"OFF"); 2657 2658 logmsg sprintf("* Env: %s%s", $valgrind?"Valgrind ":"", 2659 $run_event_based?"event-based ":""); 2660 logmsg sprintf("%s\n", $libtool?"Libtool ":""); 2661 2662 if($verbose) { 2663 logmsg "* Ports:\n"; 2664 2665 logmsg sprintf("* HTTP/%d ", $HTTPPORT); 2666 logmsg sprintf("FTP/%d ", $FTPPORT); 2667 logmsg sprintf("FTP2/%d ", $FTP2PORT); 2668 logmsg sprintf("RTSP/%d ", $RTSPPORT); 2669 if($stunnel) { 2670 logmsg sprintf("FTPS/%d ", $FTPSPORT); 2671 logmsg sprintf("HTTPS/%d ", $HTTPSPORT); 2672 } 2673 logmsg sprintf("\n* TFTP/%d ", $TFTPPORT); 2674 if($http_ipv6) { 2675 logmsg sprintf("HTTP-IPv6/%d ", $HTTP6PORT); 2676 logmsg sprintf("RTSP-IPv6/%d ", $RTSP6PORT); 2677 } 2678 if($ftp_ipv6) { 2679 logmsg sprintf("FTP-IPv6/%d ", $FTP6PORT); 2680 } 2681 if($tftp_ipv6) { 2682 logmsg sprintf("TFTP-IPv6/%d ", $TFTP6PORT); 2683 } 2684 logmsg sprintf("\n* GOPHER/%d ", $GOPHERPORT); 2685 if($gopher_ipv6) { 2686 logmsg sprintf("GOPHER-IPv6/%d", $GOPHERPORT); 2687 } 2688 logmsg sprintf("\n* SSH/%d ", $SSHPORT); 2689 logmsg sprintf("SOCKS/%d ", $SOCKSPORT); 2690 logmsg sprintf("POP3/%d ", $POP3PORT); 2691 logmsg sprintf("IMAP/%d ", $IMAPPORT); 2692 logmsg sprintf("SMTP/%d\n", $SMTPPORT); 2693 if($ftp_ipv6) { 2694 logmsg sprintf("* POP3-IPv6/%d ", $POP36PORT); 2695 logmsg sprintf("IMAP-IPv6/%d ", $IMAP6PORT); 2696 logmsg sprintf("SMTP-IPv6/%d\n", $SMTP6PORT); 2697 } 2698 if($httptlssrv) { 2699 logmsg sprintf("* HTTPTLS/%d ", $HTTPTLSPORT); 2700 if($has_ipv6) { 2701 logmsg sprintf("HTTPTLS-IPv6/%d ", $HTTPTLS6PORT); 2702 } 2703 logmsg "\n"; 2704 } 2705 logmsg sprintf("* HTTP-PIPE/%d \n", $HTTPPIPEPORT); 2706 2707 if($has_unix) { 2708 logmsg "* Unix socket paths:\n"; 2709 if($http_unix) { 2710 logmsg sprintf("* HTTP-Unix:%s\n", $HTTPUNIXPATH); 2711 } 2712 } 2713 } 2714 $has_textaware = ($^O eq 'MSWin32') || ($^O eq 'msys'); 2715 2716 logmsg "***************************************** \n"; 2717} 2718 2719####################################################################### 2720# substitute the variable stuff into either a joined up file or 2721# a command, in either case passed by reference 2722# 2723sub subVariables { 2724 my ($thing) = @_; 2725 2726 # ports 2727 2728 $$thing =~ s/%FTP6PORT/$FTP6PORT/g; 2729 $$thing =~ s/%FTP2PORT/$FTP2PORT/g; 2730 $$thing =~ s/%FTPSPORT/$FTPSPORT/g; 2731 $$thing =~ s/%FTPPORT/$FTPPORT/g; 2732 2733 $$thing =~ s/%GOPHER6PORT/$GOPHER6PORT/g; 2734 $$thing =~ s/%GOPHERPORT/$GOPHERPORT/g; 2735 2736 $$thing =~ s/%HTTPTLS6PORT/$HTTPTLS6PORT/g; 2737 $$thing =~ s/%HTTPTLSPORT/$HTTPTLSPORT/g; 2738 $$thing =~ s/%HTTP6PORT/$HTTP6PORT/g; 2739 $$thing =~ s/%HTTPSPORT/$HTTPSPORT/g; 2740 $$thing =~ s/%HTTP2PORT/$HTTP2PORT/g; 2741 $$thing =~ s/%HTTPPORT/$HTTPPORT/g; 2742 $$thing =~ s/%HTTPPIPEPORT/$HTTPPIPEPORT/g; 2743 $$thing =~ s/%PROXYPORT/$HTTPPROXYPORT/g; 2744 2745 $$thing =~ s/%IMAP6PORT/$IMAP6PORT/g; 2746 $$thing =~ s/%IMAPPORT/$IMAPPORT/g; 2747 2748 $$thing =~ s/%POP36PORT/$POP36PORT/g; 2749 $$thing =~ s/%POP3PORT/$POP3PORT/g; 2750 2751 $$thing =~ s/%RTSP6PORT/$RTSP6PORT/g; 2752 $$thing =~ s/%RTSPPORT/$RTSPPORT/g; 2753 2754 $$thing =~ s/%SMTP6PORT/$SMTP6PORT/g; 2755 $$thing =~ s/%SMTPPORT/$SMTPPORT/g; 2756 2757 $$thing =~ s/%SOCKSPORT/$SOCKSPORT/g; 2758 $$thing =~ s/%SSHPORT/$SSHPORT/g; 2759 2760 $$thing =~ s/%TFTP6PORT/$TFTP6PORT/g; 2761 $$thing =~ s/%TFTPPORT/$TFTPPORT/g; 2762 2763 # server Unix domain socket paths 2764 2765 $$thing =~ s/%HTTPUNIXPATH/$HTTPUNIXPATH/g; 2766 2767 # client IP addresses 2768 2769 $$thing =~ s/%CLIENT6IP/$CLIENT6IP/g; 2770 $$thing =~ s/%CLIENTIP/$CLIENTIP/g; 2771 2772 # server IP addresses 2773 2774 $$thing =~ s/%HOST6IP/$HOST6IP/g; 2775 $$thing =~ s/%HOSTIP/$HOSTIP/g; 2776 2777 # misc 2778 2779 $$thing =~ s/%CURL/$CURL/g; 2780 $$thing =~ s/%PWD/$pwd/g; 2781 $$thing =~ s/%SRCDIR/$srcdir/g; 2782 $$thing =~ s/%USER/$USER/g; 2783 2784 # The purpose of FTPTIME2 and FTPTIME3 is to provide times that can be 2785 # used for time-out tests and that whould work on most hosts as these 2786 # adjust for the startup/check time for this particular host. We needed 2787 # to do this to make the test suite run better on very slow hosts. 2788 2789 my $ftp2 = $ftpchecktime * 2; 2790 my $ftp3 = $ftpchecktime * 3; 2791 2792 $$thing =~ s/%FTPTIME2/$ftp2/g; 2793 $$thing =~ s/%FTPTIME3/$ftp3/g; 2794 2795 # HTTP2 2796 2797 $$thing =~ s/%H2CVER/$h2cver/g; 2798} 2799 2800sub fixarray { 2801 my @in = @_; 2802 2803 for(@in) { 2804 subVariables \$_; 2805 } 2806 return @in; 2807} 2808 2809####################################################################### 2810# Provide time stamps for single test skipped events 2811# 2812sub timestampskippedevents { 2813 my $testnum = $_[0]; 2814 2815 return if((not defined($testnum)) || ($testnum < 1)); 2816 2817 if($timestats) { 2818 2819 if($timevrfyend{$testnum}) { 2820 return; 2821 } 2822 elsif($timesrvrlog{$testnum}) { 2823 $timevrfyend{$testnum} = $timesrvrlog{$testnum}; 2824 return; 2825 } 2826 elsif($timetoolend{$testnum}) { 2827 $timevrfyend{$testnum} = $timetoolend{$testnum}; 2828 $timesrvrlog{$testnum} = $timetoolend{$testnum}; 2829 } 2830 elsif($timetoolini{$testnum}) { 2831 $timevrfyend{$testnum} = $timetoolini{$testnum}; 2832 $timesrvrlog{$testnum} = $timetoolini{$testnum}; 2833 $timetoolend{$testnum} = $timetoolini{$testnum}; 2834 } 2835 elsif($timesrvrend{$testnum}) { 2836 $timevrfyend{$testnum} = $timesrvrend{$testnum}; 2837 $timesrvrlog{$testnum} = $timesrvrend{$testnum}; 2838 $timetoolend{$testnum} = $timesrvrend{$testnum}; 2839 $timetoolini{$testnum} = $timesrvrend{$testnum}; 2840 } 2841 elsif($timesrvrini{$testnum}) { 2842 $timevrfyend{$testnum} = $timesrvrini{$testnum}; 2843 $timesrvrlog{$testnum} = $timesrvrini{$testnum}; 2844 $timetoolend{$testnum} = $timesrvrini{$testnum}; 2845 $timetoolini{$testnum} = $timesrvrini{$testnum}; 2846 $timesrvrend{$testnum} = $timesrvrini{$testnum}; 2847 } 2848 elsif($timeprepini{$testnum}) { 2849 $timevrfyend{$testnum} = $timeprepini{$testnum}; 2850 $timesrvrlog{$testnum} = $timeprepini{$testnum}; 2851 $timetoolend{$testnum} = $timeprepini{$testnum}; 2852 $timetoolini{$testnum} = $timeprepini{$testnum}; 2853 $timesrvrend{$testnum} = $timeprepini{$testnum}; 2854 $timesrvrini{$testnum} = $timeprepini{$testnum}; 2855 } 2856 } 2857} 2858 2859####################################################################### 2860# Run a single specified test case 2861# 2862sub singletest { 2863 my ($evbased, # 1 means switch on if possible (and "curl" is tested) 2864 # returns "not a test" if it can't be used for this test 2865 $testnum, 2866 $count, 2867 $total)=@_; 2868 2869 my @what; 2870 my $why; 2871 my %feature; 2872 my $cmd; 2873 my $disablevalgrind; 2874 2875 # copy test number to a global scope var, this allows 2876 # testnum checking when starting test harness servers. 2877 $testnumcheck = $testnum; 2878 2879 # timestamp test preparation start 2880 $timeprepini{$testnum} = Time::HiRes::time() if($timestats); 2881 2882 if($disttests !~ /test$testnum\W/ ) { 2883 logmsg "Warning: test$testnum not present in tests/data/Makefile.inc\n"; 2884 } 2885 if($disabled{$testnum}) { 2886 logmsg "Warning: test$testnum is explicitly disabled\n"; 2887 } 2888 2889 # load the test case file definition 2890 if(loadtest("${TESTDIR}/test${testnum}")) { 2891 if($verbose) { 2892 # this is not a test 2893 logmsg "RUN: $testnum doesn't look like a test case\n"; 2894 } 2895 $why = "no test"; 2896 } 2897 else { 2898 @what = getpart("client", "features"); 2899 } 2900 2901 # We require a feature to be present 2902 for(@what) { 2903 my $f = $_; 2904 $f =~ s/\s//g; 2905 2906 if($f =~ /^([^!].*)$/) { 2907 # Store the feature for later 2908 $feature{$1} = $1; 2909 2910 if($1 eq "SSL") { 2911 if($has_ssl) { 2912 next; 2913 } 2914 } 2915 elsif($1 eq "SSLpinning") { 2916 if($has_sslpinning) { 2917 next; 2918 } 2919 } 2920 elsif($1 eq "OpenSSL") { 2921 if($has_openssl) { 2922 next; 2923 } 2924 } 2925 elsif($1 eq "GnuTLS") { 2926 if($has_gnutls) { 2927 next; 2928 } 2929 } 2930 elsif($1 eq "NSS") { 2931 if($has_nss) { 2932 next; 2933 } 2934 } 2935 elsif($1 eq "axTLS") { 2936 if($has_axtls) { 2937 next; 2938 } 2939 } 2940 elsif($1 eq "WinSSL") { 2941 if($has_winssl) { 2942 next; 2943 } 2944 } 2945 elsif($1 eq "DarwinSSL") { 2946 if($has_darwinssl) { 2947 next; 2948 } 2949 } 2950 elsif($1 eq "unittest") { 2951 if($debug_build) { 2952 next; 2953 } 2954 } 2955 elsif($1 eq "debug") { 2956 if($debug_build) { 2957 next; 2958 } 2959 } 2960 elsif($1 eq "TrackMemory") { 2961 if($has_memory_tracking) { 2962 next; 2963 } 2964 } 2965 elsif($1 eq "large_file") { 2966 if($has_largefile) { 2967 next; 2968 } 2969 } 2970 elsif($1 eq "idn") { 2971 if($has_idn) { 2972 next; 2973 } 2974 } 2975 elsif($1 eq "ipv6") { 2976 if($has_ipv6) { 2977 next; 2978 } 2979 } 2980 elsif($1 eq "libz") { 2981 if($has_libz) { 2982 next; 2983 } 2984 } 2985 elsif($1 eq "NTLM") { 2986 if($has_ntlm) { 2987 next; 2988 } 2989 } 2990 elsif($1 eq "NTLM_WB") { 2991 if($has_ntlm_wb) { 2992 next; 2993 } 2994 } 2995 elsif($1 eq "SSPI") { 2996 if($has_sspi) { 2997 next; 2998 } 2999 } 3000 elsif($1 eq "GSS-API") { 3001 if($has_gssapi) { 3002 next; 3003 } 3004 } 3005 elsif($1 eq "Kerberos") { 3006 if($has_kerberos) { 3007 next; 3008 } 3009 } 3010 elsif($1 eq "SPNEGO") { 3011 if($has_spnego) { 3012 next; 3013 } 3014 } 3015 elsif($1 eq "getrlimit") { 3016 if($has_getrlimit) { 3017 next; 3018 } 3019 } 3020 elsif($1 eq "crypto") { 3021 if($has_crypto) { 3022 next; 3023 } 3024 } 3025 elsif($1 eq "TLS-SRP") { 3026 if($has_tls_srp) { 3027 next; 3028 } 3029 } 3030 elsif($1 eq "Metalink") { 3031 if($has_metalink) { 3032 next; 3033 } 3034 } 3035 elsif($1 eq "http/2") { 3036 if($has_http2) { 3037 next; 3038 } 3039 } 3040 elsif($1 eq "PSL") { 3041 if($has_psl) { 3042 next; 3043 } 3044 } 3045 elsif($1 eq "socks") { 3046 next; 3047 } 3048 elsif($1 eq "unix-sockets") { 3049 next if $has_unix; 3050 } 3051 # See if this "feature" is in the list of supported protocols 3052 elsif (grep /^\Q$1\E$/i, @protocols) { 3053 next; 3054 } 3055 3056 $why = "curl lacks $1 support"; 3057 last; 3058 } 3059 } 3060 3061 # We require a feature to not be present 3062 if(!$why) { 3063 for(@what) { 3064 my $f = $_; 3065 $f =~ s/\s//g; 3066 3067 if($f =~ /^!(.*)$/) { 3068 if($1 eq "SSL") { 3069 if(!$has_ssl) { 3070 next; 3071 } 3072 } 3073 elsif($1 eq "OpenSSL") { 3074 if(!$has_openssl) { 3075 next; 3076 } 3077 } 3078 elsif($1 eq "GnuTLS") { 3079 if(!$has_gnutls) { 3080 next; 3081 } 3082 } 3083 elsif($1 eq "NSS") { 3084 if(!$has_nss) { 3085 next; 3086 } 3087 } 3088 elsif($1 eq "axTLS") { 3089 if(!$has_axtls) { 3090 next; 3091 } 3092 } 3093 elsif($1 eq "WinSSL") { 3094 if(!$has_winssl) { 3095 next; 3096 } 3097 } 3098 elsif($1 eq "DarwinSSL") { 3099 if(!$has_darwinssl) { 3100 next; 3101 } 3102 } 3103 elsif($1 eq "TrackMemory") { 3104 if(!$has_memory_tracking) { 3105 next; 3106 } 3107 } 3108 elsif($1 eq "large_file") { 3109 if(!$has_largefile) { 3110 next; 3111 } 3112 } 3113 elsif($1 eq "idn") { 3114 if(!$has_idn) { 3115 next; 3116 } 3117 } 3118 elsif($1 eq "ipv6") { 3119 if(!$has_ipv6) { 3120 next; 3121 } 3122 } 3123 elsif($1 eq "unix-sockets") { 3124 next if !$has_unix; 3125 } 3126 elsif($1 eq "libz") { 3127 if(!$has_libz) { 3128 next; 3129 } 3130 } 3131 elsif($1 eq "NTLM") { 3132 if(!$has_ntlm) { 3133 next; 3134 } 3135 } 3136 elsif($1 eq "NTLM_WB") { 3137 if(!$has_ntlm_wb) { 3138 next; 3139 } 3140 } 3141 elsif($1 eq "SSPI") { 3142 if(!$has_sspi) { 3143 next; 3144 } 3145 } 3146 elsif($1 eq "GSS-API") { 3147 if(!$has_gssapi) { 3148 next; 3149 } 3150 } 3151 elsif($1 eq "Kerberos") { 3152 if(!$has_kerberos) { 3153 next; 3154 } 3155 } 3156 elsif($1 eq "SPNEGO") { 3157 if(!$has_spnego) { 3158 next; 3159 } 3160 } 3161 elsif($1 eq "getrlimit") { 3162 if(!$has_getrlimit) { 3163 next; 3164 } 3165 } 3166 elsif($1 eq "crypto") { 3167 if(!$has_crypto) { 3168 next; 3169 } 3170 } 3171 elsif($1 eq "TLS-SRP") { 3172 if(!$has_tls_srp) { 3173 next; 3174 } 3175 } 3176 elsif($1 eq "Metalink") { 3177 if(!$has_metalink) { 3178 next; 3179 } 3180 } 3181 elsif($1 eq "PSL") { 3182 if(!$has_psl) { 3183 next; 3184 } 3185 } 3186 else { 3187 next; 3188 } 3189 } 3190 else { 3191 next; 3192 } 3193 3194 $why = "curl has $1 support"; 3195 last; 3196 } 3197 } 3198 3199 if(!$why) { 3200 my @keywords = getpart("info", "keywords"); 3201 my $match; 3202 my $k; 3203 3204 if(!$keywords[0]) { 3205 $why = "missing the <keywords> section!"; 3206 } 3207 3208 for $k (@keywords) { 3209 chomp $k; 3210 if ($disabled_keywords{$k}) { 3211 $why = "disabled by keyword"; 3212 } elsif ($enabled_keywords{$k}) { 3213 $match = 1; 3214 } 3215 } 3216 3217 if(!$why && !$match && %enabled_keywords) { 3218 $why = "disabled by missing keyword"; 3219 } 3220 } 3221 3222 # test definition may instruct to (un)set environment vars 3223 # this is done this early, so that the precheck can use environment 3224 # variables and still bail out fine on errors 3225 3226 # restore environment variables that were modified in a previous run 3227 foreach my $var (keys %oldenv) { 3228 if($oldenv{$var} eq 'notset') { 3229 delete $ENV{$var} if($ENV{$var}); 3230 } 3231 else { 3232 $ENV{$var} = $oldenv{$var}; 3233 } 3234 delete $oldenv{$var}; 3235 } 3236 3237 # remove test server commands file before servers are started/verified 3238 unlink($FTPDCMD) if(-f $FTPDCMD); 3239 3240 # timestamp required servers verification start 3241 $timesrvrini{$testnum} = Time::HiRes::time() if($timestats); 3242 3243 if(!$why) { 3244 $why = serverfortest($testnum); 3245 } 3246 3247 # timestamp required servers verification end 3248 $timesrvrend{$testnum} = Time::HiRes::time() if($timestats); 3249 3250 my @setenv = getpart("client", "setenv"); 3251 if(@setenv) { 3252 foreach my $s (@setenv) { 3253 chomp $s; 3254 subVariables \$s; 3255 if($s =~ /([^=]*)=(.*)/) { 3256 my ($var, $content) = ($1, $2); 3257 # remember current setting, to restore it once test runs 3258 $oldenv{$var} = ($ENV{$var})?"$ENV{$var}":'notset'; 3259 # set new value 3260 if(!$content) { 3261 delete $ENV{$var} if($ENV{$var}); 3262 } 3263 else { 3264 if($var =~ /^LD_PRELOAD/) { 3265 if(exe_ext() && (exe_ext() eq '.exe')) { 3266 # print "Skipping LD_PRELOAD due to lack of OS support\n"; 3267 next; 3268 } 3269 if($debug_build || ($has_shared ne "yes")) { 3270 # print "Skipping LD_PRELOAD due to no release shared build\n"; 3271 next; 3272 } 3273 } 3274 $ENV{$var} = "$content"; 3275 } 3276 } 3277 } 3278 } 3279 3280 if(!$why) { 3281 # TODO: 3282 # Add a precheck cache. If a precheck command was already invoked 3283 # exactly like this, then use the previous result to speed up 3284 # successive test invokes! 3285 3286 my @precheck = getpart("client", "precheck"); 3287 if(@precheck) { 3288 $cmd = $precheck[0]; 3289 chomp $cmd; 3290 subVariables \$cmd; 3291 if($cmd) { 3292 my @p = split(/ /, $cmd); 3293 if($p[0] !~ /\//) { 3294 # the first word, the command, does not contain a slash so 3295 # we will scan the "improved" PATH to find the command to 3296 # be able to run it 3297 my $fullp = checktestcmd($p[0]); 3298 3299 if($fullp) { 3300 $p[0] = $fullp; 3301 } 3302 $cmd = join(" ", @p); 3303 } 3304 3305 my @o = `$cmd 2>/dev/null`; 3306 if($o[0]) { 3307 $why = $o[0]; 3308 chomp $why; 3309 } elsif($?) { 3310 $why = "precheck command error"; 3311 } 3312 logmsg "prechecked $cmd\n" if($verbose); 3313 } 3314 } 3315 } 3316 3317 if($why && !$listonly) { 3318 # there's a problem, count it as "skipped" 3319 $skipped++; 3320 $skipped{$why}++; 3321 $teststat[$testnum]=$why; # store reason for this test case 3322 3323 if(!$short) { 3324 if($skipped{$why} <= 3) { 3325 # show only the first three skips for each reason 3326 logmsg sprintf("test %04d SKIPPED: $why\n", $testnum); 3327 } 3328 } 3329 3330 timestampskippedevents($testnum); 3331 return -1; 3332 } 3333 logmsg sprintf("test %04d...", $testnum) if(!$automakestyle); 3334 3335 # extract the reply data 3336 my @reply = getpart("reply", "data"); 3337 my @replycheck = getpart("reply", "datacheck"); 3338 3339 my %replyattr = getpartattr("reply", "data"); 3340 my %replycheckattr = getpartattr("reply", "datacheck"); 3341 3342 if (@replycheck) { 3343 # we use this file instead to check the final output against 3344 # get the mode attribute 3345 my $filemode=$replycheckattr{'mode'}; 3346 if($filemode && ($filemode eq "text") && $has_textaware) { 3347 # text mode when running on windows: fix line endings 3348 map s/\r\n/\n/g, @replycheck; 3349 map s/\n/\r\n/g, @replycheck; 3350 } 3351 if($replycheckattr{'nonewline'}) { 3352 # Yes, we must cut off the final newline from the final line 3353 # of the datacheck 3354 chomp($replycheck[$#replycheck]); 3355 } 3356 3357 for my $partsuffix (('1', '2', '3', '4')) { 3358 my @replycheckpart = getpart("reply", "datacheck".$partsuffix); 3359 if(@replycheckpart || partexists("reply", "datacheck".$partsuffix) ) { 3360 my %replycheckpartattr = getpartattr("reply", "datacheck".$partsuffix); 3361 # get the mode attribute 3362 my $filemode=$replycheckpartattr{'mode'}; 3363 if($filemode && ($filemode eq "text") && $has_textaware) { 3364 # text mode when running on windows: fix line endings 3365 map s/\r\n/\n/g, @replycheckpart; 3366 map s/\n/\r\n/g, @replycheckpart; 3367 } 3368 if($replycheckpartattr{'nonewline'}) { 3369 # Yes, we must cut off the final newline from the final line 3370 # of the datacheck 3371 chomp($replycheckpart[$#replycheckpart]); 3372 } 3373 push(@replycheck, @replycheckpart); 3374 } 3375 } 3376 3377 @reply=@replycheck; 3378 } 3379 else { 3380 # get the mode attribute 3381 my $filemode=$replyattr{'mode'}; 3382 if($filemode && ($filemode eq "text") && $has_textaware) { 3383 # text mode when running on windows: fix line endings 3384 map s/\r\n/\n/g, @reply; 3385 map s/\n/\r\n/g, @reply; 3386 } 3387 } 3388 3389 # this is the valid protocol blurb curl should generate 3390 my @protocol= fixarray ( getpart("verify", "protocol") ); 3391 3392 # this is the valid protocol blurb curl should generate to a proxy 3393 my @proxyprot = fixarray ( getpart("verify", "proxy") ); 3394 3395 # redirected stdout/stderr to these files 3396 $STDOUT="$LOGDIR/stdout$testnum"; 3397 $STDERR="$LOGDIR/stderr$testnum"; 3398 3399 # if this section exists, we verify that the stdout contained this: 3400 my @validstdout = fixarray ( getpart("verify", "stdout") ); 3401 3402 # if this section exists, we verify upload 3403 my @upload = getpart("verify", "upload"); 3404 3405 # if this section exists, it might be FTP server instructions: 3406 my @ftpservercmd = getpart("reply", "servercmd"); 3407 3408 my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout 3409 3410 # name of the test 3411 my @testname= getpart("client", "name"); 3412 my $testname = $testname[0]; 3413 $testname =~ s/\n//g; 3414 logmsg "[$testname]\n" if(!$short); 3415 3416 if($listonly) { 3417 timestampskippedevents($testnum); 3418 return 0; # look successful 3419 } 3420 3421 my @codepieces = getpart("client", "tool"); 3422 3423 my $tool=""; 3424 if(@codepieces) { 3425 $tool = $codepieces[0]; 3426 chomp $tool; 3427 } 3428 3429 # remove server output logfile 3430 unlink($SERVERIN); 3431 unlink($SERVER2IN); 3432 unlink($PROXYIN); 3433 3434 if(@ftpservercmd) { 3435 # write the instructions to file 3436 writearray($FTPDCMD, \@ftpservercmd); 3437 } 3438 3439 # get the command line options to use 3440 my @blaha; 3441 ($cmd, @blaha)= getpart("client", "command"); 3442 3443 if($cmd) { 3444 # make some nice replace operations 3445 $cmd =~ s/\n//g; # no newlines please 3446 # substitute variables in the command line 3447 subVariables \$cmd; 3448 } 3449 else { 3450 # there was no command given, use something silly 3451 $cmd="-"; 3452 } 3453 if($has_memory_tracking) { 3454 unlink($memdump); 3455 } 3456 3457 # create a (possibly-empty) file before starting the test 3458 my @inputfile=getpart("client", "file"); 3459 my %fileattr = getpartattr("client", "file"); 3460 my $filename=$fileattr{'name'}; 3461 if(@inputfile || $filename) { 3462 if(!$filename) { 3463 logmsg "ERROR: section client=>file has no name attribute\n"; 3464 timestampskippedevents($testnum); 3465 return -1; 3466 } 3467 my $fileContent = join('', @inputfile); 3468 subVariables \$fileContent; 3469# logmsg "DEBUG: writing file " . $filename . "\n"; 3470 open(OUTFILE, ">$filename"); 3471 binmode OUTFILE; # for crapage systems, use binary 3472 print OUTFILE $fileContent; 3473 close(OUTFILE); 3474 } 3475 3476 my %cmdhash = getpartattr("client", "command"); 3477 3478 my $out=""; 3479 3480 if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-output/)) { 3481 #We may slap on --output! 3482 if (!@validstdout) { 3483 $out=" --output $CURLOUT "; 3484 } 3485 } 3486 3487 my $serverlogslocktimeout = $defserverlogslocktimeout; 3488 if($cmdhash{'timeout'}) { 3489 # test is allowed to override default server logs lock timeout 3490 if($cmdhash{'timeout'} =~ /(\d+)/) { 3491 $serverlogslocktimeout = $1 if($1 >= 0); 3492 } 3493 } 3494 3495 my $postcommanddelay = $defpostcommanddelay; 3496 if($cmdhash{'delay'}) { 3497 # test is allowed to specify a delay after command is executed 3498 if($cmdhash{'delay'} =~ /(\d+)/) { 3499 $postcommanddelay = $1 if($1 > 0); 3500 } 3501 } 3502 3503 my $CMDLINE; 3504 my $cmdargs; 3505 my $cmdtype = $cmdhash{'type'} || "default"; 3506 my $fail_due_event_based = $evbased; 3507 if($cmdtype eq "perl") { 3508 # run the command line prepended with "perl" 3509 $cmdargs ="$cmd"; 3510 $CMDLINE = "perl "; 3511 $tool=$CMDLINE; 3512 $disablevalgrind=1; 3513 } 3514 elsif($cmdtype eq "shell") { 3515 # run the command line prepended with "/bin/sh" 3516 $cmdargs ="$cmd"; 3517 $CMDLINE = "/bin/sh "; 3518 $tool=$CMDLINE; 3519 $disablevalgrind=1; 3520 } 3521 elsif(!$tool) { 3522 # run curl, add suitable command line options 3523 $cmd = "-1 ".$cmd if(exists $feature{"SSL"} && ($has_axtls)); 3524 3525 my $inc=""; 3526 if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) { 3527 $inc = " --include"; 3528 } 3529 3530 $cmdargs = "$out$inc "; 3531 $cmdargs .= "--trace-ascii log/trace$testnum "; 3532 $cmdargs .= "--trace-time "; 3533 if($evbased) { 3534 $cmdargs .= "--test-event "; 3535 $fail_due_event_based--; 3536 } 3537 $cmdargs .= $cmd; 3538 } 3539 else { 3540 $cmdargs = " $cmd"; # $cmd is the command line for the test file 3541 $CURLOUT = $STDOUT; # sends received data to stdout 3542 3543 if($tool =~ /^lib/) { 3544 $CMDLINE="$LIBDIR/$tool"; 3545 } 3546 elsif($tool =~ /^unit/) { 3547 $CMDLINE="$UNITDIR/$tool"; 3548 } 3549 3550 if(! -f $CMDLINE) { 3551 logmsg "The tool set in the test case for this: '$tool' does not exist\n"; 3552 timestampskippedevents($testnum); 3553 return -1; 3554 } 3555 $DBGCURL=$CMDLINE; 3556 } 3557 3558 if($gdbthis) { 3559 # gdb is incompatible with valgrind, so disable it when debugging 3560 # Perhaps a better approach would be to run it under valgrind anyway 3561 # with --db-attach=yes or --vgdb=yes. 3562 $disablevalgrind=1; 3563 } 3564 3565 if($fail_due_event_based) { 3566 logmsg "This test cannot run event based\n"; 3567 return -1; 3568 } 3569 3570 my @stdintest = getpart("client", "stdin"); 3571 3572 if(@stdintest) { 3573 my $stdinfile="$LOGDIR/stdin-for-$testnum"; 3574 3575 my %hash = getpartattr("client", "stdin"); 3576 if($hash{'nonewline'}) { 3577 # cut off the final newline from the final line of the stdin data 3578 chomp($stdintest[$#stdintest]); 3579 } 3580 3581 writearray($stdinfile, \@stdintest); 3582 3583 $cmdargs .= " <$stdinfile"; 3584 } 3585 3586 if(!$tool) { 3587 $CMDLINE="$CURL"; 3588 } 3589 3590 my $usevalgrind; 3591 if($valgrind && !$disablevalgrind) { 3592 my @valgrindoption = getpart("verify", "valgrind"); 3593 if((!@valgrindoption) || ($valgrindoption[0] !~ /disable/)) { 3594 $usevalgrind = 1; 3595 my $valgrindcmd = "$valgrind "; 3596 $valgrindcmd .= "$valgrind_tool " if($valgrind_tool); 3597 $valgrindcmd .= "--leak-check=yes "; 3598 $valgrindcmd .= "--suppressions=$srcdir/valgrind.supp "; 3599 # $valgrindcmd .= "--gen-suppressions=all "; 3600 $valgrindcmd .= "--num-callers=16 "; 3601 $valgrindcmd .= "${valgrind_logfile}=$LOGDIR/valgrind$testnum"; 3602 $CMDLINE = "$valgrindcmd $CMDLINE"; 3603 } 3604 } 3605 3606 $CMDLINE .= "$cmdargs >$STDOUT 2>$STDERR"; 3607 3608 if($verbose) { 3609 logmsg "$CMDLINE\n"; 3610 } 3611 3612 print CMDLOG "$CMDLINE\n"; 3613 3614 unlink("core"); 3615 3616 my $dumped_core; 3617 my $cmdres; 3618 3619 # Apr 2007: precommand isn't being used and could be removed 3620 my @precommand= getpart("client", "precommand"); 3621 if($precommand[0]) { 3622 # this is pure perl to eval! 3623 my $code = join("", @precommand); 3624 eval $code; 3625 if($@) { 3626 logmsg "perl: $code\n"; 3627 logmsg "precommand: $@"; 3628 stopservers($verbose); 3629 timestampskippedevents($testnum); 3630 return -1; 3631 } 3632 } 3633 3634 if($gdbthis) { 3635 my $gdbinit = "$TESTDIR/gdbinit$testnum"; 3636 open(GDBCMD, ">$LOGDIR/gdbcmd"); 3637 print GDBCMD "set args $cmdargs\n"; 3638 print GDBCMD "show args\n"; 3639 print GDBCMD "source $gdbinit\n" if -e $gdbinit; 3640 close(GDBCMD); 3641 } 3642 3643 # timestamp starting of test command 3644 $timetoolini{$testnum} = Time::HiRes::time() if($timestats); 3645 3646 # run the command line we built 3647 if ($torture) { 3648 $cmdres = torture($CMDLINE, 3649 "$gdb --directory libtest $DBGCURL -x $LOGDIR/gdbcmd"); 3650 } 3651 elsif($gdbthis) { 3652 my $GDBW = ($gdbxwin) ? "-w" : ""; 3653 runclient("$gdb --directory libtest $DBGCURL $GDBW -x $LOGDIR/gdbcmd"); 3654 $cmdres=0; # makes it always continue after a debugged run 3655 } 3656 else { 3657 $cmdres = runclient("$CMDLINE"); 3658 my $signal_num = $cmdres & 127; 3659 $dumped_core = $cmdres & 128; 3660 3661 if(!$anyway && ($signal_num || $dumped_core)) { 3662 $cmdres = 1000; 3663 } 3664 else { 3665 $cmdres >>= 8; 3666 $cmdres = (2000 + $signal_num) if($signal_num && !$cmdres); 3667 } 3668 } 3669 3670 # timestamp finishing of test command 3671 $timetoolend{$testnum} = Time::HiRes::time() if($timestats); 3672 3673 if(!$dumped_core) { 3674 if(-r "core") { 3675 # there's core file present now! 3676 $dumped_core = 1; 3677 } 3678 } 3679 3680 if($dumped_core) { 3681 logmsg "core dumped\n"; 3682 if(0 && $gdb) { 3683 logmsg "running gdb for post-mortem analysis:\n"; 3684 open(GDBCMD, ">$LOGDIR/gdbcmd2"); 3685 print GDBCMD "bt\n"; 3686 close(GDBCMD); 3687 runclient("$gdb --directory libtest -x $LOGDIR/gdbcmd2 -batch $DBGCURL core "); 3688 # unlink("$LOGDIR/gdbcmd2"); 3689 } 3690 } 3691 3692 # If a server logs advisor read lock file exists, it is an indication 3693 # that the server has not yet finished writing out all its log files, 3694 # including server request log files used for protocol verification. 3695 # So, if the lock file exists the script waits here a certain amount 3696 # of time until the server removes it, or the given time expires. 3697 3698 if($serverlogslocktimeout) { 3699 my $lockretry = $serverlogslocktimeout * 20; 3700 while((-f $SERVERLOGS_LOCK) && $lockretry--) { 3701 select(undef, undef, undef, 0.05); 3702 } 3703 if(($lockretry < 0) && 3704 ($serverlogslocktimeout >= $defserverlogslocktimeout)) { 3705 logmsg "Warning: server logs lock timeout ", 3706 "($serverlogslocktimeout seconds) expired\n"; 3707 } 3708 } 3709 3710 # Test harness ssh server does not have this synchronization mechanism, 3711 # this implies that some ssh server based tests might need a small delay 3712 # once that the client command has run to avoid false test failures. 3713 # 3714 # gnutls-serv also lacks this synchronization mechanism, so gnutls-serv 3715 # based tests might need a small delay once that the client command has 3716 # run to avoid false test failures. 3717 3718 sleep($postcommanddelay) if($postcommanddelay); 3719 3720 # timestamp removal of server logs advisor read lock 3721 $timesrvrlog{$testnum} = Time::HiRes::time() if($timestats); 3722 3723 # test definition might instruct to stop some servers 3724 # stop also all servers relative to the given one 3725 3726 my @killtestservers = getpart("client", "killserver"); 3727 if(@killtestservers) { 3728 # 3729 # All servers relative to the given one must be stopped also 3730 # 3731 my @killservers; 3732 foreach my $server (@killtestservers) { 3733 chomp $server; 3734 if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) { 3735 # given a stunnel ssl server, also kill non-ssl underlying one 3736 push @killservers, "${1}${2}"; 3737 } 3738 elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) { 3739 # given a non-ssl server, also kill stunnel piggybacking one 3740 push @killservers, "${1}s${2}"; 3741 } 3742 elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) { 3743 # given a socks server, also kill ssh underlying one 3744 push @killservers, "ssh${2}"; 3745 } 3746 elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) { 3747 # given a ssh server, also kill socks piggybacking one 3748 push @killservers, "socks${2}"; 3749 } 3750 push @killservers, $server; 3751 } 3752 # 3753 # kill sockfilter processes for pingpong relative servers 3754 # 3755 foreach my $server (@killservers) { 3756 if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) { 3757 my $proto = $1; 3758 my $idnum = ($2 && ($2 > 1)) ? $2 : 1; 3759 my $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4; 3760 killsockfilters($proto, $ipvnum, $idnum, $verbose); 3761 } 3762 } 3763 # 3764 # kill server relative pids clearing them in %run hash 3765 # 3766 my $pidlist; 3767 foreach my $server (@killservers) { 3768 if($run{$server}) { 3769 $pidlist .= "$run{$server} "; 3770 $run{$server} = 0; 3771 } 3772 $runcert{$server} = 0 if($runcert{$server}); 3773 } 3774 killpid($verbose, $pidlist); 3775 # 3776 # cleanup server pid files 3777 # 3778 foreach my $server (@killservers) { 3779 my $pidfile = $serverpidfile{$server}; 3780 my $pid = processexists($pidfile); 3781 if($pid > 0) { 3782 logmsg "Warning: $server server unexpectedly alive\n"; 3783 killpid($verbose, $pid); 3784 } 3785 unlink($pidfile) if(-f $pidfile); 3786 } 3787 } 3788 3789 # remove the test server commands file after each test 3790 unlink($FTPDCMD) if(-f $FTPDCMD); 3791 3792 # run the postcheck command 3793 my @postcheck= getpart("client", "postcheck"); 3794 if(@postcheck) { 3795 $cmd = $postcheck[0]; 3796 chomp $cmd; 3797 subVariables \$cmd; 3798 if($cmd) { 3799 logmsg "postcheck $cmd\n" if($verbose); 3800 my $rc = runclient("$cmd"); 3801 # Must run the postcheck command in torture mode in order 3802 # to clean up, but the result can't be relied upon. 3803 if($rc != 0 && !$torture) { 3804 logmsg " postcheck FAILED\n"; 3805 # timestamp test result verification end 3806 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 3807 return 1; 3808 } 3809 } 3810 } 3811 3812 # restore environment variables that were modified 3813 if(%oldenv) { 3814 foreach my $var (keys %oldenv) { 3815 if($oldenv{$var} eq 'notset') { 3816 delete $ENV{$var} if($ENV{$var}); 3817 } 3818 else { 3819 $ENV{$var} = "$oldenv{$var}"; 3820 } 3821 } 3822 } 3823 3824 # Skip all the verification on torture tests 3825 if ($torture) { 3826 if(!$cmdres && !$keepoutfiles) { 3827 cleardir($LOGDIR); 3828 } 3829 # timestamp test result verification end 3830 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 3831 return $cmdres; 3832 } 3833 3834 my @err = getpart("verify", "errorcode"); 3835 my $errorcode = $err[0] || "0"; 3836 my $ok=""; 3837 my $res; 3838 chomp $errorcode; 3839 if (@validstdout) { 3840 # verify redirected stdout 3841 my @actual = loadarray($STDOUT); 3842 3843 # what parts to cut off from stdout 3844 my @stripfile = getpart("verify", "stripfile"); 3845 3846 foreach my $strip (@stripfile) { 3847 chomp $strip; 3848 my @newgen; 3849 for(@actual) { 3850 eval $strip; 3851 if($_) { 3852 push @newgen, $_; 3853 } 3854 } 3855 # this is to get rid of array entries that vanished (zero 3856 # length) because of replacements 3857 @actual = @newgen; 3858 } 3859 3860 # variable-replace in the stdout we have from the test case file 3861 @validstdout = fixarray(@validstdout); 3862 3863 # get all attributes 3864 my %hash = getpartattr("verify", "stdout"); 3865 3866 # get the mode attribute 3867 my $filemode=$hash{'mode'}; 3868 if($filemode && ($filemode eq "text") && $has_textaware) { 3869 # text mode when running on windows: fix line endings 3870 map s/\r\n/\n/g, @validstdout; 3871 map s/\n/\r\n/g, @validstdout; 3872 } 3873 3874 if($hash{'nonewline'}) { 3875 # Yes, we must cut off the final newline from the final line 3876 # of the protocol data 3877 chomp($validstdout[$#validstdout]); 3878 } 3879 3880 $res = compare($testnum, $testname, "stdout", \@actual, \@validstdout); 3881 if($res) { 3882 return 1; 3883 } 3884 $ok .= "s"; 3885 } 3886 else { 3887 $ok .= "-"; # stdout not checked 3888 } 3889 3890 if(@protocol) { 3891 # Verify the sent request 3892 my @out = loadarray($SERVERIN); 3893 3894 # what to cut off from the live protocol sent by curl 3895 my @strip = getpart("verify", "strip"); 3896 3897 my @protstrip=@protocol; 3898 3899 # check if there's any attributes on the verify/protocol section 3900 my %hash = getpartattr("verify", "protocol"); 3901 3902 if($hash{'nonewline'}) { 3903 # Yes, we must cut off the final newline from the final line 3904 # of the protocol data 3905 chomp($protstrip[$#protstrip]); 3906 } 3907 3908 for(@strip) { 3909 # strip off all lines that match the patterns from both arrays 3910 chomp $_; 3911 @out = striparray( $_, \@out); 3912 @protstrip= striparray( $_, \@protstrip); 3913 } 3914 3915 # what parts to cut off from the protocol 3916 my @strippart = getpart("verify", "strippart"); 3917 my $strip; 3918 for $strip (@strippart) { 3919 chomp $strip; 3920 for(@out) { 3921 eval $strip; 3922 } 3923 } 3924 3925 $res = compare($testnum, $testname, "protocol", \@out, \@protstrip); 3926 if($res) { 3927 return 1; 3928 } 3929 3930 $ok .= "p"; 3931 3932 } 3933 else { 3934 $ok .= "-"; # protocol not checked 3935 } 3936 3937 if(!$replyattr{'nocheck'} && (@reply || $replyattr{'sendzero'})) { 3938 # verify the received data 3939 my @out = loadarray($CURLOUT); 3940 $res = compare($testnum, $testname, "data", \@out, \@reply); 3941 if ($res) { 3942 return 1; 3943 } 3944 $ok .= "d"; 3945 } 3946 else { 3947 $ok .= "-"; # data not checked 3948 } 3949 3950 if(@upload) { 3951 # verify uploaded data 3952 my @out = loadarray("$LOGDIR/upload.$testnum"); 3953 $res = compare($testnum, $testname, "upload", \@out, \@upload); 3954 if ($res) { 3955 return 1; 3956 } 3957 $ok .= "u"; 3958 } 3959 else { 3960 $ok .= "-"; # upload not checked 3961 } 3962 3963 if(@proxyprot) { 3964 # Verify the sent proxy request 3965 my @out = loadarray($PROXYIN); 3966 3967 # what to cut off from the live protocol sent by curl, we use the 3968 # same rules as for <protocol> 3969 my @strip = getpart("verify", "strip"); 3970 3971 my @protstrip=@proxyprot; 3972 3973 # check if there's any attributes on the verify/protocol section 3974 my %hash = getpartattr("verify", "proxy"); 3975 3976 if($hash{'nonewline'}) { 3977 # Yes, we must cut off the final newline from the final line 3978 # of the protocol data 3979 chomp($protstrip[$#protstrip]); 3980 } 3981 3982 for(@strip) { 3983 # strip off all lines that match the patterns from both arrays 3984 chomp $_; 3985 @out = striparray( $_, \@out); 3986 @protstrip= striparray( $_, \@protstrip); 3987 } 3988 3989 # what parts to cut off from the protocol 3990 my @strippart = getpart("verify", "strippart"); 3991 my $strip; 3992 for $strip (@strippart) { 3993 chomp $strip; 3994 for(@out) { 3995 eval $strip; 3996 } 3997 } 3998 3999 $res = compare($testnum, $testname, "proxy", \@out, \@protstrip); 4000 if($res) { 4001 return 1; 4002 } 4003 4004 $ok .= "P"; 4005 4006 } 4007 else { 4008 $ok .= "-"; # protocol not checked 4009 } 4010 4011 my $outputok; 4012 for my $partsuffix (('', '1', '2', '3', '4')) { 4013 my @outfile=getpart("verify", "file".$partsuffix); 4014 if(@outfile || partexists("verify", "file".$partsuffix) ) { 4015 # we're supposed to verify a dynamically generated file! 4016 my %hash = getpartattr("verify", "file".$partsuffix); 4017 4018 my $filename=$hash{'name'}; 4019 if(!$filename) { 4020 logmsg "ERROR: section verify=>file$partsuffix ". 4021 "has no name attribute\n"; 4022 stopservers($verbose); 4023 # timestamp test result verification end 4024 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 4025 return -1; 4026 } 4027 my @generated=loadarray($filename); 4028 4029 # what parts to cut off from the file 4030 my @stripfile = getpart("verify", "stripfile".$partsuffix); 4031 4032 my $filemode=$hash{'mode'}; 4033 if($filemode && ($filemode eq "text") && $has_textaware) { 4034 # text mode when running on windows: fix line endings 4035 map s/\r\n/\n/g, @outfile; 4036 map s/\n/\r\n/g, @outfile; 4037 } 4038 4039 my $strip; 4040 for $strip (@stripfile) { 4041 chomp $strip; 4042 my @newgen; 4043 for(@generated) { 4044 eval $strip; 4045 if($_) { 4046 push @newgen, $_; 4047 } 4048 } 4049 # this is to get rid of array entries that vanished (zero 4050 # length) because of replacements 4051 @generated = @newgen; 4052 } 4053 4054 @outfile = fixarray(@outfile); 4055 4056 $res = compare($testnum, $testname, "output ($filename)", 4057 \@generated, \@outfile); 4058 if($res) { 4059 return 1; 4060 } 4061 4062 $outputok = 1; # output checked 4063 } 4064 } 4065 $ok .= ($outputok) ? "o" : "-"; # output checked or not 4066 4067 # accept multiple comma-separated error codes 4068 my @splerr = split(/ *, */, $errorcode); 4069 my $errok; 4070 foreach my $e (@splerr) { 4071 if($e == $cmdres) { 4072 # a fine error code 4073 $errok = 1; 4074 last; 4075 } 4076 } 4077 4078 if($errok) { 4079 $ok .= "e"; 4080 } 4081 else { 4082 if(!$short) { 4083 logmsg sprintf("\n%s returned $cmdres, when expecting %s\n", 4084 (!$tool)?"curl":$tool, $errorcode); 4085 } 4086 logmsg " exit FAILED\n"; 4087 # timestamp test result verification end 4088 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 4089 return 1; 4090 } 4091 4092 if($has_memory_tracking) { 4093 if(! -f $memdump) { 4094 logmsg "\n** ALERT! memory tracking with no output file?\n" 4095 if(!$cmdtype eq "perl"); 4096 } 4097 else { 4098 my @memdata=`$memanalyze $memdump`; 4099 my $leak=0; 4100 for(@memdata) { 4101 if($_ ne "") { 4102 # well it could be other memory problems as well, but 4103 # we call it leak for short here 4104 $leak=1; 4105 } 4106 } 4107 if($leak) { 4108 logmsg "\n** MEMORY FAILURE\n"; 4109 logmsg @memdata; 4110 # timestamp test result verification end 4111 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 4112 return 1; 4113 } 4114 else { 4115 $ok .= "m"; 4116 } 4117 } 4118 } 4119 else { 4120 $ok .= "-"; # memory not checked 4121 } 4122 4123 if($valgrind) { 4124 if($usevalgrind) { 4125 unless(opendir(DIR, "$LOGDIR")) { 4126 logmsg "ERROR: unable to read $LOGDIR\n"; 4127 # timestamp test result verification end 4128 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 4129 return 1; 4130 } 4131 my @files = readdir(DIR); 4132 closedir(DIR); 4133 my $vgfile; 4134 foreach my $file (@files) { 4135 if($file =~ /^valgrind$testnum(\..*|)$/) { 4136 $vgfile = $file; 4137 last; 4138 } 4139 } 4140 if(!$vgfile) { 4141 logmsg "ERROR: valgrind log file missing for test $testnum\n"; 4142 # timestamp test result verification end 4143 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 4144 return 1; 4145 } 4146 my @e = valgrindparse($srcdir, $feature{'SSL'}, "$LOGDIR/$vgfile"); 4147 if(@e && $e[0]) { 4148 if($automakestyle) { 4149 logmsg "FAIL: $testnum - $testname - valgrind\n"; 4150 } 4151 else { 4152 logmsg " valgrind ERROR "; 4153 logmsg @e; 4154 } 4155 # timestamp test result verification end 4156 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 4157 return 1; 4158 } 4159 $ok .= "v"; 4160 } 4161 else { 4162 if(!$short && !$disablevalgrind) { 4163 logmsg " valgrind SKIPPED\n"; 4164 } 4165 $ok .= "-"; # skipped 4166 } 4167 } 4168 else { 4169 $ok .= "-"; # valgrind not checked 4170 } 4171 # add 'E' for event-based 4172 $ok .= $evbased ? "E" : "-"; 4173 4174 logmsg "$ok " if(!$short); 4175 4176 my $sofar= time()-$start; 4177 my $esttotal = $sofar/$count * $total; 4178 my $estleft = $esttotal - $sofar; 4179 my $left=sprintf("remaining: %02d:%02d", 4180 $estleft/60, 4181 $estleft%60); 4182 4183 if(!$automakestyle) { 4184 logmsg sprintf("OK (%-3d out of %-3d, %s)\n", $count, $total, $left); 4185 } 4186 else { 4187 logmsg "PASS: $testnum - $testname\n"; 4188 } 4189 4190 # the test succeeded, remove all log files 4191 if(!$keepoutfiles) { 4192 cleardir($LOGDIR); 4193 } 4194 4195 # timestamp test result verification end 4196 $timevrfyend{$testnum} = Time::HiRes::time() if($timestats); 4197 4198 return 0; 4199} 4200 4201####################################################################### 4202# Stop all running test servers 4203# 4204sub stopservers { 4205 my $verbose = $_[0]; 4206 # 4207 # kill sockfilter processes for all pingpong servers 4208 # 4209 killallsockfilters($verbose); 4210 # 4211 # kill all server pids from %run hash clearing them 4212 # 4213 my $pidlist; 4214 foreach my $server (keys %run) { 4215 if($run{$server}) { 4216 if($verbose) { 4217 my $prev = 0; 4218 my $pids = $run{$server}; 4219 foreach my $pid (split(' ', $pids)) { 4220 if($pid != $prev) { 4221 logmsg sprintf("* kill pid for %s => %d\n", 4222 $server, $pid); 4223 $prev = $pid; 4224 } 4225 } 4226 } 4227 $pidlist .= "$run{$server} "; 4228 $run{$server} = 0; 4229 } 4230 $runcert{$server} = 0 if($runcert{$server}); 4231 } 4232 killpid($verbose, $pidlist); 4233 # 4234 # cleanup all server pid files 4235 # 4236 foreach my $server (keys %serverpidfile) { 4237 my $pidfile = $serverpidfile{$server}; 4238 my $pid = processexists($pidfile); 4239 if($pid > 0) { 4240 logmsg "Warning: $server server unexpectedly alive\n"; 4241 killpid($verbose, $pid); 4242 } 4243 unlink($pidfile) if(-f $pidfile); 4244 } 4245} 4246 4247####################################################################### 4248# startservers() starts all the named servers 4249# 4250# Returns: string with error reason or blank for success 4251# 4252sub startservers { 4253 my @what = @_; 4254 my ($pid, $pid2); 4255 for(@what) { 4256 my (@whatlist) = split(/\s+/,$_); 4257 my $what = lc($whatlist[0]); 4258 $what =~ s/[^a-z0-9\/-]//g; 4259 4260 my $certfile; 4261 if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) { 4262 $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem'; 4263 } 4264 4265 if(($what eq "pop3") || 4266 ($what eq "ftp") || 4267 ($what eq "imap") || 4268 ($what eq "smtp")) { 4269 if($torture && $run{$what} && 4270 !responsive_pingpong_server($what, "", $verbose)) { 4271 stopserver($what); 4272 } 4273 if(!$run{$what}) { 4274 ($pid, $pid2) = runpingpongserver($what, "", $verbose); 4275 if($pid <= 0) { 4276 return "failed starting ". uc($what) ." server"; 4277 } 4278 printf ("* pid $what => %d %d\n", $pid, $pid2) if($verbose); 4279 $run{$what}="$pid $pid2"; 4280 } 4281 } 4282 elsif($what eq "ftp2") { 4283 if($torture && $run{'ftp2'} && 4284 !responsive_pingpong_server("ftp", "2", $verbose)) { 4285 stopserver('ftp2'); 4286 } 4287 if(!$run{'ftp2'}) { 4288 ($pid, $pid2) = runpingpongserver("ftp", "2", $verbose); 4289 if($pid <= 0) { 4290 return "failed starting FTP2 server"; 4291 } 4292 printf ("* pid ftp2 => %d %d\n", $pid, $pid2) if($verbose); 4293 $run{'ftp2'}="$pid $pid2"; 4294 } 4295 } 4296 elsif($what eq "ftp-ipv6") { 4297 if($torture && $run{'ftp-ipv6'} && 4298 !responsive_pingpong_server("ftp", "", $verbose, "ipv6")) { 4299 stopserver('ftp-ipv6'); 4300 } 4301 if(!$run{'ftp-ipv6'}) { 4302 ($pid, $pid2) = runpingpongserver("ftp", "", $verbose, "ipv6"); 4303 if($pid <= 0) { 4304 return "failed starting FTP-IPv6 server"; 4305 } 4306 logmsg sprintf("* pid ftp-ipv6 => %d %d\n", $pid, 4307 $pid2) if($verbose); 4308 $run{'ftp-ipv6'}="$pid $pid2"; 4309 } 4310 } 4311 elsif($what eq "gopher") { 4312 if($torture && $run{'gopher'} && 4313 !responsive_http_server("gopher", $verbose, 0, $GOPHERPORT)) { 4314 stopserver('gopher'); 4315 } 4316 if(!$run{'gopher'}) { 4317 ($pid, $pid2) = runhttpserver("gopher", $verbose, 0, 4318 $GOPHERPORT); 4319 if($pid <= 0) { 4320 return "failed starting GOPHER server"; 4321 } 4322 logmsg sprintf ("* pid gopher => %d %d\n", $pid, $pid2) 4323 if($verbose); 4324 $run{'gopher'}="$pid $pid2"; 4325 } 4326 } 4327 elsif($what eq "gopher-ipv6") { 4328 if($torture && $run{'gopher-ipv6'} && 4329 !responsive_http_server("gopher", $verbose, "ipv6", 4330 $GOPHER6PORT)) { 4331 stopserver('gopher-ipv6'); 4332 } 4333 if(!$run{'gopher-ipv6'}) { 4334 ($pid, $pid2) = runhttpserver("gopher", $verbose, "ipv6", 4335 $GOPHER6PORT); 4336 if($pid <= 0) { 4337 return "failed starting GOPHER-IPv6 server"; 4338 } 4339 logmsg sprintf("* pid gopher-ipv6 => %d %d\n", $pid, 4340 $pid2) if($verbose); 4341 $run{'gopher-ipv6'}="$pid $pid2"; 4342 } 4343 } 4344 elsif($what eq "http/2") { 4345 if(!$run{'http/2'}) { 4346 ($pid, $pid2) = runhttp2server($verbose, $HTTP2PORT); 4347 if($pid <= 0) { 4348 return "failed starting HTTP/2 server"; 4349 } 4350 logmsg sprintf ("* pid http/2 => %d %d\n", $pid, $pid2) 4351 if($verbose); 4352 $run{'http/2'}="$pid $pid2"; 4353 } 4354 } 4355 elsif($what eq "http") { 4356 if($torture && $run{'http'} && 4357 !responsive_http_server("http", $verbose, 0, $HTTPPORT)) { 4358 stopserver('http'); 4359 } 4360 if(!$run{'http'}) { 4361 ($pid, $pid2) = runhttpserver("http", $verbose, 0, 4362 $HTTPPORT); 4363 if($pid <= 0) { 4364 return "failed starting HTTP server"; 4365 } 4366 logmsg sprintf ("* pid http => %d %d\n", $pid, $pid2) 4367 if($verbose); 4368 $run{'http'}="$pid $pid2"; 4369 } 4370 } 4371 elsif($what eq "http-proxy") { 4372 if($torture && $run{'http-proxy'} && 4373 !responsive_http_server("http", $verbose, "proxy", 4374 $HTTPPROXYPORT)) { 4375 stopserver('http-proxy'); 4376 } 4377 if(!$run{'http-proxy'}) { 4378 ($pid, $pid2) = runhttpserver("http", $verbose, "proxy", 4379 $HTTPPROXYPORT); 4380 if($pid <= 0) { 4381 return "failed starting HTTP-proxy server"; 4382 } 4383 logmsg sprintf ("* pid http-proxy => %d %d\n", $pid, $pid2) 4384 if($verbose); 4385 $run{'http-proxy'}="$pid $pid2"; 4386 } 4387 } 4388 elsif($what eq "http-ipv6") { 4389 if($torture && $run{'http-ipv6'} && 4390 !responsive_http_server("http", $verbose, "ipv6", $HTTP6PORT)) { 4391 stopserver('http-ipv6'); 4392 } 4393 if(!$run{'http-ipv6'}) { 4394 ($pid, $pid2) = runhttpserver("http", $verbose, "ipv6", 4395 $HTTP6PORT); 4396 if($pid <= 0) { 4397 return "failed starting HTTP-IPv6 server"; 4398 } 4399 logmsg sprintf("* pid http-ipv6 => %d %d\n", $pid, $pid2) 4400 if($verbose); 4401 $run{'http-ipv6'}="$pid $pid2"; 4402 } 4403 } 4404 elsif($what eq "http-pipe") { 4405 if($torture && $run{'http-pipe'} && 4406 !responsive_http_server("http", $verbose, "pipe", 4407 $HTTPPIPEPORT)) { 4408 stopserver('http-pipe'); 4409 } 4410 if(!$run{'http-pipe'}) { 4411 ($pid, $pid2) = runhttpserver("http", $verbose, "pipe", 4412 $HTTPPIPEPORT); 4413 if($pid <= 0) { 4414 return "failed starting HTTP-pipe server"; 4415 } 4416 logmsg sprintf ("* pid http-pipe => %d %d\n", $pid, $pid2) 4417 if($verbose); 4418 $run{'http-pipe'}="$pid $pid2"; 4419 } 4420 } 4421 elsif($what eq "rtsp") { 4422 if($torture && $run{'rtsp'} && 4423 !responsive_rtsp_server($verbose)) { 4424 stopserver('rtsp'); 4425 } 4426 if(!$run{'rtsp'}) { 4427 ($pid, $pid2) = runrtspserver($verbose); 4428 if($pid <= 0) { 4429 return "failed starting RTSP server"; 4430 } 4431 printf ("* pid rtsp => %d %d\n", $pid, $pid2) if($verbose); 4432 $run{'rtsp'}="$pid $pid2"; 4433 } 4434 } 4435 elsif($what eq "rtsp-ipv6") { 4436 if($torture && $run{'rtsp-ipv6'} && 4437 !responsive_rtsp_server($verbose, "ipv6")) { 4438 stopserver('rtsp-ipv6'); 4439 } 4440 if(!$run{'rtsp-ipv6'}) { 4441 ($pid, $pid2) = runrtspserver($verbose, "ipv6"); 4442 if($pid <= 0) { 4443 return "failed starting RTSP-IPv6 server"; 4444 } 4445 logmsg sprintf("* pid rtsp-ipv6 => %d %d\n", $pid, $pid2) 4446 if($verbose); 4447 $run{'rtsp-ipv6'}="$pid $pid2"; 4448 } 4449 } 4450 elsif($what eq "ftps") { 4451 if(!$stunnel) { 4452 # we can't run ftps tests without stunnel 4453 return "no stunnel"; 4454 } 4455 if(!$has_ssl) { 4456 # we can't run ftps tests if libcurl is SSL-less 4457 return "curl lacks SSL support"; 4458 } 4459 if($runcert{'ftps'} && ($runcert{'ftps'} ne $certfile)) { 4460 # stop server when running and using a different cert 4461 stopserver('ftps'); 4462 } 4463 if($torture && $run{'ftp'} && 4464 !responsive_pingpong_server("ftp", "", $verbose)) { 4465 stopserver('ftp'); 4466 } 4467 if(!$run{'ftp'}) { 4468 ($pid, $pid2) = runpingpongserver("ftp", "", $verbose); 4469 if($pid <= 0) { 4470 return "failed starting FTP server"; 4471 } 4472 printf ("* pid ftp => %d %d\n", $pid, $pid2) if($verbose); 4473 $run{'ftp'}="$pid $pid2"; 4474 } 4475 if(!$run{'ftps'}) { 4476 ($pid, $pid2) = runftpsserver($verbose, "", $certfile); 4477 if($pid <= 0) { 4478 return "failed starting FTPS server (stunnel)"; 4479 } 4480 logmsg sprintf("* pid ftps => %d %d\n", $pid, $pid2) 4481 if($verbose); 4482 $run{'ftps'}="$pid $pid2"; 4483 } 4484 } 4485 elsif($what eq "file") { 4486 # we support it but have no server! 4487 } 4488 elsif($what eq "https") { 4489 if(!$stunnel) { 4490 # we can't run https tests without stunnel 4491 return "no stunnel"; 4492 } 4493 if(!$has_ssl) { 4494 # we can't run https tests if libcurl is SSL-less 4495 return "curl lacks SSL support"; 4496 } 4497 if($runcert{'https'} && ($runcert{'https'} ne $certfile)) { 4498 # stop server when running and using a different cert 4499 stopserver('https'); 4500 } 4501 if($torture && $run{'http'} && 4502 !responsive_http_server("http", $verbose, 0, $HTTPPORT)) { 4503 stopserver('http'); 4504 } 4505 if(!$run{'http'}) { 4506 ($pid, $pid2) = runhttpserver("http", $verbose, 0, 4507 $HTTPPORT); 4508 if($pid <= 0) { 4509 return "failed starting HTTP server"; 4510 } 4511 printf ("* pid http => %d %d\n", $pid, $pid2) if($verbose); 4512 $run{'http'}="$pid $pid2"; 4513 } 4514 if(!$run{'https'}) { 4515 ($pid, $pid2) = runhttpsserver($verbose, "", $certfile); 4516 if($pid <= 0) { 4517 return "failed starting HTTPS server (stunnel)"; 4518 } 4519 logmsg sprintf("* pid https => %d %d\n", $pid, $pid2) 4520 if($verbose); 4521 $run{'https'}="$pid $pid2"; 4522 } 4523 } 4524 elsif($what eq "httptls") { 4525 if(!$httptlssrv) { 4526 # for now, we can't run http TLS-EXT tests without gnutls-serv 4527 return "no gnutls-serv"; 4528 } 4529 if($torture && $run{'httptls'} && 4530 !responsive_httptls_server($verbose, "IPv4")) { 4531 stopserver('httptls'); 4532 } 4533 if(!$run{'httptls'}) { 4534 ($pid, $pid2) = runhttptlsserver($verbose, "IPv4"); 4535 if($pid <= 0) { 4536 return "failed starting HTTPTLS server (gnutls-serv)"; 4537 } 4538 logmsg sprintf("* pid httptls => %d %d\n", $pid, $pid2) 4539 if($verbose); 4540 $run{'httptls'}="$pid $pid2"; 4541 } 4542 } 4543 elsif($what eq "httptls-ipv6") { 4544 if(!$httptlssrv) { 4545 # for now, we can't run http TLS-EXT tests without gnutls-serv 4546 return "no gnutls-serv"; 4547 } 4548 if($torture && $run{'httptls-ipv6'} && 4549 !responsive_httptls_server($verbose, "ipv6")) { 4550 stopserver('httptls-ipv6'); 4551 } 4552 if(!$run{'httptls-ipv6'}) { 4553 ($pid, $pid2) = runhttptlsserver($verbose, "ipv6"); 4554 if($pid <= 0) { 4555 return "failed starting HTTPTLS-IPv6 server (gnutls-serv)"; 4556 } 4557 logmsg sprintf("* pid httptls-ipv6 => %d %d\n", $pid, $pid2) 4558 if($verbose); 4559 $run{'httptls-ipv6'}="$pid $pid2"; 4560 } 4561 } 4562 elsif($what eq "tftp") { 4563 if($torture && $run{'tftp'} && 4564 !responsive_tftp_server("", $verbose)) { 4565 stopserver('tftp'); 4566 } 4567 if(!$run{'tftp'}) { 4568 ($pid, $pid2) = runtftpserver("", $verbose); 4569 if($pid <= 0) { 4570 return "failed starting TFTP server"; 4571 } 4572 printf ("* pid tftp => %d %d\n", $pid, $pid2) if($verbose); 4573 $run{'tftp'}="$pid $pid2"; 4574 } 4575 } 4576 elsif($what eq "tftp-ipv6") { 4577 if($torture && $run{'tftp-ipv6'} && 4578 !responsive_tftp_server("", $verbose, "ipv6")) { 4579 stopserver('tftp-ipv6'); 4580 } 4581 if(!$run{'tftp-ipv6'}) { 4582 ($pid, $pid2) = runtftpserver("", $verbose, "ipv6"); 4583 if($pid <= 0) { 4584 return "failed starting TFTP-IPv6 server"; 4585 } 4586 printf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose); 4587 $run{'tftp-ipv6'}="$pid $pid2"; 4588 } 4589 } 4590 elsif($what eq "sftp" || $what eq "scp" || $what eq "socks4" || $what eq "socks5" ) { 4591 if(!$run{'ssh'}) { 4592 ($pid, $pid2) = runsshserver("", $verbose); 4593 if($pid <= 0) { 4594 return "failed starting SSH server"; 4595 } 4596 printf ("* pid ssh => %d %d\n", $pid, $pid2) if($verbose); 4597 $run{'ssh'}="$pid $pid2"; 4598 } 4599 if($what eq "socks4" || $what eq "socks5") { 4600 if(!$run{'socks'}) { 4601 ($pid, $pid2) = runsocksserver("", $verbose); 4602 if($pid <= 0) { 4603 return "failed starting socks server"; 4604 } 4605 printf ("* pid socks => %d %d\n", $pid, $pid2) if($verbose); 4606 $run{'socks'}="$pid $pid2"; 4607 } 4608 } 4609 if($what eq "socks5") { 4610 if(!$sshdid) { 4611 # Not an OpenSSH or SunSSH ssh daemon 4612 logmsg "Not OpenSSH or SunSSH; socks5 tests need at least OpenSSH 3.7\n"; 4613 return "failed starting socks5 server"; 4614 } 4615 elsif(($sshdid =~ /OpenSSH/) && ($sshdvernum < 370)) { 4616 # Need OpenSSH 3.7 for socks5 - http://www.openssh.com/txt/release-3.7 4617 logmsg "$sshdverstr insufficient; socks5 tests need at least OpenSSH 3.7\n"; 4618 return "failed starting socks5 server"; 4619 } 4620 elsif(($sshdid =~ /SunSSH/) && ($sshdvernum < 100)) { 4621 # Need SunSSH 1.0 for socks5 4622 logmsg "$sshdverstr insufficient; socks5 tests need at least SunSSH 1.0\n"; 4623 return "failed starting socks5 server"; 4624 } 4625 } 4626 } 4627 elsif($what eq "http-unix") { 4628 if($torture && $run{'http-unix'} && 4629 !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) { 4630 stopserver('http-unix'); 4631 } 4632 if(!$run{'http-unix'}) { 4633 ($pid, $pid2) = runhttpserver("http", $verbose, "unix", 4634 $HTTPUNIXPATH); 4635 if($pid <= 0) { 4636 return "failed starting HTTP-unix server"; 4637 } 4638 logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2) 4639 if($verbose); 4640 $run{'http-unix'}="$pid $pid2"; 4641 } 4642 } 4643 elsif($what eq "none") { 4644 logmsg "* starts no server\n" if ($verbose); 4645 } 4646 else { 4647 warn "we don't support a server for $what"; 4648 return "no server for $what"; 4649 } 4650 } 4651 return 0; 4652} 4653 4654############################################################################## 4655# This function makes sure the right set of server is running for the 4656# specified test case. This is a useful design when we run single tests as not 4657# all servers need to run then! 4658# 4659# Returns: a string, blank if everything is fine or a reason why it failed 4660# 4661sub serverfortest { 4662 my ($testnum)=@_; 4663 4664 my @what = getpart("client", "server"); 4665 4666 if(!$what[0]) { 4667 warn "Test case $testnum has no server(s) specified"; 4668 return "no server specified"; 4669 } 4670 4671 for(my $i = scalar(@what) - 1; $i >= 0; $i--) { 4672 my $srvrline = $what[$i]; 4673 chomp $srvrline if($srvrline); 4674 if($srvrline =~ /^(\S+)((\s*)(.*))/) { 4675 my $server = "${1}"; 4676 my $lnrest = "${2}"; 4677 my $tlsext; 4678 if($server =~ /^(httptls)(\+)(ext|srp)(\d*)(-ipv6|)$/) { 4679 $server = "${1}${4}${5}"; 4680 $tlsext = uc("TLS-${3}"); 4681 } 4682 if(! grep /^\Q$server\E$/, @protocols) { 4683 if(substr($server,0,5) ne "socks") { 4684 if($tlsext) { 4685 return "curl lacks $tlsext support"; 4686 } 4687 else { 4688 return "curl lacks $server server support"; 4689 } 4690 } 4691 } 4692 $what[$i] = "$server$lnrest" if($tlsext); 4693 } 4694 } 4695 4696 return &startservers(@what); 4697} 4698 4699####################################################################### 4700# runtimestats displays test-suite run time statistics 4701# 4702sub runtimestats { 4703 my $lasttest = $_[0]; 4704 4705 return if(not $timestats); 4706 4707 logmsg "\nTest suite total running time breakdown per task...\n\n"; 4708 4709 my @timesrvr; 4710 my @timeprep; 4711 my @timetool; 4712 my @timelock; 4713 my @timevrfy; 4714 my @timetest; 4715 my $timesrvrtot = 0.0; 4716 my $timepreptot = 0.0; 4717 my $timetooltot = 0.0; 4718 my $timelocktot = 0.0; 4719 my $timevrfytot = 0.0; 4720 my $timetesttot = 0.0; 4721 my $counter; 4722 4723 for my $testnum (1 .. $lasttest) { 4724 if($timesrvrini{$testnum}) { 4725 $timesrvrtot += $timesrvrend{$testnum} - $timesrvrini{$testnum}; 4726 $timepreptot += 4727 (($timetoolini{$testnum} - $timeprepini{$testnum}) - 4728 ($timesrvrend{$testnum} - $timesrvrini{$testnum})); 4729 $timetooltot += $timetoolend{$testnum} - $timetoolini{$testnum}; 4730 $timelocktot += $timesrvrlog{$testnum} - $timetoolend{$testnum}; 4731 $timevrfytot += $timevrfyend{$testnum} - $timesrvrlog{$testnum}; 4732 $timetesttot += $timevrfyend{$testnum} - $timeprepini{$testnum}; 4733 push @timesrvr, sprintf("%06.3f %04d", 4734 $timesrvrend{$testnum} - $timesrvrini{$testnum}, $testnum); 4735 push @timeprep, sprintf("%06.3f %04d", 4736 ($timetoolini{$testnum} - $timeprepini{$testnum}) - 4737 ($timesrvrend{$testnum} - $timesrvrini{$testnum}), $testnum); 4738 push @timetool, sprintf("%06.3f %04d", 4739 $timetoolend{$testnum} - $timetoolini{$testnum}, $testnum); 4740 push @timelock, sprintf("%06.3f %04d", 4741 $timesrvrlog{$testnum} - $timetoolend{$testnum}, $testnum); 4742 push @timevrfy, sprintf("%06.3f %04d", 4743 $timevrfyend{$testnum} - $timesrvrlog{$testnum}, $testnum); 4744 push @timetest, sprintf("%06.3f %04d", 4745 $timevrfyend{$testnum} - $timeprepini{$testnum}, $testnum); 4746 } 4747 } 4748 4749 { 4750 no warnings 'numeric'; 4751 @timesrvr = sort { $b <=> $a } @timesrvr; 4752 @timeprep = sort { $b <=> $a } @timeprep; 4753 @timetool = sort { $b <=> $a } @timetool; 4754 @timelock = sort { $b <=> $a } @timelock; 4755 @timevrfy = sort { $b <=> $a } @timevrfy; 4756 @timetest = sort { $b <=> $a } @timetest; 4757 } 4758 4759 logmsg "Spent ". sprintf("%08.3f ", $timesrvrtot) . 4760 "seconds starting and verifying test harness servers.\n"; 4761 logmsg "Spent ". sprintf("%08.3f ", $timepreptot) . 4762 "seconds reading definitions and doing test preparations.\n"; 4763 logmsg "Spent ". sprintf("%08.3f ", $timetooltot) . 4764 "seconds actually running test tools.\n"; 4765 logmsg "Spent ". sprintf("%08.3f ", $timelocktot) . 4766 "seconds awaiting server logs lock removal.\n"; 4767 logmsg "Spent ". sprintf("%08.3f ", $timevrfytot) . 4768 "seconds verifying test results.\n"; 4769 logmsg "Spent ". sprintf("%08.3f ", $timetesttot) . 4770 "seconds doing all of the above.\n"; 4771 4772 $counter = 25; 4773 logmsg "\nTest server starting and verification time per test ". 4774 sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full"); 4775 logmsg "-time- test\n"; 4776 logmsg "------ ----\n"; 4777 foreach my $txt (@timesrvr) { 4778 last if((not $fullstats) && (not $counter--)); 4779 logmsg "$txt\n"; 4780 } 4781 4782 $counter = 10; 4783 logmsg "\nTest definition reading and preparation time per test ". 4784 sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full"); 4785 logmsg "-time- test\n"; 4786 logmsg "------ ----\n"; 4787 foreach my $txt (@timeprep) { 4788 last if((not $fullstats) && (not $counter--)); 4789 logmsg "$txt\n"; 4790 } 4791 4792 $counter = 25; 4793 logmsg "\nTest tool execution time per test ". 4794 sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full"); 4795 logmsg "-time- test\n"; 4796 logmsg "------ ----\n"; 4797 foreach my $txt (@timetool) { 4798 last if((not $fullstats) && (not $counter--)); 4799 logmsg "$txt\n"; 4800 } 4801 4802 $counter = 15; 4803 logmsg "\nTest server logs lock removal time per test ". 4804 sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full"); 4805 logmsg "-time- test\n"; 4806 logmsg "------ ----\n"; 4807 foreach my $txt (@timelock) { 4808 last if((not $fullstats) && (not $counter--)); 4809 logmsg "$txt\n"; 4810 } 4811 4812 $counter = 10; 4813 logmsg "\nTest results verification time per test ". 4814 sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full"); 4815 logmsg "-time- test\n"; 4816 logmsg "------ ----\n"; 4817 foreach my $txt (@timevrfy) { 4818 last if((not $fullstats) && (not $counter--)); 4819 logmsg "$txt\n"; 4820 } 4821 4822 $counter = 50; 4823 logmsg "\nTotal time per test ". 4824 sprintf("(%s)...\n\n", (not $fullstats)?"top $counter":"full"); 4825 logmsg "-time- test\n"; 4826 logmsg "------ ----\n"; 4827 foreach my $txt (@timetest) { 4828 last if((not $fullstats) && (not $counter--)); 4829 logmsg "$txt\n"; 4830 } 4831 4832 logmsg "\n"; 4833} 4834 4835####################################################################### 4836# Check options to this test program 4837# 4838 4839my $number=0; 4840my $fromnum=-1; 4841my @testthis; 4842while(@ARGV) { 4843 if ($ARGV[0] eq "-v") { 4844 # verbose output 4845 $verbose=1; 4846 } 4847 elsif($ARGV[0] =~ /^-b(.*)/) { 4848 my $portno=$1; 4849 if($portno =~ s/(\d+)$//) { 4850 $base = int $1; 4851 } 4852 } 4853 elsif ($ARGV[0] eq "-c") { 4854 # use this path to curl instead of default 4855 $DBGCURL=$CURL="\"$ARGV[1]\""; 4856 shift @ARGV; 4857 } 4858 elsif ($ARGV[0] eq "-vc") { 4859 # use this path to a curl used to verify servers 4860 4861 # Particularly useful when you introduce a crashing bug somewhere in 4862 # the development version as then it won't be able to run any tests 4863 # since it can't verify the servers! 4864 4865 $VCURL="\"$ARGV[1]\""; 4866 shift @ARGV; 4867 } 4868 elsif ($ARGV[0] eq "-d") { 4869 # have the servers display protocol output 4870 $debugprotocol=1; 4871 } 4872 elsif ($ARGV[0] eq "-g") { 4873 # run this test with gdb 4874 $gdbthis=1; 4875 } 4876 elsif ($ARGV[0] eq "-gw") { 4877 # run this test with windowed gdb 4878 $gdbthis=1; 4879 $gdbxwin=1; 4880 } 4881 elsif($ARGV[0] eq "-s") { 4882 # short output 4883 $short=1; 4884 } 4885 elsif($ARGV[0] eq "-am") { 4886 # automake-style output 4887 $short=1; 4888 $automakestyle=1; 4889 } 4890 elsif($ARGV[0] eq "-n") { 4891 # no valgrind 4892 undef $valgrind; 4893 } 4894 elsif($ARGV[0] =~ /^-t(.*)/) { 4895 # torture 4896 $torture=1; 4897 my $xtra = $1; 4898 4899 if($xtra =~ s/(\d+)$//) { 4900 $tortalloc = $1; 4901 } 4902 # we undef valgrind to make this fly in comparison 4903 undef $valgrind; 4904 } 4905 elsif($ARGV[0] eq "-a") { 4906 # continue anyway, even if a test fail 4907 $anyway=1; 4908 } 4909 elsif($ARGV[0] eq "-e") { 4910 # run the tests cases event based if possible 4911 $run_event_based=1; 4912 } 4913 elsif($ARGV[0] eq "-p") { 4914 $postmortem=1; 4915 } 4916 elsif($ARGV[0] eq "-l") { 4917 # lists the test case names only 4918 $listonly=1; 4919 } 4920 elsif($ARGV[0] eq "-k") { 4921 # keep stdout and stderr files after tests 4922 $keepoutfiles=1; 4923 } 4924 elsif($ARGV[0] eq "-r") { 4925 # run time statistics needs Time::HiRes 4926 if($Time::HiRes::VERSION) { 4927 keys(%timeprepini) = 1000; 4928 keys(%timesrvrini) = 1000; 4929 keys(%timesrvrend) = 1000; 4930 keys(%timetoolini) = 1000; 4931 keys(%timetoolend) = 1000; 4932 keys(%timesrvrlog) = 1000; 4933 keys(%timevrfyend) = 1000; 4934 $timestats=1; 4935 $fullstats=0; 4936 } 4937 } 4938 elsif($ARGV[0] eq "-rf") { 4939 # run time statistics needs Time::HiRes 4940 if($Time::HiRes::VERSION) { 4941 keys(%timeprepini) = 1000; 4942 keys(%timesrvrini) = 1000; 4943 keys(%timesrvrend) = 1000; 4944 keys(%timetoolini) = 1000; 4945 keys(%timetoolend) = 1000; 4946 keys(%timesrvrlog) = 1000; 4947 keys(%timevrfyend) = 1000; 4948 $timestats=1; 4949 $fullstats=1; 4950 } 4951 } 4952 elsif(($ARGV[0] eq "-h") || ($ARGV[0] eq "--help")) { 4953 # show help text 4954 print <<EOHELP 4955Usage: runtests.pl [options] [test selection(s)] 4956 -a continue even if a test fails 4957 -bN use base port number N for test servers (default $base) 4958 -c path use this curl executable 4959 -d display server debug info 4960 -g run the test case with gdb 4961 -gw run the test case with gdb as a windowed application 4962 -h this help text 4963 -k keep stdout and stderr files present after tests 4964 -l list all test case names/descriptions 4965 -n no valgrind 4966 -p print log file contents when a test fails 4967 -r run time statistics 4968 -rf full run time statistics 4969 -s short output 4970 -am automake style output PASS/FAIL: [number] [name] 4971 -t[N] torture (simulate memory alloc failures); N means fail Nth alloc 4972 -v verbose output 4973 -vc path use this curl only to verify the existing servers 4974 [num] like "5 6 9" or " 5 to 22 " to run those tests only 4975 [!num] like "!5 !6 !9" to disable those tests 4976 [keyword] like "IPv6" to select only tests containing the key word 4977 [!keyword] like "!cookies" to disable any tests containing the key word 4978EOHELP 4979 ; 4980 exit; 4981 } 4982 elsif($ARGV[0] =~ /^(\d+)/) { 4983 $number = $1; 4984 if($fromnum >= 0) { 4985 for($fromnum .. $number) { 4986 push @testthis, $_; 4987 } 4988 $fromnum = -1; 4989 } 4990 else { 4991 push @testthis, $1; 4992 } 4993 } 4994 elsif($ARGV[0] =~ /^to$/i) { 4995 $fromnum = $number+1; 4996 } 4997 elsif($ARGV[0] =~ /^!(\d+)/) { 4998 $fromnum = -1; 4999 $disabled{$1}=$1; 5000 } 5001 elsif($ARGV[0] =~ /^!(.+)/) { 5002 $disabled_keywords{$1}=$1; 5003 } 5004 elsif($ARGV[0] =~ /^([-[{a-zA-Z].*)/) { 5005 $enabled_keywords{$1}=$1; 5006 } 5007 else { 5008 print "Unknown option: $ARGV[0]\n"; 5009 exit; 5010 } 5011 shift @ARGV; 5012} 5013 5014if(@testthis && ($testthis[0] ne "")) { 5015 $TESTCASES=join(" ", @testthis); 5016} 5017 5018if($valgrind) { 5019 # we have found valgrind on the host, use it 5020 5021 # verify that we can invoke it fine 5022 my $code = runclient("valgrind >/dev/null 2>&1"); 5023 5024 if(($code>>8) != 1) { 5025 #logmsg "Valgrind failure, disable it\n"; 5026 undef $valgrind; 5027 } else { 5028 5029 # since valgrind 2.1.x, '--tool' option is mandatory 5030 # use it, if it is supported by the version installed on the system 5031 runclient("valgrind --help 2>&1 | grep -- --tool > /dev/null 2>&1"); 5032 if (($? >> 8)==0) { 5033 $valgrind_tool="--tool=memcheck"; 5034 } 5035 open(C, "<$CURL"); 5036 my $l = <C>; 5037 if($l =~ /^\#\!/) { 5038 # A shell script. This is typically when built with libtool, 5039 $valgrind="../libtool --mode=execute $valgrind"; 5040 } 5041 close(C); 5042 5043 # valgrind 3 renamed the --logfile option to --log-file!!! 5044 my $ver=join(' ', runclientoutput("valgrind --version")); 5045 # cut off all but digits and dots 5046 $ver =~ s/[^0-9.]//g; 5047 5048 if($ver =~ /^(\d+)/) { 5049 $ver = $1; 5050 if($ver >= 3) { 5051 $valgrind_logfile="--log-file"; 5052 } 5053 } 5054 } 5055} 5056 5057if ($gdbthis) { 5058 # open the executable curl and read the first 4 bytes of it 5059 open(CHECK, "<$CURL"); 5060 my $c; 5061 sysread CHECK, $c, 4; 5062 close(CHECK); 5063 if($c eq "#! /") { 5064 # A shell script. This is typically when built with libtool, 5065 $libtool = 1; 5066 $gdb = "../libtool --mode=execute gdb"; 5067 } 5068} 5069 5070$HTTPPORT = $base++; # HTTP server port 5071$HTTPSPORT = $base++; # HTTPS (stunnel) server port 5072$FTPPORT = $base++; # FTP server port 5073$FTPSPORT = $base++; # FTPS (stunnel) server port 5074$HTTP6PORT = $base++; # HTTP IPv6 server port 5075$FTP2PORT = $base++; # FTP server 2 port 5076$FTP6PORT = $base++; # FTP IPv6 port 5077$TFTPPORT = $base++; # TFTP (UDP) port 5078$TFTP6PORT = $base++; # TFTP IPv6 (UDP) port 5079$SSHPORT = $base++; # SSH (SCP/SFTP) port 5080$SOCKSPORT = $base++; # SOCKS port 5081$POP3PORT = $base++; # POP3 server port 5082$POP36PORT = $base++; # POP3 IPv6 server port 5083$IMAPPORT = $base++; # IMAP server port 5084$IMAP6PORT = $base++; # IMAP IPv6 server port 5085$SMTPPORT = $base++; # SMTP server port 5086$SMTP6PORT = $base++; # SMTP IPv6 server port 5087$RTSPPORT = $base++; # RTSP server port 5088$RTSP6PORT = $base++; # RTSP IPv6 server port 5089$GOPHERPORT = $base++; # Gopher IPv4 server port 5090$GOPHER6PORT = $base++; # Gopher IPv6 server port 5091$HTTPTLSPORT = $base++; # HTTP TLS (non-stunnel) server port 5092$HTTPTLS6PORT = $base++; # HTTP TLS (non-stunnel) IPv6 server port 5093$HTTPPROXYPORT = $base++; # HTTP proxy port, when using CONNECT 5094$HTTPPIPEPORT = $base++; # HTTP pipelining port 5095$HTTP2PORT = $base++; # HTTP/2 port 5096$HTTPUNIXPATH = 'http.sock'; # HTTP server Unix domain socket path 5097 5098####################################################################### 5099# clear and create logging directory: 5100# 5101 5102cleardir($LOGDIR); 5103mkdir($LOGDIR, 0777); 5104 5105####################################################################### 5106# initialize some variables 5107# 5108 5109get_disttests(); 5110init_serverpidfile_hash(); 5111 5112####################################################################### 5113# Output curl version and host info being tested 5114# 5115 5116if(!$listonly) { 5117 checksystem(); 5118} 5119 5120####################################################################### 5121# Fetch all disabled tests, if there are any 5122# 5123 5124sub disabledtests { 5125 my ($file) = @_; 5126 5127 if(open(D, "<$file")) { 5128 while(<D>) { 5129 if(/^ *\#/) { 5130 # allow comments 5131 next; 5132 } 5133 if($_ =~ /(\d+)/) { 5134 $disabled{$1}=$1; # disable this test number 5135 } 5136 } 5137 close(D); 5138 } 5139} 5140 5141# globally disabled tests 5142disabledtests("$TESTDIR/DISABLED"); 5143 5144# locally disabled tests, ignored by git etc 5145disabledtests("$TESTDIR/DISABLED.local"); 5146 5147####################################################################### 5148# If 'all' tests are requested, find out all test numbers 5149# 5150 5151if ( $TESTCASES eq "all") { 5152 # Get all commands and find out their test numbers 5153 opendir(DIR, $TESTDIR) || die "can't opendir $TESTDIR: $!"; 5154 my @cmds = grep { /^test([0-9]+)$/ && -f "$TESTDIR/$_" } readdir(DIR); 5155 closedir(DIR); 5156 5157 $TESTCASES=""; # start with no test cases 5158 5159 # cut off everything but the digits 5160 for(@cmds) { 5161 $_ =~ s/[a-z\/\.]*//g; 5162 } 5163 # sort the numbers from low to high 5164 foreach my $n (sort { $a <=> $b } @cmds) { 5165 if($disabled{$n}) { 5166 # skip disabled test cases 5167 my $why = "configured as DISABLED"; 5168 $skipped++; 5169 $skipped{$why}++; 5170 $teststat[$n]=$why; # store reason for this test case 5171 next; 5172 } 5173 $TESTCASES .= " $n"; 5174 } 5175} 5176else { 5177 my $verified=""; 5178 map { 5179 if (-e "$TESTDIR/test$_") { 5180 $verified.="$_ "; 5181 } 5182 } split(" ", $TESTCASES); 5183 if($verified eq "") { 5184 print "No existing test cases were specified\n"; 5185 exit; 5186 } 5187 $TESTCASES = $verified; 5188} 5189 5190####################################################################### 5191# Start the command line log 5192# 5193open(CMDLOG, ">$CURLLOG") || 5194 logmsg "can't log command lines to $CURLLOG\n"; 5195 5196####################################################################### 5197 5198# Display the contents of the given file. Line endings are canonicalized 5199# and excessively long files are elided 5200sub displaylogcontent { 5201 my ($file)=@_; 5202 if(open(SINGLE, "<$file")) { 5203 my $linecount = 0; 5204 my $truncate; 5205 my @tail; 5206 while(my $string = <SINGLE>) { 5207 $string =~ s/\r\n/\n/g; 5208 $string =~ s/[\r\f\032]/\n/g; 5209 $string .= "\n" unless ($string =~ /\n$/); 5210 $string =~ tr/\n//; 5211 for my $line (split("\n", $string)) { 5212 $line =~ s/\s*\!$//; 5213 if ($truncate) { 5214 push @tail, " $line\n"; 5215 } else { 5216 logmsg " $line\n"; 5217 } 5218 $linecount++; 5219 $truncate = $linecount > 1000; 5220 } 5221 } 5222 if(@tail) { 5223 my $tailshow = 200; 5224 my $tailskip = 0; 5225 my $tailtotal = scalar @tail; 5226 if($tailtotal > $tailshow) { 5227 $tailskip = $tailtotal - $tailshow; 5228 logmsg "=== File too long: $tailskip lines omitted here\n"; 5229 } 5230 for($tailskip .. $tailtotal-1) { 5231 logmsg "$tail[$_]"; 5232 } 5233 } 5234 close(SINGLE); 5235 } 5236} 5237 5238sub displaylogs { 5239 my ($testnum)=@_; 5240 opendir(DIR, "$LOGDIR") || 5241 die "can't open dir: $!"; 5242 my @logs = readdir(DIR); 5243 closedir(DIR); 5244 5245 logmsg "== Contents of files in the $LOGDIR/ dir after test $testnum\n"; 5246 foreach my $log (sort @logs) { 5247 if($log =~ /\.(\.|)$/) { 5248 next; # skip "." and ".." 5249 } 5250 if($log =~ /^\.nfs/) { 5251 next; # skip ".nfs" 5252 } 5253 if(($log eq "memdump") || ($log eq "core")) { 5254 next; # skip "memdump" and "core" 5255 } 5256 if((-d "$LOGDIR/$log") || (! -s "$LOGDIR/$log")) { 5257 next; # skip directory and empty files 5258 } 5259 if(($log =~ /^stdout\d+/) && ($log !~ /^stdout$testnum/)) { 5260 next; # skip stdoutNnn of other tests 5261 } 5262 if(($log =~ /^stderr\d+/) && ($log !~ /^stderr$testnum/)) { 5263 next; # skip stderrNnn of other tests 5264 } 5265 if(($log =~ /^upload\d+/) && ($log !~ /^upload$testnum/)) { 5266 next; # skip uploadNnn of other tests 5267 } 5268 if(($log =~ /^curl\d+\.out/) && ($log !~ /^curl$testnum\.out/)) { 5269 next; # skip curlNnn.out of other tests 5270 } 5271 if(($log =~ /^test\d+\.txt/) && ($log !~ /^test$testnum\.txt/)) { 5272 next; # skip testNnn.txt of other tests 5273 } 5274 if(($log =~ /^file\d+\.txt/) && ($log !~ /^file$testnum\.txt/)) { 5275 next; # skip fileNnn.txt of other tests 5276 } 5277 if(($log =~ /^netrc\d+/) && ($log !~ /^netrc$testnum/)) { 5278 next; # skip netrcNnn of other tests 5279 } 5280 if(($log =~ /^trace\d+/) && ($log !~ /^trace$testnum/)) { 5281 next; # skip traceNnn of other tests 5282 } 5283 if(($log =~ /^valgrind\d+/) && ($log !~ /^valgrind$testnum(\..*|)$/)) { 5284 next; # skip valgrindNnn of other tests 5285 } 5286 logmsg "=== Start of file $log\n"; 5287 displaylogcontent("$LOGDIR/$log"); 5288 logmsg "=== End of file $log\n"; 5289 } 5290} 5291 5292####################################################################### 5293# The main test-loop 5294# 5295 5296my $failed; 5297my $testnum; 5298my $ok=0; 5299my $total=0; 5300my $lasttest=0; 5301my @at = split(" ", $TESTCASES); 5302my $count=0; 5303 5304$start = time(); 5305 5306foreach $testnum (@at) { 5307 5308 $lasttest = $testnum if($testnum > $lasttest); 5309 $count++; 5310 5311 my $error = singletest($run_event_based, $testnum, $count, scalar(@at)); 5312 if($error < 0) { 5313 # not a test we can run 5314 next; 5315 } 5316 5317 $total++; # number of tests we've run 5318 5319 if($error>0) { 5320 $failed.= "$testnum "; 5321 if($postmortem) { 5322 # display all files in log/ in a nice way 5323 displaylogs($testnum); 5324 } 5325 if(!$anyway) { 5326 # a test failed, abort 5327 logmsg "\n - abort tests\n"; 5328 last; 5329 } 5330 } 5331 elsif(!$error) { 5332 $ok++; # successful test counter 5333 } 5334 5335 # loop for next test 5336} 5337 5338my $sofar = time() - $start; 5339 5340####################################################################### 5341# Close command log 5342# 5343close(CMDLOG); 5344 5345# Tests done, stop the servers 5346stopservers($verbose); 5347 5348my $all = $total + $skipped; 5349 5350runtimestats($lasttest); 5351 5352if($total) { 5353 logmsg sprintf("TESTDONE: $ok tests out of $total reported OK: %d%%\n", 5354 $ok/$total*100); 5355 5356 if($ok != $total) { 5357 logmsg "TESTFAIL: These test cases failed: $failed\n"; 5358 } 5359} 5360else { 5361 logmsg "TESTFAIL: No tests were performed\n"; 5362} 5363 5364if($all) { 5365 logmsg "TESTDONE: $all tests were considered during ". 5366 sprintf("%.0f", $sofar) ." seconds.\n"; 5367} 5368 5369if($skipped && !$short) { 5370 my $s=0; 5371 logmsg "TESTINFO: $skipped tests were skipped due to these restraints:\n"; 5372 5373 for(keys %skipped) { 5374 my $r = $_; 5375 printf "TESTINFO: \"%s\" %d times (", $r, $skipped{$_}; 5376 5377 # now show all test case numbers that had this reason for being 5378 # skipped 5379 my $c=0; 5380 my $max = 9; 5381 for(0 .. scalar @teststat) { 5382 my $t = $_; 5383 if($teststat[$_] && ($teststat[$_] eq $r)) { 5384 if($c < $max) { 5385 logmsg ", " if($c); 5386 logmsg $_; 5387 } 5388 $c++; 5389 } 5390 } 5391 if($c > $max) { 5392 logmsg " and ".($c-$max)." more"; 5393 } 5394 logmsg ")\n"; 5395 } 5396} 5397 5398if($total && ($ok != $total)) { 5399 exit 1; 5400} 5401