summaryrefslogtreecommitdiff
path: root/openssh-8.7p1-recursive-scp.patch
blob: f0d9b0fed4898e8536615edeffe6a122aace88fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c
--- openssh-8.7p1/scp.c.scp-sftpdirs	2022-02-07 12:31:07.407740407 +0100
+++ openssh-8.7p1/scp.c	2022-02-07 12:31:07.409740424 +0100
@@ -1324,7 +1324,7 @@ source_sftp(int argc, char *src, char *t
 
 	if (src_is_dir && iamrecursive) {
 		if (upload_dir(conn, src, abs_dst, pflag,
-		    SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
+		    SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) {
			error("failed to upload directory %s to %s", src, targ);
			errs = 1;
		}
diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c
--- openssh-8.7p1/sftp-client.c.scp-sftpdirs	2021-08-20 06:03:49.000000000 +0200
+++ openssh-8.7p1/sftp-client.c	2022-02-07 12:47:59.117516131 +0100
@@ -971,7 +971,7 @@ do_fsetstat(struct sftp_conn *conn, cons
 
 /* Implements both the realpath and expand-path operations */
 static char *
-do_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
+do_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir)
 {
 	struct sshbuf *msg;
 	u_int expected_id, count, id;
@@ -1033,11 +1033,43 @@ do_realpath_expand(struct sftp_conn *con
 		if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
 		    (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
 			fatal_fr(r, "parse status");
-		error("%s %s: %s", expand ? "expand" : "realpath",
-		    path, *errmsg == '\0' ? fx2txt(status) : errmsg);
-		free(errmsg);
-		sshbuf_free(msg);
-		return NULL;
+		if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir)  {
+			memset(&a, '\0', sizeof(a));
+			if ((r = do_mkdir(conn, path, &a, 0)) != 0) {
+				sshbuf_free(msg);
+				return NULL;
+			}
+			debug2("Sending SSH2_FXP_REALPATH \"%s\" - create dir", path);
+			send_string_request(conn, id, SSH2_FXP_REALPATH,
+					path, strlen(path));
+
+			get_msg(conn, msg);
+			if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+			    (r = sshbuf_get_u32(msg, &id)) != 0)
+				fatal_fr(r, "parse");
+
+			if (id != expected_id)
+				fatal("ID mismatch (%u != %u)", id, expected_id);
+
+			if (type == SSH2_FXP_STATUS) {
+				free(errmsg);
+
+				if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
+				    (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
+					fatal_fr(r, "parse status");
+				error("%s %s: %s", expand ? "expand" : "realpath",
+				    path, *errmsg == '\0' ? fx2txt(status) : errmsg);
+				free(errmsg);
+				sshbuf_free(msg);
+				return NULL;
+			}
+		} else {
+			error("%s %s: %s", expand ? "expand" : "realpath",
+			    path, *errmsg == '\0' ? fx2txt(status) : errmsg);
+			free(errmsg);
+			sshbuf_free(msg);
+			return NULL;
+		}
 	} else if (type != SSH2_FXP_NAME)
 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
 		    SSH2_FXP_NAME, type);
@@ -1039,9 +1067,9 @@ do_realpath_expand(struct sftp_conn *con
 }
 
 char *
-do_realpath(struct sftp_conn *conn, const char *path)
+do_realpath(struct sftp_conn *conn, const char *path, int create_dir)
 {
-	return do_realpath_expand(conn, path, 0);
+	return do_realpath_expand(conn, path, 0, create_dir);
 }
 
 int
@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c
 {
 	if (!can_expand_path(conn)) {
 		debug3_f("no server support, fallback to realpath");
-		return do_realpath_expand(conn, path, 0);
+		return do_realpath_expand(conn, path, 0, 0);
 	}
-	return do_realpath_expand(conn, path, 1);
+	return do_realpath_expand(conn, path, 1, 0);
 }
 
 int
@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con
 	char *src_canon;
 	int ret;
 
-	if ((src_canon = do_realpath(conn, src)) == NULL) {
+	if ((src_canon = do_realpath(conn, src, 0)) == NULL) {
		error("download \"%s\": path canonicalization failed", src);
		return -1;
	}
@@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co
 int
 upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
     int preserve_flag, int print_flag, int resume, int fsync_flag,
-    int follow_link_flag, int inplace_flag)
+    int follow_link_flag, int inplace_flag, int create_dir)
 {
 	char *dst_canon;
 	int ret;
 
-	if ((dst_canon = do_realpath(conn, dst)) == NULL) {
+	if ((dst_canon = do_realpath(conn, dst, create_dir)) == NULL) {
		error("upload \"%s\": path canonicalization failed", dst);
		return -1;
	}
@@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st
 	char *from_path_canon;
 	int ret;
 
-	if ((from_path_canon = do_realpath(from, from_path)) == NULL) {
+	if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) {
		error("crossload \"%s\": path canonicalization failed",
		    from_path);
		return -1;
diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h
--- openssh-8.7p1/sftp-client.h.scp-sftpdirs	2021-08-20 06:03:49.000000000 +0200
+++ openssh-8.7p1/sftp-client.h	2022-02-07 12:31:07.410740433 +0100
@@ -111,7 +111,7 @@ int do_fsetstat(struct sftp_conn *, cons
 int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
 
 /* Canonicalise 'path' - caller must free result */
-char *do_realpath(struct sftp_conn *, const char *);
+char *do_realpath(struct sftp_conn *, const char *, int);
 
 /* Canonicalisation with tilde expansion (requires server extension) */
 char *do_expand_path(struct sftp_conn *, const char *);
@@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const
  * times if 'pflag' is set
  */
 int upload_dir(struct sftp_conn *, const char *, const char *,
-    int, int, int, int, int, int);
+    int, int, int, int, int, int, int);
 
 /*
  * Download a 'from_path' from the 'from' connection and upload it to
diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c
--- openssh-8.7p1/sftp.c.scp-sftpdirs	2021-08-20 06:03:49.000000000 +0200
+++ openssh-8.7p1/sftp.c	2022-02-07 12:31:07.411740442 +0100
@@ -760,7 +760,7 @@ process_put(struct sftp_conn *conn, cons
 		if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
 			if (upload_dir(conn, g.gl_pathv[i], abs_dst,
 			    pflag || global_pflag, 1, resume,
-			    fflag || global_fflag, 0, 0) == -1)
+			    fflag || global_fflag, 0, 0, 0) == -1)
 				err = -1;
 		} else {
 			if (do_upload(conn, g.gl_pathv[i], abs_dst,
@@ -1577,7 +1577,7 @@ parse_dispatch_command(struct sftp_conn
 		if (path1 == NULL || *path1 == '\0')
 			path1 = xstrdup(startdir);
 		path1 = make_absolute(path1, *pwd);
-		if ((tmp = do_realpath(conn, path1)) == NULL) {
+		if ((tmp = do_realpath(conn, path1, 0)) == NULL) {
 			err = 1;
 			break;
 		}
@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn,
 	}
 #endif /* USE_LIBEDIT */
 
-	remote_path = do_realpath(conn, ".");
+	remote_path = do_realpath(conn, ".", 0);
 	if (remote_path == NULL)
 		fatal("Need cwd");
 	startdir = xstrdup(remote_path);