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