1#!/usr/bin/env perl 2#*************************************************************************** 3# _ _ ____ _ 4# Project ___| | | | _ \| | 5# / __| | | | |_) | | 6# | (__| |_| | _ <| |___ 7# \___|\___/|_| \_\_____| 8# 9# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 10# 11# This software is licensed as described in the file COPYING, which 12# you should have received as part of this distribution. The terms 13# are also available at https://curl.se/docs/copyright.html. 14# 15# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16# copies of the Software, and permit persons to whom the Software is 17# furnished to do so, under the terms of the COPYING file. 18# 19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20# KIND, either express or implied. 21# 22# SPDX-License-Identifier: curl 23# 24#*************************************************************************** 25 26# Starts sshd for use in the SCP and SFTP curl test harness tests. 27# Also creates the ssh configuration files needed for these tests. 28 29use strict; 30use warnings; 31use Cwd; 32use Cwd 'abs_path'; 33use Digest::MD5; 34use Digest::MD5 'md5_hex'; 35use Digest::SHA; 36use Digest::SHA 'sha256_base64'; 37use MIME::Base64; 38use File::Basename; 39 40#*************************************************************************** 41# Variables and subs imported from sshhelp module 42# 43use sshhelp qw( 44 $sshdexe 45 $sshexe 46 $sftpsrvexe 47 $sftpexe 48 $sshkeygenexe 49 $sshdconfig 50 $sshconfig 51 $sftpconfig 52 $knownhosts 53 $sshdlog 54 $sshlog 55 $sftplog 56 $sftpcmds 57 $hstprvkeyf 58 $hstpubkeyf 59 $hstpubmd5f 60 $hstpubsha256f 61 $cliprvkeyf 62 $clipubkeyf 63 display_sshdconfig 64 display_sshconfig 65 display_sftpconfig 66 display_sshdlog 67 display_sshlog 68 display_sftplog 69 dump_array 70 find_sshd 71 find_ssh 72 find_sftpsrv 73 find_sftp 74 find_sshkeygen 75 sshversioninfo 76 ); 77 78#*************************************************************************** 79# Subs imported from serverhelp module 80# 81use serverhelp qw( 82 logmsg 83 $logfile 84 server_pidfilename 85 server_logfilename 86 ); 87 88use pathhelp; 89 90#*************************************************************************** 91 92my $verbose = 0; # set to 1 for debugging 93my $debugprotocol = 0; # set to 1 for protocol debugging 94my $port = 8999; # our default SCP/SFTP server port 95my $listenaddr = '127.0.0.1'; # default address on which to listen 96my $ipvnum = 4; # default IP version of listener address 97my $idnum = 1; # default ssh daemon instance number 98my $proto = 'ssh'; # protocol the ssh daemon speaks 99my $path = getcwd(); # current working directory 100my $logdir = $path .'/log'; # directory for log files 101my $piddir; # directory for server config files 102my $username = $ENV{USER}; # default user 103my $pidfile; # ssh daemon pid file 104my $identity = 'curl_client_key'; # default identity file 105 106my $error; 107my @cfgarr; 108 109#*************************************************************************** 110# Returns a path of the given file name in the log directory (PiddirPath) 111# 112sub pp { 113 my $file = $_[0]; 114 return "$piddir/$file"; 115 # TODO: do Windows path conversion here 116} 117 118#*************************************************************************** 119# Parse command line options 120# 121while(@ARGV) { 122 if($ARGV[0] eq '--verbose') { 123 $verbose = 1; 124 } 125 elsif($ARGV[0] eq '--debugprotocol') { 126 $verbose = 1; 127 $debugprotocol = 1; 128 } 129 elsif($ARGV[0] eq '--user') { 130 if($ARGV[1]) { 131 $username = $ARGV[1]; 132 shift @ARGV; 133 } 134 } 135 elsif($ARGV[0] eq '--id') { 136 if($ARGV[1]) { 137 if($ARGV[1] =~ /^(\d+)$/) { 138 $idnum = $1 if($1 > 0); 139 shift @ARGV; 140 } 141 } 142 } 143 elsif($ARGV[0] eq '--ipv4') { 144 $ipvnum = 4; 145 $listenaddr = '127.0.0.1' if($listenaddr eq '::1'); 146 } 147 elsif($ARGV[0] eq '--ipv6') { 148 $ipvnum = 6; 149 $listenaddr = '::1' if($listenaddr eq '127.0.0.1'); 150 } 151 elsif($ARGV[0] eq '--addr') { 152 if($ARGV[1]) { 153 my $tmpstr = $ARGV[1]; 154 if($tmpstr =~ /^(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)$/) { 155 $listenaddr = "$1.$2.$3.$4" if($ipvnum == 4); 156 shift @ARGV; 157 } 158 elsif($ipvnum == 6) { 159 $listenaddr = $tmpstr; 160 $listenaddr =~ s/^\[(.*)\]$/$1/; 161 shift @ARGV; 162 } 163 } 164 } 165 elsif($ARGV[0] eq '--pidfile') { 166 if($ARGV[1]) { 167 $pidfile = "$path/". $ARGV[1]; 168 shift @ARGV; 169 } 170 } 171 elsif($ARGV[0] eq '--logdir') { 172 if($ARGV[1]) { 173 $logdir = "$path/". $ARGV[1]; 174 shift @ARGV; 175 } 176 } 177 elsif($ARGV[0] eq '--sshport') { 178 if($ARGV[1]) { 179 if($ARGV[1] =~ /^(\d+)$/) { 180 $port = $1; 181 shift @ARGV; 182 } 183 } 184 } 185 else { 186 print STDERR "\nWarning: sshserver.pl unknown parameter: $ARGV[0]\n"; 187 } 188 shift @ARGV; 189} 190 191#*************************************************************************** 192# Initialize command line option dependent variables 193# 194 195#*************************************************************************** 196# Default ssh daemon pid file name & directory 197# 198if($pidfile) { 199 # Use our pidfile directory to store server config files 200 $piddir = dirname($pidfile); 201} 202else { 203 # Use the current directory to store server config files 204 $piddir = $path; 205 $pidfile = server_pidfilename($piddir, $proto, $ipvnum, $idnum); 206} 207 208#*************************************************************************** 209# ssh and sftp server log file names 210# 211$sshdlog = server_logfilename($logdir, 'ssh', $ipvnum, $idnum); 212$sftplog = server_logfilename($logdir, 'sftp', $ipvnum, $idnum); 213$logfile = "$logdir/sshserver.log"; # used by logmsg 214 215#*************************************************************************** 216# Logging level for ssh server and client 217# 218my $loglevel = $debugprotocol?'DEBUG3':'DEBUG2'; 219 220 221#*************************************************************************** 222# Validate username 223# 224if(!$username) { 225 $error = 'Will not run ssh server without a user name'; 226} 227elsif($username eq 'root') { 228 $error = 'Will not run ssh server as root to mitigate security risks'; 229} 230if($error) { 231 logmsg "$error\n"; 232 exit 1; 233} 234 235 236#*************************************************************************** 237# Find out ssh daemon canonical file name 238# 239my $sshd = find_sshd(); 240if(!$sshd) { 241 logmsg "cannot find $sshdexe\n"; 242 exit 1; 243} 244 245 246#*************************************************************************** 247# Find out ssh daemon version info 248# 249my ($sshdid, $sshdvernum, $sshdverstr, $sshderror) = sshversioninfo($sshd); 250if(!$sshdid) { 251 # Not an OpenSSH or SunSSH ssh daemon 252 logmsg "$sshderror\n" if($verbose); 253 logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n"; 254 exit 1; 255} 256logmsg "ssh server found $sshd is $sshdverstr\n" if($verbose); 257 258 259#*************************************************************************** 260# ssh daemon command line options we might use and version support 261# 262# -e: log stderr : OpenSSH 2.9.0 and later 263# -f: sshd config file : OpenSSH 1.2.1 and later 264# -D: no daemon forking : OpenSSH 2.5.0 and later 265# -o: command-line option : OpenSSH 3.1.0 and later 266# -t: test config file : OpenSSH 2.9.9 and later 267# -?: sshd version info : OpenSSH 1.2.1 and later 268# 269# -e: log stderr : SunSSH 1.0.0 and later 270# -f: sshd config file : SunSSH 1.0.0 and later 271# -D: no daemon forking : SunSSH 1.0.0 and later 272# -o: command-line option : SunSSH 1.0.0 and later 273# -t: test config file : SunSSH 1.0.0 and later 274# -?: sshd version info : SunSSH 1.0.0 and later 275 276 277#*************************************************************************** 278# Verify minimum ssh daemon version 279# 280if((($sshdid =~ /OpenSSH/) && ($sshdvernum < 299)) || 281 (($sshdid =~ /SunSSH/) && ($sshdvernum < 100))) { 282 logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n"; 283 exit 1; 284} 285 286 287#*************************************************************************** 288# Find out sftp server plugin canonical file name 289# 290my $sftpsrv = find_sftpsrv(); 291if(!$sftpsrv) { 292 logmsg "cannot find $sftpsrvexe\n"; 293 exit 1; 294} 295logmsg "sftp server plugin found $sftpsrv\n" if($verbose); 296 297 298#*************************************************************************** 299# Find out sftp client canonical file name 300# 301my $sftp = find_sftp(); 302if(!$sftp) { 303 logmsg "cannot find $sftpexe\n"; 304 exit 1; 305} 306logmsg "sftp client found $sftp\n" if($verbose); 307 308 309#*************************************************************************** 310# Find out ssh keygen canonical file name 311# 312my $sshkeygen = find_sshkeygen(); 313if(!$sshkeygen) { 314 logmsg "cannot find $sshkeygenexe\n"; 315 exit 1; 316} 317logmsg "ssh keygen found $sshkeygen\n" if($verbose); 318 319 320#*************************************************************************** 321# Find out ssh client canonical file name 322# 323my $ssh = find_ssh(); 324if(!$ssh) { 325 logmsg "cannot find $sshexe\n"; 326 exit 1; 327} 328 329 330#*************************************************************************** 331# Find out ssh client version info 332# 333my ($sshid, $sshvernum, $sshverstr, $ssherror) = sshversioninfo($ssh); 334if(!$sshid) { 335 # Not an OpenSSH or SunSSH ssh client 336 logmsg "$ssherror\n" if($verbose); 337 logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n"; 338 exit 1; 339} 340logmsg "ssh client found $ssh is $sshverstr\n" if($verbose); 341 342 343#*************************************************************************** 344# ssh client command line options we might use and version support 345# 346# -D: dynamic app port forwarding : OpenSSH 2.9.9 and later 347# -F: ssh config file : OpenSSH 2.9.9 and later 348# -N: no shell/command : OpenSSH 2.1.0 and later 349# -p: connection port : OpenSSH 1.2.1 and later 350# -v: verbose messages : OpenSSH 1.2.1 and later 351# -vv: increase verbosity : OpenSSH 2.3.0 and later 352# -V: ssh version info : OpenSSH 1.2.1 and later 353# 354# -D: dynamic app port forwarding : SunSSH 1.0.0 and later 355# -F: ssh config file : SunSSH 1.0.0 and later 356# -N: no shell/command : SunSSH 1.0.0 and later 357# -p: connection port : SunSSH 1.0.0 and later 358# -v: verbose messages : SunSSH 1.0.0 and later 359# -vv: increase verbosity : SunSSH 1.0.0 and later 360# -V: ssh version info : SunSSH 1.0.0 and later 361 362 363#*************************************************************************** 364# Verify minimum ssh client version 365# 366if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) || 367 (($sshid =~ /SunSSH/) && ($sshvernum < 100))) { 368 logmsg "SCP and SFTP tests require OpenSSH 2.9.9 or later\n"; 369 exit 1; 370} 371 372 373#*************************************************************************** 374# ssh keygen command line options we actually use and version support 375# 376# -C: identity comment : OpenSSH 1.2.1 and later 377# -f: key filename : OpenSSH 1.2.1 and later 378# -N: new passphrase : OpenSSH 1.2.1 and later 379# -q: quiet keygen : OpenSSH 1.2.1 and later 380# -t: key type : OpenSSH 2.5.0 and later 381# 382# -C: identity comment : SunSSH 1.0.0 and later 383# -f: key filename : SunSSH 1.0.0 and later 384# -N: new passphrase : SunSSH 1.0.0 and later 385# -q: quiet keygen : SunSSH 1.0.0 and later 386# -t: key type : SunSSH 1.0.0 and later 387 388 389#*************************************************************************** 390# Generate host and client key files for curl's tests 391# 392if((! -e pp($hstprvkeyf)) || (! -s pp($hstprvkeyf)) || 393 (! -e pp($hstpubkeyf)) || (! -s pp($hstpubkeyf)) || 394 (! -e pp($hstpubmd5f)) || (! -s pp($hstpubmd5f)) || 395 (! -e pp($hstpubsha256f)) || (! -s pp($hstpubsha256f)) || 396 (! -e pp($cliprvkeyf)) || (! -s pp($cliprvkeyf)) || 397 (! -e pp($clipubkeyf)) || (! -s pp($clipubkeyf))) { 398 # Make sure all files are gone so ssh-keygen doesn't complain 399 unlink(pp($hstprvkeyf), pp($hstpubkeyf), pp($hstpubmd5f), 400 pp($hstpubsha256f), pp($cliprvkeyf), pp($clipubkeyf)); 401 logmsg "generating host keys...\n" if($verbose); 402 if(system "\"$sshkeygen\" -q -t rsa -f " . pp($hstprvkeyf) . " -C 'curl test server' -N ''") { 403 logmsg "Could not generate host key\n"; 404 exit 1; 405 } 406 logmsg "generating client keys...\n" if($verbose); 407 if(system "\"$sshkeygen\" -q -t rsa -f " . pp($cliprvkeyf) . " -C 'curl test client' -N ''") { 408 logmsg "Could not generate client key\n"; 409 exit 1; 410 } 411 # Make sure that permissions are restricted so openssh doesn't complain 412 system "chmod 600 " . pp($hstprvkeyf); 413 system "chmod 600 " . pp($cliprvkeyf); 414 # Save md5 and sha256 hashes of public host key 415 open(my $rsakeyfile, "<", pp($hstpubkeyf)); 416 my @rsahostkey = do { local $/ = ' '; <$rsakeyfile> }; 417 close($rsakeyfile); 418 if(!$rsahostkey[1]) { 419 logmsg "Failed parsing base64 encoded RSA host key\n"; 420 exit 1; 421 } 422 open(my $pubmd5file, ">", pp($hstpubmd5f)); 423 print $pubmd5file md5_hex(decode_base64($rsahostkey[1])); 424 close($pubmd5file); 425 if((! -e pp($hstpubmd5f)) || (! -s pp($hstpubmd5f))) { 426 logmsg "Failed writing md5 hash of RSA host key\n"; 427 exit 1; 428 } 429 open(my $pubsha256file, ">", pp($hstpubsha256f)); 430 print $pubsha256file sha256_base64(decode_base64($rsahostkey[1])); 431 close($pubsha256file); 432 if((! -e pp($hstpubsha256f)) || (! -s pp($hstpubsha256f))) { 433 logmsg "Failed writing sha256 hash of RSA host key\n"; 434 exit 1; 435 } 436} 437 438 439#*************************************************************************** 440# Convert paths for curl's tests running on Windows with Cygwin/Msys OpenSSH 441# 442my $clipubkeyf_config; 443my $hstprvkeyf_config; 444my $pidfile_config; 445my $sftpsrv_config; 446if ($sshdid =~ /OpenSSH-Windows/) { 447 # Ensure to use native Windows paths with OpenSSH for Windows 448 $clipubkeyf_config = pathhelp::sys_native_abs_path(pp($clipubkeyf)); 449 $hstprvkeyf_config = pathhelp::sys_native_abs_path(pp($hstprvkeyf)); 450 $pidfile_config = pathhelp::sys_native_abs_path($pidfile); 451 $sftpsrv_config = pathhelp::sys_native_abs_path($sftpsrv); 452} 453elsif (pathhelp::os_is_win()) { 454 # Ensure to use MinGW/Cygwin paths 455 $clipubkeyf_config = pathhelp::build_sys_abs_path($clipubkeyf_config); 456 $hstprvkeyf_config = pathhelp::build_sys_abs_path($hstprvkeyf_config); 457 $pidfile_config = pathhelp::build_sys_abs_path($pidfile_config); 458 $sftpsrv_config = "internal-sftp"; 459} 460else { 461 $clipubkeyf_config = abs_path(pp($clipubkeyf)); 462 $hstprvkeyf_config = abs_path(pp($hstprvkeyf)); 463 $pidfile_config = $pidfile; 464 $sftpsrv_config = $sftpsrv; 465} 466my $sshdconfig_abs = pathhelp::sys_native_abs_path(pp($sshdconfig)); 467 468#*************************************************************************** 469# ssh daemon configuration file options we might use and version support 470# 471# AFSTokenPassing : OpenSSH 1.2.1 and later [1] 472# AddressFamily : OpenSSH 4.0.0 and later 473# AllowTcpForwarding : OpenSSH 2.3.0 and later 474# AllowUsers : OpenSSH 1.2.1 and later 475# AuthorizedKeysFile : OpenSSH 2.9.9 and later 476# AuthorizedKeysFile2 : OpenSSH 2.9.9 and later 477# Banner : OpenSSH 2.5.0 and later 478# ChallengeResponseAuthentication : OpenSSH 2.5.0 and later 479# Ciphers : OpenSSH 2.1.0 and later [3] 480# ClientAliveCountMax : OpenSSH 2.9.0 and later 481# ClientAliveInterval : OpenSSH 2.9.0 and later 482# Compression : OpenSSH 3.3.0 and later 483# DenyUsers : OpenSSH 1.2.1 and later 484# ForceCommand : OpenSSH 4.4.0 and later [3] 485# GatewayPorts : OpenSSH 2.1.0 and later 486# GSSAPIAuthentication : OpenSSH 3.7.0 and later [1] 487# GSSAPICleanupCredentials : OpenSSH 3.8.0 and later [1] 488# GSSAPIKeyExchange : SunSSH 1.0.0 and later [1] 489# GSSAPIStoreDelegatedCredentials : SunSSH 1.0.0 and later [1] 490# GSSCleanupCreds : SunSSH 1.0.0 and later [1] 491# GSSUseSessionCredCache : SunSSH 1.0.0 and later [1] 492# HostbasedAuthentication : OpenSSH 2.9.0 and later 493# HostbasedUsesNameFromPacketOnly : OpenSSH 2.9.0 and later 494# HostKey : OpenSSH 1.2.1 and later 495# IgnoreRhosts : OpenSSH 1.2.1 and later 496# IgnoreUserKnownHosts : OpenSSH 1.2.1 and later 497# KbdInteractiveAuthentication : OpenSSH 2.3.0 and later 498# KeepAlive : OpenSSH 1.2.1 and later 499# KerberosAuthentication : OpenSSH 1.2.1 and later [1] 500# KerberosGetAFSToken : OpenSSH 3.8.0 and later [1] 501# KerberosOrLocalPasswd : OpenSSH 1.2.1 and later [1] 502# KerberosTgtPassing : OpenSSH 1.2.1 and later [1] 503# KerberosTicketCleanup : OpenSSH 1.2.1 and later [1] 504# KeyRegenerationInterval : OpenSSH 1.2.1 and later 505# ListenAddress : OpenSSH 1.2.1 and later 506# LoginGraceTime : OpenSSH 1.2.1 and later 507# LogLevel : OpenSSH 1.2.1 and later 508# LookupClientHostnames : SunSSH 1.0.0 and later 509# MACs : OpenSSH 2.5.0 and later [3] 510# Match : OpenSSH 4.4.0 and later [3] 511# MaxAuthTries : OpenSSH 3.9.0 and later 512# MaxStartups : OpenSSH 2.2.0 and later 513# PAMAuthenticationViaKbdInt : OpenSSH 2.9.0 and later [2] 514# PasswordAuthentication : OpenSSH 1.2.1 and later 515# PermitEmptyPasswords : OpenSSH 1.2.1 and later 516# PermitOpen : OpenSSH 4.4.0 and later [3] 517# PermitRootLogin : OpenSSH 1.2.1 and later 518# PermitTunnel : OpenSSH 4.3.0 and later 519# PermitUserEnvironment : OpenSSH 3.5.0 and later 520# PidFile : OpenSSH 2.1.0 and later 521# Port : OpenSSH 1.2.1 and later 522# PrintLastLog : OpenSSH 2.9.0 and later 523# PrintMotd : OpenSSH 1.2.1 and later 524# Protocol : OpenSSH 2.1.0 and later 525# PubkeyAuthentication : OpenSSH 2.5.0 and later 526# RhostsAuthentication : OpenSSH 1.2.1 and later 527# RhostsRSAAuthentication : OpenSSH 1.2.1 and later 528# RSAAuthentication : OpenSSH 1.2.1 and later 529# ServerKeyBits : OpenSSH 1.2.1 and later 530# SkeyAuthentication : OpenSSH 1.2.1 and later [1] 531# StrictModes : OpenSSH 1.2.1 and later 532# Subsystem : OpenSSH 2.2.0 and later 533# SyslogFacility : OpenSSH 1.2.1 and later 534# TCPKeepAlive : OpenSSH 3.8.0 and later 535# UseDNS : OpenSSH 3.7.0 and later 536# UseLogin : OpenSSH 1.2.1 and later 537# UsePAM : OpenSSH 3.7.0 and later [1][2] 538# UsePrivilegeSeparation : OpenSSH 3.2.2 and later 539# VerifyReverseMapping : OpenSSH 3.1.0 and later 540# X11DisplayOffset : OpenSSH 1.2.1 and later [3] 541# X11Forwarding : OpenSSH 1.2.1 and later 542# X11UseLocalhost : OpenSSH 3.1.0 and later 543# XAuthLocation : OpenSSH 2.1.1 and later [3] 544# 545# [1] Option only available if activated at compile time 546# [2] Option specific for portable versions 547# [3] Option not used in our ssh server config file 548 549 550#*************************************************************************** 551# Initialize sshd config with options actually supported in OpenSSH 2.9.9 552# 553logmsg "generating ssh server config file...\n" if($verbose); 554@cfgarr = (); 555push @cfgarr, '# This is a generated file. Do not edit.'; 556push @cfgarr, "# $sshdverstr sshd configuration file for curl testing"; 557push @cfgarr, '#'; 558 559# AllowUsers and DenyUsers options should use lowercase on Windows 560# and do not support quotes around values for some unknown reason. 561if ($sshdid =~ /OpenSSH-Windows/) { 562 my $username_lc = lc $username; 563 if (exists $ENV{USERDOMAIN}) { 564 my $userdomain_lc = lc $ENV{USERDOMAIN}; 565 $username_lc = "$userdomain_lc\\$username_lc"; 566 } 567 $username_lc =~ s/ /\?/g; # replace space with ? 568 push @cfgarr, "DenyUsers !$username_lc"; 569 push @cfgarr, "AllowUsers $username_lc"; 570} else { 571 push @cfgarr, "DenyUsers !$username"; 572 push @cfgarr, "AllowUsers $username"; 573} 574 575push @cfgarr, "AuthorizedKeysFile $clipubkeyf_config"; 576push @cfgarr, "AuthorizedKeysFile2 $clipubkeyf_config"; 577push @cfgarr, "HostKey $hstprvkeyf_config"; 578if ($sshdid !~ /OpenSSH-Windows/) { 579 push @cfgarr, "PidFile $pidfile_config"; 580 push @cfgarr, '#'; 581} 582if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 880)) { 583 push @cfgarr, 'HostKeyAlgorithms +ssh-rsa'; 584 push @cfgarr, 'PubkeyAcceptedKeyTypes +ssh-rsa'; 585} 586push @cfgarr, '#'; 587push @cfgarr, "Port $port"; 588push @cfgarr, "ListenAddress $listenaddr"; 589push @cfgarr, 'Protocol 2'; 590push @cfgarr, '#'; 591push @cfgarr, 'AllowTcpForwarding yes'; 592push @cfgarr, 'Banner none'; 593push @cfgarr, 'ChallengeResponseAuthentication no'; 594push @cfgarr, 'ClientAliveCountMax 3'; 595push @cfgarr, 'ClientAliveInterval 0'; 596push @cfgarr, 'GatewayPorts no'; 597push @cfgarr, 'HostbasedAuthentication no'; 598push @cfgarr, 'HostbasedUsesNameFromPacketOnly no'; 599push @cfgarr, 'IgnoreRhosts yes'; 600push @cfgarr, 'IgnoreUserKnownHosts yes'; 601push @cfgarr, 'KeyRegenerationInterval 0'; 602push @cfgarr, 'LoginGraceTime 30'; 603push @cfgarr, "LogLevel $loglevel"; 604push @cfgarr, 'MaxStartups 5'; 605push @cfgarr, 'PasswordAuthentication no'; 606push @cfgarr, 'PermitEmptyPasswords no'; 607push @cfgarr, 'PermitRootLogin no'; 608push @cfgarr, 'PrintLastLog no'; 609push @cfgarr, 'PrintMotd no'; 610push @cfgarr, 'PubkeyAuthentication yes'; 611push @cfgarr, 'RhostsRSAAuthentication no'; 612push @cfgarr, 'RSAAuthentication no'; 613push @cfgarr, 'ServerKeyBits 768'; 614push @cfgarr, 'StrictModes no'; 615push @cfgarr, "Subsystem sftp \"$sftpsrv_config\""; 616push @cfgarr, 'SyslogFacility AUTH'; 617push @cfgarr, 'UseLogin no'; 618push @cfgarr, 'X11Forwarding no'; 619push @cfgarr, '#'; 620 621 622#*************************************************************************** 623# Write out initial sshd configuration file for curl's tests 624# 625$error = dump_array(pp($sshdconfig), @cfgarr); 626if($error) { 627 logmsg "$error\n"; 628 exit 1; 629} 630 631 632#*************************************************************************** 633# Verifies at run time if sshd supports a given configuration file option 634# 635sub sshd_supports_opt { 636 my ($option, $value) = @_; 637 my $err; 638 # 639 if((($sshdid =~ /OpenSSH/) && ($sshdvernum >= 310)) || 640 ($sshdid =~ /SunSSH/)) { 641 # ssh daemon supports command line options -t -f and -o 642 $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/, 643 `\"$sshd\" -t -f $sshdconfig_abs -o \"$option=$value\" 2>&1`; 644 return !$err; 645 } 646 if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 299)) { 647 # ssh daemon supports command line options -t and -f 648 $err = dump_array(pp($sshdconfig), (@cfgarr, "$option $value")); 649 if($err) { 650 logmsg "$err\n"; 651 return 0; 652 } 653 $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/, 654 `\"$sshd\" -t -f $sshdconfig_abs 2>&1`; 655 unlink pp($sshdconfig); 656 return !$err; 657 } 658 return 0; 659} 660 661 662#*************************************************************************** 663# Kerberos Authentication support may have not been built into sshd 664# 665if(sshd_supports_opt('KerberosAuthentication','no')) { 666 push @cfgarr, 'KerberosAuthentication no'; 667} 668if(sshd_supports_opt('KerberosGetAFSToken','no')) { 669 push @cfgarr, 'KerberosGetAFSToken no'; 670} 671if(sshd_supports_opt('KerberosOrLocalPasswd','no')) { 672 push @cfgarr, 'KerberosOrLocalPasswd no'; 673} 674if(sshd_supports_opt('KerberosTgtPassing','no')) { 675 push @cfgarr, 'KerberosTgtPassing no'; 676} 677if(sshd_supports_opt('KerberosTicketCleanup','yes')) { 678 push @cfgarr, 'KerberosTicketCleanup yes'; 679} 680 681 682#*************************************************************************** 683# Andrew File System support may have not been built into sshd 684# 685if(sshd_supports_opt('AFSTokenPassing','no')) { 686 push @cfgarr, 'AFSTokenPassing no'; 687} 688 689 690#*************************************************************************** 691# S/Key authentication support may have not been built into sshd 692# 693if(sshd_supports_opt('SkeyAuthentication','no')) { 694 push @cfgarr, 'SkeyAuthentication no'; 695} 696 697 698#*************************************************************************** 699# GSSAPI Authentication support may have not been built into sshd 700# 701my $sshd_builtwith_GSSAPI; 702if(sshd_supports_opt('GSSAPIAuthentication','no')) { 703 push @cfgarr, 'GSSAPIAuthentication no'; 704 $sshd_builtwith_GSSAPI = 1; 705} 706if(sshd_supports_opt('GSSAPICleanupCredentials','yes')) { 707 push @cfgarr, 'GSSAPICleanupCredentials yes'; 708} 709if(sshd_supports_opt('GSSAPIKeyExchange','no')) { 710 push @cfgarr, 'GSSAPIKeyExchange no'; 711} 712if(sshd_supports_opt('GSSAPIStoreDelegatedCredentials','no')) { 713 push @cfgarr, 'GSSAPIStoreDelegatedCredentials no'; 714} 715if(sshd_supports_opt('GSSCleanupCreds','yes')) { 716 push @cfgarr, 'GSSCleanupCreds yes'; 717} 718if(sshd_supports_opt('GSSUseSessionCredCache','no')) { 719 push @cfgarr, 'GSSUseSessionCredCache no'; 720} 721push @cfgarr, '#'; 722 723 724#*************************************************************************** 725# Options that might be supported or not in sshd OpenSSH 2.9.9 and later 726# 727if(sshd_supports_opt('AddressFamily','any')) { 728 # Address family must be specified before ListenAddress 729 splice @cfgarr, 11, 0, 'AddressFamily any'; 730} 731if(sshd_supports_opt('Compression','no')) { 732 push @cfgarr, 'Compression no'; 733} 734if(sshd_supports_opt('KbdInteractiveAuthentication','no')) { 735 push @cfgarr, 'KbdInteractiveAuthentication no'; 736} 737if(sshd_supports_opt('KeepAlive','no')) { 738 push @cfgarr, 'KeepAlive no'; 739} 740if(sshd_supports_opt('LookupClientHostnames','no')) { 741 push @cfgarr, 'LookupClientHostnames no'; 742} 743if(sshd_supports_opt('MaxAuthTries','10')) { 744 push @cfgarr, 'MaxAuthTries 10'; 745} 746if(sshd_supports_opt('PAMAuthenticationViaKbdInt','no')) { 747 push @cfgarr, 'PAMAuthenticationViaKbdInt no'; 748} 749if(sshd_supports_opt('PermitTunnel','no')) { 750 push @cfgarr, 'PermitTunnel no'; 751} 752if(sshd_supports_opt('PermitUserEnvironment','no')) { 753 push @cfgarr, 'PermitUserEnvironment no'; 754} 755if(sshd_supports_opt('RhostsAuthentication','no')) { 756 push @cfgarr, 'RhostsAuthentication no'; 757} 758if(sshd_supports_opt('TCPKeepAlive','no')) { 759 push @cfgarr, 'TCPKeepAlive no'; 760} 761if(sshd_supports_opt('UseDNS','no')) { 762 push @cfgarr, 'UseDNS no'; 763} 764if(sshd_supports_opt('UsePAM','no')) { 765 push @cfgarr, 'UsePAM no'; 766} 767 768if($sshdid =~ /OpenSSH/) { 769 # http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6492415 770 if(sshd_supports_opt('UsePrivilegeSeparation','no')) { 771 push @cfgarr, 'UsePrivilegeSeparation no'; 772 } 773} 774 775if(sshd_supports_opt('VerifyReverseMapping','no')) { 776 push @cfgarr, 'VerifyReverseMapping no'; 777} 778if(sshd_supports_opt('X11UseLocalhost','yes')) { 779 push @cfgarr, 'X11UseLocalhost yes'; 780} 781push @cfgarr, '#'; 782 783 784#*************************************************************************** 785# Write out resulting sshd configuration file for curl's tests 786# 787$error = dump_array(pp($sshdconfig), @cfgarr); 788if($error) { 789 logmsg "$error\n"; 790 exit 1; 791} 792 793 794#*************************************************************************** 795# Verify that sshd actually supports our generated configuration file 796# 797if(system "\"$sshd\" -t -f $sshdconfig_abs > $sshdlog 2>&1") { 798 logmsg "sshd configuration file $sshdconfig failed verification\n"; 799 display_sshdlog(); 800 display_sshdconfig(); 801 exit 1; 802} 803 804 805#*************************************************************************** 806# Generate ssh client host key database file for curl's tests 807# 808if((! -e pp($knownhosts)) || (! -s pp($knownhosts))) { 809 logmsg "generating ssh client known hosts file...\n" if($verbose); 810 unlink(pp($knownhosts)); 811 if(open(my $rsakeyfile, "<", pp($hstpubkeyf))) { 812 my @rsahostkey = do { local $/ = ' '; <$rsakeyfile> }; 813 if(close($rsakeyfile)) { 814 if(open(my $knownhostsh, ">", pp($knownhosts))) { 815 print $knownhostsh "$listenaddr ssh-rsa $rsahostkey[1]\n"; 816 if(!close($knownhostsh)) { 817 $error = "Error: cannot close file $knownhosts"; 818 } 819 } 820 else { 821 $error = "Error: cannot write file $knownhosts"; 822 } 823 } 824 else { 825 $error = "Error: cannot close file $hstpubkeyf"; 826 } 827 } 828 else { 829 $error = "Error: cannot read file $hstpubkeyf"; 830 } 831 if($error) { 832 logmsg "$error\n"; 833 exit 1; 834 } 835} 836 837 838#*************************************************************************** 839# Convert paths for curl's tests running on Windows using Cygwin OpenSSH 840# 841my $identity_config; 842my $knownhosts_config; 843if ($sshdid =~ /OpenSSH-Windows/) { 844 # Ensure to use native Windows paths with OpenSSH for Windows 845 $identity_config = pathhelp::sys_native_abs_path(pp($identity)); 846 $knownhosts_config = pathhelp::sys_native_abs_path(pp($knownhosts)); 847} 848elsif (pathhelp::os_is_win()) { 849 # Ensure to use MinGW/Cygwin paths 850 $identity_config = pathhelp::build_sys_abs_path($identity_config); 851 $knownhosts_config = pathhelp::build_sys_abs_path($knownhosts_config); 852} 853else { 854 $identity_config = abs_path(pp($identity)); 855 $knownhosts_config = abs_path(pp($knownhosts)); 856} 857 858 859#*************************************************************************** 860# ssh client configuration file options we might use and version support 861# 862# AddressFamily : OpenSSH 3.7.0 and later 863# BatchMode : OpenSSH 1.2.1 and later 864# BindAddress : OpenSSH 2.9.9 and later 865# ChallengeResponseAuthentication : OpenSSH 2.5.0 and later 866# CheckHostIP : OpenSSH 1.2.1 and later 867# Cipher : OpenSSH 1.2.1 and later [3] 868# Ciphers : OpenSSH 2.1.0 and later [3] 869# ClearAllForwardings : OpenSSH 2.9.9 and later 870# Compression : OpenSSH 1.2.1 and later 871# CompressionLevel : OpenSSH 1.2.1 and later [3] 872# ConnectionAttempts : OpenSSH 1.2.1 and later 873# ConnectTimeout : OpenSSH 3.7.0 and later 874# ControlMaster : OpenSSH 3.9.0 and later 875# ControlPath : OpenSSH 3.9.0 and later 876# DisableBanner : SunSSH 1.2.0 and later 877# DynamicForward : OpenSSH 2.9.0 and later 878# EnableSSHKeysign : OpenSSH 3.6.0 and later 879# EscapeChar : OpenSSH 1.2.1 and later [3] 880# ExitOnForwardFailure : OpenSSH 4.4.0 and later 881# ForwardAgent : OpenSSH 1.2.1 and later 882# ForwardX11 : OpenSSH 1.2.1 and later 883# ForwardX11Trusted : OpenSSH 3.8.0 and later 884# GatewayPorts : OpenSSH 1.2.1 and later 885# GlobalKnownHostsFile : OpenSSH 1.2.1 and later 886# GSSAPIAuthentication : OpenSSH 3.7.0 and later [1] 887# GSSAPIDelegateCredentials : OpenSSH 3.7.0 and later [1] 888# HashKnownHosts : OpenSSH 4.0.0 and later 889# Host : OpenSSH 1.2.1 and later 890# HostbasedAuthentication : OpenSSH 2.9.0 and later 891# HostKeyAlgorithms : OpenSSH 2.9.0 and later [3] 892# HostKeyAlias : OpenSSH 2.5.0 and later [3] 893# HostName : OpenSSH 1.2.1 and later 894# IdentitiesOnly : OpenSSH 3.9.0 and later 895# IdentityFile : OpenSSH 1.2.1 and later 896# IgnoreIfUnknown : SunSSH 1.2.0 and later 897# KeepAlive : OpenSSH 1.2.1 and later 898# KbdInteractiveAuthentication : OpenSSH 2.3.0 and later 899# KbdInteractiveDevices : OpenSSH 2.3.0 and later [3] 900# LocalCommand : OpenSSH 4.3.0 and later [3] 901# LocalForward : OpenSSH 1.2.1 and later [3] 902# LogLevel : OpenSSH 1.2.1 and later 903# MACs : OpenSSH 2.5.0 and later [3] 904# NoHostAuthenticationForLocalhost : OpenSSH 3.0.0 and later 905# NumberOfPasswordPrompts : OpenSSH 1.2.1 and later 906# PasswordAuthentication : OpenSSH 1.2.1 and later 907# PermitLocalCommand : OpenSSH 4.3.0 and later 908# Port : OpenSSH 1.2.1 and later 909# PreferredAuthentications : OpenSSH 2.5.2 and later 910# Protocol : OpenSSH 2.1.0 and later 911# ProxyCommand : OpenSSH 1.2.1 and later [3] 912# PubkeyAuthentication : OpenSSH 2.5.0 and later 913# RekeyLimit : OpenSSH 3.7.0 and later 914# RemoteForward : OpenSSH 1.2.1 and later [3] 915# RhostsRSAAuthentication : OpenSSH 1.2.1 and later 916# RSAAuthentication : OpenSSH 1.2.1 and later 917# ServerAliveCountMax : OpenSSH 3.8.0 and later 918# ServerAliveInterval : OpenSSH 3.8.0 and later 919# SmartcardDevice : OpenSSH 2.9.9 and later [1][3] 920# StrictHostKeyChecking : OpenSSH 1.2.1 and later 921# TCPKeepAlive : OpenSSH 3.8.0 and later 922# Tunnel : OpenSSH 4.3.0 and later 923# TunnelDevice : OpenSSH 4.3.0 and later [3] 924# UsePAM : OpenSSH 3.7.0 and later [1][2][3] 925# UsePrivilegedPort : OpenSSH 1.2.1 and later 926# User : OpenSSH 1.2.1 and later 927# UserKnownHostsFile : OpenSSH 1.2.1 and later 928# VerifyHostKeyDNS : OpenSSH 3.8.0 and later 929# XAuthLocation : OpenSSH 2.1.1 and later [3] 930# 931# [1] Option only available if activated at compile time 932# [2] Option specific for portable versions 933# [3] Option not used in our ssh client config file 934 935 936#*************************************************************************** 937# Initialize ssh config with options actually supported in OpenSSH 2.9.9 938# 939logmsg "generating ssh client config file...\n" if($verbose); 940@cfgarr = (); 941push @cfgarr, '# This is a generated file. Do not edit.'; 942push @cfgarr, "# $sshverstr ssh client configuration file for curl testing"; 943push @cfgarr, '#'; 944push @cfgarr, 'Host *'; 945push @cfgarr, '#'; 946push @cfgarr, "Port $port"; 947push @cfgarr, "HostName $listenaddr"; 948push @cfgarr, "User $username"; 949push @cfgarr, 'Protocol 2'; 950push @cfgarr, '#'; 951 952# BindAddress option is not supported by OpenSSH for Windows 953if (!($sshdid =~ /OpenSSH-Windows/)) { 954 push @cfgarr, "BindAddress $listenaddr"; 955} 956 957push @cfgarr, '#'; 958push @cfgarr, "IdentityFile $identity_config"; 959push @cfgarr, "UserKnownHostsFile $knownhosts_config"; 960push @cfgarr, '#'; 961push @cfgarr, 'BatchMode yes'; 962push @cfgarr, 'ChallengeResponseAuthentication no'; 963push @cfgarr, 'CheckHostIP no'; 964push @cfgarr, 'ClearAllForwardings no'; 965push @cfgarr, 'Compression no'; 966push @cfgarr, 'ConnectionAttempts 3'; 967push @cfgarr, 'ForwardAgent no'; 968push @cfgarr, 'ForwardX11 no'; 969push @cfgarr, 'GatewayPorts no'; 970push @cfgarr, 'GlobalKnownHostsFile /dev/null'; 971push @cfgarr, 'HostbasedAuthentication no'; 972push @cfgarr, 'KbdInteractiveAuthentication no'; 973push @cfgarr, "LogLevel $loglevel"; 974push @cfgarr, 'NumberOfPasswordPrompts 0'; 975push @cfgarr, 'PasswordAuthentication no'; 976push @cfgarr, 'PreferredAuthentications publickey'; 977push @cfgarr, 'PubkeyAuthentication yes'; 978 979# RSA authentication options are not supported by OpenSSH for Windows 980if (!($sshdid =~ /OpenSSH-Windows/)) { 981 push @cfgarr, 'RhostsRSAAuthentication no'; 982 push @cfgarr, 'RSAAuthentication no'; 983} 984 985# Disabled StrictHostKeyChecking since it makes the tests fail on my 986# OpenSSH_6.0p1 on Debian Linux / Daniel 987push @cfgarr, 'StrictHostKeyChecking no'; 988push @cfgarr, 'UsePrivilegedPort no'; 989push @cfgarr, '#'; 990 991 992#*************************************************************************** 993# Options supported in ssh client newer than OpenSSH 2.9.9 994# 995 996if(($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) { 997 push @cfgarr, 'AddressFamily any'; 998} 999 1000if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) || 1001 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 1002 push @cfgarr, 'ConnectTimeout 30'; 1003} 1004 1005if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) { 1006 push @cfgarr, 'ControlMaster no'; 1007} 1008 1009if(($sshid =~ /OpenSSH/) && ($sshvernum >= 420)) { 1010 push @cfgarr, 'ControlPath none'; 1011} 1012 1013if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) { 1014 push @cfgarr, 'DisableBanner yes'; 1015} 1016 1017if(($sshid =~ /OpenSSH/) && ($sshvernum >= 360)) { 1018 push @cfgarr, 'EnableSSHKeysign no'; 1019} 1020 1021if(($sshid =~ /OpenSSH/) && ($sshvernum >= 440)) { 1022 push @cfgarr, 'ExitOnForwardFailure yes'; 1023} 1024 1025if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) || 1026 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 1027 push @cfgarr, 'ForwardX11Trusted no'; 1028} 1029 1030if(($sshd_builtwith_GSSAPI) && ($sshdid eq $sshid) && 1031 ($sshdvernum == $sshvernum)) { 1032 push @cfgarr, 'GSSAPIAuthentication no'; 1033 push @cfgarr, 'GSSAPIDelegateCredentials no'; 1034 if($sshid =~ /SunSSH/) { 1035 push @cfgarr, 'GSSAPIKeyExchange no'; 1036 } 1037} 1038 1039if((($sshid =~ /OpenSSH/) && ($sshvernum >= 400)) || 1040 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 1041 push @cfgarr, 'HashKnownHosts no'; 1042} 1043 1044if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) { 1045 push @cfgarr, 'IdentitiesOnly yes'; 1046} 1047 1048if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) { 1049 push @cfgarr, 'IgnoreIfUnknown no'; 1050} 1051 1052if((($sshid =~ /OpenSSH/) && ($sshvernum < 380)) || 1053 ($sshid =~ /SunSSH/)) { 1054 push @cfgarr, 'KeepAlive no'; 1055} 1056 1057if((($sshid =~ /OpenSSH/) && ($sshvernum >= 300)) || 1058 ($sshid =~ /SunSSH/)) { 1059 push @cfgarr, 'NoHostAuthenticationForLocalhost no'; 1060} 1061 1062if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) { 1063 push @cfgarr, 'PermitLocalCommand no'; 1064} 1065 1066if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) || 1067 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 1068 push @cfgarr, 'RekeyLimit 1G'; 1069} 1070 1071if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) || 1072 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 1073 push @cfgarr, 'ServerAliveCountMax 3'; 1074 push @cfgarr, 'ServerAliveInterval 0'; 1075} 1076 1077if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) { 1078 push @cfgarr, 'TCPKeepAlive no'; 1079} 1080 1081if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) { 1082 push @cfgarr, 'Tunnel no'; 1083} 1084 1085if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) { 1086 push @cfgarr, 'VerifyHostKeyDNS no'; 1087} 1088 1089push @cfgarr, '#'; 1090 1091 1092#*************************************************************************** 1093# Write out resulting ssh client configuration file for curl's tests 1094# 1095$error = dump_array(pp($sshconfig), @cfgarr); 1096if($error) { 1097 logmsg "$error\n"; 1098 exit 1; 1099} 1100 1101 1102#*************************************************************************** 1103# Initialize client sftp config with options actually supported. 1104# 1105logmsg "generating sftp client config file...\n" if($verbose); 1106splice @cfgarr, 1, 1, "# $sshverstr sftp client configuration file for curl testing"; 1107# 1108for(my $i = scalar(@cfgarr) - 1; $i > 0; $i--) { 1109 if($cfgarr[$i] =~ /^DynamicForward/) { 1110 splice @cfgarr, $i, 1; 1111 next; 1112 } 1113 if($cfgarr[$i] =~ /^ClearAllForwardings/) { 1114 splice @cfgarr, $i, 1, "ClearAllForwardings yes"; 1115 next; 1116 } 1117} 1118 1119 1120#*************************************************************************** 1121# Write out resulting sftp client configuration file for curl's tests 1122# 1123$error = dump_array(pp($sftpconfig), @cfgarr); 1124if($error) { 1125 logmsg "$error\n"; 1126 exit 1; 1127} 1128@cfgarr = (); 1129 1130 1131#*************************************************************************** 1132# Generate client sftp commands batch file for sftp server verification 1133# 1134logmsg "generating sftp client commands file...\n" if($verbose); 1135push @cfgarr, 'pwd'; 1136push @cfgarr, 'quit'; 1137$error = dump_array(pp($sftpcmds), @cfgarr); 1138if($error) { 1139 logmsg "$error\n"; 1140 exit 1; 1141} 1142@cfgarr = (); 1143 1144#*************************************************************************** 1145# Prepare command line of ssh server daemon 1146# 1147my $cmd = "\"$sshd\" -e -D -f $sshdconfig_abs > $sshdlog 2>&1"; 1148logmsg "SCP/SFTP server listening on port $port\n" if($verbose); 1149logmsg "RUN: $cmd\n" if($verbose); 1150 1151#*************************************************************************** 1152# Start the ssh server daemon on Windows without forking it 1153# 1154if ($sshdid =~ /OpenSSH-Windows/) { 1155 # Fake pidfile for ssh server on Windows. 1156 if(open(my $out, ">", "$pidfile")) { 1157 print $out $$ . "\n"; 1158 close($out); 1159 } 1160 1161 # Flush output. 1162 $| = 1; 1163 1164 # Put an "exec" in front of the command so that the child process 1165 # keeps this child's process ID by being tied to the spawned shell. 1166 exec("exec $cmd") || die "Can't exec() $cmd: $!"; 1167 # exec() will create a new process, but ties the existence of the 1168 # new process to the parent waiting perl.exe and sh.exe processes. 1169 1170 # exec() should never return back here to this process. We protect 1171 # ourselves by calling die() just in case something goes really bad. 1172 die "error: exec() has returned"; 1173} 1174 1175#*************************************************************************** 1176# Start the ssh server daemon without forking it 1177# 1178# "exec" avoids the shell process sticking around 1179my $rc = system("exec " . $cmd); 1180if($rc == -1) { 1181 logmsg "\"$sshd\" failed with: $!\n"; 1182} 1183elsif($rc & 127) { 1184 logmsg sprintf("\"$sshd\" died with signal %d, and %s coredump\n", 1185 ($rc & 127), ($rc & 128)?'a':'no'); 1186} 1187elsif($verbose && ($rc >> 8)) { 1188 logmsg sprintf("\"$sshd\" exited with %d\n", $rc >> 8); 1189} 1190 1191 1192#*************************************************************************** 1193# Clean up once the server has stopped 1194# 1195unlink(pp($hstprvkeyf), pp($hstpubkeyf), pp($hstpubmd5f), pp($hstpubsha256f), 1196 pp($cliprvkeyf), pp($clipubkeyf), pp($knownhosts), 1197 pp($sshdconfig), pp($sshconfig), pp($sftpconfig)); 1198 1199exit 0; 1200