Use 512 bit keys to reduce the time taken to generate them. This shouldn't
[platform/upstream/curl.git] / tests / sshserver.pl
1 #/usr/bin/env perl
2 # $Id$
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
5 # separate script).
6
7 # Options:
8 # -u user
9 # -v
10 # target_port
11
12 use strict;
13 use File::Spec;
14
15 my $verbose=0; # set to 1 for debugging
16
17 my $port = 8999;        # just our default, weird enough
18
19 my $path = `pwd`;
20 chomp $path;
21
22 my $exeext;
23 if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys' || $^O eq 'dos' || $^O eq 'os2') {
24     $exeext = '.exe';
25 }
26
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);
29
30 my $username = $ENV{USER};
31
32 # Find a file somewhere in the given path
33 sub searchpath {
34   my $fn = $_[0] . $exeext;
35   shift;
36   my @path = @_;
37   foreach (@path) {
38       my $file = File::Spec->catfile($_, $fn);
39       if (-e $file) {
40           return $file;
41       }
42   }
43 }
44
45 # Parse options
46 do {
47     if($ARGV[0] eq "-v") {
48         $verbose=1;
49     }
50     elsif($ARGV[0] eq "-u") {
51         $username=$ARGV[1];
52         shift @ARGV;
53     }
54     elsif($ARGV[0] =~ /^(\d+)$/) {
55         $port = $1;
56     }
57 } while(shift @ARGV);
58
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
62
63 # Searching for sshd and sftp-server will be done first
64 # in the PATH and afterwards in other common locations.
65 my @spath;
66 push(@spath, File::Spec->path()); 
67 push(@spath, @sftppath); 
68
69 # sshd insists on being called with an absolute path.
70 my $sshd = searchpath("sshd", @spath);
71 if (!$sshd) {
72     print "sshd$exeext not found\n";
73     exit 1;
74 }
75 if ($verbose) {
76     print STDERR "SSH server found at $sshd\n";
77 }
78
79 my $sftp = searchpath("sftp-server", @spath);
80 if (!$sftp) {
81     print "Could not find sftp-server$exeext plugin\n";
82     exit 1;
83 }
84 if ($verbose) {
85     print STDERR "SFTP server plugin found at $sftp\n";
86 }
87
88 if ($username eq "root") {
89     print "Will not run ssh daemon as root to mitigate security risks\n";
90     exit 1;
91 }
92
93 # Find out sshd version.
94 my $tmpstr;
95 my $ssh_daemon;
96 my $ssh_ver_major;
97 my $ssh_ver_minor;
98 my $ssh_ver_patch;
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';
103 }
104 if ($verbose) {
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";
109 }
110
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";
114     exit 1;
115 }
116
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";
121 close CONF;
122
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($) {
127     my ($option) = @_;
128     my $err = grep /Unsupported .* $option/, qx($sshd -t -f $conffile -o $option=no 2>&1);
129     return !$err;
130 }
131
132 my $supports_UsePAM = sshd_supports_opt('UsePAM');
133 my $supports_UseDNS = sshd_supports_opt('UseDNS');
134 my $supports_ChReAu = sshd_supports_opt('ChallengeResponseAuthentication');
135 if ($verbose) {
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";
142 }
143
144 if (! -e "curl_client_key.pub") {
145     if ($verbose) {
146         print STDERR "Generating host and client keys...\n";
147     }
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";
152 }
153
154 open(FILE, ">>$conffile") || die "Could not write $conffile";
155 print FILE <<EOFSSHD
156 AllowUsers $username
157 DenyUsers
158 DenyGroups
159 AuthorizedKeysFile $path/curl_client_key.pub
160 HostKey $path/curl_host_dsa_key
161 PidFile $path/.ssh.pid
162 Port $port
163 ListenAddress localhost
164 Protocol 2
165 AllowTcpForwarding yes
166 GatewayPorts no
167 HostbasedAuthentication no
168 IgnoreRhosts yes
169 IgnoreUserKnownHosts yes
170 KeepAlive no
171 PasswordAuthentication no
172 PermitEmptyPasswords no
173 PermitUserEnvironment no
174 PermitRootLogin no
175 PrintLastLog no
176 PrintMotd no
177 StrictModes no
178 Subsystem sftp $sftp
179 UseLogin no
180 PrintLastLog no
181 X11Forwarding no
182 UsePrivilegeSeparation no
183 # Newer OpenSSH options
184 EOFSSHD
185 ;
186 close FILE ||  die "Could not close $conffile";
187
188 sub set_sshd_option {
189     my ($string) = @_;
190     if (open(FILE, ">>$conffile")) {
191         print FILE "$string\n";
192         close FILE;
193     }
194 }
195
196 if ($supports_UsePAM) {
197     set_sshd_option('UsePAM no');
198 }
199 if ($supports_UseDNS) {
200     set_sshd_option('UseDNS no');
201 }
202 if ($supports_ChReAu) {
203     set_sshd_option('ChallengeResponseAuthentication no');
204 }
205
206
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";
211
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";
215
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
221 Protocol 2
222 BatchMode yes
223 CheckHostIP no
224 Compression no
225 ConnectTimeout 20
226 ForwardX11 no
227 HostbasedAuthentication yes
228 NoHostAuthenticationForLocalhost no
229 # Newer OpenSSH options
230 #SetupTimeOut 20
231 EOFSSH
232 ;
233 close SSHFILE ||  die "Could not close $conffile_ssh";
234
235
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";
239     unlink $conffile;
240     exit 1;
241 }
242
243 # Start the server
244 my $rc = system "$sshd -e -D -f $conffile > log/sshd.log 2>&1";
245 $rc >>= 8;
246 if($rc && $verbose) {
247     print STDERR "$sshd exited with $rc!\n";
248 }
249
250 unlink $conffile;
251
252 exit $rc;