To verify that the sftp server is actually running, responsive and that
authorYang Tse <yangsita@gmail.com>
Fri, 8 Feb 2008 13:54:02 +0000 (13:54 +0000)
committerYang Tse <yangsita@gmail.com>
Fri, 8 Feb 2008 13:54:02 +0000 (13:54 +0000)
all curl's tests generated configuration and key files are fine, a real
connection is established to the test harness sftp server authenticating
and running a simple sftp remote pwd command.

The verification is done using OpenSSH's or SunSSH's sftp client tool with
a configuration file with the same options as the test harness socks server
with the exception that dynamic forwarding is not used for sftp.

CHANGES
tests/.cvsignore
tests/runtests.pl
tests/sshhelp.pm
tests/sshserver.pl

diff --git a/CHANGES b/CHANGES
index feef3cf..fc9932c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,11 @@
 
                                   Changelog
 
+Yang Tse (8 Feb 2008)
+- Improved test harness SCP/SFTP start up server verification, doing a real
+  connection to the sftp server, authenticating and running a simple sftp
+  pwd command using the test harness generated configuration and key files.
+
 Daniel S (8 Feb 2008)
 - Günter Knauf added lib/mk-ca-bundle.pl which gets the Firefox ca bundle and
   creates a suitable ca-bundle.crt file in PEM format for use with curl. The
index 217b757..e6d5aa1 100644 (file)
@@ -5,11 +5,13 @@ log
 *.pid
 *.pdf
 *.html
-curl_client_knownhosts
 curl_client_key
 curl_client_key.pub
+curl_client_knownhosts
 curl_host_dsa_key
 curl_host_dsa_key.pub
-curl_sshd_config
+curl_sftp_cmds
+curl_sftp_config
 curl_ssh_config
+curl_sshd_config
 stunnel.conf
index 77b57b1..b0520db 100755 (executable)
@@ -69,14 +69,21 @@ use Cwd;
 use sshhelp qw(
     $sshdexe
     $sshexe
+    $sftpexe
     $sshconfig
+    $sftpconfig
     $sshlog
+    $sftplog
+    $sftpcmds
     display_sshdconfig
     display_sshconfig
+    display_sftpconfig
     display_sshdlog
     display_sshlog
+    display_sftplog
     find_sshd
     find_ssh
+    find_sftp
     sshversioninfo
     );
 
@@ -658,7 +665,9 @@ sub verifyftp {
 }
 
 #######################################################################
-# STUB for verifying scp/sftp
+# Verify that the ssh server has written out its pidfile, recovering
+# the pid from the file and returning it if a process with that pid is
+# actually alive.
 
 sub verifyssh {
     my ($proto, $ip, $port) = @_;
@@ -681,6 +690,37 @@ sub verifyssh {
 }
 
 #######################################################################
+# Verify that we can connect to the sftp server, properly authenticate
+# with generated config and key files and run a simple remote pwd.
+
+sub verifysftp {
+    my ($proto, $ip, $port) = @_;
+    my $verified = 0;
+    # Find out sftp client canonical file name
+    my $sftp = find_sftp();
+    if(!$sftp) {
+        logmsg "RUN: SFTP server cannot find $sftpexe\n";
+        return -1;
+    }
+    # Connect to sftp server, authenticate and run a remote pwd
+    # command using our generated configuration and key files
+    my $cmd = "$sftp -b $sftpcmds -F $sftpconfig $ip > $sftplog 2>&1";
+    my $res = runclient($cmd);
+    # Search for pwd command response in log file
+    if(open(SFTPLOGFILE, "<$sftplog")) {
+        while(<SFTPLOGFILE>) {
+            if(/^Remote working directory: /) {
+                $verified = 1;
+                last;
+            }
+        }
+        close(SFTPLOGFILE);
+    }
+    return $verified;
+}
+
+
+#######################################################################
 # STUB for verifying socks
 
 sub verifysocks {
@@ -716,6 +756,7 @@ my %protofunc = ('http' => \&verifyhttp,
                  'ftps' => \&verifyftp,
                  'tftp' => \&verifyftp,
                  'ssh' => \&verifyssh,
+                 'sftp' => \&verifysftp,
                  'socks' => \&verifysocks);
 
 sub verifyserver {
@@ -1122,19 +1163,35 @@ sub runsshserver {
         return (0,0);
     }
 
-    # server verification allows some extra time for the server to start up
-    # and gives us the opportunity of recovering the pid from the pidfile,
-    # which will be assigned to pid2 ONLY if pid2 was not already positive.
+    # ssh server verification allows some extra time for the server to start up
+    # and gives us the opportunity of recovering the pid from the pidfile, when
+    # this verification succeeds the recovered pid is assigned to pid2.
 
     my $pid3 = verifyserver("ssh",$ip,$port);
     if(!$pid3) {
         logmsg "RUN: SSH server failed verification\n";
+        # failed to fetch server pid. Kill the server and return failure
+        stopserver("$sshpid $pid2");
+        $doesntrun{$pidfile} = 1;
+        return (0,0);
+    }
+    $pid2 = $pid3;
+
+    # once it is known that the ssh server is alive, sftp server verification
+    # is performed actually connecting to it, authenticating and performing a
+    # very simple remote command.
+
+    if(!verifyserver("sftp",$ip,$port)) {
+        logmsg "RUN: SFTP server failed verification\n";
         # failed to talk to it properly. Kill the server and return failure
+        display_sftplog();
+        display_sftpconfig();
+        display_sshdlog();
+        display_sshdconfig();
         stopserver("$sshpid $pid2");
         $doesntrun{$pidfile} = 1;
         return (0,0);
     }
-    $pid2 = $pid3 if($pid2 <= 0);
 
     if($verbose) {
         logmsg "RUN: SSH server is now running PID $pid2\n";
index b76c42d..7cd4b5c 100644 (file)
@@ -37,13 +37,17 @@ use vars qw(
     @EXPORT_OK
     $sshdexe
     $sshexe
+    $sftpsrvexe
     $sftpexe
     $sshkeygenexe
     $sshdconfig
     $sshconfig
+    $sftpconfig
     $knownhosts
     $sshdlog
     $sshlog
+    $sftplog
+    $sftpcmds
     $hstprvkeyf
     $hstpubkeyf
     $cliprvkeyf
@@ -64,24 +68,31 @@ use vars qw(
 @EXPORT_OK = qw(
     $sshdexe
     $sshexe
+    $sftpsrvexe
     $sftpexe
     $sshkeygenexe
     $sshdconfig
     $sshconfig
+    $sftpconfig
     $knownhosts
     $sshdlog
     $sshlog
+    $sftplog
+    $sftpcmds
     $hstprvkeyf
     $hstpubkeyf
     $cliprvkeyf
     $clipubkeyf
     display_sshdconfig
     display_sshconfig
+    display_sftpconfig
     display_sshdlog
     display_sshlog
+    display_sftplog
     dump_array
     find_sshd
     find_ssh
+    find_sftpsrv
     find_sftp
     find_sshkeygen
     logmsg
@@ -94,12 +105,16 @@ use vars qw(
 #
 $sshdexe      = 'sshd'        .exe_ext(); # base name and ext of ssh daemon
 $sshexe       = 'ssh'         .exe_ext(); # base name and ext of ssh client
-$sftpexe      = 'sftp-server' .exe_ext(); # base name and ext of sftp-server
+$sftpsrvexe   = 'sftp-server' .exe_ext(); # base name and ext of sftp-server
+$sftpexe      = 'sftp'        .exe_ext(); # base name and ext of sftp client
 $sshkeygenexe = 'ssh-keygen'  .exe_ext(); # base name and ext of ssh-keygen
 $sshdconfig   = 'curl_sshd_config';       # ssh daemon config file
 $sshconfig    = 'curl_ssh_config';        # ssh client config file
+$sftpconfig   = 'curl_sftp_config';       # sftp client config file
 $sshdlog      = 'log/sshd.log';           # ssh daemon log file
 $sshlog       = 'log/ssh.log';            # ssh client log file
+$sftplog      = 'log/sftp.log';           # sftp client log file
+$sftpcmds     = 'curl_sftp_cmds';         # sftp client commands batch file
 $knownhosts   = 'curl_client_knownhosts'; # ssh knownhosts file
 $hstprvkeyf   = 'curl_host_dsa_key';      # host private key file
 $hstpubkeyf   = 'curl_host_dsa_key.pub';  # host public key file
@@ -214,6 +229,14 @@ sub display_sshconfig {
 
 
 #***************************************************************************
+# Display contents of the sftp client config file
+#
+sub display_sftpconfig {
+    display_file($sftpconfig);
+}
+
+
+#***************************************************************************
 # Display contents of the ssh daemon log file
 #
 sub display_sshdlog {
@@ -230,6 +253,14 @@ sub display_sshlog {
 
 
 #***************************************************************************
+# Display contents of the sftp client log file
+#
+sub display_sftplog {
+    display_file($sftplog);
+}
+
+
+#***************************************************************************
 # Find a file somewhere in the given path
 #
 sub find_file {
@@ -276,6 +307,14 @@ sub find_ssh {
 #***************************************************************************
 # Find sftp-server plugin and return canonical filename
 #
+sub find_sftpsrv {
+    return find_sfile($sftpsrvexe);
+}
+
+
+#***************************************************************************
+# Find sftp client and return canonical filename
+#
 sub find_sftp {
     return find_sfile($sftpexe);
 }
index e941253..3eb57a6 100644 (file)
@@ -44,24 +44,31 @@ use Cwd;
 use sshhelp qw(
     $sshdexe
     $sshexe
+    $sftpsrvexe
     $sftpexe
     $sshkeygenexe
     $sshdconfig
     $sshconfig
+    $sftpconfig
     $knownhosts
     $sshdlog
     $sshlog
+    $sftplog
+    $sftpcmds
     $hstprvkeyf
     $hstpubkeyf
     $cliprvkeyf
     $clipubkeyf
     display_sshdconfig
     display_sshconfig
+    display_sftpconfig
     display_sshdlog
     display_sshlog
+    display_sftplog
     dump_array
     find_sshd
     find_ssh
+    find_sftpsrv
     find_sftp
     find_sshkeygen
     logmsg
@@ -193,12 +200,23 @@ if((($sshdid =~ /OpenSSH/) && ($sshdvernum < 299)) ||
 #***************************************************************************
 # Find out sftp server plugin canonical file name
 #
+my $sftpsrv = find_sftpsrv();
+if(!$sftpsrv) {
+    logmsg "cannot find $sftpsrvexe";
+    exit 1;
+}
+logmsg "sftp server plugin found $sftpsrv" if($verbose);
+
+
+#***************************************************************************
+# Find out sftp client canonical file name
+#
 my $sftp = find_sftp();
 if(!$sftp) {
     logmsg "cannot find $sftpexe";
     exit 1;
 }
-logmsg "sftp server plugin found $sftp" if($verbose);
+logmsg "sftp client found $sftp" if($verbose);
 
 
 #***************************************************************************
@@ -428,7 +446,7 @@ push @cfgarr, 'RhostsRSAAuthentication no';
 push @cfgarr, 'RSAAuthentication no';
 push @cfgarr, 'ServerKeyBits 768';
 push @cfgarr, 'StrictModes no';
-push @cfgarr, "Subsystem sftp $sftp";
+push @cfgarr, "Subsystem sftp $sftpsrv -f AUTH -l $loglevel";
 push @cfgarr, 'SyslogFacility AUTH';
 push @cfgarr, 'UseLogin no';
 push @cfgarr, 'X11Forwarding no';
@@ -861,12 +879,55 @@ if($error) {
     logmsg $error;
     exit 1;
 }
+
+
+#***************************************************************************
+# Initialize client sftp config with options actually supported.
+#
+logmsg 'generating sftp client config file...' if($verbose);
+splice @cfgarr, 1, 1, "# $sshverstr sftp client configuration file for curl testing";
+#
+for(my $i = scalar(@cfgarr) - 1; $i > 0; $i--) {
+    if($cfgarr[$i] =~ /^DynamicForward/) {
+        splice @cfgarr, $i, 1;
+        next;
+    }
+    if($cfgarr[$i] =~ /^ClearAllForwardings/) {
+        splice @cfgarr, $i, 1, "ClearAllForwardings yes";
+        next;
+    }
+}
+
+
+#***************************************************************************
+# Write out resulting sftp client configuration file for curl's tests
+#
+$error = dump_array($sftpconfig, @cfgarr);
+if($error) {
+    logmsg $error;
+    exit 1;
+}
+@cfgarr = ();
+
+
+#***************************************************************************
+# Generate client sftp commands batch file for sftp server verification
+#
+logmsg 'generating sftp client commands file...' if($verbose);
+push @cfgarr, 'pwd';
+push @cfgarr, 'quit';
+$error = dump_array($sftpcmds, @cfgarr);
+if($error) {
+    logmsg $error;
+    exit 1;
+}
 @cfgarr = ();
 
 
 #***************************************************************************
 # Start the ssh server daemon without forking it
 #
+logmsg "SCP/SFTP server listening on port $port" if($verbose);
 my $rc = system "$sshd -e -D -f $sshdconfig > $sshdlog 2>&1";
 if($rc == -1) {
     logmsg "$sshd failed with: $!";
@@ -884,7 +945,7 @@ elsif($verbose && ($rc >> 8)) {
 # Clean up once the server has stopped
 #
 unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf, $knownhosts);
-unlink($sshdconfig, $sshconfig);
+unlink($sshdconfig, $sshconfig, $sftpconfig);
 
 
 exit 0;