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