3 # Starts sshd for use in the SCP, SFTP and SOCKS curl test harness tests.
4 # Also creates the ssh configuration files (this could be moved to a
15 my $verbose=0; # set to 1 for debugging
17 my $port = 8999; # just our default, weird enough
23 if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys' || $^O eq 'dos' || $^O eq 'os2') {
27 # Where to look for sftp-server
28 my @sftppath=qw(/usr/lib/openssh /usr/libexec/openssh /usr/libexec /usr/local/libexec /opt/local/libexec /usr/lib/ssh /usr/libexec/ssh /usr/sbin /usr/lib /usr/lib/ssh/openssh /usr/lib64/ssh /usr/lib64/misc /usr/lib/misc);
30 my $username = $ENV{USER};
32 # Find a file somewhere in the given path
34 my $fn = $_[0] . $exeext;
38 my $file = File::Spec->catfile($_, $fn);
47 if($ARGV[0] eq "-v") {
50 elsif($ARGV[0] eq "-u") {
54 elsif($ARGV[0] =~ /^(\d+)$/) {
59 my $conffile="curl_sshd_config"; # sshd configuration data
60 my $conffile_ssh="curl_ssh_config"; # ssh configuration data
61 my $knownhostsfile="curl_client_knownhosts"; # ssh knownhosts file
63 # Searching for sshd and sftp-server will be done first
64 # in the PATH and afterwards in other common locations.
66 push(@spath, File::Spec->path());
67 push(@spath, @sftppath);
69 # sshd insists on being called with an absolute path.
70 my $sshd = searchpath("sshd", @spath);
72 print "sshd$exeext not found\n";
76 print STDERR "SSH server found at $sshd\n";
79 my $sftp = searchpath("sftp-server", @spath);
81 print "Could not find sftp-server$exeext plugin\n";
85 print STDERR "SFTP server plugin found at $sftp\n";
88 if ($username eq "root") {
89 print "Will not run ssh daemon as root to mitigate security risks\n";
93 # Find out sshd version.
99 chomp($tmpstr = qx($sshd -V 2>&1 | grep OpenSSH));
100 if ($tmpstr =~ /OpenSSH[_-](\d+)\.(\d+)(\.(\d+))*/) {
101 ($ssh_ver_major, $ssh_ver_minor, $ssh_ver_patch) = ($1, $2, $4);
102 $ssh_daemon = 'OpenSSH';
105 print STDERR "ssh_daemon: $ssh_daemon\n";
106 print STDERR "ssh_ver_major: $ssh_ver_major\n";
107 print STDERR "ssh_ver_minor: $ssh_ver_minor\n";
108 print STDERR "ssh_ver_patch: $ssh_ver_patch\n";
111 # Verify minimum OpenSSH version.
112 if (($ssh_daemon !~ /OpenSSH/) || (10 * $ssh_ver_major + $ssh_ver_minor < 37)) {
113 print "SCP, SFTP and SOCKS tests require OpenSSH 3.7 or later\n";
117 # Initialize sshd configuration file for curl's tests.
118 open(CONF, ">$conffile") || die "Could not write $conffile";
119 print CONF "# This is a generated file! Do not edit!\n";
120 print CONF "# OpenSSH sshd configuration file for curl testing\n";
123 # Support for some options might have not been built into sshd. On some
124 # platforms specifying an unsupported option prevents sshd from starting.
125 # Check here for possible unsupported options, avoiding its use in sshd.
126 sub sshd_supports_opt($) {
128 my $err = grep /Unsupported .* $option/, qx($sshd -t -f $conffile -o $option=no 2>&1);
132 my $supports_UsePAM = sshd_supports_opt('UsePAM');
133 my $supports_UseDNS = sshd_supports_opt('UseDNS');
134 my $supports_ChReAu = sshd_supports_opt('ChallengeResponseAuthentication');
136 print STDERR "sshd supports UsePAM: ";
137 print STDERR $supports_UsePAM ? "yes\n" : "no\n";
138 print STDERR "sshd supports UseDNS: ";
139 print STDERR $supports_UseDNS ? "yes\n" : "no\n";
140 print STDERR "sshd supports ChallengeResponseAuthentication: ";
141 print STDERR $supports_ChReAu ? "yes\n" : "no\n";
144 if (! -e "curl_client_key.pub") {
146 print STDERR "Generating host and client keys...\n";
148 # Make sure all files are gone so ssh-keygen doesn't complain
149 unlink("curl_host_dsa_key", "curl_client_key","curl_host_dsa_key.pub", "curl_client_key.pub");
150 system "ssh-keygen -q -t dsa -b 512 -f curl_host_dsa_key -C 'curl test server' -N ''" and die "Could not generate host key";
151 system "ssh-keygen -q -t dsa -b 512 -f curl_client_key -C 'curl test client' -N ''" and die "Could not generate client key";
154 open(FILE, ">>$conffile") || die "Could not write $conffile";
159 AuthorizedKeysFile $path/curl_client_key.pub
160 HostKey $path/curl_host_dsa_key
161 PidFile $path/.ssh.pid
163 ListenAddress localhost
165 AllowTcpForwarding yes
167 HostbasedAuthentication no
169 IgnoreUserKnownHosts yes
171 PasswordAuthentication no
172 PermitEmptyPasswords no
173 PermitUserEnvironment no
182 UsePrivilegeSeparation no
183 # Newer OpenSSH options
186 close FILE || die "Could not close $conffile";
188 sub set_sshd_option {
190 if (open(FILE, ">>$conffile")) {
191 print FILE "$string\n";
196 if ($supports_UsePAM) {
197 set_sshd_option('UsePAM no');
199 if ($supports_UseDNS) {
200 set_sshd_option('UseDNS no');
202 if ($supports_ChReAu) {
203 set_sshd_option('ChallengeResponseAuthentication no');
207 # Now, set up some configuration files for the ssh client
208 open(DSAKEYFILE, "<curl_host_dsa_key.pub") || die 'Could not read curl_host_dsa_key.pub';
209 my @dsahostkey = do { local $/ = ' '; <DSAKEYFILE> };
210 close DSAKEYFILE || die "Could not close DSAKEYFILE";
212 open(KNOWNHOSTS, ">$knownhostsfile") || die "Could not write $knownhostsfile";
213 print KNOWNHOSTS "[127.0.0.1]:$port ssh-dss $dsahostkey[1]\n" || die 'Could not write to KNOWNHOSTS';
214 close KNOWNHOSTS || die "Could not close KNOWNHOSTS";
216 open(SSHFILE, ">$conffile_ssh") || die "Could not write $conffile_ssh";
217 print SSHFILE <<EOFSSH
218 IdentityFile $path/curl_client_key
219 UserKnownHostsFile $path/$knownhostsfile
220 StrictHostKeyChecking no
227 HostbasedAuthentication yes
228 NoHostAuthenticationForLocalhost no
229 # Newer OpenSSH options
233 close SSHFILE || die "Could not close $conffile_ssh";
236 if (system "$sshd -t -q -f $conffile") {
237 # This is likely due to missing support for UsePam
238 print "$sshd is too old and is not supported\n";
244 my $rc = system "$sshd -e -D -f $conffile > log/sshd.log 2>&1";
246 if($rc && $verbose) {
247 print STDERR "$sshd exited with $rc!\n";