- djm@cvs.openbsd.org 2003/07/19 00:45:53
     [sftp-int.c]
     fix sftp filename parsing for arguments with escaped quotes. bz #517;
     ok markus
diff --git a/ChangeLog b/ChangeLog
index f645e68..c2bb7bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,10 @@
    - deraadt@cvs.openbsd.org 2003/07/18 01:54:25
      [scp.c]
      userid is unsigned, but well, force it anyways; andrushock@korovino.net
+   - djm@cvs.openbsd.org 2003/07/19 00:45:53
+     [sftp-int.c]
+     fix sftp filename parsing for arguments with escaped quotes. bz #517;
+     ok markus
 
 20030714
  - (dtucker) [acconfig.h configure.ac port-aix.c] Older AIXes don't declare
@@ -711,4 +715,4 @@
  - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
    Report from murple@murple.net, diagnosis from dtucker@zip.com.au
 
-$Id: ChangeLog,v 1.2861 2003/07/19 10:07:45 dtucker Exp $
+$Id: ChangeLog,v 1.2862 2003/07/19 10:09:21 dtucker Exp $
diff --git a/sftp-int.c b/sftp-int.c
index f2d3f94..73653b7 100644
--- a/sftp-int.c
+++ b/sftp-int.c
@@ -25,7 +25,7 @@
 /* XXX: recursive operations */
 
 #include "includes.h"
-RCSID("$OpenBSD: sftp-int.c,v 1.60 2003/05/15 03:43:59 mouring Exp $");
+RCSID("$OpenBSD: sftp-int.c,v 1.61 2003/07/19 00:45:53 djm Exp $");
 
 #include "buffer.h"
 #include "xmalloc.h"
@@ -332,7 +332,7 @@
 {
 	const char *cp = *cpp, *end;
 	char quot;
-	int i;
+	int i, j;
 
 	cp += strspn(cp, WHITESPACE);
 	if (!*cp) {
@@ -341,37 +341,54 @@
 		return (0);
 	}
 
+	*path = xmalloc(strlen(cp) + 1);
+
 	/* Check for quoted filenames */
 	if (*cp == '\"' || *cp == '\'') {
 		quot = *cp++;
 
-		end = strchr(cp, quot);
-		if (end == NULL) {
-			error("Unterminated quote");
-			goto fail;
+		/* Search for terminating quote, unescape some chars */
+		for (i = j = 0; i <= strlen(cp); i++) {
+			if (cp[i] == quot) {	/* Found quote */
+				(*path)[j] = '\0';
+				break;
+			}
+			if (cp[i] == '\0') {	/* End of string */
+				error("Unterminated quote");
+				goto fail;
+			}
+			if (cp[i] == '\\') {	/* Escaped characters */
+				i++;
+				if (cp[i] != '\'' && cp[i] != '\"' && 
+				    cp[i] != '\\') {
+					error("Bad escaped character '\%c'",
+					    cp[i]);
+					goto fail;
+				}
+			}
+			(*path)[j++] = cp[i];
 		}
-		if (cp == end) {
+
+		if (j == 0) {
 			error("Empty quotes");
 			goto fail;
 		}
-		*cpp = end + 1 + strspn(end + 1, WHITESPACE);
+		*cpp = cp + i + strspn(cp + i, WHITESPACE);
 	} else {
 		/* Read to end of filename */
 		end = strpbrk(cp, WHITESPACE);
 		if (end == NULL)
 			end = strchr(cp, '\0');
 		*cpp = end + strspn(end, WHITESPACE);
+
+		memcpy(*path, cp, end - cp);
+		(*path)[end - cp] = '\0';
 	}
-
-	i = end - cp;
-
-	*path = xmalloc(i + 1);
-	memcpy(*path, cp, i);
-	(*path)[i] = '\0';
-	return(0);
+	return (0);
 
  fail:
-	*path = NULL;
+ 	xfree(*path);
+	*path = NULL;	
 	return (-1);
 }