servers.pm 103 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143
  1. #***************************************************************************
  2. # _ _ ____ _
  3. # Project ___| | | | _ \| |
  4. # / __| | | | |_) | |
  5. # | (__| |_| | _ <| |___
  6. # \___|\___/|_| \_\_____|
  7. #
  8. # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. #
  10. # This software is licensed as described in the file COPYING, which
  11. # you should have received as part of this distribution. The terms
  12. # are also available at https://curl.se/docs/copyright.html.
  13. #
  14. # You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. # copies of the Software, and permit persons to whom the Software is
  16. # furnished to do so, under the terms of the COPYING file.
  17. #
  18. # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. # KIND, either express or implied.
  20. #
  21. # SPDX-License-Identifier: curl
  22. #
  23. ###########################################################################
  24. # This module contains functions that are useful for managing the lifecycle of
  25. # test servers required when running tests. It is not intended for use within
  26. # those servers, but rather for starting and stopping them.
  27. package servers;
  28. use IO::Socket;
  29. use strict;
  30. use warnings;
  31. BEGIN {
  32. use base qw(Exporter);
  33. our @EXPORT = (
  34. # variables
  35. qw(
  36. $SOCKSIN
  37. $err_unexpected
  38. $debugprotocol
  39. $stunnel
  40. ),
  41. # functions
  42. qw(
  43. initserverconfig
  44. )
  45. );
  46. our @EXPORT_OK = (
  47. # functions
  48. qw(
  49. checkcmd
  50. clearlocks
  51. serverfortest
  52. stopserver
  53. stopservers
  54. subvariables
  55. localhttp
  56. ),
  57. # for debugging only
  58. qw(
  59. protoport
  60. )
  61. );
  62. }
  63. use serverhelp qw(
  64. serverfactors
  65. servername_id
  66. servername_str
  67. servername_canon
  68. server_pidfilename
  69. server_portfilename
  70. server_logfilename
  71. );
  72. use sshhelp qw(
  73. $hstpubmd5f
  74. $hstpubsha256f
  75. $sshexe
  76. $sftpexe
  77. $sftpconfig
  78. $sshdlog
  79. $sftplog
  80. $sftpcmds
  81. display_sshdconfig
  82. display_sftpconfig
  83. display_sshdlog
  84. display_sftplog
  85. find_sshd
  86. find_ssh
  87. find_sftp
  88. find_httptlssrv
  89. sshversioninfo
  90. );
  91. use pathhelp qw(
  92. exe_ext
  93. os_is_win
  94. sys_native_abs_path
  95. );
  96. use processhelp;
  97. use globalconfig;
  98. use testutil qw(
  99. logmsg
  100. runclient
  101. runclientoutput
  102. );
  103. my %serverpidfile; # all server pid file names, identified by server id
  104. my %serverportfile;# all server port file names, identified by server id
  105. my $sshdvernum; # for socks server, ssh daemon version number
  106. my $sshdverstr; # for socks server, ssh daemon version string
  107. my $sshderror; # for socks server, ssh daemon version error
  108. my %doesntrun; # servers that don't work, identified by pidfile
  109. my %PORT = (nolisten => 47); # port we use for a local non-listening service
  110. my $server_response_maxtime=13;
  111. my $httptlssrv = find_httptlssrv();
  112. my %run; # running server
  113. my %runcert; # cert file currently in use by an ssl running server
  114. my $CLIENTIP="127.0.0.1"; # address which curl uses for incoming connections
  115. my $CLIENT6IP="[::1]"; # address which curl uses for incoming connections
  116. my $posix_pwd=$pwd; # current working directory
  117. my $h2cver = "h2c"; # this version is decided by the nghttp2 lib being used
  118. my $portrange = 999; # space from which to choose a random port
  119. # don't increase without making sure generated port
  120. # numbers will always be valid (<=65535)
  121. my $HOSTIP="127.0.0.1"; # address on which the test server listens
  122. my $HOST6IP="[::1]"; # address on which the test server listens
  123. my $HTTPUNIXPATH; # HTTP server Unix domain socket path
  124. my $SOCKSUNIXPATH; # socks server Unix domain socket path
  125. my $SSHSRVMD5 = "[uninitialized]"; # MD5 of ssh server public key
  126. my $SSHSRVSHA256 = "[uninitialized]"; # SHA256 of ssh server public key
  127. my $USER; # name of the current user
  128. my $sshdid; # for socks server, ssh daemon version id
  129. my $ftpchecktime=1; # time it took to verify our test FTP server
  130. # Variables shared with runtests.pl
  131. our $SOCKSIN="socksd-request.log"; # what curl sent to the SOCKS proxy
  132. our $err_unexpected; # error instead of warning on server unexpectedly alive
  133. our $debugprotocol; # nonzero for verbose server logs
  134. our $stunnel; # path to stunnel command
  135. #######################################################################
  136. # Check for a command in the PATH of the test server.
  137. #
  138. sub checkcmd {
  139. my ($cmd, @extrapaths)=@_;
  140. my $sep = '[:]';
  141. if ($^O eq 'MSWin32' || $^O eq 'dos' || $^O eq 'os2') {
  142. # PATH separator is different
  143. $sep = '[;]';
  144. }
  145. my @paths=(split(m/$sep/, $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
  146. "/sbin", "/usr/bin", "/usr/local/bin", @extrapaths);
  147. for(@paths) {
  148. if( -x "$_/$cmd" . exe_ext('SYS') && ! -d "$_/$cmd" . exe_ext('SYS')) {
  149. # executable bit but not a directory!
  150. return "$_/$cmd";
  151. }
  152. }
  153. return "";
  154. }
  155. #######################################################################
  156. # Create a server socket on a random (unused) port, then close it and
  157. # return the port number
  158. #
  159. sub getfreeport {
  160. my ($ipnum) = @_;
  161. my $server = IO::Socket->new(LocalPort => 0,
  162. Domain => $ipnum == 6 ? AF_INET6 : AF_INET,
  163. Type => SOCK_STREAM,
  164. Reuse => 1,
  165. Listen => 10 )
  166. or die "Couldn't create tcp server socket: $@\n";
  167. return $server->sockport();
  168. }
  169. use File::Temp qw/ tempfile/;
  170. #######################################################################
  171. # Initialize configuration variables
  172. sub initserverconfig {
  173. my ($fh, $socks) = tempfile("curl-socksd-XXXXXXXX", TMPDIR => 1);
  174. close($fh);
  175. unlink($socks);
  176. my ($f2, $http) = tempfile("curl-http-XXXXXXXX", TMPDIR => 1);
  177. close($f2);
  178. unlink($http);
  179. $SOCKSUNIXPATH = $socks; # SOCKS Unix domain socket
  180. $HTTPUNIXPATH = $http; # HTTP Unix domain socket
  181. $stunnel = checkcmd("stunnel4") || checkcmd("tstunnel") || checkcmd("stunnel");
  182. # get the name of the current user
  183. $USER = $ENV{USER}; # Linux
  184. if (!$USER) {
  185. $USER = $ENV{USERNAME}; # Windows
  186. if (!$USER) {
  187. $USER = $ENV{LOGNAME}; # Some Unix (I think)
  188. }
  189. }
  190. init_serverpidfile_hash();
  191. }
  192. #######################################################################
  193. # Load serverpidfile and serverportfile hashes with file names for all
  194. # possible servers.
  195. #
  196. sub init_serverpidfile_hash {
  197. for my $proto (('ftp', 'gopher', 'http', 'imap', 'pop3', 'smtp', 'http/2', 'http/3')) {
  198. for my $ssl (('', 's')) {
  199. for my $ipvnum ((4, 6)) {
  200. for my $idnum ((1, 2, 3)) {
  201. my $serv = servername_id("$proto$ssl", $ipvnum, $idnum);
  202. my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
  203. $ipvnum, $idnum);
  204. $serverpidfile{$serv} = $pidf;
  205. my $portf = server_portfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
  206. $ipvnum, $idnum);
  207. $serverportfile{$serv} = $portf;
  208. }
  209. }
  210. }
  211. }
  212. for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'httptls',
  213. 'dict', 'smb', 'smbs', 'telnet', 'mqtt')) {
  214. for my $ipvnum ((4, 6)) {
  215. for my $idnum ((1, 2)) {
  216. my $serv = servername_id($proto, $ipvnum, $idnum);
  217. my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
  218. $idnum);
  219. $serverpidfile{$serv} = $pidf;
  220. my $portf = server_portfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
  221. $idnum);
  222. $serverportfile{$serv} = $portf;
  223. }
  224. }
  225. }
  226. for my $proto (('http', 'imap', 'pop3', 'smtp', 'http/2', 'http/3')) {
  227. for my $ssl (('', 's')) {
  228. my $serv = servername_id("$proto$ssl", "unix", 1);
  229. my $pidf = server_pidfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
  230. "unix", 1);
  231. $serverpidfile{$serv} = $pidf;
  232. my $portf = server_portfilename("$LOGDIR/$PIDDIR", "$proto$ssl",
  233. "unix", 1);
  234. $serverportfile{$serv} = $portf;
  235. }
  236. }
  237. }
  238. #######################################################################
  239. # Kill the processes that still have lock files in a directory
  240. #
  241. sub clearlocks {
  242. my $dir = $_[0];
  243. my $done = 0;
  244. if(os_is_win()) {
  245. $dir = sys_native_abs_path($dir);
  246. $dir =~ s/\//\\\\/g;
  247. my $handle = "handle";
  248. if($ENV{"PROCESSOR_ARCHITECTURE"} =~ /64$/) {
  249. $handle = "handle64";
  250. }
  251. if(checkcmd($handle)) {
  252. # https://learn.microsoft.com/sysinternals/downloads/handle#usage
  253. my $cmd = "$handle $dir -accepteula -nobanner";
  254. logmsg "Executing: '$cmd'\n";
  255. my @handles = `$cmd`;
  256. for my $tryhandle (@handles) {
  257. # Skip the "No matching handles found." warning when returned
  258. if($tryhandle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) {
  259. logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n";
  260. # Ignore stunnel since we cannot do anything about its locks
  261. if("$3" eq "File" && "$1" ne "tstunnel.exe") {
  262. logmsg "Killing IMAGENAME eq $1 and PID eq $2\n";
  263. # https://ss64.com/nt/taskkill.html
  264. my $cmd = "taskkill.exe -f -t -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1";
  265. logmsg "Executing: '$cmd'\n";
  266. system($cmd);
  267. $done = 1;
  268. }
  269. }
  270. }
  271. }
  272. else {
  273. logmsg "Warning: 'handle' tool not found.\n";
  274. }
  275. }
  276. return $done;
  277. }
  278. #######################################################################
  279. # Check if a given child process has just died. Reaps it if so.
  280. #
  281. sub checkdied {
  282. my $pid = $_[0];
  283. if((not defined $pid) || $pid <= 0) {
  284. return 0;
  285. }
  286. use POSIX ":sys_wait_h";
  287. my $rc = pidwait($pid, &WNOHANG);
  288. return ($rc == $pid)?1:0;
  289. }
  290. ##############################################################################
  291. # This function makes sure the right set of server is running for the
  292. # specified test case. This is a useful design when we run single tests as not
  293. # all servers need to run then!
  294. #
  295. # Returns: a string, blank if everything is fine or a reason why it failed, and
  296. # an integer:
  297. # 0 for success
  298. # 1 for an error starting the server
  299. # 2 for not the first time getting an error starting the server
  300. # 3 for a failure to stop a server in order to restart it
  301. # 4 for an unsupported server type
  302. #
  303. sub serverfortest {
  304. my (@what)=@_;
  305. for(my $i = scalar(@what) - 1; $i >= 0; $i--) {
  306. my $srvrline = $what[$i];
  307. chomp $srvrline if($srvrline);
  308. if($srvrline =~ /^(\S+)((\s*)(.*))/) {
  309. my $server = "${1}";
  310. my $lnrest = "${2}";
  311. my $tlsext;
  312. if($server =~ /^(httptls)(\+)(ext|srp)(\d*)(-ipv6|)$/) {
  313. $server = "${1}${4}${5}";
  314. $tlsext = uc("TLS-${3}");
  315. }
  316. if(! grep /^\Q$server\E$/, @protocols) {
  317. if(substr($server,0,5) ne "socks") {
  318. if($tlsext) {
  319. return ("curl lacks $tlsext support", 4);
  320. }
  321. else {
  322. return ("curl lacks $server server support", 4);
  323. }
  324. }
  325. }
  326. $what[$i] = "$server$lnrest" if($tlsext);
  327. }
  328. }
  329. return &startservers(@what);
  330. }
  331. #######################################################################
  332. # Start a new thread/process and run the given command line in there.
  333. # Return the pids (yes plural) of the new child process to the parent.
  334. #
  335. sub startnew {
  336. my ($cmd, $pidfile, $timeout, $fakepidfile)=@_;
  337. logmsg "startnew: $cmd\n" if ($verbose);
  338. my $child = fork();
  339. if(not defined $child) {
  340. logmsg "startnew: fork() failure detected\n";
  341. return (-1,-1);
  342. }
  343. if(0 == $child) {
  344. # Here we are the child. Run the given command.
  345. # Flush output.
  346. $| = 1;
  347. # Put an "exec" in front of the command so that the child process
  348. # keeps this child's process ID.
  349. exec("exec $cmd") || die "Can't exec() $cmd: $!";
  350. # exec() should never return back here to this process. We protect
  351. # ourselves by calling die() just in case something goes really bad.
  352. die "error: exec() has returned";
  353. }
  354. # Ugly hack but ssh client and gnutls-serv don't support pid files
  355. if ($fakepidfile) {
  356. if(open(my $out, ">", "$pidfile")) {
  357. print $out $child . "\n";
  358. close($out) || die "Failure writing pidfile";
  359. logmsg "startnew: $pidfile faked with pid=$child\n" if($verbose);
  360. }
  361. else {
  362. logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
  363. }
  364. # could/should do a while connect fails sleep a bit and loop
  365. portable_sleep($timeout);
  366. if (checkdied($child)) {
  367. logmsg "startnew: child process has failed to start\n" if($verbose);
  368. return (-1,-1);
  369. }
  370. }
  371. my $pid2 = 0;
  372. my $count = $timeout;
  373. while($count--) {
  374. $pid2 = pidfromfile($pidfile);
  375. if(($pid2 > 0) && pidexists($pid2)) {
  376. # if $pid2 is valid, then make sure this pid is alive, as
  377. # otherwise it is just likely to be the _previous_ pidfile or
  378. # similar!
  379. last;
  380. }
  381. if (checkdied($child)) {
  382. logmsg "startnew: child process has died, server might start up\n"
  383. if($verbose);
  384. # We can't just abort waiting for the server with a
  385. # return (-1,-1);
  386. # because the server might have forked and could still start
  387. # up normally. Instead, just reduce the amount of time we remain
  388. # waiting.
  389. $count >>= 2;
  390. }
  391. sleep(1);
  392. }
  393. # Return two PIDs, the one for the child process we spawned and the one
  394. # reported by the server itself (in case it forked again on its own).
  395. # Both (potentially) need to be killed at the end of the test.
  396. return ($child, $pid2);
  397. }
  398. #######################################################################
  399. # Return the port to use for the given protocol.
  400. #
  401. sub protoport {
  402. my ($proto) = @_;
  403. return $PORT{$proto} || "[not running]";
  404. }
  405. #######################################################################
  406. # Stop a test server along with pids which aren't in the %run hash yet.
  407. # This also stops all servers which are relative to the given one.
  408. #
  409. sub stopserver {
  410. my ($server, $pidlist) = @_;
  411. my $ipvnum = 4;
  412. #
  413. # kill sockfilter processes for pingpong relative server
  414. #
  415. if($server =~ /^(ftp|imap|pop3|smtp)s?(\d*)(-ipv6|)$/) {
  416. my $proto = $1;
  417. my $idnum = ($2 && ($2 > 1)) ? $2 : 1;
  418. $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4;
  419. killsockfilters("$LOGDIR/$PIDDIR", $proto, $ipvnum, $idnum, $verbose);
  420. }
  421. #
  422. # All servers relative to the given one must be stopped also
  423. #
  424. my @killservers;
  425. if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
  426. # given a stunnel based ssl server, also kill non-ssl underlying one
  427. push @killservers, "${1}${2}";
  428. }
  429. elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) {
  430. # given a non-ssl server, also kill stunnel based ssl piggybacking one
  431. push @killservers, "${1}s${2}";
  432. }
  433. elsif($server =~ /^(socks)((\d*)(-ipv6|))$/) {
  434. # given a socks server, also kill ssh underlying one
  435. push @killservers, "ssh${2}";
  436. }
  437. elsif($server =~ /^(ssh)((\d*)(-ipv6|))$/) {
  438. # given a ssh server, also kill socks piggybacking one
  439. push @killservers, "socks${2}";
  440. }
  441. if($server eq "http" or $server eq "https") {
  442. # since the http2+3 server is a proxy that needs to know about the
  443. # dynamic http port it too needs to get restarted when the http server
  444. # is killed
  445. push @killservers, "http/2";
  446. push @killservers, "http/3";
  447. }
  448. push @killservers, $server;
  449. #
  450. # kill given pids and server relative ones clearing them in %run hash
  451. #
  452. foreach my $server (@killservers) {
  453. if($run{$server}) {
  454. # we must prepend a space since $pidlist may already contain a pid
  455. $pidlist .= " $run{$server}";
  456. $run{$server} = 0;
  457. }
  458. $runcert{$server} = 0 if($runcert{$server});
  459. }
  460. killpid($verbose, $pidlist);
  461. #
  462. # cleanup server pid files
  463. #
  464. my $result = 0;
  465. foreach my $server (@killservers) {
  466. my $pidfile = $serverpidfile{$server};
  467. unlink($pidfile) if(-f $pidfile);
  468. }
  469. #
  470. # cleanup server lock files
  471. #
  472. foreach my $server (@killservers) {
  473. # servers seem to produce (some of) these lock files
  474. my @lockfiles = (
  475. "$LOGDIR/$LOCKDIR/$server.lock",
  476. "$LOGDIR/$LOCKDIR/$server-IPv$ipvnum.lock",
  477. "$LOGDIR/$LOCKDIR/sws-".uc($server)."-IPv$ipvnum.lock"
  478. );
  479. foreach my $lockfile (@lockfiles) {
  480. if(-f $lockfile) {
  481. unlink($lockfile);
  482. logmsg "RUN: kill $server, cleaned up $lockfile\n" if ($verbose);
  483. }
  484. }
  485. }
  486. return $result;
  487. }
  488. #######################################################################
  489. # Return flags to let curl use an external HTTP proxy
  490. #
  491. sub getexternalproxyflags {
  492. return " --proxy $proxy_address ";
  493. }
  494. #######################################################################
  495. # Verify that the server that runs on $ip, $port is our server. This also
  496. # implies that we can speak with it, as there might be occasions when the
  497. # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
  498. # assign requested address")
  499. #
  500. sub verifyhttp {
  501. my ($proto, $ipvnum, $idnum, $ip, $port_or_path, $do_http3) = @_;
  502. my $server = servername_id($proto, $ipvnum, $idnum);
  503. my $bonus="";
  504. # $port_or_path contains a path for Unix sockets, sws ignores the port
  505. my $port = ($ipvnum eq "unix") ? 80 : $port_or_path;
  506. my $infix = ($do_http3) ? "_h3" : "";
  507. my $verifyout = "$LOGDIR/".
  508. servername_canon($proto, $ipvnum, $idnum) .$infix .'_verify.out';
  509. unlink($verifyout) if(-f $verifyout);
  510. my $verifylog = "$LOGDIR/".
  511. servername_canon($proto, $ipvnum, $idnum) .$infix .'_verify.log';
  512. unlink($verifylog) if(-f $verifylog);
  513. if($proto eq "gopher") {
  514. # gopher is funny
  515. $bonus="1/";
  516. }
  517. my $flags = "--max-time $server_response_maxtime ";
  518. $flags .= "--output $verifyout ";
  519. $flags .= "--silent ";
  520. $flags .= "--verbose ";
  521. $flags .= "--globoff ";
  522. $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix";
  523. $flags .= "--insecure " if($proto eq 'https');
  524. if($proxy_address) {
  525. $flags .= getexternalproxyflags();
  526. }
  527. $flags .= "--http3-only " if($do_http3);
  528. $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\"";
  529. my $cmd = "$VCURL $flags 2>$verifylog";
  530. # verify if our/any server is running on this port
  531. logmsg "RUN: $cmd\n" if($verbose);
  532. my $res = runclient($cmd);
  533. $res >>= 8; # rotate the result
  534. if($res & 128) {
  535. logmsg "RUN: curl command died with a coredump\n";
  536. return -1;
  537. }
  538. if($res && $verbose) {
  539. logmsg "RUN: curl command returned $res\n";
  540. if(open(my $file, "<", "$verifylog")) {
  541. while(my $string = <$file>) {
  542. logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
  543. }
  544. close($file);
  545. }
  546. }
  547. my $data;
  548. if(open(my $file, "<", "$verifyout")) {
  549. while(my $string = <$file>) {
  550. $data = $string;
  551. last; # only want first line
  552. }
  553. close($file);
  554. }
  555. my $pid = 0;
  556. if($data && ($data =~ /WE ROOLZ: (\d+)/)) {
  557. $pid = 0+$1;
  558. }
  559. elsif($res == 6) {
  560. # curl: (6) Couldn't resolve host '::1'
  561. logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
  562. return -1;
  563. }
  564. elsif($data || ($res && ($res != 7))) {
  565. logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
  566. return -1;
  567. }
  568. return $pid;
  569. }
  570. #######################################################################
  571. # Verify that the server that runs on $ip, $port is our server. This also
  572. # implies that we can speak with it, as there might be occasions when the
  573. # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
  574. # assign requested address")
  575. #
  576. sub verifyftp {
  577. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  578. my $server = servername_id($proto, $ipvnum, $idnum);
  579. my $time=time();
  580. my $extra="";
  581. my $verifylog = "$LOGDIR/".
  582. servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
  583. unlink($verifylog) if(-f $verifylog);
  584. if($proto eq "ftps") {
  585. $extra .= "--insecure --ftp-ssl-control ";
  586. }
  587. my $flags = "--max-time $server_response_maxtime ";
  588. $flags .= "--silent ";
  589. $flags .= "--verbose ";
  590. $flags .= "--globoff ";
  591. $flags .= $extra;
  592. if($proxy_address) {
  593. $flags .= getexternalproxyflags();
  594. }
  595. $flags .= "\"$proto://$ip:$port/verifiedserver\"";
  596. my $cmd = "$VCURL $flags 2>$verifylog";
  597. # check if this is our server running on this port:
  598. logmsg "RUN: $cmd\n" if($verbose);
  599. my @data = runclientoutput($cmd);
  600. my $res = $? >> 8; # rotate the result
  601. if($res & 128) {
  602. logmsg "RUN: curl command died with a coredump\n";
  603. return -1;
  604. }
  605. my $pid = 0;
  606. foreach my $line (@data) {
  607. if($line =~ /WE ROOLZ: (\d+)/) {
  608. # this is our test server with a known pid!
  609. $pid = 0+$1;
  610. last;
  611. }
  612. }
  613. if($pid <= 0 && @data && $data[0]) {
  614. # this is not a known server
  615. logmsg "RUN: Unknown server on our $server port: $port\n";
  616. return 0;
  617. }
  618. # we can/should use the time it took to verify the FTP server as a measure
  619. # on how fast/slow this host/FTP is.
  620. my $took = int(0.5+time()-$time);
  621. if($verbose) {
  622. logmsg "RUN: Verifying our test $server server took $took seconds\n";
  623. }
  624. $ftpchecktime = $took>=1?$took:1; # make sure it never is below 1
  625. return $pid;
  626. }
  627. #######################################################################
  628. # Verify that the server that runs on $ip, $port is our server. This also
  629. # implies that we can speak with it, as there might be occasions when the
  630. # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
  631. # assign requested address")
  632. #
  633. sub verifyrtsp {
  634. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  635. my $server = servername_id($proto, $ipvnum, $idnum);
  636. my $verifyout = "$LOGDIR/".
  637. servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
  638. unlink($verifyout) if(-f $verifyout);
  639. my $verifylog = "$LOGDIR/".
  640. servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
  641. unlink($verifylog) if(-f $verifylog);
  642. my $flags = "--max-time $server_response_maxtime ";
  643. $flags .= "--output $verifyout ";
  644. $flags .= "--silent ";
  645. $flags .= "--verbose ";
  646. $flags .= "--globoff ";
  647. if($proxy_address) {
  648. $flags .= getexternalproxyflags();
  649. }
  650. # currently verification is done using http
  651. $flags .= "\"http://$ip:$port/verifiedserver\"";
  652. my $cmd = "$VCURL $flags 2>$verifylog";
  653. # verify if our/any server is running on this port
  654. logmsg "RUN: $cmd\n" if($verbose);
  655. my $res = runclient($cmd);
  656. $res >>= 8; # rotate the result
  657. if($res & 128) {
  658. logmsg "RUN: curl command died with a coredump\n";
  659. return -1;
  660. }
  661. if($res && $verbose) {
  662. logmsg "RUN: curl command returned $res\n";
  663. if(open(my $file, "<", "$verifylog")) {
  664. while(my $string = <$file>) {
  665. logmsg "RUN: $string" if($string !~ /^[ \t]*$/);
  666. }
  667. close($file);
  668. }
  669. }
  670. my $data;
  671. if(open(my $file, "<", "$verifyout")) {
  672. while(my $string = <$file>) {
  673. $data = $string;
  674. last; # only want first line
  675. }
  676. close($file);
  677. }
  678. my $pid = 0;
  679. if($data && ($data =~ /RTSP_SERVER WE ROOLZ: (\d+)/)) {
  680. $pid = 0+$1;
  681. }
  682. elsif($res == 6) {
  683. # curl: (6) Couldn't resolve host '::1'
  684. logmsg "RUN: failed to resolve host ($proto://$ip:$port/verifiedserver)\n";
  685. return -1;
  686. }
  687. elsif($data || ($res != 7)) {
  688. logmsg "RUN: Unknown server on our $server port: $port\n";
  689. return -1;
  690. }
  691. return $pid;
  692. }
  693. #######################################################################
  694. # Verify that the ssh server has written out its pidfile, recovering
  695. # the pid from the file and returning it if a process with that pid is
  696. # actually alive, or a negative value if the process is dead.
  697. #
  698. sub verifyssh {
  699. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  700. my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
  701. $idnum);
  702. my $pid = processexists($pidfile);
  703. if($pid < 0) {
  704. logmsg "RUN: SSH server has died after starting up\n";
  705. }
  706. return $pid;
  707. }
  708. #######################################################################
  709. # Verify that we can connect to the sftp server, properly authenticate
  710. # with generated config and key files and run a simple remote pwd.
  711. #
  712. sub verifysftp {
  713. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  714. my $server = servername_id($proto, $ipvnum, $idnum);
  715. my $verified = 0;
  716. # Find out sftp client canonical file name
  717. my $sftp = find_sftp();
  718. if(!$sftp) {
  719. logmsg "RUN: SFTP server cannot find $sftpexe\n";
  720. return -1;
  721. }
  722. # Find out ssh client canonical file name
  723. my $ssh = find_ssh();
  724. if(!$ssh) {
  725. logmsg "RUN: SFTP server cannot find $sshexe\n";
  726. return -1;
  727. }
  728. # Connect to sftp server, authenticate and run a remote pwd
  729. # command using our generated configuration and key files
  730. my $cmd = "\"$sftp\" -b $LOGDIR/$PIDDIR/$sftpcmds -F $LOGDIR/$PIDDIR/$sftpconfig -S \"$ssh\" $ip > $sftplog 2>&1";
  731. my $res = runclient($cmd);
  732. # Search for pwd command response in log file
  733. if(open(my $sftplogfile, "<", "$sftplog")) {
  734. while(<$sftplogfile>) {
  735. if(/^Remote working directory: /) {
  736. $verified = 1;
  737. last;
  738. }
  739. }
  740. close($sftplogfile);
  741. }
  742. return $verified;
  743. }
  744. #######################################################################
  745. # Verify that the non-stunnel HTTP TLS extensions capable server that runs
  746. # on $ip, $port is our server. This also implies that we can speak with it,
  747. # as there might be occasions when the server runs fine but we cannot talk
  748. # to it ("Failed to connect to ::1: Can't assign requested address")
  749. #
  750. sub verifyhttptls {
  751. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  752. my $server = servername_id($proto, $ipvnum, $idnum);
  753. my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
  754. $idnum);
  755. my $verifyout = "$LOGDIR/".
  756. servername_canon($proto, $ipvnum, $idnum) .'_verify.out';
  757. unlink($verifyout) if(-f $verifyout);
  758. my $verifylog = "$LOGDIR/".
  759. servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
  760. unlink($verifylog) if(-f $verifylog);
  761. my $flags = "--max-time $server_response_maxtime ";
  762. $flags .= "--output $verifyout ";
  763. $flags .= "--verbose ";
  764. $flags .= "--globoff ";
  765. $flags .= "--insecure ";
  766. $flags .= "--tlsauthtype SRP ";
  767. $flags .= "--tlsuser jsmith ";
  768. $flags .= "--tlspassword abc ";
  769. if($proxy_address) {
  770. $flags .= getexternalproxyflags();
  771. }
  772. $flags .= "\"https://$ip:$port/verifiedserver\"";
  773. my $cmd = "$VCURL $flags 2>$verifylog";
  774. # verify if our/any server is running on this port
  775. logmsg "RUN: $cmd\n" if($verbose);
  776. my $res = runclient($cmd);
  777. $res >>= 8; # rotate the result
  778. if($res & 128) {
  779. logmsg "RUN: curl command died with a coredump\n";
  780. return -1;
  781. }
  782. if($res && $verbose) {
  783. logmsg "RUN: curl command returned $res\n";
  784. if(open(my $file, "<", "$verifylog")) {
  785. while(my $string = <$file>) {
  786. logmsg "RUN: $string" if($string !~ /^([ \t]*)$/);
  787. }
  788. close($file);
  789. }
  790. }
  791. my $data;
  792. if(open(my $file, "<", "$verifyout")) {
  793. while(my $string = <$file>) {
  794. $data .= $string;
  795. }
  796. close($file);
  797. }
  798. my $pid = 0;
  799. if($data && ($data =~ /(GNUTLS|GnuTLS)/) && ($pid = processexists($pidfile))) {
  800. if($pid < 0) {
  801. logmsg "RUN: $server server has died after starting up\n";
  802. }
  803. return $pid;
  804. }
  805. elsif($res == 6) {
  806. # curl: (6) Couldn't resolve host '::1'
  807. logmsg "RUN: failed to resolve host (https://$ip:$port/verifiedserver)\n";
  808. return -1;
  809. }
  810. elsif($data || ($res && ($res != 7))) {
  811. logmsg "RUN: Unknown server on our $server port: $port ($res)\n";
  812. return -1;
  813. }
  814. return $pid;
  815. }
  816. #######################################################################
  817. # STUB for verifying mqtt
  818. #
  819. sub verifymqtt {
  820. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  821. my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
  822. $idnum);
  823. my $pid = processexists($pidfile);
  824. if($pid < 0) {
  825. logmsg "RUN: MQTT server has died after starting up\n";
  826. }
  827. return $pid;
  828. }
  829. #######################################################################
  830. # STUB for verifying socks
  831. #
  832. sub verifysocks {
  833. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  834. my $pidfile = server_pidfilename("$LOGDIR/$PIDDIR", $proto, $ipvnum,
  835. $idnum);
  836. my $pid = processexists($pidfile);
  837. if($pid < 0) {
  838. logmsg "RUN: SOCKS server has died after starting up\n";
  839. }
  840. return $pid;
  841. }
  842. #######################################################################
  843. # Verify that the server that runs on $ip, $port is our server. This also
  844. # implies that we can speak with it, as there might be occasions when the
  845. # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
  846. # assign requested address")
  847. #
  848. sub verifysmb {
  849. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  850. my $server = servername_id($proto, $ipvnum, $idnum);
  851. my $time=time();
  852. my $extra="";
  853. my $verifylog = "$LOGDIR/".
  854. servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
  855. unlink($verifylog) if(-f $verifylog);
  856. my $flags = "--max-time $server_response_maxtime ";
  857. $flags .= "--silent ";
  858. $flags .= "--verbose ";
  859. $flags .= "--globoff ";
  860. $flags .= "-u 'curltest:curltest' ";
  861. $flags .= $extra;
  862. $flags .= "\"$proto://$ip:$port/SERVER/verifiedserver\"";
  863. my $cmd = "$VCURL $flags 2>$verifylog";
  864. # check if this is our server running on this port:
  865. logmsg "RUN: $cmd\n" if($verbose);
  866. my @data = runclientoutput($cmd);
  867. my $res = $? >> 8; # rotate the result
  868. if($res & 128) {
  869. logmsg "RUN: curl command died with a coredump\n";
  870. return -1;
  871. }
  872. my $pid = 0;
  873. foreach my $line (@data) {
  874. if($line =~ /WE ROOLZ: (\d+)/) {
  875. # this is our test server with a known pid!
  876. $pid = 0+$1;
  877. last;
  878. }
  879. }
  880. if($pid <= 0 && @data && $data[0]) {
  881. # this is not a known server
  882. logmsg "RUN: Unknown server on our $server port: $port\n";
  883. return 0;
  884. }
  885. # we can/should use the time it took to verify the server as a measure
  886. # on how fast/slow this host is.
  887. my $took = int(0.5+time()-$time);
  888. if($verbose) {
  889. logmsg "RUN: Verifying our test $server server took $took seconds\n";
  890. }
  891. return $pid;
  892. }
  893. #######################################################################
  894. # Verify that the server that runs on $ip, $port is our server. This also
  895. # implies that we can speak with it, as there might be occasions when the
  896. # server runs fine but we cannot talk to it ("Failed to connect to ::1: Can't
  897. # assign requested address")
  898. #
  899. sub verifytelnet {
  900. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  901. my $server = servername_id($proto, $ipvnum, $idnum);
  902. my $time=time();
  903. my $extra="";
  904. my $verifylog = "$LOGDIR/".
  905. servername_canon($proto, $ipvnum, $idnum) .'_verify.log';
  906. unlink($verifylog) if(-f $verifylog);
  907. my $flags = "--max-time $server_response_maxtime ";
  908. $flags .= "--silent ";
  909. $flags .= "--verbose ";
  910. $flags .= "--globoff ";
  911. $flags .= "--upload-file - ";
  912. $flags .= $extra;
  913. $flags .= "\"$proto://$ip:$port\"";
  914. my $cmd = "echo 'verifiedserver' | $VCURL $flags 2>$verifylog";
  915. # check if this is our server running on this port:
  916. logmsg "RUN: $cmd\n" if($verbose);
  917. my @data = runclientoutput($cmd);
  918. my $res = $? >> 8; # rotate the result
  919. if($res & 128) {
  920. logmsg "RUN: curl command died with a coredump\n";
  921. return -1;
  922. }
  923. my $pid = 0;
  924. foreach my $line (@data) {
  925. if($line =~ /WE ROOLZ: (\d+)/) {
  926. # this is our test server with a known pid!
  927. $pid = 0+$1;
  928. last;
  929. }
  930. }
  931. if($pid <= 0 && @data && $data[0]) {
  932. # this is not a known server
  933. logmsg "RUN: Unknown server on our $server port: $port\n";
  934. return 0;
  935. }
  936. # we can/should use the time it took to verify the server as a measure
  937. # on how fast/slow this host is.
  938. my $took = int(0.5+time()-$time);
  939. if($verbose) {
  940. logmsg "RUN: Verifying our test $server server took $took seconds\n";
  941. }
  942. return $pid;
  943. }
  944. #######################################################################
  945. # Verify that the server that runs on $ip, $port is our server.
  946. # Retry over several seconds before giving up. The ssh server in
  947. # particular can take a long time to start if it needs to generate
  948. # keys on a slow or loaded host.
  949. #
  950. # Just for convenience, test harness uses 'https' and 'httptls' literals
  951. # as values for 'proto' variable in order to differentiate different
  952. # servers. 'https' literal is used for stunnel based https test servers,
  953. # and 'httptls' is used for non-stunnel https test servers.
  954. #
  955. my %protofunc = ('http' => \&verifyhttp,
  956. 'https' => \&verifyhttp,
  957. 'rtsp' => \&verifyrtsp,
  958. 'ftp' => \&verifyftp,
  959. 'pop3' => \&verifyftp,
  960. 'imap' => \&verifyftp,
  961. 'smtp' => \&verifyftp,
  962. 'ftps' => \&verifyftp,
  963. 'pop3s' => \&verifyftp,
  964. 'imaps' => \&verifyftp,
  965. 'mqtt' => \&verifymqtt,
  966. 'smtps' => \&verifyftp,
  967. 'tftp' => \&verifyftp,
  968. 'ssh' => \&verifyssh,
  969. 'socks' => \&verifysocks,
  970. 'socks5unix' => \&verifysocks,
  971. 'gopher' => \&verifyhttp,
  972. 'httptls' => \&verifyhttptls,
  973. 'dict' => \&verifyftp,
  974. 'smb' => \&verifysmb,
  975. 'telnet' => \&verifytelnet);
  976. sub verifyserver {
  977. my ($proto, $ipvnum, $idnum, $ip, $port) = @_;
  978. my $count = 30; # try for this many seconds
  979. my $pid;
  980. while($count--) {
  981. my $fun = $protofunc{$proto};
  982. $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port);
  983. if($pid > 0) {
  984. last;
  985. }
  986. elsif($pid < 0) {
  987. # a real failure, stop trying and bail out
  988. return 0;
  989. }
  990. sleep(1);
  991. }
  992. return $pid;
  993. }
  994. #######################################################################
  995. # Single shot server responsiveness test. This should only be used
  996. # to verify that a server present in %run hash is still functional
  997. #
  998. sub responsiveserver {
  999. my ($proto, $ipvnum, $idnum, $ip, $port, $do_http3) = @_;
  1000. my $prev_verbose = $verbose;
  1001. $verbose = 0;
  1002. my $fun = $protofunc{$proto};
  1003. my $pid = &$fun($proto, $ipvnum, $idnum, $ip, $port, $do_http3);
  1004. $verbose = $prev_verbose;
  1005. if($pid > 0) {
  1006. return 1; # responsive
  1007. }
  1008. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1009. logmsg " server precheck FAILED (unresponsive $srvrname server)\n";
  1010. return 0;
  1011. }
  1012. #######################################################################
  1013. # start the http server
  1014. #
  1015. sub runhttpserver {
  1016. my ($proto, $verb, $alt, $port_or_path) = @_;
  1017. my $ip = $HOSTIP;
  1018. my $ipvnum = 4;
  1019. my $idnum = 1;
  1020. my $exe = "$perl $srcdir/http-server.pl";
  1021. my $verbose_flag = "--verbose ";
  1022. my $keepalive_secs = 30; # forwarded to sws, was 5 by default which
  1023. # led to pukes in CI jobs
  1024. if($alt eq "ipv6") {
  1025. # if IPv6, use a different setup
  1026. $ipvnum = 6;
  1027. $ip = $HOST6IP;
  1028. }
  1029. elsif($alt eq "proxy") {
  1030. # basically the same, but another ID
  1031. $idnum = 2;
  1032. }
  1033. elsif($alt eq "unix") {
  1034. # IP (protocol) is mutually exclusive with Unix sockets
  1035. $ipvnum = "unix";
  1036. }
  1037. my $server = servername_id($proto, $ipvnum, $idnum);
  1038. my $pidfile = $serverpidfile{$server};
  1039. # don't retry if the server doesn't work
  1040. if ($doesntrun{$pidfile}) {
  1041. return (2, 0, 0, 0);
  1042. }
  1043. my $pid = processexists($pidfile);
  1044. if($pid > 0) {
  1045. stopserver($server, "$pid");
  1046. }
  1047. unlink($pidfile) if(-f $pidfile);
  1048. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1049. my $portfile = $serverportfile{$server};
  1050. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1051. my $flags = "";
  1052. $flags .= "--gopher " if($proto eq "gopher");
  1053. $flags .= "--connect $HOSTIP " if($alt eq "proxy");
  1054. $flags .= "--keepalive $keepalive_secs ";
  1055. $flags .= $verbose_flag if($debugprotocol);
  1056. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1057. $flags .= "--logdir \"$LOGDIR\" ";
  1058. $flags .= "--portfile $portfile ";
  1059. $flags .= "--config $LOGDIR/$SERVERCMD ";
  1060. $flags .= "--id $idnum " if($idnum > 1);
  1061. if($ipvnum eq "unix") {
  1062. $flags .= "--unix-socket '$port_or_path' ";
  1063. } else {
  1064. $flags .= "--ipv$ipvnum --port 0 ";
  1065. }
  1066. $flags .= "--srcdir \"$srcdir\"";
  1067. my $cmd = "$exe $flags";
  1068. my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1069. if($httppid <= 0 || !pidexists($httppid)) {
  1070. # it is NOT alive
  1071. logmsg "RUN: failed to start the $srvrname server\n";
  1072. stopserver($server, "$pid2");
  1073. $doesntrun{$pidfile} = 1;
  1074. return (1, 0, 0, 0);
  1075. }
  1076. # where is it?
  1077. my $port = 0;
  1078. if(!$port_or_path) {
  1079. $port = $port_or_path = pidfromfile($portfile);
  1080. }
  1081. # Server is up. Verify that we can speak to it.
  1082. my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path);
  1083. if(!$pid3) {
  1084. logmsg "RUN: $srvrname server failed verification\n";
  1085. # failed to talk to it properly. Kill the server and return failure
  1086. stopserver($server, "$httppid $pid2");
  1087. $doesntrun{$pidfile} = 1;
  1088. return (1, 0, 0, 0);
  1089. }
  1090. $pid2 = $pid3;
  1091. if($verb) {
  1092. logmsg "RUN: $srvrname server is on PID $httppid port $port_or_path\n";
  1093. }
  1094. return (0, $httppid, $pid2, $port);
  1095. }
  1096. #######################################################################
  1097. # start the http2 server
  1098. #
  1099. sub runhttp2server {
  1100. my ($verb) = @_;
  1101. my $proto="http/2";
  1102. my $ipvnum = 4;
  1103. my $idnum = 0;
  1104. my $exe = "$perl $srcdir/http2-server.pl";
  1105. my $verbose_flag = "--verbose ";
  1106. my $server = servername_id($proto, $ipvnum, $idnum);
  1107. my $pidfile = $serverpidfile{$server};
  1108. # don't retry if the server doesn't work
  1109. if ($doesntrun{$pidfile}) {
  1110. return (2, 0, 0, 0, 0);
  1111. }
  1112. my $pid = processexists($pidfile);
  1113. if($pid > 0) {
  1114. stopserver($server, "$pid");
  1115. }
  1116. unlink($pidfile) if(-f $pidfile);
  1117. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1118. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1119. my $flags = "";
  1120. $flags .= "--nghttpx \"$ENV{'NGHTTPX'}\" ";
  1121. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1122. $flags .= "--logdir \"$LOGDIR\" ";
  1123. $flags .= "--connect $HOSTIP:" . protoport("http") . " ";
  1124. $flags .= $verbose_flag if($debugprotocol);
  1125. my $port = getfreeport($ipvnum);
  1126. my $port2 = getfreeport($ipvnum);
  1127. my $aflags = "--port $port --port2 $port2 $flags";
  1128. my $cmd = "$exe $aflags";
  1129. my ($http2pid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1130. if($http2pid <= 0 || !pidexists($http2pid)) {
  1131. # it is NOT alive
  1132. stopserver($server, "$pid2");
  1133. $doesntrun{$pidfile} = 1;
  1134. $http2pid = $pid2 = 0;
  1135. logmsg "RUN: failed to start the $srvrname server\n";
  1136. return (3, 0, 0, 0, 0);
  1137. }
  1138. $doesntrun{$pidfile} = 0;
  1139. if($verb) {
  1140. logmsg "RUN: $srvrname server PID $http2pid ".
  1141. "http-port $port https-port $port2 ".
  1142. "backend $HOSTIP:" . protoport("http") . "\n";
  1143. }
  1144. return (0+!$http2pid, $http2pid, $pid2, $port, $port2);
  1145. }
  1146. #######################################################################
  1147. # start the http3 server
  1148. #
  1149. sub runhttp3server {
  1150. my ($verb, $cert) = @_;
  1151. my $proto="http/3";
  1152. my $ipvnum = 4;
  1153. my $idnum = 0;
  1154. my $exe = "$perl $srcdir/http3-server.pl";
  1155. my $verbose_flag = "--verbose ";
  1156. my $server = servername_id($proto, $ipvnum, $idnum);
  1157. my $pidfile = $serverpidfile{$server};
  1158. # don't retry if the server doesn't work
  1159. if ($doesntrun{$pidfile}) {
  1160. return (2, 0, 0, 0);
  1161. }
  1162. my $pid = processexists($pidfile);
  1163. if($pid > 0) {
  1164. stopserver($server, "$pid");
  1165. }
  1166. unlink($pidfile) if(-f $pidfile);
  1167. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1168. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1169. my $flags = "";
  1170. $flags .= "--nghttpx \"$ENV{'NGHTTPX'}\" ";
  1171. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1172. $flags .= "--logdir \"$LOGDIR\" ";
  1173. $flags .= "--connect $HOSTIP:" . protoport("http") . " ";
  1174. $flags .= "--cert \"$cert\" " if($cert);
  1175. $flags .= $verbose_flag if($debugprotocol);
  1176. my $port = getfreeport($ipvnum);
  1177. my $aflags = "--port $port $flags";
  1178. my $cmd = "$exe $aflags";
  1179. my ($http3pid, $pid3) = startnew($cmd, $pidfile, 15, 0);
  1180. if($http3pid <= 0 || !pidexists($http3pid)) {
  1181. # it is NOT alive
  1182. stopserver($server, "$pid3");
  1183. $doesntrun{$pidfile} = 1;
  1184. $http3pid = $pid3 = 0;
  1185. logmsg "RUN: failed to start the $srvrname server\n";
  1186. return (3, 0, 0, 0);
  1187. }
  1188. $doesntrun{$pidfile} = 0;
  1189. if($verb) {
  1190. logmsg "RUN: $srvrname server PID $http3pid port $port\n";
  1191. }
  1192. return (0+!$http3pid, $http3pid, $pid3, $port);
  1193. }
  1194. #######################################################################
  1195. # start the https stunnel based server
  1196. #
  1197. sub runhttpsserver {
  1198. my ($verb, $proto, $proxy, $certfile) = @_;
  1199. my $ip = $HOSTIP;
  1200. my $ipvnum = 4;
  1201. my $idnum = 1;
  1202. if($proxy eq "proxy") {
  1203. # the https-proxy runs as https2
  1204. $idnum = 2;
  1205. }
  1206. if(!$stunnel) {
  1207. return (4, 0, 0, 0);
  1208. }
  1209. my $server = servername_id($proto, $ipvnum, $idnum);
  1210. my $pidfile = $serverpidfile{$server};
  1211. # don't retry if the server doesn't work
  1212. if ($doesntrun{$pidfile}) {
  1213. return (2, 0, 0, 0);
  1214. }
  1215. my $pid = processexists($pidfile);
  1216. if($pid > 0) {
  1217. stopserver($server, "$pid");
  1218. }
  1219. unlink($pidfile) if(-f $pidfile);
  1220. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1221. $certfile = 'stunnel.pem' unless($certfile);
  1222. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1223. my $flags = "";
  1224. $flags .= "--verbose " if($debugprotocol);
  1225. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1226. $flags .= "--logdir \"$LOGDIR\" ";
  1227. $flags .= "--id $idnum " if($idnum > 1);
  1228. $flags .= "--ipv$ipvnum --proto $proto ";
  1229. $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
  1230. $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
  1231. if($proto eq "gophers") {
  1232. $flags .= "--connect " . protoport("gopher");
  1233. }
  1234. elsif(!$proxy) {
  1235. $flags .= "--connect " . protoport("http");
  1236. }
  1237. else {
  1238. # for HTTPS-proxy we connect to the HTTP proxy
  1239. $flags .= "--connect " . protoport("httpproxy");
  1240. }
  1241. my $port = getfreeport($ipvnum);
  1242. my $options = "$flags --accept $port";
  1243. my $cmd = "$perl $srcdir/secureserver.pl $options";
  1244. my ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1245. if($httpspid <= 0 || !pidexists($httpspid)) {
  1246. # it is NOT alive
  1247. # don't call stopserver since that will also kill the dependent
  1248. # server that has already been started properly
  1249. $doesntrun{$pidfile} = 1;
  1250. $httpspid = $pid2 = 0;
  1251. logmsg "RUN: failed to start the $srvrname server\n";
  1252. return (3, 0, 0, 0);
  1253. }
  1254. $doesntrun{$pidfile} = 0;
  1255. # we have a server!
  1256. if($verb) {
  1257. logmsg "RUN: $srvrname server is PID $httpspid port $port\n";
  1258. }
  1259. $runcert{$server} = $certfile;
  1260. return (0+!$httpspid, $httpspid, $pid2, $port);
  1261. }
  1262. #######################################################################
  1263. # start the non-stunnel HTTP TLS extensions capable server
  1264. #
  1265. sub runhttptlsserver {
  1266. my ($verb, $ipv6) = @_;
  1267. my $proto = "httptls";
  1268. my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
  1269. my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
  1270. my $idnum = 1;
  1271. if(!$httptlssrv) {
  1272. return (4, 0, 0);
  1273. }
  1274. my $server = servername_id($proto, $ipvnum, $idnum);
  1275. my $pidfile = $serverpidfile{$server};
  1276. # don't retry if the server doesn't work
  1277. if ($doesntrun{$pidfile}) {
  1278. return (2, 0, 0, 0);
  1279. }
  1280. my $pid = processexists($pidfile);
  1281. if($pid > 0) {
  1282. stopserver($server, "$pid");
  1283. }
  1284. unlink($pidfile) if(-f $pidfile);
  1285. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1286. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1287. my $flags = "";
  1288. $flags .= "--http ";
  1289. $flags .= "--debug 1 " if($debugprotocol);
  1290. $flags .= "--priority NORMAL:+SRP ";
  1291. $flags .= "--srppasswd $srcdir/certs/srp-verifier-db ";
  1292. $flags .= "--srppasswdconf $srcdir/certs/srp-verifier-conf";
  1293. my $port = getfreeport($ipvnum);
  1294. my $allflags = "--port $port $flags";
  1295. my $cmd = "$httptlssrv $allflags > $logfile 2>&1";
  1296. my ($httptlspid, $pid2) = startnew($cmd, $pidfile, 10, 1);
  1297. if($httptlspid <= 0 || !pidexists($httptlspid)) {
  1298. # it is NOT alive
  1299. stopserver($server, "$pid2");
  1300. $doesntrun{$pidfile} = 1;
  1301. $httptlspid = $pid2 = 0;
  1302. logmsg "RUN: failed to start the $srvrname server\n";
  1303. return (3, 0, 0, 0);
  1304. }
  1305. $doesntrun{$pidfile} = 0;
  1306. if($verb) {
  1307. logmsg "RUN: $srvrname server PID $httptlspid port $port\n";
  1308. }
  1309. return (0+!$httptlspid, $httptlspid, $pid2, $port);
  1310. }
  1311. #######################################################################
  1312. # start the pingpong server (FTP, POP3, IMAP, SMTP)
  1313. #
  1314. sub runpingpongserver {
  1315. my ($proto, $id, $verb, $ipv6) = @_;
  1316. # Check the requested server
  1317. if($proto !~ /^(?:ftp|imap|pop3|smtp)$/) {
  1318. logmsg "Unsupported protocol $proto!!\n";
  1319. return (4, 0, 0);
  1320. }
  1321. my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
  1322. my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
  1323. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1324. my $server = servername_id($proto, $ipvnum, $idnum);
  1325. my $pidfile = $serverpidfile{$server};
  1326. my $portfile = $serverportfile{$server};
  1327. # don't retry if the server doesn't work
  1328. if ($doesntrun{$pidfile}) {
  1329. return (2, 0, 0);
  1330. }
  1331. my $pid = processexists($pidfile);
  1332. if($pid > 0) {
  1333. stopserver($server, "$pid");
  1334. }
  1335. unlink($pidfile) if(-f $pidfile);
  1336. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1337. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1338. my $flags = "";
  1339. $flags .= "--verbose " if($debugprotocol);
  1340. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1341. $flags .= "--logdir \"$LOGDIR\" ";
  1342. $flags .= "--portfile \"$portfile\" ";
  1343. $flags .= "--srcdir \"$srcdir\" --proto $proto ";
  1344. $flags .= "--id $idnum " if($idnum > 1);
  1345. $flags .= "--ipv$ipvnum --port 0 --addr \"$ip\"";
  1346. my $cmd = "$perl $srcdir/ftpserver.pl $flags";
  1347. my ($ftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1348. if($ftppid <= 0 || !pidexists($ftppid)) {
  1349. # it is NOT alive
  1350. logmsg "RUN: failed to start the $srvrname server\n";
  1351. stopserver($server, "$pid2");
  1352. $doesntrun{$pidfile} = 1;
  1353. return (1, 0, 0);
  1354. }
  1355. # where is it?
  1356. my $port = pidfromfile($portfile);
  1357. logmsg "PINGPONG runs on port $port ($portfile)\n" if($verb);
  1358. # Server is up. Verify that we can speak to it.
  1359. my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
  1360. if(!$pid3) {
  1361. logmsg "RUN: $srvrname server failed verification\n";
  1362. # failed to talk to it properly. Kill the server and return failure
  1363. stopserver($server, "$ftppid $pid2");
  1364. $doesntrun{$pidfile} = 1;
  1365. return (1, 0, 0);
  1366. }
  1367. $pid2 = $pid3;
  1368. logmsg "RUN: $srvrname server is PID $ftppid port $port\n" if($verb);
  1369. # Assign the correct port variable!
  1370. $PORT{$proto . ($ipvnum == 6? '6': '')} = $port;
  1371. return (0, $pid2, $ftppid);
  1372. }
  1373. #######################################################################
  1374. # start the ftps/imaps/pop3s/smtps server (or rather, tunnel)
  1375. #
  1376. sub runsecureserver {
  1377. my ($verb, $ipv6, $certfile, $proto, $clearport) = @_;
  1378. my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
  1379. my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
  1380. my $idnum = 1;
  1381. if(!$stunnel) {
  1382. return (4, 0, 0, 0);
  1383. }
  1384. my $server = servername_id($proto, $ipvnum, $idnum);
  1385. my $pidfile = $serverpidfile{$server};
  1386. # don't retry if the server doesn't work
  1387. if ($doesntrun{$pidfile}) {
  1388. return (2, 0, 0, 0);
  1389. }
  1390. my $pid = processexists($pidfile);
  1391. if($pid > 0) {
  1392. stopserver($server, "$pid");
  1393. }
  1394. unlink($pidfile) if(-f $pidfile);
  1395. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1396. $certfile = 'stunnel.pem' unless($certfile);
  1397. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1398. my $flags = "";
  1399. $flags .= "--verbose " if($debugprotocol);
  1400. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1401. $flags .= "--logdir \"$LOGDIR\" ";
  1402. $flags .= "--id $idnum " if($idnum > 1);
  1403. $flags .= "--ipv$ipvnum --proto $proto ";
  1404. $flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
  1405. $flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
  1406. $flags .= "--connect $clearport";
  1407. my $port = getfreeport($ipvnum);
  1408. my $options = "$flags --accept $port";
  1409. my $cmd = "$perl $srcdir/secureserver.pl $options";
  1410. my ($protospid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1411. if($protospid <= 0 || !pidexists($protospid)) {
  1412. # it is NOT alive
  1413. # don't call stopserver since that will also kill the dependent
  1414. # server that has already been started properly
  1415. $doesntrun{$pidfile} = 1;
  1416. $protospid = $pid2 = 0;
  1417. logmsg "RUN: failed to start the $srvrname server\n";
  1418. return (3, 0, 0, 0);
  1419. }
  1420. $doesntrun{$pidfile} = 0;
  1421. $runcert{$server} = $certfile;
  1422. if($verb) {
  1423. logmsg "RUN: $srvrname server is PID $protospid port $port\n";
  1424. }
  1425. return (0+!$protospid, $protospid, $pid2, $port);
  1426. }
  1427. #######################################################################
  1428. # start the tftp server
  1429. #
  1430. sub runtftpserver {
  1431. my ($id, $verb, $ipv6) = @_;
  1432. my $ip = $HOSTIP;
  1433. my $proto = 'tftp';
  1434. my $ipvnum = 4;
  1435. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1436. if($ipv6) {
  1437. # if IPv6, use a different setup
  1438. $ipvnum = 6;
  1439. $ip = $HOST6IP;
  1440. }
  1441. my $server = servername_id($proto, $ipvnum, $idnum);
  1442. my $pidfile = $serverpidfile{$server};
  1443. # don't retry if the server doesn't work
  1444. if ($doesntrun{$pidfile}) {
  1445. return (2, 0, 0, 0);
  1446. }
  1447. my $pid = processexists($pidfile);
  1448. if($pid > 0) {
  1449. stopserver($server, "$pid");
  1450. }
  1451. unlink($pidfile) if(-f $pidfile);
  1452. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1453. my $portfile = $serverportfile{$server};
  1454. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1455. my $flags = "";
  1456. $flags .= "--verbose " if($debugprotocol);
  1457. $flags .= "--pidfile \"$pidfile\" ";
  1458. $flags .= "--portfile \"$portfile\" ";
  1459. $flags .= "--logfile \"$logfile\" ";
  1460. $flags .= "--logdir \"$LOGDIR\" ";
  1461. $flags .= "--id $idnum " if($idnum > 1);
  1462. $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
  1463. my $cmd = "$perl $srcdir/tftpserver.pl $flags";
  1464. my ($tftppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1465. if($tftppid <= 0 || !pidexists($tftppid)) {
  1466. # it is NOT alive
  1467. logmsg "RUN: failed to start the $srvrname server\n";
  1468. stopserver($server, "$pid2");
  1469. $doesntrun{$pidfile} = 1;
  1470. return (1, 0, 0, 0);
  1471. }
  1472. my $port = pidfromfile($portfile);
  1473. # Server is up. Verify that we can speak to it.
  1474. my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
  1475. if(!$pid3) {
  1476. logmsg "RUN: $srvrname server failed verification\n";
  1477. # failed to talk to it properly. Kill the server and return failure
  1478. stopserver($server, "$tftppid $pid2");
  1479. $doesntrun{$pidfile} = 1;
  1480. return (1, 0, 0, 0);
  1481. }
  1482. $pid2 = $pid3;
  1483. if($verb) {
  1484. logmsg "RUN: $srvrname server on PID $tftppid port $port\n";
  1485. }
  1486. return (0, $pid2, $tftppid, $port);
  1487. }
  1488. #######################################################################
  1489. # start the rtsp server
  1490. #
  1491. sub runrtspserver {
  1492. my ($verb, $ipv6) = @_;
  1493. my $ip = $HOSTIP;
  1494. my $proto = 'rtsp';
  1495. my $ipvnum = 4;
  1496. my $idnum = 1;
  1497. if($ipv6) {
  1498. # if IPv6, use a different setup
  1499. $ipvnum = 6;
  1500. $ip = $HOST6IP;
  1501. }
  1502. my $server = servername_id($proto, $ipvnum, $idnum);
  1503. my $pidfile = $serverpidfile{$server};
  1504. my $portfile = $serverportfile{$server};
  1505. # don't retry if the server doesn't work
  1506. if ($doesntrun{$pidfile}) {
  1507. return (2, 0, 0, 0);
  1508. }
  1509. my $pid = processexists($pidfile);
  1510. if($pid > 0) {
  1511. stopserver($server, "$pid");
  1512. }
  1513. unlink($pidfile) if(-f $pidfile);
  1514. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1515. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1516. my $flags = "";
  1517. $flags .= "--verbose " if($debugprotocol);
  1518. $flags .= "--pidfile \"$pidfile\" ";
  1519. $flags .= "--portfile \"$portfile\" ";
  1520. $flags .= "--logfile \"$logfile\" ";
  1521. $flags .= "--logdir \"$LOGDIR\" ";
  1522. $flags .= "--id $idnum " if($idnum > 1);
  1523. $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\"";
  1524. my $cmd = "$perl $srcdir/rtspserver.pl $flags";
  1525. my ($rtsppid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1526. if($rtsppid <= 0 || !pidexists($rtsppid)) {
  1527. # it is NOT alive
  1528. logmsg "RUN: failed to start the $srvrname server\n";
  1529. stopserver($server, "$pid2");
  1530. $doesntrun{$pidfile} = 1;
  1531. return (1, 0, 0, 0);
  1532. }
  1533. my $port = pidfromfile($portfile);
  1534. # Server is up. Verify that we can speak to it.
  1535. my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
  1536. if(!$pid3) {
  1537. logmsg "RUN: $srvrname server failed verification\n";
  1538. # failed to talk to it properly. Kill the server and return failure
  1539. stopserver($server, "$rtsppid $pid2");
  1540. $doesntrun{$pidfile} = 1;
  1541. return (1, 0, 0, 0);
  1542. }
  1543. $pid2 = $pid3;
  1544. if($verb) {
  1545. logmsg "RUN: $srvrname server PID $rtsppid port $port\n";
  1546. }
  1547. return (0, $rtsppid, $pid2, $port);
  1548. }
  1549. #######################################################################
  1550. # Start the ssh (scp/sftp) server
  1551. #
  1552. sub runsshserver {
  1553. my ($id, $verb, $ipv6) = @_;
  1554. my $ip=$HOSTIP;
  1555. my $proto = 'ssh';
  1556. my $ipvnum = 4;
  1557. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1558. if(!$USER) {
  1559. logmsg "Can't start ssh server due to lack of USER name\n";
  1560. return (4, 0, 0, 0);
  1561. }
  1562. my $server = servername_id($proto, $ipvnum, $idnum);
  1563. my $pidfile = $serverpidfile{$server};
  1564. # don't retry if the server doesn't work
  1565. if ($doesntrun{$pidfile}) {
  1566. return (2, 0, 0, 0);
  1567. }
  1568. my $sshd = find_sshd();
  1569. if($sshd) {
  1570. ($sshdid,$sshdvernum,$sshdverstr,$sshderror) = sshversioninfo($sshd);
  1571. logmsg $sshderror if($sshderror);
  1572. }
  1573. my $pid = processexists($pidfile);
  1574. if($pid > 0) {
  1575. stopserver($server, "$pid");
  1576. }
  1577. unlink($pidfile) if(-f $pidfile);
  1578. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1579. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1580. my $flags = "";
  1581. $flags .= "--verbose " if($verb);
  1582. $flags .= "--debugprotocol " if($debugprotocol);
  1583. $flags .= "--pidfile \"$pidfile\" ";
  1584. $flags .= "--logdir \"$LOGDIR\" ";
  1585. $flags .= "--id $idnum " if($idnum > 1);
  1586. $flags .= "--ipv$ipvnum --addr \"$ip\" ";
  1587. $flags .= "--user \"$USER\"";
  1588. my @tports;
  1589. my $port = getfreeport($ipvnum);
  1590. push @tports, $port;
  1591. my $options = "$flags --sshport $port";
  1592. my $cmd = "$perl $srcdir/sshserver.pl $options";
  1593. my ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0);
  1594. # on loaded systems sshserver start up can take longer than the
  1595. # timeout passed to startnew, when this happens startnew completes
  1596. # without being able to read the pidfile and consequently returns a
  1597. # zero pid2 above.
  1598. if($sshpid <= 0 || !pidexists($sshpid)) {
  1599. # it is NOT alive
  1600. stopserver($server, "$pid2");
  1601. $doesntrun{$pidfile} = 1;
  1602. $sshpid = $pid2 = 0;
  1603. logmsg "RUN: failed to start the $srvrname server on $port\n";
  1604. return (3, 0, 0, 0);
  1605. }
  1606. # once it is known that the ssh server is alive, sftp server
  1607. # verification is performed actually connecting to it, authenticating
  1608. # and performing a very simple remote command. This verification is
  1609. # tried only one time.
  1610. $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum);
  1611. $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum);
  1612. if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) {
  1613. logmsg "RUN: SFTP server failed verification\n";
  1614. # failed to talk to it properly. Kill the server and return failure
  1615. display_sftplog();
  1616. display_sftpconfig();
  1617. display_sshdlog();
  1618. display_sshdconfig();
  1619. stopserver($server, "$sshpid $pid2");
  1620. $doesntrun{$pidfile} = 1;
  1621. $sshpid = $pid2 = 0;
  1622. logmsg "RUN: failed to verify the $srvrname server on $port\n";
  1623. return (5, 0, 0, 0);
  1624. }
  1625. # we're happy, no need to loop anymore!
  1626. $doesntrun{$pidfile} = 0;
  1627. my $hostfile;
  1628. if(!open($hostfile, "<", "$LOGDIR/$PIDDIR/$hstpubmd5f") ||
  1629. (read($hostfile, $SSHSRVMD5, 32) != 32) ||
  1630. !close($hostfile) ||
  1631. ($SSHSRVMD5 !~ /^[a-f0-9]{32}$/i))
  1632. {
  1633. my $msg = "Fatal: $srvrname pubkey md5 missing : \"$hstpubmd5f\" : $!";
  1634. logmsg "$msg\n";
  1635. stopservers($verb);
  1636. die $msg;
  1637. }
  1638. if(!open($hostfile, "<", "$LOGDIR/$PIDDIR/$hstpubsha256f") ||
  1639. (read($hostfile, $SSHSRVSHA256, 48) == 0) ||
  1640. !close($hostfile))
  1641. {
  1642. my $msg = "Fatal: $srvrname pubkey sha256 missing : \"$hstpubsha256f\" : $!";
  1643. logmsg "$msg\n";
  1644. stopservers($verb);
  1645. die $msg;
  1646. }
  1647. logmsg "RUN: $srvrname on PID $pid2 port $port\n" if($verb);
  1648. return (0, $pid2, $sshpid, $port);
  1649. }
  1650. #######################################################################
  1651. # Start the MQTT server
  1652. #
  1653. sub runmqttserver {
  1654. my ($id, $verb, $ipv6) = @_;
  1655. my $ip=$HOSTIP;
  1656. my $proto = 'mqtt';
  1657. my $port = protoport($proto);
  1658. my $ipvnum = 4;
  1659. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1660. my $server = servername_id($proto, $ipvnum, $idnum);
  1661. my $pidfile = $serverpidfile{$server};
  1662. my $portfile = $serverportfile{$server};
  1663. # don't retry if the server doesn't work
  1664. if ($doesntrun{$pidfile}) {
  1665. return (2, 0, 0);
  1666. }
  1667. my $pid = processexists($pidfile);
  1668. if($pid > 0) {
  1669. stopserver($server, "$pid");
  1670. }
  1671. unlink($pidfile) if(-f $pidfile);
  1672. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1673. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1674. # start our MQTT server - on a random port!
  1675. my $cmd="server/mqttd".exe_ext('SRV').
  1676. " --port 0 ".
  1677. " --pidfile $pidfile".
  1678. " --portfile $portfile".
  1679. " --config $LOGDIR/$SERVERCMD".
  1680. " --logfile $logfile".
  1681. " --logdir $LOGDIR";
  1682. my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
  1683. if($sockspid <= 0 || !pidexists($sockspid)) {
  1684. # it is NOT alive
  1685. logmsg "RUN: failed to start the $srvrname server\n";
  1686. stopserver($server, "$pid2");
  1687. $doesntrun{$pidfile} = 1;
  1688. return (1, 0, 0);
  1689. }
  1690. my $mqttport = pidfromfile($portfile);
  1691. if($verb) {
  1692. logmsg "RUN: $srvrname server is now running PID $pid2 on PORT $mqttport\n";
  1693. }
  1694. return (0, $pid2, $sockspid, $mqttport);
  1695. }
  1696. #######################################################################
  1697. # Start the socks server
  1698. #
  1699. sub runsocksserver {
  1700. my ($id, $verb, $ipv6, $is_unix) = @_;
  1701. my $ip=$HOSTIP;
  1702. my $proto = 'socks';
  1703. my $ipvnum = 4;
  1704. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1705. my $server = servername_id($proto, $ipvnum, $idnum);
  1706. my $pidfile = $serverpidfile{$server};
  1707. # don't retry if the server doesn't work
  1708. if ($doesntrun{$pidfile}) {
  1709. return (2, 0, 0, 0);
  1710. }
  1711. my $pid = processexists($pidfile);
  1712. if($pid > 0) {
  1713. stopserver($server, "$pid");
  1714. }
  1715. unlink($pidfile) if(-f $pidfile);
  1716. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1717. my $portfile = $serverportfile{$server};
  1718. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1719. # start our socks server, get commands from the FTP cmd file
  1720. my $cmd="";
  1721. if($is_unix) {
  1722. $cmd="server/socksd".exe_ext('SRV').
  1723. " --pidfile $pidfile".
  1724. " --reqfile $LOGDIR/$SOCKSIN".
  1725. " --logfile $logfile".
  1726. " --unix-socket $SOCKSUNIXPATH".
  1727. " --backend $HOSTIP".
  1728. " --config $LOGDIR/$SERVERCMD";
  1729. } else {
  1730. $cmd="server/socksd".exe_ext('SRV').
  1731. " --port 0 ".
  1732. " --pidfile $pidfile".
  1733. " --portfile $portfile".
  1734. " --reqfile $LOGDIR/$SOCKSIN".
  1735. " --logfile $logfile".
  1736. " --backend $HOSTIP".
  1737. " --config $LOGDIR/$SERVERCMD";
  1738. }
  1739. my ($sockspid, $pid2) = startnew($cmd, $pidfile, 30, 0);
  1740. if($sockspid <= 0 || !pidexists($sockspid)) {
  1741. # it is NOT alive
  1742. logmsg "RUN: failed to start the $srvrname server\n";
  1743. stopserver($server, "$pid2");
  1744. $doesntrun{$pidfile} = 1;
  1745. return (1, 0, 0, 0);
  1746. }
  1747. my $port = pidfromfile($portfile);
  1748. if($verb) {
  1749. logmsg "RUN: $srvrname server is now running PID $pid2\n";
  1750. }
  1751. return (0, $pid2, $sockspid, $port);
  1752. }
  1753. #######################################################################
  1754. # start the dict server
  1755. #
  1756. sub rundictserver {
  1757. my ($verb, $alt) = @_;
  1758. my $proto = "dict";
  1759. my $ip = $HOSTIP;
  1760. my $ipvnum = 4;
  1761. my $idnum = 1;
  1762. if($alt eq "ipv6") {
  1763. # No IPv6
  1764. }
  1765. my $server = servername_id($proto, $ipvnum, $idnum);
  1766. my $pidfile = $serverpidfile{$server};
  1767. # don't retry if the server doesn't work
  1768. if ($doesntrun{$pidfile}) {
  1769. return (2, 0, 0, 0);
  1770. }
  1771. my $pid = processexists($pidfile);
  1772. if($pid > 0) {
  1773. stopserver($server, "$pid");
  1774. }
  1775. unlink($pidfile) if(-f $pidfile);
  1776. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1777. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1778. my $flags = "";
  1779. $flags .= "--verbose 1 " if($debugprotocol);
  1780. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1781. $flags .= "--id $idnum " if($idnum > 1);
  1782. $flags .= "--srcdir \"$srcdir\" ";
  1783. $flags .= "--host $HOSTIP";
  1784. my $port = getfreeport($ipvnum);
  1785. my $aflags = "--port $port $flags";
  1786. my $cmd = "$srcdir/dictserver.py $aflags";
  1787. my ($dictpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1788. if($dictpid <= 0 || !pidexists($dictpid)) {
  1789. # it is NOT alive
  1790. stopserver($server, "$pid2");
  1791. $doesntrun{$pidfile} = 1;
  1792. $dictpid = $pid2 = 0;
  1793. logmsg "RUN: failed to start the $srvrname server\n";
  1794. return (3, 0, 0, 0);
  1795. }
  1796. $doesntrun{$pidfile} = 0;
  1797. if($verb) {
  1798. logmsg "RUN: $srvrname server PID $dictpid port $port\n";
  1799. }
  1800. return (0+!$dictpid, $dictpid, $pid2, $port);
  1801. }
  1802. #######################################################################
  1803. # start the SMB server
  1804. #
  1805. sub runsmbserver {
  1806. my ($verb, $alt) = @_;
  1807. my $proto = "smb";
  1808. my $ip = $HOSTIP;
  1809. my $ipvnum = 4;
  1810. my $idnum = 1;
  1811. if($alt eq "ipv6") {
  1812. # No IPv6
  1813. }
  1814. my $server = servername_id($proto, $ipvnum, $idnum);
  1815. my $pidfile = $serverpidfile{$server};
  1816. # don't retry if the server doesn't work
  1817. if ($doesntrun{$pidfile}) {
  1818. return (2, 0, 0, 0);
  1819. }
  1820. my $pid = processexists($pidfile);
  1821. if($pid > 0) {
  1822. stopserver($server, "$pid");
  1823. }
  1824. unlink($pidfile) if(-f $pidfile);
  1825. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1826. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1827. my $flags = "";
  1828. $flags .= "--verbose 1 " if($debugprotocol);
  1829. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1830. $flags .= "--id $idnum " if($idnum > 1);
  1831. $flags .= "--srcdir \"$srcdir\" ";
  1832. $flags .= "--host $HOSTIP";
  1833. my $port = getfreeport($ipvnum);
  1834. my $aflags = "--port $port $flags";
  1835. my $cmd = "$srcdir/smbserver.py $aflags";
  1836. my ($smbpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1837. if($smbpid <= 0 || !pidexists($smbpid)) {
  1838. # it is NOT alive
  1839. stopserver($server, "$pid2");
  1840. $doesntrun{$pidfile} = 1;
  1841. $smbpid = $pid2 = 0;
  1842. logmsg "RUN: failed to start the $srvrname server\n";
  1843. return (3, 0, 0, 0);
  1844. }
  1845. $doesntrun{$pidfile} = 0;
  1846. if($verb) {
  1847. logmsg "RUN: $srvrname server PID $smbpid port $port\n";
  1848. }
  1849. return (0+!$smbpid, $smbpid, $pid2, $port);
  1850. }
  1851. #######################################################################
  1852. # start the telnet server
  1853. #
  1854. sub runnegtelnetserver {
  1855. my ($verb, $alt) = @_;
  1856. my $proto = "telnet";
  1857. my $ip = $HOSTIP;
  1858. my $ipvnum = 4;
  1859. my $idnum = 1;
  1860. if($alt eq "ipv6") {
  1861. # No IPv6
  1862. }
  1863. my $server = servername_id($proto, $ipvnum, $idnum);
  1864. my $pidfile = $serverpidfile{$server};
  1865. # don't retry if the server doesn't work
  1866. if ($doesntrun{$pidfile}) {
  1867. return (2, 0, 0, 0);
  1868. }
  1869. my $pid = processexists($pidfile);
  1870. if($pid > 0) {
  1871. stopserver($server, "$pid");
  1872. }
  1873. unlink($pidfile) if(-f $pidfile);
  1874. my $srvrname = servername_str($proto, $ipvnum, $idnum);
  1875. my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
  1876. my $flags = "";
  1877. $flags .= "--verbose 1 " if($debugprotocol);
  1878. $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
  1879. $flags .= "--id $idnum " if($idnum > 1);
  1880. $flags .= "--srcdir \"$srcdir\"";
  1881. my $port = getfreeport($ipvnum);
  1882. my $aflags = "--port $port $flags";
  1883. my $cmd = "$srcdir/negtelnetserver.py $aflags";
  1884. my ($ntelpid, $pid2) = startnew($cmd, $pidfile, 15, 0);
  1885. if($ntelpid <= 0 || !pidexists($ntelpid)) {
  1886. # it is NOT alive
  1887. stopserver($server, "$pid2");
  1888. $doesntrun{$pidfile} = 1;
  1889. $ntelpid = $pid2 = 0;
  1890. logmsg "RUN: failed to start the $srvrname server\n";
  1891. return (3, 0, 0, 0);
  1892. }
  1893. $doesntrun{$pidfile} = 0;
  1894. if($verb) {
  1895. logmsg "RUN: $srvrname server PID $ntelpid port $port\n";
  1896. }
  1897. return (0+!$ntelpid, $ntelpid, $pid2, $port);
  1898. }
  1899. #######################################################################
  1900. # Single shot http and gopher server responsiveness test. This should only
  1901. # be used to verify that a server present in %run hash is still functional
  1902. #
  1903. sub responsive_http_server {
  1904. my ($proto, $verb, $alt, $port_or_path, $do_http3) = @_;
  1905. my $ip = $HOSTIP;
  1906. my $ipvnum = 4;
  1907. my $idnum = 1;
  1908. if($alt eq "ipv6") {
  1909. # if IPv6, use a different setup
  1910. $ipvnum = 6;
  1911. $ip = $HOST6IP;
  1912. }
  1913. elsif($alt eq "proxy") {
  1914. $idnum = 2;
  1915. }
  1916. elsif($alt eq "unix") {
  1917. # IP (protocol) is mutually exclusive with Unix sockets
  1918. $ipvnum = "unix";
  1919. }
  1920. return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path, $do_http3);
  1921. }
  1922. #######################################################################
  1923. # Single shot mqtt server responsiveness test. This should only
  1924. # be used to verify that a server present in %run hash is still functional
  1925. #
  1926. sub responsive_mqtt_server {
  1927. my ($proto, $id, $verb, $ipv6) = @_;
  1928. my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
  1929. my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
  1930. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1931. return &responsiveserver($proto, $ipvnum, $idnum, $ip);
  1932. }
  1933. #######################################################################
  1934. # Single shot pingpong server responsiveness test. This should only be
  1935. # used to verify that a server present in %run hash is still functional
  1936. #
  1937. sub responsive_pingpong_server {
  1938. my ($proto, $id, $verb, $ipv6) = @_;
  1939. my $port;
  1940. my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
  1941. my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
  1942. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1943. my $protoip = $proto . ($ipvnum == 6? '6': '');
  1944. if($proto =~ /^(?:ftp|imap|pop3|smtp)$/) {
  1945. $port = protoport($protoip);
  1946. }
  1947. else {
  1948. logmsg "Unsupported protocol $proto!!\n";
  1949. return 0;
  1950. }
  1951. return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
  1952. }
  1953. #######################################################################
  1954. # Single shot rtsp server responsiveness test. This should only be
  1955. # used to verify that a server present in %run hash is still functional
  1956. #
  1957. sub responsive_rtsp_server {
  1958. my ($verb, $ipv6) = @_;
  1959. my $proto = 'rtsp';
  1960. my $port = protoport($proto);
  1961. my $ip = $HOSTIP;
  1962. my $ipvnum = 4;
  1963. my $idnum = 1;
  1964. if($ipv6) {
  1965. # if IPv6, use a different setup
  1966. $ipvnum = 6;
  1967. $port = protoport('rtsp6');
  1968. $ip = $HOST6IP;
  1969. }
  1970. return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
  1971. }
  1972. #######################################################################
  1973. # Single shot tftp server responsiveness test. This should only be
  1974. # used to verify that a server present in %run hash is still functional
  1975. #
  1976. sub responsive_tftp_server {
  1977. my ($id, $verb, $ipv6) = @_;
  1978. my $proto = 'tftp';
  1979. my $port = protoport($proto);
  1980. my $ip = $HOSTIP;
  1981. my $ipvnum = 4;
  1982. my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
  1983. if($ipv6) {
  1984. # if IPv6, use a different setup
  1985. $ipvnum = 6;
  1986. $port = protoport('tftp6');
  1987. $ip = $HOST6IP;
  1988. }
  1989. return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
  1990. }
  1991. #######################################################################
  1992. # Single shot non-stunnel HTTP TLS extensions capable server
  1993. # responsiveness test. This should only be used to verify that a
  1994. # server present in %run hash is still functional
  1995. #
  1996. sub responsive_httptls_server {
  1997. my ($verb, $ipv6) = @_;
  1998. my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
  1999. my $proto = "httptls";
  2000. my $port = protoport($proto);
  2001. my $ip = "$HOSTIP";
  2002. my $idnum = 1;
  2003. if ($ipvnum == 6) {
  2004. $port = protoport("httptls6");
  2005. $ip = "$HOST6IP";
  2006. }
  2007. return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port);
  2008. }
  2009. #######################################################################
  2010. # startservers() starts all the named servers
  2011. #
  2012. # Returns: string with error reason or blank for success, and an integer:
  2013. # 0 for success
  2014. # 1 for an error starting the server
  2015. # 2 for not the first time getting an error starting the server
  2016. # 3 for a failure to stop a server in order to restart it
  2017. # 4 for an unsupported server type
  2018. #
  2019. sub startservers {
  2020. my @what = @_;
  2021. my ($pid, $pid2);
  2022. my $serr; # error while starting a server (as of the return enumerations)
  2023. for(@what) {
  2024. my (@whatlist) = split(/\s+/,$_);
  2025. my $what = lc($whatlist[0]);
  2026. $what =~ s/[^a-z0-9\/-]//g;
  2027. my $certfile;
  2028. if($what =~ /^(ftp|gopher|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) {
  2029. $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem';
  2030. }
  2031. if(($what eq "pop3") ||
  2032. ($what eq "ftp") ||
  2033. ($what eq "imap") ||
  2034. ($what eq "smtp")) {
  2035. if($run{$what} &&
  2036. !responsive_pingpong_server($what, "", $verbose)) {
  2037. if(stopserver($what)) {
  2038. return ("failed stopping unresponsive ".uc($what)." server", 3);
  2039. }
  2040. }
  2041. if(!$run{$what}) {
  2042. ($serr, $pid, $pid2) = runpingpongserver($what, "", $verbose);
  2043. if($pid <= 0) {
  2044. return ("failed starting ". uc($what) ." server", $serr);
  2045. }
  2046. logmsg sprintf("* pid $what => %d %d\n", $pid, $pid2) if($verbose);
  2047. $run{$what}="$pid $pid2";
  2048. }
  2049. }
  2050. elsif($what eq "ftp-ipv6") {
  2051. if($run{'ftp-ipv6'} &&
  2052. !responsive_pingpong_server("ftp", "", $verbose, "ipv6")) {
  2053. if(stopserver('ftp-ipv6')) {
  2054. return ("failed stopping unresponsive FTP-IPv6 server", 3);
  2055. }
  2056. }
  2057. if(!$run{'ftp-ipv6'}) {
  2058. ($serr, $pid, $pid2) = runpingpongserver("ftp", "", $verbose, "ipv6");
  2059. if($pid <= 0) {
  2060. return ("failed starting FTP-IPv6 server", $serr);
  2061. }
  2062. logmsg sprintf("* pid ftp-ipv6 => %d %d\n", $pid,
  2063. $pid2) if($verbose);
  2064. $run{'ftp-ipv6'}="$pid $pid2";
  2065. }
  2066. }
  2067. elsif($what eq "gopher") {
  2068. if($run{'gopher'} &&
  2069. !responsive_http_server("gopher", $verbose, 0,
  2070. protoport("gopher"))) {
  2071. if(stopserver('gopher')) {
  2072. return ("failed stopping unresponsive GOPHER server", 3);
  2073. }
  2074. }
  2075. if(!$run{'gopher'}) {
  2076. ($serr, $pid, $pid2, $PORT{'gopher'}) =
  2077. runhttpserver("gopher", $verbose, 0);
  2078. if($pid <= 0) {
  2079. return ("failed starting GOPHER server", $serr);
  2080. }
  2081. logmsg sprintf ("* pid gopher => %d %d\n", $pid, $pid2)
  2082. if($verbose);
  2083. $run{'gopher'}="$pid $pid2";
  2084. }
  2085. }
  2086. elsif($what eq "gopher-ipv6") {
  2087. if($run{'gopher-ipv6'} &&
  2088. !responsive_http_server("gopher", $verbose, "ipv6",
  2089. protoport("gopher"))) {
  2090. if(stopserver('gopher-ipv6')) {
  2091. return ("failed stopping unresponsive GOPHER-IPv6 server", 3);
  2092. }
  2093. }
  2094. if(!$run{'gopher-ipv6'}) {
  2095. ($serr, $pid, $pid2, $PORT{"gopher6"}) =
  2096. runhttpserver("gopher", $verbose, "ipv6");
  2097. if($pid <= 0) {
  2098. return ("failed starting GOPHER-IPv6 server", $serr);
  2099. }
  2100. logmsg sprintf("* pid gopher-ipv6 => %d %d\n", $pid,
  2101. $pid2) if($verbose);
  2102. $run{'gopher-ipv6'}="$pid $pid2";
  2103. }
  2104. }
  2105. elsif($what eq "http") {
  2106. if($run{'http'} &&
  2107. !responsive_http_server("http", $verbose, 0, protoport('http'))) {
  2108. logmsg "* restarting unresponsive HTTP server\n";
  2109. if(stopserver('http')) {
  2110. return ("failed stopping unresponsive HTTP server", 3);
  2111. }
  2112. }
  2113. if(!$run{'http'}) {
  2114. ($serr, $pid, $pid2, $PORT{'http'}) =
  2115. runhttpserver("http", $verbose, 0);
  2116. if($pid <= 0) {
  2117. return ("failed starting HTTP server", $serr);
  2118. }
  2119. logmsg sprintf ("* pid http => %d %d\n", $pid, $pid2)
  2120. if($verbose);
  2121. $run{'http'}="$pid $pid2";
  2122. }
  2123. }
  2124. elsif($what eq "http-proxy") {
  2125. if($run{'http-proxy'} &&
  2126. !responsive_http_server("http", $verbose, "proxy",
  2127. protoport("httpproxy"))) {
  2128. if(stopserver('http-proxy')) {
  2129. return ("failed stopping unresponsive HTTP-proxy server", 3);
  2130. }
  2131. }
  2132. if(!$run{'http-proxy'}) {
  2133. ($serr, $pid, $pid2, $PORT{"httpproxy"}) =
  2134. runhttpserver("http", $verbose, "proxy");
  2135. if($pid <= 0) {
  2136. return ("failed starting HTTP-proxy server", $serr);
  2137. }
  2138. logmsg sprintf ("* pid http-proxy => %d %d\n", $pid, $pid2)
  2139. if($verbose);
  2140. $run{'http-proxy'}="$pid $pid2";
  2141. }
  2142. }
  2143. elsif($what eq "http-ipv6") {
  2144. if($run{'http-ipv6'} &&
  2145. !responsive_http_server("http", $verbose, "ipv6",
  2146. protoport("http6"))) {
  2147. if(stopserver('http-ipv6')) {
  2148. return ("failed stopping unresponsive HTTP-IPv6 server", 3);
  2149. }
  2150. }
  2151. if(!$run{'http-ipv6'}) {
  2152. ($serr, $pid, $pid2, $PORT{"http6"}) =
  2153. runhttpserver("http", $verbose, "ipv6");
  2154. if($pid <= 0) {
  2155. return ("failed starting HTTP-IPv6 server", $serr);
  2156. }
  2157. logmsg sprintf("* pid http-ipv6 => %d %d\n", $pid, $pid2)
  2158. if($verbose);
  2159. $run{'http-ipv6'}="$pid $pid2";
  2160. }
  2161. }
  2162. elsif($what eq "rtsp") {
  2163. if($run{'rtsp'} &&
  2164. !responsive_rtsp_server($verbose)) {
  2165. if(stopserver('rtsp')) {
  2166. return ("failed stopping unresponsive RTSP server", 3);
  2167. }
  2168. }
  2169. if(!$run{'rtsp'}) {
  2170. ($serr, $pid, $pid2, $PORT{'rtsp'}) = runrtspserver($verbose);
  2171. if($pid <= 0) {
  2172. return ("failed starting RTSP server", $serr);
  2173. }
  2174. logmsg sprintf("* pid rtsp => %d %d\n", $pid, $pid2) if($verbose);
  2175. $run{'rtsp'}="$pid $pid2";
  2176. }
  2177. }
  2178. elsif($what eq "rtsp-ipv6") {
  2179. if($run{'rtsp-ipv6'} &&
  2180. !responsive_rtsp_server($verbose, "ipv6")) {
  2181. if(stopserver('rtsp-ipv6')) {
  2182. return ("failed stopping unresponsive RTSP-IPv6 server", 3);
  2183. }
  2184. }
  2185. if(!$run{'rtsp-ipv6'}) {
  2186. ($serr, $pid, $pid2, $PORT{'rtsp6'}) = runrtspserver($verbose, "ipv6");
  2187. if($pid <= 0) {
  2188. return ("failed starting RTSP-IPv6 server", $serr);
  2189. }
  2190. logmsg sprintf("* pid rtsp-ipv6 => %d %d\n", $pid, $pid2)
  2191. if($verbose);
  2192. $run{'rtsp-ipv6'}="$pid $pid2";
  2193. }
  2194. }
  2195. elsif($what =~ /^(ftp|imap|pop3|smtp)s$/) {
  2196. my $cproto = $1;
  2197. if(!$stunnel) {
  2198. # we can't run ftps tests without stunnel
  2199. return ("no stunnel", 4);
  2200. }
  2201. if($runcert{$what} && ($runcert{$what} ne $certfile)) {
  2202. # stop server when running and using a different cert
  2203. if(stopserver($what)) {
  2204. return ("failed stopping $what server with different cert", 3);
  2205. }
  2206. }
  2207. if($run{$cproto} &&
  2208. !responsive_pingpong_server($cproto, "", $verbose)) {
  2209. if(stopserver($cproto)) {
  2210. return ("failed stopping unresponsive $cproto server", 3);
  2211. }
  2212. }
  2213. if(!$run{$cproto}) {
  2214. ($serr, $pid, $pid2) = runpingpongserver($cproto, "", $verbose);
  2215. if($pid <= 0) {
  2216. return ("failed starting $cproto server", $serr);
  2217. }
  2218. logmsg sprintf("* pid $cproto => %d %d\n", $pid, $pid2) if($verbose);
  2219. $run{$cproto}="$pid $pid2";
  2220. }
  2221. if(!$run{$what}) {
  2222. ($serr, $pid, $pid2, $PORT{$what}) =
  2223. runsecureserver($verbose, "", $certfile, $what,
  2224. protoport($cproto));
  2225. if($pid <= 0) {
  2226. return ("failed starting $what server (stunnel)", $serr);
  2227. }
  2228. logmsg sprintf("* pid $what => %d %d\n", $pid, $pid2)
  2229. if($verbose);
  2230. $run{$what}="$pid $pid2";
  2231. }
  2232. }
  2233. elsif($what eq "file") {
  2234. # we support it but have no server!
  2235. }
  2236. elsif($what eq "https") {
  2237. if(!$stunnel) {
  2238. # we can't run https tests without stunnel
  2239. return ("no stunnel", 4);
  2240. }
  2241. if($runcert{'https'} && ($runcert{'https'} ne $certfile)) {
  2242. # stop server when running and using a different cert
  2243. if(stopserver('https')) {
  2244. return ("failed stopping HTTPS server with different cert", 3);
  2245. }
  2246. # also stop http server, we do not know which state it is in
  2247. if($run{'http'} && stopserver('http')) {
  2248. return ("failed stopping HTTP server", 3);
  2249. }
  2250. }
  2251. if($run{'https'} &&
  2252. !responsive_http_server("https", $verbose, 0,
  2253. protoport('https'))) {
  2254. if(stopserver('https')) {
  2255. return ("failed stopping unresponsive HTTPS server", 3);
  2256. }
  2257. # also stop http server, we do not know which state it is in
  2258. if($run{'http'} && stopserver('http')) {
  2259. return ("failed stopping unresponsive HTTP server", 3);
  2260. }
  2261. }
  2262. # check a running http server if we not already checked https
  2263. if($run{'http'} && !$run{'https'} &&
  2264. !responsive_http_server("http", $verbose, 0,
  2265. protoport('http'))) {
  2266. if(stopserver('http')) {
  2267. return ("failed stopping unresponsive HTTP server", 3);
  2268. }
  2269. }
  2270. if(!$run{'http'}) {
  2271. ($serr, $pid, $pid2, $PORT{'http'}) =
  2272. runhttpserver("http", $verbose, 0);
  2273. if($pid <= 0) {
  2274. return ("failed starting HTTP server", $serr);
  2275. }
  2276. logmsg sprintf("* pid http => %d %d\n", $pid, $pid2) if($verbose);
  2277. $run{'http'}="$pid $pid2";
  2278. }
  2279. if(!$run{'https'}) {
  2280. ($serr, $pid, $pid2, $PORT{'https'}) =
  2281. runhttpsserver($verbose, "https", "", $certfile);
  2282. if($pid <= 0) {
  2283. return ("failed starting HTTPS server (stunnel)", $serr);
  2284. }
  2285. logmsg sprintf("* pid https => %d %d\n", $pid, $pid2)
  2286. if($verbose);
  2287. $run{'https'}="$pid $pid2";
  2288. }
  2289. }
  2290. elsif($what eq "http/2") {
  2291. # http/2 server proxies to a http server
  2292. if($run{'http/2'} &&
  2293. !responsive_http_server("https", $verbose, 0, protoport('http2tls'))) {
  2294. logmsg "* restarting unresponsive HTTP/2 server\n";
  2295. if(stopserver('http/2')) {
  2296. return ("failed stopping unresponsive HTTP/2 server", 3);
  2297. }
  2298. # also stop http server, we do not know which state it is in
  2299. if($run{'http'} && stopserver('http')) {
  2300. return ("failed stopping HTTP server", 3);
  2301. }
  2302. }
  2303. # check a running http server if we not already checked http/2
  2304. if($run{'http'} && !$run{'http/2'} &&
  2305. !responsive_http_server("http", $verbose, 0,
  2306. protoport('http'))) {
  2307. if(stopserver('http')) {
  2308. return ("failed stopping unresponsive HTTP server", 3);
  2309. }
  2310. }
  2311. if(!$run{'http'}) {
  2312. ($serr, $pid, $pid2, $PORT{'http'}) =
  2313. runhttpserver("http", $verbose, 0);
  2314. if($pid <= 0) {
  2315. return ("failed starting HTTP server", $serr);
  2316. }
  2317. logmsg sprintf("* pid http => %d %d\n", $pid, $pid2) if($verbose);
  2318. $run{'http'}="$pid $pid2";
  2319. }
  2320. if(!$run{'http/2'}) {
  2321. ($serr, $pid, $pid2, $PORT{"http2"}, $PORT{"http2tls"}) =
  2322. runhttp2server($verbose);
  2323. if($pid <= 0) {
  2324. return ("failed starting HTTP/2 server", $serr);
  2325. }
  2326. logmsg sprintf ("* pid http/2 => %d %d\n", $pid, $pid2)
  2327. if($verbose);
  2328. $run{'http/2'}="$pid $pid2";
  2329. }
  2330. }
  2331. elsif($what eq "http/3") {
  2332. # http/3 server proxies to a http server
  2333. if($run{'http/3'} &&
  2334. !responsive_http_server("https", $verbose, 0, protoport('http3'), 1)) {
  2335. logmsg "* restarting unresponsive HTTP/3 server\n";
  2336. if(stopserver('http/3')) {
  2337. return ("failed stopping unresponsive HTTP/3 server", 3);
  2338. }
  2339. # also stop http server, we do not know which state it is in
  2340. if($run{'http'} && stopserver('http')) {
  2341. return ("failed stopping HTTP server", 3);
  2342. }
  2343. }
  2344. # check a running http server if we not already checked http/3
  2345. if($run{'http'} && !$run{'http/3'} &&
  2346. !responsive_http_server("http", $verbose, 0,
  2347. protoport('http'))) {
  2348. if(stopserver('http')) {
  2349. return ("failed stopping unresponsive HTTP server", 3);
  2350. }
  2351. }
  2352. if(!$run{'http'}) {
  2353. ($serr, $pid, $pid2, $PORT{'http'}) =
  2354. runhttpserver("http", $verbose, 0);
  2355. if($pid <= 0) {
  2356. return ("failed starting HTTP server", $serr);
  2357. }
  2358. logmsg sprintf("* pid http => %d %d\n", $pid, $pid2) if($verbose);
  2359. $run{'http'}="$pid $pid2";
  2360. }
  2361. if(!$run{'http/3'}) {
  2362. ($serr, $pid, $pid2, $PORT{"http3"}) = runhttp3server($verbose);
  2363. if($pid <= 0) {
  2364. return ("failed starting HTTP/3 server", $serr);
  2365. }
  2366. logmsg sprintf ("* pid http/3 => %d %d\n", $pid, $pid2)
  2367. if($verbose);
  2368. $run{'http/3'}="$pid $pid2";
  2369. }
  2370. }
  2371. elsif($what eq "gophers") {
  2372. if(!$stunnel) {
  2373. # we can't run TLS tests without stunnel
  2374. return ("no stunnel", 4);
  2375. }
  2376. if($runcert{'gophers'} && ($runcert{'gophers'} ne $certfile)) {
  2377. # stop server when running and using a different cert
  2378. if(stopserver('gophers')) {
  2379. return ("failed stopping GOPHERS server with different cert", 3);
  2380. }
  2381. }
  2382. if($run{'gopher'} &&
  2383. !responsive_http_server("gopher", $verbose, 0,
  2384. protoport('gopher'))) {
  2385. if(stopserver('gopher')) {
  2386. return ("failed stopping unresponsive GOPHER server", 3);
  2387. }
  2388. }
  2389. if(!$run{'gopher'}) {
  2390. my $port;
  2391. ($serr, $pid, $pid2, $port) =
  2392. runhttpserver("gopher", $verbose, 0);
  2393. $PORT{'gopher'} = $port;
  2394. if($pid <= 0) {
  2395. return ("failed starting GOPHER server", $serr);
  2396. }
  2397. logmsg sprintf("* pid gopher => %d %d\n", $pid, $pid2) if($verbose);
  2398. logmsg "GOPHERPORT => $port\n" if($verbose);
  2399. $run{'gopher'}="$pid $pid2";
  2400. }
  2401. if(!$run{'gophers'}) {
  2402. my $port;
  2403. ($serr, $pid, $pid2, $port) =
  2404. runhttpsserver($verbose, "gophers", "", $certfile);
  2405. $PORT{'gophers'} = $port;
  2406. if($pid <= 0) {
  2407. return ("failed starting GOPHERS server (stunnel)", $serr);
  2408. }
  2409. logmsg sprintf("* pid gophers => %d %d\n", $pid, $pid2)
  2410. if($verbose);
  2411. logmsg "GOPHERSPORT => $port\n" if($verbose);
  2412. $run{'gophers'}="$pid $pid2";
  2413. }
  2414. }
  2415. elsif($what eq "https-proxy") {
  2416. if(!$stunnel) {
  2417. # we can't run https-proxy tests without stunnel
  2418. return ("no stunnel", 4);
  2419. }
  2420. if($runcert{'https-proxy'} &&
  2421. ($runcert{'https-proxy'} ne $certfile)) {
  2422. # stop server when running and using a different cert
  2423. if(stopserver('https-proxy')) {
  2424. return ("failed stopping HTTPS-proxy with different cert", 3);
  2425. }
  2426. }
  2427. # we front the http-proxy with stunnel so we need to make sure the
  2428. # proxy runs as well
  2429. my ($f, $e) = startservers("http-proxy");
  2430. if($f) {
  2431. return ($f, $e);
  2432. }
  2433. if(!$run{'https-proxy'}) {
  2434. ($serr, $pid, $pid2, $PORT{"httpsproxy"}) =
  2435. runhttpsserver($verbose, "https", "proxy", $certfile);
  2436. if($pid <= 0) {
  2437. return ("failed starting HTTPS-proxy (stunnel)", $serr);
  2438. }
  2439. logmsg sprintf("* pid https-proxy => %d %d\n", $pid, $pid2)
  2440. if($verbose);
  2441. $run{'https-proxy'}="$pid $pid2";
  2442. }
  2443. }
  2444. elsif($what eq "httptls") {
  2445. if(!$httptlssrv) {
  2446. # for now, we can't run http TLS-EXT tests without gnutls-serv
  2447. return ("no gnutls-serv (with SRP support)", 4);
  2448. }
  2449. if($run{'httptls'} &&
  2450. !responsive_httptls_server($verbose, "IPv4")) {
  2451. if(stopserver('httptls')) {
  2452. return ("failed stopping unresponsive HTTPTLS server", 3);
  2453. }
  2454. }
  2455. if(!$run{'httptls'}) {
  2456. ($serr, $pid, $pid2, $PORT{'httptls'}) =
  2457. runhttptlsserver($verbose, "IPv4");
  2458. if($pid <= 0) {
  2459. return ("failed starting HTTPTLS server (gnutls-serv)", $serr);
  2460. }
  2461. logmsg sprintf("* pid httptls => %d %d\n", $pid, $pid2)
  2462. if($verbose);
  2463. $run{'httptls'}="$pid $pid2";
  2464. }
  2465. }
  2466. elsif($what eq "httptls-ipv6") {
  2467. if(!$httptlssrv) {
  2468. # for now, we can't run http TLS-EXT tests without gnutls-serv
  2469. return ("no gnutls-serv", 4);
  2470. }
  2471. if($run{'httptls-ipv6'} &&
  2472. !responsive_httptls_server($verbose, "ipv6")) {
  2473. if(stopserver('httptls-ipv6')) {
  2474. return ("failed stopping unresponsive HTTPTLS-IPv6 server", 3);
  2475. }
  2476. }
  2477. if(!$run{'httptls-ipv6'}) {
  2478. ($serr, $pid, $pid2, $PORT{"httptls6"}) =
  2479. runhttptlsserver($verbose, "ipv6");
  2480. if($pid <= 0) {
  2481. return ("failed starting HTTPTLS-IPv6 server (gnutls-serv)", $serr);
  2482. }
  2483. logmsg sprintf("* pid httptls-ipv6 => %d %d\n", $pid, $pid2)
  2484. if($verbose);
  2485. $run{'httptls-ipv6'}="$pid $pid2";
  2486. }
  2487. }
  2488. elsif($what eq "tftp") {
  2489. if($run{'tftp'} &&
  2490. !responsive_tftp_server("", $verbose)) {
  2491. if(stopserver('tftp')) {
  2492. return ("failed stopping unresponsive TFTP server", 3);
  2493. }
  2494. }
  2495. if(!$run{'tftp'}) {
  2496. ($serr, $pid, $pid2, $PORT{'tftp'}) =
  2497. runtftpserver("", $verbose);
  2498. if($pid <= 0) {
  2499. return ("failed starting TFTP server", $serr);
  2500. }
  2501. logmsg sprintf("* pid tftp => %d %d\n", $pid, $pid2) if($verbose);
  2502. $run{'tftp'}="$pid $pid2";
  2503. }
  2504. }
  2505. elsif($what eq "tftp-ipv6") {
  2506. if($run{'tftp-ipv6'} &&
  2507. !responsive_tftp_server("", $verbose, "ipv6")) {
  2508. if(stopserver('tftp-ipv6')) {
  2509. return ("failed stopping unresponsive TFTP-IPv6 server", 3);
  2510. }
  2511. }
  2512. if(!$run{'tftp-ipv6'}) {
  2513. ($serr, $pid, $pid2, $PORT{'tftp6'}) =
  2514. runtftpserver("", $verbose, "ipv6");
  2515. if($pid <= 0) {
  2516. return ("failed starting TFTP-IPv6 server", $serr);
  2517. }
  2518. logmsg sprintf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose);
  2519. $run{'tftp-ipv6'}="$pid $pid2";
  2520. }
  2521. }
  2522. elsif($what eq "sftp" || $what eq "scp") {
  2523. if(!$run{'ssh'}) {
  2524. ($serr, $pid, $pid2, $PORT{'ssh'}) = runsshserver("", $verbose);
  2525. if($pid <= 0) {
  2526. return ("failed starting SSH server", $serr);
  2527. }
  2528. logmsg sprintf("* pid ssh => %d %d\n", $pid, $pid2) if($verbose);
  2529. $run{'ssh'}="$pid $pid2";
  2530. }
  2531. }
  2532. elsif($what eq "socks4" || $what eq "socks5" ) {
  2533. if(!$run{'socks'}) {
  2534. ($serr, $pid, $pid2, $PORT{"socks"}) = runsocksserver("", $verbose);
  2535. if($pid <= 0) {
  2536. return ("failed starting socks server", $serr);
  2537. }
  2538. logmsg sprintf("* pid socks => %d %d\n", $pid, $pid2) if($verbose);
  2539. $run{'socks'}="$pid $pid2";
  2540. }
  2541. }
  2542. elsif($what eq "socks5unix") {
  2543. if(!$run{'socks5unix'}) {
  2544. ($serr, $pid, $pid2) = runsocksserver("2", $verbose, "", "unix");
  2545. if($pid <= 0) {
  2546. return ("failed starting socks5unix server", $serr);
  2547. }
  2548. logmsg sprintf("* pid socks5unix => %d %d\n", $pid, $pid2) if($verbose);
  2549. $run{'socks5unix'}="$pid $pid2";
  2550. }
  2551. }
  2552. elsif($what eq "mqtt" ) {
  2553. if($run{'mqtt'} &&
  2554. !responsive_mqtt_server("mqtt", "", $verbose)) {
  2555. if(stopserver('mqtt')) {
  2556. return ("failed stopping unresponsive MQTT server", 3);
  2557. }
  2558. }
  2559. if(!$run{'mqtt'}) {
  2560. ($serr, $pid, $pid2, $PORT{"mqtt"}) = runmqttserver("", $verbose);
  2561. if($pid <= 0) {
  2562. return ("failed starting mqtt server", $serr);
  2563. }
  2564. logmsg sprintf("* pid mqtt => %d %d\n", $pid, $pid2) if($verbose);
  2565. $run{'mqtt'}="$pid $pid2";
  2566. }
  2567. }
  2568. elsif($what eq "http-unix") {
  2569. if($run{'http-unix'} &&
  2570. !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
  2571. if(stopserver('http-unix')) {
  2572. return ("failed stopping unresponsive HTTP-unix server", 3);
  2573. }
  2574. }
  2575. if(!$run{'http-unix'}) {
  2576. my $unused;
  2577. ($serr, $pid, $pid2, $unused) =
  2578. runhttpserver("http", $verbose, "unix", $HTTPUNIXPATH);
  2579. if($pid <= 0) {
  2580. return ("failed starting HTTP-unix server", $serr);
  2581. }
  2582. logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2)
  2583. if($verbose);
  2584. $run{'http-unix'}="$pid $pid2";
  2585. }
  2586. }
  2587. elsif($what eq "dict") {
  2588. if(!$run{'dict'}) {
  2589. ($serr, $pid, $pid2, $PORT{"dict"}) = rundictserver($verbose, "");
  2590. if($pid <= 0) {
  2591. return ("failed starting DICT server", $serr);
  2592. }
  2593. logmsg sprintf ("* pid DICT => %d %d\n", $pid, $pid2)
  2594. if($verbose);
  2595. $run{'dict'}="$pid $pid2";
  2596. }
  2597. }
  2598. elsif($what eq "smb") {
  2599. if(!$run{'smb'}) {
  2600. ($serr, $pid, $pid2, $PORT{"smb"}) = runsmbserver($verbose, "");
  2601. if($pid <= 0) {
  2602. return ("failed starting SMB server", $serr);
  2603. }
  2604. logmsg sprintf ("* pid SMB => %d %d\n", $pid, $pid2)
  2605. if($verbose);
  2606. $run{'smb'}="$pid $pid2";
  2607. }
  2608. }
  2609. elsif($what eq "telnet") {
  2610. if(!$run{'telnet'}) {
  2611. ($serr, $pid, $pid2, $PORT{"telnet"}) =
  2612. runnegtelnetserver($verbose, "");
  2613. if($pid <= 0) {
  2614. return ("failed starting neg TELNET server", $serr);
  2615. }
  2616. logmsg sprintf ("* pid neg TELNET => %d %d\n", $pid, $pid2)
  2617. if($verbose);
  2618. $run{'telnet'}="$pid $pid2";
  2619. }
  2620. }
  2621. elsif($what eq "none") {
  2622. logmsg "* starts no server\n" if ($verbose);
  2623. }
  2624. else {
  2625. warn "we don't support a server for $what";
  2626. return ("no server for $what", 4);
  2627. }
  2628. }
  2629. return ("", 0);
  2630. }
  2631. #######################################################################
  2632. # Stop all running test servers
  2633. #
  2634. sub stopservers {
  2635. my $verb = $_[0];
  2636. #
  2637. # kill sockfilter processes for all pingpong servers
  2638. #
  2639. killallsockfilters("$LOGDIR/$PIDDIR", $verb);
  2640. #
  2641. # kill all server pids from %run hash clearing them
  2642. #
  2643. my $pidlist;
  2644. foreach my $server (keys %run) {
  2645. if($run{$server}) {
  2646. if($verb) {
  2647. my $prev = 0;
  2648. my $pids = $run{$server};
  2649. foreach my $pid (split(' ', $pids)) {
  2650. if($pid != $prev) {
  2651. logmsg sprintf("* kill pid for %s => %d\n",
  2652. $server, $pid);
  2653. $prev = $pid;
  2654. }
  2655. }
  2656. }
  2657. $pidlist .= "$run{$server} ";
  2658. $run{$server} = 0;
  2659. }
  2660. $runcert{$server} = 0 if($runcert{$server});
  2661. }
  2662. killpid($verb, $pidlist);
  2663. #
  2664. # cleanup all server pid files
  2665. #
  2666. my $result = 0;
  2667. foreach my $server (keys %serverpidfile) {
  2668. my $pidfile = $serverpidfile{$server};
  2669. my $pid = processexists($pidfile);
  2670. if($pid > 0) {
  2671. if($err_unexpected) {
  2672. logmsg "ERROR: ";
  2673. $result = -1;
  2674. }
  2675. else {
  2676. logmsg "Warning: ";
  2677. }
  2678. logmsg "$server server unexpectedly alive\n";
  2679. killpid($verb, $pid);
  2680. }
  2681. unlink($pidfile) if(-f $pidfile);
  2682. }
  2683. return $result;
  2684. }
  2685. #######################################################################
  2686. # substitute the variable stuff into either a joined up file or
  2687. # a command, in either case passed by reference
  2688. #
  2689. sub subvariables {
  2690. my ($thing, $testnum, $prefix) = @_;
  2691. my $port;
  2692. if(!$prefix) {
  2693. $prefix = "%";
  2694. }
  2695. # test server ports
  2696. # Substitutes variables like %HTTPPORT and %SMTP6PORT with the server ports
  2697. foreach my $proto ('DICT',
  2698. 'FTP', 'FTP6', 'FTPS',
  2699. 'GOPHER', 'GOPHER6', 'GOPHERS',
  2700. 'HTTP', 'HTTP6', 'HTTPS',
  2701. 'HTTPSPROXY', 'HTTPTLS', 'HTTPTLS6',
  2702. 'HTTP2', 'HTTP2TLS',
  2703. 'HTTP3',
  2704. 'IMAP', 'IMAP6', 'IMAPS',
  2705. 'MQTT',
  2706. 'NOLISTEN',
  2707. 'POP3', 'POP36', 'POP3S',
  2708. 'RTSP', 'RTSP6',
  2709. 'SMB', 'SMBS',
  2710. 'SMTP', 'SMTP6', 'SMTPS',
  2711. 'SOCKS',
  2712. 'SSH',
  2713. 'TELNET',
  2714. 'TFTP', 'TFTP6') {
  2715. $port = protoport(lc $proto);
  2716. $$thing =~ s/${prefix}(?:$proto)PORT/$port/g;
  2717. }
  2718. # Special case: for PROXYPORT substitution, use httpproxy.
  2719. $port = protoport('httpproxy');
  2720. $$thing =~ s/${prefix}PROXYPORT/$port/g;
  2721. # server Unix domain socket paths
  2722. $$thing =~ s/${prefix}HTTPUNIXPATH/$HTTPUNIXPATH/g;
  2723. $$thing =~ s/${prefix}SOCKSUNIXPATH/$SOCKSUNIXPATH/g;
  2724. # client IP addresses
  2725. my $nb = $CLIENT6IP;
  2726. $nb =~ s/^\[(.*)\]/$1/; # trim off the brackets
  2727. $$thing =~ s/${prefix}CLIENT6IP-NB/$nb/g;
  2728. $$thing =~ s/${prefix}CLIENT6IP/$CLIENT6IP/g;
  2729. $$thing =~ s/${prefix}CLIENTIP/$CLIENTIP/g;
  2730. # server IP addresses
  2731. $$thing =~ s/${prefix}HOST6IP/$HOST6IP/g;
  2732. $$thing =~ s/${prefix}HOSTIP/$HOSTIP/g;
  2733. # misc
  2734. $$thing =~ s/${prefix}CURL/$CURL/g;
  2735. $$thing =~ s/${prefix}LOGDIR/$LOGDIR/g;
  2736. $$thing =~ s/${prefix}PWD/$pwd/g;
  2737. $$thing =~ s/${prefix}POSIX_PWD/$posix_pwd/g;
  2738. $$thing =~ s/${prefix}VERSION/$CURLVERSION/g;
  2739. $$thing =~ s/${prefix}VERNUM/$CURLVERNUM/g;
  2740. $$thing =~ s/${prefix}DATE/$DATE/g;
  2741. $$thing =~ s/${prefix}TESTNUMBER/$testnum/g;
  2742. my $file_pwd = $pwd;
  2743. if($file_pwd !~ /^\//) {
  2744. $file_pwd = "/$file_pwd";
  2745. }
  2746. my $ssh_pwd = $posix_pwd;
  2747. # this only works after the SSH server has been started
  2748. # TODO: call sshversioninfo early and store $sshdid so this substitution
  2749. # always works
  2750. if ($sshdid && $sshdid =~ /OpenSSH-Windows/) {
  2751. $ssh_pwd = $file_pwd;
  2752. }
  2753. $$thing =~ s/${prefix}FILE_PWD/$file_pwd/g;
  2754. $$thing =~ s/${prefix}SSH_PWD/$ssh_pwd/g;
  2755. $$thing =~ s/${prefix}SRCDIR/$srcdir/g;
  2756. $$thing =~ s/${prefix}USER/$USER/g;
  2757. $$thing =~ s/${prefix}SSHSRVMD5/$SSHSRVMD5/g;
  2758. $$thing =~ s/${prefix}SSHSRVSHA256/$SSHSRVSHA256/g;
  2759. # The purpose of FTPTIME2 is to provide times that can be
  2760. # used for time-out tests and that would work on most hosts as these
  2761. # adjust for the startup/check time for this particular host. We needed to
  2762. # do this to make the test suite run better on very slow hosts.
  2763. my $ftp2 = $ftpchecktime * 8;
  2764. $$thing =~ s/${prefix}FTPTIME2/$ftp2/g;
  2765. # HTTP2
  2766. $$thing =~ s/${prefix}H2CVER/$h2cver/g;
  2767. }
  2768. sub localhttp {
  2769. return $HOSTIP eq "127.0.0.1";
  2770. }
  2771. 1;