From b9da1524d95559132cbaf6442271fa1eea6e7a7d Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Sun, 25 Apr 2004 22:18:19 +0000 Subject: [PATCH] Implement `pscp-select-backend'. [originally from svn r4142] --- doc/pscp.but | 37 ++++++++++++++++++++++++++++++++++-- scp.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/doc/pscp.but b/doc/pscp.but index c4ccc644..c69b0228 100644 --- a/doc/pscp.but +++ b/doc/pscp.but @@ -1,4 +1,4 @@ -\versionid $Id: pscp.but,v 1.26 2004/04/24 12:25:08 jacob Exp $ +\versionid $Id: pscp.but,v 1.27 2004/04/25 22:18:19 jacob Exp $ \#FIXME: Need examples @@ -60,6 +60,8 @@ use PSCP: \c -batch disable all interactive prompts \c -unsafe allow server-side wildcards (DANGEROUS) \c -V print version information +\c -scp force use of SCP protocol +\c -sftp force use of SFTP protocol (PSCP's interface is much like the Unix \c{scp} command, if you're familiar with that.) @@ -113,7 +115,8 @@ pattern. PSCP will attempt to use the newer SFTP protocol (part of SSH 2) where possible, which does not suffer from this security flaw. If you are talking to an SSH 2 server which supports SFTP, you will -never see this warning. +never see this warning. (You can force use of the SFTP protocol, +if available, with \c{-sftp} - see \k{pscp-usage-options-backend}.) If you really need to use a server-side wildcard with an SSH 1 server, you can use the \c{-unsafe} command line option with PSCP: @@ -222,6 +225,36 @@ This may help PSCP's behaviour when it is used in automated scripts: using \c{-batch}, if something goes wrong at connection time, the batch job will fail rather than hang. +\S2{pscp-usage-options-backend}\c{-sftp}, \c{-scp} force use of +particular protocol + +As mentioned in \k{pscp-usage-basics}, there are two different file +transfer protocols in use with SSH. Despite its name, PSCP (like many +other ostensible \cw{scp} clients) can use either of these protocols. + +The older SCP protocol does not have a written specification and +leaves a lot of detail to the server platform. Wildcards are expanded +on the server. The simple design means that any wildcard specification +supported by the server platform (such as brace expansion) can be +used, but also leads to interoperability issues such as with filename +quoting (for instance, where filenames contain spaces), and also the +security issue described in \k{pscp-usage-basics}. + +The newer SFTP protocol, which is usually associated with SSH 2 +servers, is specified in a more platform independent way, and leaves +issues such as wildcard syntax up to the client. This makes it more +consistent across platforms, more suitable for scripting and +automation, and avoids security issues with wilcard matching. + +Normally PSCP will attempt to use the SFTP protocol, and only fall +back to the SCP protocol if SFTP is not available on the server. + +The \c{-scp} option forces PSCP to use the SCP protocol or quit. + +The \c{-sftp} option forces PSCP to use the SFTP protocol or quit. +When this option is specified, PSCP looks harder for an SFTP server, +which may allow use of SFTP with SSH 1 depending on server setup. + \S{pscp-retval} Return value PSCP returns an \cw{ERRORLEVEL} of zero (success) only if the files diff --git a/scp.c b/scp.c index f3aa5e05..781e3758 100644 --- a/scp.c +++ b/scp.c @@ -36,6 +36,10 @@ static int prev_stats_len = 0; static int scp_unsafe_mode = 0; static int errs = 0; static int gui_mode = 0; +static int try_scp = 1; +static int try_sftp = 1; +static int main_cmd_is_sftp = 0; +static int fallback_cmd_is_sftp = 0; static int using_sftp = 0; static Backend *back; @@ -262,7 +266,13 @@ static void ssh_scp_init(void) if (ssh_sftp_loop_iteration() < 0) return; /* doom */ } - using_sftp = !ssh_fallback_cmd(backhandle); + + /* Work out which backend we ended up using. */ + if (!ssh_fallback_cmd(backhandle)) + using_sftp = main_cmd_is_sftp; + else + using_sftp = fallback_cmd_is_sftp; + if (verbose) { if (using_sftp) tell_user(stderr, "Using SFTP"); @@ -402,13 +412,40 @@ static void do_cmd(char *host, char *user, char *cmd) cfg.portfwd[0] = cfg.portfwd[1] = '\0'; /* + * Set up main and possibly fallback command depending on + * options specified by user. * Attempt to start the SFTP subsystem as a first choice, * falling back to the provided scp command if that fails. */ - strcpy(cfg.remote_cmd, "sftp"); - cfg.ssh_subsys = TRUE; - cfg.remote_cmd_ptr2 = cmd; - cfg.ssh_subsys2 = FALSE; + cfg.remote_cmd_ptr2 = NULL; + if (try_sftp) { + /* First choice is SFTP subsystem. */ + main_cmd_is_sftp = 1; + strcpy(cfg.remote_cmd, "sftp"); + cfg.ssh_subsys = TRUE; + if (try_scp) { + /* Fallback is to use the provided scp command. */ + fallback_cmd_is_sftp = 0; + cfg.remote_cmd_ptr2 = cmd; + cfg.ssh_subsys2 = FALSE; + } else { + /* Since we're not going to try SCP, we may as well try + * harder to find an SFTP server, since in the current + * implementation we have a spare slot. */ + fallback_cmd_is_sftp = 1; + /* see psftp.c for full explanation of this kludge */ + cfg.remote_cmd_ptr2 = + "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" + "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" + "exec sftp-server"; + cfg.ssh_subsys2 = FALSE; + } + } else { + /* Don't try SFTP at all; just try the scp command. */ + main_cmd_is_sftp = 0; + cfg.remote_cmd_ptr = cmd; + cfg.ssh_subsys = FALSE; + } cfg.nopty = TRUE; back = &ssh_backend; @@ -2065,6 +2102,8 @@ static void usage(void) printf(" -batch disable all interactive prompts\n"); printf(" -unsafe allow server-side wildcards (DANGEROUS)\n"); printf(" -V print version information\n"); + printf(" -sftp force use of SFTP protocol\n"); + printf(" -scp force use of SCP protocol\n"); #if 0 /* * -gui is an internal option, used by GUI front ends to get @@ -2148,6 +2187,10 @@ int psftp_main(int argc, char *argv[]) console_batch_mode = 1; } else if (strcmp(argv[i], "-unsafe") == 0) { scp_unsafe_mode = 1; + } else if (strcmp(argv[i], "-sftp") == 0) { + try_scp = 0; try_sftp = 1; + } else if (strcmp(argv[i], "-scp") == 0) { + try_scp = 1; try_sftp = 0; } else if (strcmp(argv[i], "--") == 0) { i++; break;