scp and filenames with weird characters

Stian Soiland stain at nvg.org
Wed Dec 13 04:12:37 EST 2000


I've experienced some troubles using scp with remote files with spaces,
amphersands or parantheses in their filenames on Linux hosts.

This happens:

  stain at false:~$ scp "bender.linpro.no:blapp blapp" .
  scp: blapp: No such file or directory
  scp: blapp: No such file or directory
  
  stain at false:~$ scp "bender.linpro.no:blapp&blapp" .
  bash: blapp: command not found

This might be abused, like this:

  stain at false:~$ scp "bender.linpro.no:blapp&cat /etc/passwd" .
  root:x:0:0:root:/root:/bin/bash

You might object that the person could done this simply with 
  stain at false:~$ ssh bender.linpro.no cat /etc/passwd
  
and even received more than one line, but the problem here is that one
does not always have the same control over filenames as with commands. 

Note: This bug does not seem to effect local-to-remote copying or
remote-to-local copying with shell filename expansion (*)

One might temporarily overcome the problem with doublescaping, ie, 

  stain at false:~$ scp "bender.linpro.no:blapp\ blapp" .
  blapp blapp          100% |*****************************************|     0       --:-- ETA


Although the simplest is to patch the sourcecode:

(A patchfile for the CVS-version is included, but these fixes should
work for any 2.2.0-version (as the one in Debian woody) as far as I can
see) 

in scp.c:

-           strlen(thost) + strlen(targ) + CMDNEEDS + 32;
+           strlen(thost) + strlen(targ) + CMDNEEDS + 40;

-   "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
+   "%s%s -x -o'FallBackToRsh no' -n -l 
     \"%s\" \"%s\" \"%s\"\"%s\" '%s%s%s:%s'",

-   "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
+   "exec %s%s -x -o'FallBackToRsh no' -n 
     \"%s\" \"%s\" \"%s\" '%s%s%s:%s'",

-               len = strlen(src) + CMDNEEDS + 20;
+               len = strlen(src) + CMDNEEDS + 22;

-               (void) sprintf(bp, "%s -f %s", cmd, src);
+               (void) sprintf(bp, "%s -f \"%s\"", cmd, src);


as the clever eye might see, all I do is to surround arguments to the
remote ssh with ""es and increases the memory allocation caused
by this.

Note: This even applies to other arguments, such as host and username,
although it rarely happens that one haves usernames or hostnames with &
or "".


IMPORTANT: This does not fix the problem with filenames with " in them.

(you probabbly need to tripple escape with something as ugly as
  scp "blapp.machine.com:filename\\\"blapp" .
)  

A search-replace routine on the src-string (" to \") would fix this,
but my C-knowledge is non-existing. 

-- 
Stian Søiland - Trondheim, Norway - http://stain.portveien.to/

                         Uten forutgående varsel har utleier rett til å
                         tilintetgjøre illeluktende gjenstander - enten
                        dette er mat eller andre ting. [Voll studentby]
-------------- next part --------------
--- scp.c	Tue Dec 12 17:36:30 2000
+++ /home/stain/scp.c	Tue Dec 12 17:36:17 2000
@@ -387,7 +387,7 @@
 			host = strchr(argv[i], '@');
 			len = strlen(ssh_program) + strlen(argv[i]) +
 			    strlen(src) + (tuser ? strlen(tuser) : 0) +
-			    strlen(thost) + strlen(targ) + CMDNEEDS + 32;
+			    strlen(thost) + strlen(targ) + CMDNEEDS + 40;
 			bp = xmalloc(len);
 			if (host) {
 				*host++ = 0;
@@ -398,7 +398,7 @@
 				else if (!okname(suser))
 					continue;
 				sprintf(bp,
-				    "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
+				    "%s%s -x -o'FallBackToRsh no' -n -l \"%s\" \"%s\" \"%s\" \"%s\" '%s%s%s:%s'",
 				    ssh_program, verbose_mode ? " -v" : "",
 				    suser, host, cmd, src,
 				    tuser ? tuser : "", tuser ? "@" : "",
@@ -406,7 +406,7 @@
 			} else {
 				host = cleanhostname(argv[i]);
 				sprintf(bp,
-				    "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
+				    "exec %s%s -x -o'FallBackToRsh no' -n \"%s\" \"%s\" \"%s\" '%s%s%s:%s'",
 				    ssh_program, verbose_mode ? " -v" : "",
 				    host, cmd, src,
 				    tuser ? tuser : "", tuser ? "@" : "",
@@ -472,9 +472,9 @@
 				continue;
 		}
 		host = cleanhostname(host);
-		len = strlen(src) + CMDNEEDS + 20;
+		len = strlen(src) + CMDNEEDS + 22;
 		bp = xmalloc(len);
-		(void) sprintf(bp, "%s -f %s", cmd, src);
+		(void) sprintf(bp, "%s -f \"%s\"", cmd, src);
 		if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) {
 			(void) xfree(bp);
 			++errs;


More information about the openssh-unix-dev mailing list