1#!/usr/bin/env perl 2#*************************************************************************** 3# _ _ ____ _ 4# Project ___| | | | _ \| | 5# / __| | | | |_) | | 6# | (__| |_| | _ <| |___ 7# \___|\___/|_| \_\_____| 8# 9# Copyright (C) 1998 - 2010, 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) || (! -e $hstpubkeyf) || 366 (! -e $cliprvkeyf) || (! -e $clipubkeyf)) { 367 # Make sure all files are gone so ssh-keygen doesn't complain 368 unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf); 369 logmsg 'generating host keys...' if($verbose); 370 if(system "$sshkeygen -q -t dsa -f $hstprvkeyf -C 'curl test server' -N ''") { 371 logmsg 'Could not generate host key'; 372 exit 1; 373 } 374 logmsg 'generating client keys...' if($verbose); 375 if(system "$sshkeygen -q -t dsa -f $cliprvkeyf -C 'curl test client' -N ''") { 376 logmsg 'Could not generate client key'; 377 exit 1; 378 } 379} 380 381 382#*************************************************************************** 383# ssh daemon configuration file options we might use and version support 384# 385# AFSTokenPassing : OpenSSH 1.2.1 and later [1] 386# AcceptEnv : OpenSSH 3.9.0 and later 387# AddressFamily : OpenSSH 4.0.0 and later 388# AllowGroups : OpenSSH 1.2.1 and later 389# AllowTcpForwarding : OpenSSH 2.3.0 and later 390# AllowUsers : OpenSSH 1.2.1 and later 391# AuthorizedKeysFile : OpenSSH 2.9.9 and later 392# AuthorizedKeysFile2 : OpenSSH 2.9.9 and later 393# Banner : OpenSSH 2.5.0 and later 394# ChallengeResponseAuthentication : OpenSSH 2.5.0 and later 395# Ciphers : OpenSSH 2.1.0 and later [3] 396# ClientAliveCountMax : OpenSSH 2.9.0 and later 397# ClientAliveInterval : OpenSSH 2.9.0 and later 398# Compression : OpenSSH 3.3.0 and later 399# DenyGroups : OpenSSH 1.2.1 and later 400# DenyUsers : OpenSSH 1.2.1 and later 401# ForceCommand : OpenSSH 4.4.0 and later [3] 402# GatewayPorts : OpenSSH 2.1.0 and later 403# GSSAPIAuthentication : OpenSSH 3.7.0 and later [1] 404# GSSAPICleanupCredentials : OpenSSH 3.8.0 and later [1] 405# GSSAPIKeyExchange : SunSSH 1.0.0 and later [1] 406# GSSAPIStoreDelegatedCredentials : SunSSH 1.0.0 and later [1] 407# GSSCleanupCreds : SunSSH 1.0.0 and later [1] 408# GSSUseSessionCredCache : SunSSH 1.0.0 and later [1] 409# HostbasedAuthentication : OpenSSH 2.9.0 and later 410# HostbasedUsesNameFromPacketOnly : OpenSSH 2.9.0 and later 411# HostKey : OpenSSH 1.2.1 and later 412# IgnoreRhosts : OpenSSH 1.2.1 and later 413# IgnoreUserKnownHosts : OpenSSH 1.2.1 and later 414# KbdInteractiveAuthentication : OpenSSH 2.3.0 and later 415# KeepAlive : OpenSSH 1.2.1 and later 416# KerberosAuthentication : OpenSSH 1.2.1 and later [1] 417# KerberosGetAFSToken : OpenSSH 3.8.0 and later [1] 418# KerberosOrLocalPasswd : OpenSSH 1.2.1 and later [1] 419# KerberosTgtPassing : OpenSSH 1.2.1 and later [1] 420# KerberosTicketCleanup : OpenSSH 1.2.1 and later [1] 421# KeyRegenerationInterval : OpenSSH 1.2.1 and later 422# ListenAddress : OpenSSH 1.2.1 and later 423# LoginGraceTime : OpenSSH 1.2.1 and later 424# LogLevel : OpenSSH 1.2.1 and later 425# LookupClientHostnames : SunSSH 1.0.0 and later 426# MACs : OpenSSH 2.5.0 and later [3] 427# Match : OpenSSH 4.4.0 and later [3] 428# MaxAuthTries : OpenSSH 3.9.0 and later 429# MaxStartups : OpenSSH 2.2.0 and later 430# PAMAuthenticationViaKbdInt : OpenSSH 2.9.0 and later [2] 431# PasswordAuthentication : OpenSSH 1.2.1 and later 432# PermitEmptyPasswords : OpenSSH 1.2.1 and later 433# PermitOpen : OpenSSH 4.4.0 and later [3] 434# PermitRootLogin : OpenSSH 1.2.1 and later 435# PermitTunnel : OpenSSH 4.3.0 and later 436# PermitUserEnvironment : OpenSSH 3.5.0 and later 437# PidFile : OpenSSH 2.1.0 and later 438# Port : OpenSSH 1.2.1 and later 439# PrintLastLog : OpenSSH 2.9.0 and later 440# PrintMotd : OpenSSH 1.2.1 and later 441# Protocol : OpenSSH 2.1.0 and later 442# PubkeyAuthentication : OpenSSH 2.5.0 and later 443# RhostsAuthentication : OpenSSH 1.2.1 and later 444# RhostsRSAAuthentication : OpenSSH 1.2.1 and later 445# RSAAuthentication : OpenSSH 1.2.1 and later 446# ServerKeyBits : OpenSSH 1.2.1 and later 447# SkeyAuthentication : OpenSSH 1.2.1 and later [1] 448# StrictModes : OpenSSH 1.2.1 and later 449# Subsystem : OpenSSH 2.2.0 and later 450# SyslogFacility : OpenSSH 1.2.1 and later 451# TCPKeepAlive : OpenSSH 3.8.0 and later 452# UseDNS : OpenSSH 3.7.0 and later 453# UseLogin : OpenSSH 1.2.1 and later 454# UsePAM : OpenSSH 3.7.0 and later [1][2] 455# UsePrivilegeSeparation : OpenSSH 3.2.2 and later 456# VerifyReverseMapping : OpenSSH 3.1.0 and later 457# X11DisplayOffset : OpenSSH 1.2.1 and later [3] 458# X11Forwarding : OpenSSH 1.2.1 and later 459# X11UseLocalhost : OpenSSH 3.1.0 and later 460# XAuthLocation : OpenSSH 2.1.1 and later [3] 461# 462# [1] Option only available if activated at compile time 463# [2] Option specific for portable versions 464# [3] Option not used in our ssh server config file 465 466 467#*************************************************************************** 468# Initialize sshd config with options actually supported in OpenSSH 2.9.9 469# 470logmsg 'generating ssh server config file...' if($verbose); 471@cfgarr = (); 472push @cfgarr, '# This is a generated file. Do not edit.'; 473push @cfgarr, "# $sshdverstr sshd configuration file for curl testing"; 474push @cfgarr, '#'; 475push @cfgarr, "DenyUsers !$username"; 476push @cfgarr, "AllowUsers $username"; 477push @cfgarr, 'DenyGroups'; 478push @cfgarr, 'AllowGroups'; 479push @cfgarr, '#'; 480push @cfgarr, "AuthorizedKeysFile $path/$clipubkeyf"; 481push @cfgarr, "AuthorizedKeysFile2 $path/$clipubkeyf"; 482push @cfgarr, "HostKey $path/$hstprvkeyf"; 483push @cfgarr, "PidFile $pidfile"; 484push @cfgarr, '#'; 485push @cfgarr, "Port $port"; 486push @cfgarr, "ListenAddress $listenaddr"; 487push @cfgarr, 'Protocol 2'; 488push @cfgarr, '#'; 489push @cfgarr, 'AllowTcpForwarding yes'; 490push @cfgarr, 'Banner none'; 491push @cfgarr, 'ChallengeResponseAuthentication no'; 492push @cfgarr, 'ClientAliveCountMax 3'; 493push @cfgarr, 'ClientAliveInterval 0'; 494push @cfgarr, 'GatewayPorts no'; 495push @cfgarr, 'HostbasedAuthentication no'; 496push @cfgarr, 'HostbasedUsesNameFromPacketOnly no'; 497push @cfgarr, 'IgnoreRhosts yes'; 498push @cfgarr, 'IgnoreUserKnownHosts yes'; 499push @cfgarr, 'KeyRegenerationInterval 0'; 500push @cfgarr, 'LoginGraceTime 30'; 501push @cfgarr, "LogLevel $loglevel"; 502push @cfgarr, 'MaxStartups 5'; 503push @cfgarr, 'PasswordAuthentication no'; 504push @cfgarr, 'PermitEmptyPasswords no'; 505push @cfgarr, 'PermitRootLogin no'; 506push @cfgarr, 'PrintLastLog no'; 507push @cfgarr, 'PrintMotd no'; 508push @cfgarr, 'PubkeyAuthentication yes'; 509push @cfgarr, 'RhostsRSAAuthentication no'; 510push @cfgarr, 'RSAAuthentication no'; 511push @cfgarr, 'ServerKeyBits 768'; 512push @cfgarr, 'StrictModes no'; 513push @cfgarr, "Subsystem sftp $sftpsrv"; 514push @cfgarr, 'SyslogFacility AUTH'; 515push @cfgarr, 'UseLogin no'; 516push @cfgarr, 'X11Forwarding no'; 517push @cfgarr, '#'; 518 519 520#*************************************************************************** 521# Write out initial sshd configuration file for curl's tests 522# 523$error = dump_array($sshdconfig, @cfgarr); 524if($error) { 525 logmsg $error; 526 exit 1; 527} 528 529 530#*************************************************************************** 531# Verifies at run time if sshd supports a given configuration file option 532# 533sub sshd_supports_opt { 534 my ($option, $value) = @_; 535 my $err; 536 # 537 if((($sshdid =~ /OpenSSH/) && ($sshdvernum >= 310)) || 538 ($sshdid =~ /SunSSH/)) { 539 # ssh daemon supports command line options -t -f and -o 540 $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/, 541 qx($sshd -t -f $sshdconfig -o $option=$value 2>&1); 542 return !$err; 543 } 544 if(($sshdid =~ /OpenSSH/) && ($sshdvernum >= 299)) { 545 # ssh daemon supports command line options -t and -f 546 $err = dump_array($sshdconfig, (@cfgarr, "$option $value")); 547 if($err) { 548 logmsg $err; 549 return 0; 550 } 551 $err = grep /((Unsupported)|(Bad configuration)|(Deprecated)) option.*$option/, 552 qx($sshd -t -f $sshdconfig 2>&1); 553 unlink $sshdconfig; 554 return !$err; 555 } 556 return 0; 557} 558 559 560#*************************************************************************** 561# Kerberos Authentication support may have not been built into sshd 562# 563if(sshd_supports_opt('KerberosAuthentication','no')) { 564 push @cfgarr, 'KerberosAuthentication no'; 565} 566if(sshd_supports_opt('KerberosGetAFSToken','no')) { 567 push @cfgarr, 'KerberosGetAFSToken no'; 568} 569if(sshd_supports_opt('KerberosOrLocalPasswd','no')) { 570 push @cfgarr, 'KerberosOrLocalPasswd no'; 571} 572if(sshd_supports_opt('KerberosTgtPassing','no')) { 573 push @cfgarr, 'KerberosTgtPassing no'; 574} 575if(sshd_supports_opt('KerberosTicketCleanup','yes')) { 576 push @cfgarr, 'KerberosTicketCleanup yes'; 577} 578 579 580#*************************************************************************** 581# Andrew File System support may have not been built into sshd 582# 583if(sshd_supports_opt('AFSTokenPassing','no')) { 584 push @cfgarr, 'AFSTokenPassing no'; 585} 586 587 588#*************************************************************************** 589# S/Key authentication support may have not been built into sshd 590# 591if(sshd_supports_opt('SkeyAuthentication','no')) { 592 push @cfgarr, 'SkeyAuthentication no'; 593} 594 595 596#*************************************************************************** 597# GSSAPI Authentication support may have not been built into sshd 598# 599my $sshd_builtwith_GSSAPI; 600if(sshd_supports_opt('GSSAPIAuthentication','no')) { 601 push @cfgarr, 'GSSAPIAuthentication no'; 602 $sshd_builtwith_GSSAPI = 1; 603} 604if(sshd_supports_opt('GSSAPICleanupCredentials','yes')) { 605 push @cfgarr, 'GSSAPICleanupCredentials yes'; 606} 607if(sshd_supports_opt('GSSAPIKeyExchange','no')) { 608 push @cfgarr, 'GSSAPIKeyExchange no'; 609} 610if(sshd_supports_opt('GSSAPIStoreDelegatedCredentials','no')) { 611 push @cfgarr, 'GSSAPIStoreDelegatedCredentials no'; 612} 613if(sshd_supports_opt('GSSCleanupCreds','yes')) { 614 push @cfgarr, 'GSSCleanupCreds yes'; 615} 616if(sshd_supports_opt('GSSUseSessionCredCache','no')) { 617 push @cfgarr, 'GSSUseSessionCredCache no'; 618} 619push @cfgarr, '#'; 620 621 622#*************************************************************************** 623# Options that might be supported or not in sshd OpenSSH 2.9.9 and later 624# 625if(sshd_supports_opt('AcceptEnv','')) { 626 push @cfgarr, 'AcceptEnv'; 627} 628if(sshd_supports_opt('AddressFamily','any')) { 629 # Address family must be specified before ListenAddress 630 splice @cfgarr, 14, 0, 'AddressFamily any'; 631} 632if(sshd_supports_opt('Compression','no')) { 633 push @cfgarr, 'Compression no'; 634} 635if(sshd_supports_opt('KbdInteractiveAuthentication','no')) { 636 push @cfgarr, 'KbdInteractiveAuthentication no'; 637} 638if(sshd_supports_opt('KeepAlive','no')) { 639 push @cfgarr, 'KeepAlive no'; 640} 641if(sshd_supports_opt('LookupClientHostnames','no')) { 642 push @cfgarr, 'LookupClientHostnames no'; 643} 644if(sshd_supports_opt('MaxAuthTries','10')) { 645 push @cfgarr, 'MaxAuthTries 10'; 646} 647if(sshd_supports_opt('PAMAuthenticationViaKbdInt','no')) { 648 push @cfgarr, 'PAMAuthenticationViaKbdInt no'; 649} 650if(sshd_supports_opt('PermitTunnel','no')) { 651 push @cfgarr, 'PermitTunnel no'; 652} 653if(sshd_supports_opt('PermitUserEnvironment','no')) { 654 push @cfgarr, 'PermitUserEnvironment no'; 655} 656if(sshd_supports_opt('RhostsAuthentication','no')) { 657 push @cfgarr, 'RhostsAuthentication no'; 658} 659if(sshd_supports_opt('TCPKeepAlive','no')) { 660 push @cfgarr, 'TCPKeepAlive no'; 661} 662if(sshd_supports_opt('UseDNS','no')) { 663 push @cfgarr, 'UseDNS no'; 664} 665if(sshd_supports_opt('UsePAM','no')) { 666 push @cfgarr, 'UsePAM no'; 667} 668 669if($sshdid =~ /OpenSSH/) { 670 # http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6492415 671 if(sshd_supports_opt('UsePrivilegeSeparation','no')) { 672 push @cfgarr, 'UsePrivilegeSeparation no'; 673 } 674} 675 676if(sshd_supports_opt('VerifyReverseMapping','no')) { 677 push @cfgarr, 'VerifyReverseMapping no'; 678} 679if(sshd_supports_opt('X11UseLocalhost','yes')) { 680 push @cfgarr, 'X11UseLocalhost yes'; 681} 682push @cfgarr, '#'; 683 684 685#*************************************************************************** 686# Write out resulting sshd configuration file for curl's tests 687# 688$error = dump_array($sshdconfig, @cfgarr); 689if($error) { 690 logmsg $error; 691 exit 1; 692} 693 694 695#*************************************************************************** 696# Verify that sshd actually supports our generated configuration file 697# 698if(system "$sshd -t -f $sshdconfig > $sshdlog 2>&1") { 699 logmsg "sshd configuration file $sshdconfig failed verification"; 700 display_sshdlog(); 701 display_sshdconfig(); 702 exit 1; 703} 704 705 706#*************************************************************************** 707# Generate ssh client host key database file for curl's tests 708# 709if(! -e $knownhosts) { 710 logmsg 'generating ssh client known hosts file...' if($verbose); 711 if(open(DSAKEYFILE, "<$hstpubkeyf")) { 712 my @dsahostkey = do { local $/ = ' '; <DSAKEYFILE> }; 713 if(close(DSAKEYFILE)) { 714 if(open(KNOWNHOSTS, ">$knownhosts")) { 715 print KNOWNHOSTS "$listenaddr ssh-dss $dsahostkey[1]\n"; 716 if(!close(KNOWNHOSTS)) { 717 $error = "Error: cannot close file $knownhosts"; 718 } 719 } 720 else { 721 $error = "Error: cannot write file $knownhosts"; 722 } 723 } 724 else { 725 $error = "Error: cannot close file $hstpubkeyf"; 726 } 727 } 728 else { 729 $error = "Error: cannot read file $hstpubkeyf"; 730 } 731 if($error) { 732 logmsg $error; 733 exit 1; 734 } 735} 736 737 738#*************************************************************************** 739# ssh client configuration file options we might use and version support 740# 741# AddressFamily : OpenSSH 3.7.0 and later 742# BatchMode : OpenSSH 1.2.1 and later 743# BindAddress : OpenSSH 2.9.9 and later 744# ChallengeResponseAuthentication : OpenSSH 2.5.0 and later 745# CheckHostIP : OpenSSH 1.2.1 and later 746# Cipher : OpenSSH 1.2.1 and later [3] 747# Ciphers : OpenSSH 2.1.0 and later [3] 748# ClearAllForwardings : OpenSSH 2.9.9 and later 749# Compression : OpenSSH 1.2.1 and later 750# CompressionLevel : OpenSSH 1.2.1 and later [3] 751# ConnectionAttempts : OpenSSH 1.2.1 and later 752# ConnectTimeout : OpenSSH 3.7.0 and later 753# ControlMaster : OpenSSH 3.9.0 and later 754# ControlPath : OpenSSH 3.9.0 and later 755# DisableBanner : SunSSH 1.2.0 and later 756# DynamicForward : OpenSSH 2.9.0 and later 757# EnableSSHKeysign : OpenSSH 3.6.0 and later 758# EscapeChar : OpenSSH 1.2.1 and later [3] 759# ExitOnForwardFailure : OpenSSH 4.4.0 and later 760# ForwardAgent : OpenSSH 1.2.1 and later 761# ForwardX11 : OpenSSH 1.2.1 and later 762# ForwardX11Trusted : OpenSSH 3.8.0 and later 763# GatewayPorts : OpenSSH 1.2.1 and later 764# GlobalKnownHostsFile : OpenSSH 1.2.1 and later 765# GSSAPIAuthentication : OpenSSH 3.7.0 and later [1] 766# GSSAPIDelegateCredentials : OpenSSH 3.7.0 and later [1] 767# HashKnownHosts : OpenSSH 4.0.0 and later 768# Host : OpenSSH 1.2.1 and later 769# HostbasedAuthentication : OpenSSH 2.9.0 and later 770# HostKeyAlgorithms : OpenSSH 2.9.0 and later [3] 771# HostKeyAlias : OpenSSH 2.5.0 and later [3] 772# HostName : OpenSSH 1.2.1 and later 773# IdentitiesOnly : OpenSSH 3.9.0 and later 774# IdentityFile : OpenSSH 1.2.1 and later 775# IgnoreIfUnknown : SunSSH 1.2.0 and later 776# KeepAlive : OpenSSH 1.2.1 and later 777# KbdInteractiveAuthentication : OpenSSH 2.3.0 and later 778# KbdInteractiveDevices : OpenSSH 2.3.0 and later [3] 779# LocalCommand : OpenSSH 4.3.0 and later [3] 780# LocalForward : OpenSSH 1.2.1 and later [3] 781# LogLevel : OpenSSH 1.2.1 and later 782# MACs : OpenSSH 2.5.0 and later [3] 783# NoHostAuthenticationForLocalhost : OpenSSH 3.0.0 and later 784# NumberOfPasswordPrompts : OpenSSH 1.2.1 and later 785# PasswordAuthentication : OpenSSH 1.2.1 and later 786# PermitLocalCommand : OpenSSH 4.3.0 and later 787# Port : OpenSSH 1.2.1 and later 788# PreferredAuthentications : OpenSSH 2.5.2 and later 789# Protocol : OpenSSH 2.1.0 and later 790# ProxyCommand : OpenSSH 1.2.1 and later [3] 791# PubkeyAuthentication : OpenSSH 2.5.0 and later 792# RekeyLimit : OpenSSH 3.7.0 and later 793# RemoteForward : OpenSSH 1.2.1 and later [3] 794# RhostsRSAAuthentication : OpenSSH 1.2.1 and later 795# RSAAuthentication : OpenSSH 1.2.1 and later 796# SendEnv : OpenSSH 3.9.0 and later 797# ServerAliveCountMax : OpenSSH 3.8.0 and later 798# ServerAliveInterval : OpenSSH 3.8.0 and later 799# SmartcardDevice : OpenSSH 2.9.9 and later [1][3] 800# StrictHostKeyChecking : OpenSSH 1.2.1 and later 801# TCPKeepAlive : OpenSSH 3.8.0 and later 802# Tunnel : OpenSSH 4.3.0 and later 803# TunnelDevice : OpenSSH 4.3.0 and later [3] 804# UsePAM : OpenSSH 3.7.0 and later [1][2][3] 805# UsePrivilegedPort : OpenSSH 1.2.1 and later 806# User : OpenSSH 1.2.1 and later 807# UserKnownHostsFile : OpenSSH 1.2.1 and later 808# VerifyHostKeyDNS : OpenSSH 3.8.0 and later 809# XAuthLocation : OpenSSH 2.1.1 and later [3] 810# 811# [1] Option only available if activated at compile time 812# [2] Option specific for portable versions 813# [3] Option not used in our ssh client config file 814 815 816#*************************************************************************** 817# Initialize ssh config with options actually supported in OpenSSH 2.9.9 818# 819logmsg 'generating ssh client config file...' if($verbose); 820@cfgarr = (); 821push @cfgarr, '# This is a generated file. Do not edit.'; 822push @cfgarr, "# $sshverstr ssh client configuration file for curl testing"; 823push @cfgarr, '#'; 824push @cfgarr, 'Host *'; 825push @cfgarr, '#'; 826push @cfgarr, "Port $port"; 827push @cfgarr, "HostName $listenaddr"; 828push @cfgarr, "User $username"; 829push @cfgarr, 'Protocol 2'; 830push @cfgarr, '#'; 831push @cfgarr, "BindAddress $listenaddr"; 832push @cfgarr, "DynamicForward $socksport"; 833push @cfgarr, '#'; 834push @cfgarr, "IdentityFile $path/curl_client_key"; 835push @cfgarr, "UserKnownHostsFile $path/$knownhosts"; 836push @cfgarr, '#'; 837push @cfgarr, 'BatchMode yes'; 838push @cfgarr, 'ChallengeResponseAuthentication no'; 839push @cfgarr, 'CheckHostIP no'; 840push @cfgarr, 'ClearAllForwardings no'; 841push @cfgarr, 'Compression no'; 842push @cfgarr, 'ConnectionAttempts 3'; 843push @cfgarr, 'ForwardAgent no'; 844push @cfgarr, 'ForwardX11 no'; 845push @cfgarr, 'GatewayPorts no'; 846push @cfgarr, 'GlobalKnownHostsFile /dev/null'; 847push @cfgarr, 'HostbasedAuthentication no'; 848push @cfgarr, 'KbdInteractiveAuthentication no'; 849push @cfgarr, "LogLevel $loglevel"; 850push @cfgarr, 'NumberOfPasswordPrompts 0'; 851push @cfgarr, 'PasswordAuthentication no'; 852push @cfgarr, 'PreferredAuthentications publickey'; 853push @cfgarr, 'PubkeyAuthentication yes'; 854push @cfgarr, 'RhostsRSAAuthentication no'; 855push @cfgarr, 'RSAAuthentication no'; 856push @cfgarr, 'StrictHostKeyChecking yes'; 857push @cfgarr, 'UsePrivilegedPort no'; 858push @cfgarr, '#'; 859 860 861#*************************************************************************** 862# Options supported in ssh client newer than OpenSSH 2.9.9 863# 864 865if(($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) { 866 push @cfgarr, 'AddressFamily any'; 867} 868 869if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) || 870 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 871 push @cfgarr, 'ConnectTimeout 30'; 872} 873 874if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) { 875 push @cfgarr, 'ControlMaster no'; 876} 877 878if(($sshid =~ /OpenSSH/) && ($sshvernum >= 420)) { 879 push @cfgarr, 'ControlPath none'; 880} 881 882if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) { 883 push @cfgarr, 'DisableBanner yes'; 884} 885 886if(($sshid =~ /OpenSSH/) && ($sshvernum >= 360)) { 887 push @cfgarr, 'EnableSSHKeysign no'; 888} 889 890if(($sshid =~ /OpenSSH/) && ($sshvernum >= 440)) { 891 push @cfgarr, 'ExitOnForwardFailure yes'; 892} 893 894if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) || 895 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 896 push @cfgarr, 'ForwardX11Trusted no'; 897} 898 899if(($sshd_builtwith_GSSAPI) && ($sshdid eq $sshid) && 900 ($sshdvernum == $sshvernum)) { 901 push @cfgarr, 'GSSAPIAuthentication no'; 902 push @cfgarr, 'GSSAPIDelegateCredentials no'; 903 if($sshid =~ /SunSSH/) { 904 push @cfgarr, 'GSSAPIKeyExchange no'; 905 } 906} 907 908if((($sshid =~ /OpenSSH/) && ($sshvernum >= 400)) || 909 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 910 push @cfgarr, 'HashKnownHosts no'; 911} 912 913if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) { 914 push @cfgarr, 'IdentitiesOnly yes'; 915} 916 917if(($sshid =~ /SunSSH/) && ($sshvernum >= 120)) { 918 push @cfgarr, 'IgnoreIfUnknown no'; 919} 920 921if((($sshid =~ /OpenSSH/) && ($sshvernum < 380)) || 922 ($sshid =~ /SunSSH/)) { 923 push @cfgarr, 'KeepAlive no'; 924} 925 926if((($sshid =~ /OpenSSH/) && ($sshvernum >= 300)) || 927 ($sshid =~ /SunSSH/)) { 928 push @cfgarr, 'NoHostAuthenticationForLocalhost no'; 929} 930 931if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) { 932 push @cfgarr, 'PermitLocalCommand no'; 933} 934 935if((($sshid =~ /OpenSSH/) && ($sshvernum >= 370)) || 936 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 937 push @cfgarr, 'RekeyLimit 1G'; 938} 939 940if(($sshid =~ /OpenSSH/) && ($sshvernum >= 390)) { 941 push @cfgarr, 'SendEnv'; 942} 943 944if((($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) || 945 (($sshid =~ /SunSSH/) && ($sshvernum >= 120))) { 946 push @cfgarr, 'ServerAliveCountMax 3'; 947 push @cfgarr, 'ServerAliveInterval 0'; 948} 949 950if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) { 951 push @cfgarr, 'TCPKeepAlive no'; 952} 953 954if(($sshid =~ /OpenSSH/) && ($sshvernum >= 430)) { 955 push @cfgarr, 'Tunnel no'; 956} 957 958if(($sshid =~ /OpenSSH/) && ($sshvernum >= 380)) { 959 push @cfgarr, 'VerifyHostKeyDNS no'; 960} 961 962push @cfgarr, '#'; 963 964 965#*************************************************************************** 966# Write out resulting ssh client configuration file for curl's tests 967# 968$error = dump_array($sshconfig, @cfgarr); 969if($error) { 970 logmsg $error; 971 exit 1; 972} 973 974 975#*************************************************************************** 976# Initialize client sftp config with options actually supported. 977# 978logmsg 'generating sftp client config file...' if($verbose); 979splice @cfgarr, 1, 1, "# $sshverstr sftp client configuration file for curl testing"; 980# 981for(my $i = scalar(@cfgarr) - 1; $i > 0; $i--) { 982 if($cfgarr[$i] =~ /^DynamicForward/) { 983 splice @cfgarr, $i, 1; 984 next; 985 } 986 if($cfgarr[$i] =~ /^ClearAllForwardings/) { 987 splice @cfgarr, $i, 1, "ClearAllForwardings yes"; 988 next; 989 } 990} 991 992 993#*************************************************************************** 994# Write out resulting sftp client configuration file for curl's tests 995# 996$error = dump_array($sftpconfig, @cfgarr); 997if($error) { 998 logmsg $error; 999 exit 1; 1000} 1001@cfgarr = (); 1002 1003 1004#*************************************************************************** 1005# Generate client sftp commands batch file for sftp server verification 1006# 1007logmsg 'generating sftp client commands file...' if($verbose); 1008push @cfgarr, 'pwd'; 1009push @cfgarr, 'quit'; 1010$error = dump_array($sftpcmds, @cfgarr); 1011if($error) { 1012 logmsg $error; 1013 exit 1; 1014} 1015@cfgarr = (); 1016 1017 1018#*************************************************************************** 1019# Start the ssh server daemon without forking it 1020# 1021logmsg "SCP/SFTP server listening on port $port" if($verbose); 1022my $rc = system "$sshd -e -D -f $sshdconfig > $sshdlog 2>&1"; 1023if($rc == -1) { 1024 logmsg "$sshd failed with: $!"; 1025} 1026elsif($rc & 127) { 1027 logmsg sprintf("$sshd died with signal %d, and %s coredump", 1028 ($rc & 127), ($rc & 128)?'a':'no'); 1029} 1030elsif($verbose && ($rc >> 8)) { 1031 logmsg sprintf("$sshd exited with %d", $rc >> 8); 1032} 1033 1034 1035#*************************************************************************** 1036# Clean up once the server has stopped 1037# 1038unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf, $knownhosts); 1039unlink($sshdconfig, $sshconfig, $sftpconfig); 1040 1041 1042exit 0; 1043