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
18 my $listenaddr = "127.0.0.1"; # address on which to listen
24 if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys' || $^O eq 'dos' || $^O eq 'os2') {
28 # Where to look for sftp-server
49 my $username = $ENV{USER};
51 # Find a file somewhere in the given path
53 my $fn = $_[0] . $exeext;
57 my $file = File::Spec->catfile($_, $fn);
66 if($ARGV[0] eq "-v") {
69 elsif($ARGV[0] eq "-u") {
73 elsif($ARGV[0] eq "-l") {
77 elsif($ARGV[0] =~ /^(\d+)$/) {
82 my $conffile="curl_sshd_config"; # sshd configuration data
83 my $conffile_ssh="curl_ssh_config"; # ssh configuration data
84 my $knownhostsfile="curl_client_knownhosts"; # ssh knownhosts file
86 # Searching for sshd and sftp-server will be done first
87 # in the PATH and afterwards in other common locations.
89 push(@spath, File::Spec->path());
90 push(@spath, @sftppath);
92 # sshd insists on being called with an absolute path.
93 my $sshd = searchpath("sshd", @spath);
95 print "sshd$exeext not found\n";
99 print STDERR "SSH server found at $sshd\n";
102 my $sftp = searchpath("sftp-server", @spath);
104 print "Could not find sftp-server$exeext plugin\n";
108 print STDERR "SFTP server plugin found at $sftp\n";
111 if ($username eq "root") {
112 print "Will not run ssh daemon as root to mitigate security risks\n";
116 # Find out sshd version.
122 chomp($tmpstr = qx($sshd -V 2>&1 | grep OpenSSH));
123 if ($tmpstr =~ /OpenSSH[_-](\d+)\.(\d+)(\.(\d+))*/) {
124 ($ssh_ver_major, $ssh_ver_minor, $ssh_ver_patch) = ($1, $2, $4);
125 $ssh_daemon = 'OpenSSH';
128 chomp($tmpstr = qx($sshd -V 2>&1 | grep Sun_SSH));
129 if($tmpstr =~ /Sun[_-]SSH[_-](\d+)\.(\d+)/) {
130 ($ssh_ver_major, $ssh_ver_minor) = ($1, $2);
131 $ssh_daemon = 'SunSSH';
135 print STDERR "ssh_daemon: $ssh_daemon\n";
136 print STDERR "ssh_ver_major: $ssh_ver_major\n";
137 print STDERR "ssh_ver_minor: $ssh_ver_minor\n";
138 print STDERR "ssh_ver_patch: $ssh_ver_patch\n";
141 # Verify minimum SSH daemon version.
143 if(($ssh_daemon =~ /OpenSSH/) && (10 * $ssh_ver_major + $ssh_ver_minor < 36)) {
144 print "SSH server daemon found is OpenSSH $ssh_ver_major.$ssh_ver_minor\n";
147 if(($ssh_daemon =~ /SunSSH/) && (10 * $ssh_ver_major + $ssh_ver_minor < 11)) {
148 print "SSH server daemon found is SunSSH $ssh_ver_major.$ssh_ver_minor\n";
152 print "SSH server daemon found is not OpenSSH nor SunSSH\n";
153 chomp($tmpstr = qx($sshd -V 2>&1));
158 print "SCP, SFTP and SOCKS tests require OpenSSH 3.7 or later\n";
162 # Initialize sshd configuration file for curl's tests.
163 open(CONF, ">$conffile") || die "Could not write $conffile";
164 print CONF "# This is a generated file! Do not edit!\n";
165 print CONF "# OpenSSH sshd configuration file for curl testing\n";
168 # Support for some options might have not been built into sshd. On some
169 # platforms specifying an unsupported option prevents sshd from starting.
170 # Check here for possible unsupported options, avoiding its use in sshd.
171 sub sshd_supports_opt($) {
173 my $err = grep /Unsupported .* $option/, qx($sshd -t -f $conffile -o $option=no 2>&1);
177 my $supports_UsePAM = sshd_supports_opt('UsePAM');
178 my $supports_UseDNS = sshd_supports_opt('UseDNS');
179 my $supports_ChReAu = sshd_supports_opt('ChallengeResponseAuthentication');
181 print STDERR "sshd supports UsePAM: ";
182 print STDERR $supports_UsePAM ? "yes\n" : "no\n";
183 print STDERR "sshd supports UseDNS: ";
184 print STDERR $supports_UseDNS ? "yes\n" : "no\n";
185 print STDERR "sshd supports ChallengeResponseAuthentication: ";
186 print STDERR $supports_ChReAu ? "yes\n" : "no\n";
189 if (! -e "curl_client_key.pub") {
191 print STDERR "Generating host and client keys...\n";
193 # Make sure all files are gone so ssh-keygen doesn't complain
194 unlink("curl_host_dsa_key", "curl_client_key","curl_host_dsa_key.pub", "curl_client_key.pub");
195 system "ssh-keygen -q -t dsa -f curl_host_dsa_key -C 'curl test server' -N ''" and die "Could not generate host key";
196 system "ssh-keygen -q -t dsa -f curl_client_key -C 'curl test client' -N ''" and die "Could not generate client key";
199 open(FILE, ">>$conffile") || die "Could not write $conffile";
204 AuthorizedKeysFile $path/curl_client_key.pub
205 HostKey $path/curl_host_dsa_key
206 PidFile $path/.ssh.pid
208 ListenAddress $listenaddr
210 AllowTcpForwarding yes
212 HostbasedAuthentication no
214 IgnoreUserKnownHosts yes
216 PasswordAuthentication no
217 PermitEmptyPasswords no
218 PermitUserEnvironment no
227 UsePrivilegeSeparation no
228 # Newer OpenSSH options
231 close FILE || die "Could not close $conffile";
233 sub set_sshd_option {
235 if (open(FILE, ">>$conffile")) {
236 print FILE "$string\n";
241 if ($supports_UsePAM) {
242 set_sshd_option('UsePAM no');
244 if ($supports_UseDNS) {
245 set_sshd_option('UseDNS no');
247 if ($supports_ChReAu) {
248 set_sshd_option('ChallengeResponseAuthentication no');
252 # Now, set up some configuration files for the ssh client
253 open(DSAKEYFILE, "<curl_host_dsa_key.pub") || die 'Could not read curl_host_dsa_key.pub';
254 my @dsahostkey = do { local $/ = ' '; <DSAKEYFILE> };
255 close DSAKEYFILE || die "Could not close DSAKEYFILE";
257 open(KNOWNHOSTS, ">$knownhostsfile") || die "Could not write $knownhostsfile";
258 print KNOWNHOSTS "[$listenaddr]:$port ssh-dss $dsahostkey[1]\n" || die 'Could not write to KNOWNHOSTS';
259 close KNOWNHOSTS || die "Could not close KNOWNHOSTS";
261 open(SSHFILE, ">$conffile_ssh") || die "Could not write $conffile_ssh";
262 print SSHFILE <<EOFSSH
263 IdentityFile $path/curl_client_key
264 UserKnownHostsFile $path/$knownhostsfile
265 StrictHostKeyChecking no
272 HostbasedAuthentication yes
273 NoHostAuthenticationForLocalhost no
274 # Newer OpenSSH options
278 close SSHFILE || die "Could not close $conffile_ssh";
281 if (system "$sshd -t -q -f $conffile") {
282 # This is likely due to missing support for UsePam
283 print "$sshd is too old and is not supported\n";
289 my $rc = system "$sshd -e -D -f $conffile > log/sshd.log 2>&1";
291 if($rc && $verbose) {
292 print STDERR "$sshd exited with $rc!\n";