diff options
author | djm@openbsd.org <djm@openbsd.org> | 2015-01-14 13:54:13 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-01-15 02:22:18 +1100 |
commit | 7d845f4a0b7ec97887be204c3760e44de8bf1f32 (patch) | |
tree | c7f7271203627c22594cc86381745acce479d250 | |
parent | 139ca81866ec1b219c717d17061e5e7ad1059e2a (diff) |
upstream commit
update sftp client and server to new buffer API. pretty
much just mechanical changes; with & ok markus
-rw-r--r-- | progressmeter.c | 6 | ||||
-rw-r--r-- | progressmeter.h | 4 | ||||
-rw-r--r-- | sftp-client.c | 861 | ||||
-rw-r--r-- | sftp-client.h | 44 | ||||
-rw-r--r-- | sftp-common.c | 99 | ||||
-rw-r--r-- | sftp-common.h | 7 | ||||
-rw-r--r-- | sftp-glob.c | 4 | ||||
-rw-r--r-- | sftp-server.c | 610 | ||||
-rw-r--r-- | sftp.c | 5 |
9 files changed, 972 insertions, 668 deletions
diff --git a/progressmeter.c b/progressmeter.c index bbbc7066b..319b7470a 100644 --- a/progressmeter.c +++ b/progressmeter.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: progressmeter.c,v 1.40 2013/09/19 00:24:52 djm Exp $ */ | 1 | /* $OpenBSD: progressmeter.c,v 1.41 2015/01/14 13:54:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2003 Nils Nordman. All rights reserved. | 3 | * Copyright (c) 2003 Nils Nordman. All rights reserved. |
4 | * | 4 | * |
@@ -65,7 +65,7 @@ static void update_progress_meter(int); | |||
65 | 65 | ||
66 | static time_t start; /* start progress */ | 66 | static time_t start; /* start progress */ |
67 | static time_t last_update; /* last progress update */ | 67 | static time_t last_update; /* last progress update */ |
68 | static char *file; /* name of the file being transferred */ | 68 | static const char *file; /* name of the file being transferred */ |
69 | static off_t start_pos; /* initial position of transfer */ | 69 | static off_t start_pos; /* initial position of transfer */ |
70 | static off_t end_pos; /* ending position of transfer */ | 70 | static off_t end_pos; /* ending position of transfer */ |
71 | static off_t cur_pos; /* transfer position as of last refresh */ | 71 | static off_t cur_pos; /* transfer position as of last refresh */ |
@@ -248,7 +248,7 @@ update_progress_meter(int ignore) | |||
248 | } | 248 | } |
249 | 249 | ||
250 | void | 250 | void |
251 | start_progress_meter(char *f, off_t filesize, off_t *ctr) | 251 | start_progress_meter(const char *f, off_t filesize, off_t *ctr) |
252 | { | 252 | { |
253 | start = last_update = monotime(); | 253 | start = last_update = monotime(); |
254 | file = f; | 254 | file = f; |
diff --git a/progressmeter.h b/progressmeter.h index 10bab99ba..bf179dca6 100644 --- a/progressmeter.h +++ b/progressmeter.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: progressmeter.h,v 1.2 2006/03/25 22:22:43 djm Exp $ */ | 1 | /* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002 Nils Nordman. All rights reserved. | 3 | * Copyright (c) 2002 Nils Nordman. All rights reserved. |
4 | * | 4 | * |
@@ -23,5 +23,5 @@ | |||
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | void start_progress_meter(char *, off_t, off_t *); | 26 | void start_progress_meter(const char *, off_t, off_t *); |
27 | void stop_progress_meter(void); | 27 | void stop_progress_meter(void); |
diff --git a/sftp-client.c b/sftp-client.c index 990b58d14..574da833a 100644 --- a/sftp-client.c +++ b/sftp-client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-client.c,v 1.115 2014/04/21 14:36:16 logan Exp $ */ | 1 | /* $OpenBSD: sftp-client.c,v 1.116 2015/01/14 13:54:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -47,7 +47,8 @@ | |||
47 | #include <unistd.h> | 47 | #include <unistd.h> |
48 | 48 | ||
49 | #include "xmalloc.h" | 49 | #include "xmalloc.h" |
50 | #include "buffer.h" | 50 | #include "ssherr.h" |
51 | #include "sshbuf.h" | ||
51 | #include "log.h" | 52 | #include "log.h" |
52 | #include "atomicio.h" | 53 | #include "atomicio.h" |
53 | #include "progressmeter.h" | 54 | #include "progressmeter.h" |
@@ -83,8 +84,8 @@ struct sftp_conn { | |||
83 | struct bwlimit bwlimit_in, bwlimit_out; | 84 | struct bwlimit bwlimit_in, bwlimit_out; |
84 | }; | 85 | }; |
85 | 86 | ||
86 | static char * | 87 | static u_char * |
87 | get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, | 88 | get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, |
88 | const char *errfmt, ...) __attribute__((format(printf, 4, 5))); | 89 | const char *errfmt, ...) __attribute__((format(printf, 4, 5))); |
89 | 90 | ||
90 | /* ARGSUSED */ | 91 | /* ARGSUSED */ |
@@ -98,36 +99,39 @@ sftpio(void *_bwlimit, size_t amount) | |||
98 | } | 99 | } |
99 | 100 | ||
100 | static void | 101 | static void |
101 | send_msg(struct sftp_conn *conn, Buffer *m) | 102 | send_msg(struct sftp_conn *conn, struct sshbuf *m) |
102 | { | 103 | { |
103 | u_char mlen[4]; | 104 | u_char mlen[4]; |
104 | struct iovec iov[2]; | 105 | struct iovec iov[2]; |
105 | 106 | ||
106 | if (buffer_len(m) > SFTP_MAX_MSG_LENGTH) | 107 | if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) |
107 | fatal("Outbound message too long %u", buffer_len(m)); | 108 | fatal("Outbound message too long %zu", sshbuf_len(m)); |
108 | 109 | ||
109 | /* Send length first */ | 110 | /* Send length first */ |
110 | put_u32(mlen, buffer_len(m)); | 111 | put_u32(mlen, sshbuf_len(m)); |
111 | iov[0].iov_base = mlen; | 112 | iov[0].iov_base = mlen; |
112 | iov[0].iov_len = sizeof(mlen); | 113 | iov[0].iov_len = sizeof(mlen); |
113 | iov[1].iov_base = buffer_ptr(m); | 114 | iov[1].iov_base = (u_char *)sshbuf_ptr(m); |
114 | iov[1].iov_len = buffer_len(m); | 115 | iov[1].iov_len = sshbuf_len(m); |
115 | 116 | ||
116 | if (atomiciov6(writev, conn->fd_out, iov, 2, | 117 | if (atomiciov6(writev, conn->fd_out, iov, 2, |
117 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != | 118 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != |
118 | buffer_len(m) + sizeof(mlen)) | 119 | sshbuf_len(m) + sizeof(mlen)) |
119 | fatal("Couldn't send packet: %s", strerror(errno)); | 120 | fatal("Couldn't send packet: %s", strerror(errno)); |
120 | 121 | ||
121 | buffer_clear(m); | 122 | sshbuf_reset(m); |
122 | } | 123 | } |
123 | 124 | ||
124 | static void | 125 | static void |
125 | get_msg(struct sftp_conn *conn, Buffer *m) | 126 | get_msg(struct sftp_conn *conn, struct sshbuf *m) |
126 | { | 127 | { |
127 | u_int msg_len; | 128 | u_int msg_len; |
129 | u_char *p; | ||
130 | int r; | ||
128 | 131 | ||
129 | buffer_append_space(m, 4); | 132 | if ((r = sshbuf_reserve(m, 4, &p)) != 0) |
130 | if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4, | 133 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
134 | if (atomicio6(read, conn->fd_in, p, 4, | ||
131 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { | 135 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { |
132 | if (errno == EPIPE) | 136 | if (errno == EPIPE) |
133 | fatal("Connection closed"); | 137 | fatal("Connection closed"); |
@@ -135,12 +139,14 @@ get_msg(struct sftp_conn *conn, Buffer *m) | |||
135 | fatal("Couldn't read packet: %s", strerror(errno)); | 139 | fatal("Couldn't read packet: %s", strerror(errno)); |
136 | } | 140 | } |
137 | 141 | ||
138 | msg_len = buffer_get_int(m); | 142 | if ((r = sshbuf_get_u32(m, &msg_len)) != 0) |
143 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
139 | if (msg_len > SFTP_MAX_MSG_LENGTH) | 144 | if (msg_len > SFTP_MAX_MSG_LENGTH) |
140 | fatal("Received message too long %u", msg_len); | 145 | fatal("Received message too long %u", msg_len); |
141 | 146 | ||
142 | buffer_append_space(m, msg_len); | 147 | if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) |
143 | if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len, | 148 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
149 | if (atomicio6(read, conn->fd_in, p, msg_len, | ||
144 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) | 150 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) |
145 | != msg_len) { | 151 | != msg_len) { |
146 | if (errno == EPIPE) | 152 | if (errno == EPIPE) |
@@ -151,46 +157,56 @@ get_msg(struct sftp_conn *conn, Buffer *m) | |||
151 | } | 157 | } |
152 | 158 | ||
153 | static void | 159 | static void |
154 | send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, | 160 | send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, |
155 | u_int len) | 161 | u_int len) |
156 | { | 162 | { |
157 | Buffer msg; | 163 | struct sshbuf *msg; |
158 | 164 | int r; | |
159 | buffer_init(&msg); | 165 | |
160 | buffer_put_char(&msg, code); | 166 | if ((msg = sshbuf_new()) == NULL) |
161 | buffer_put_int(&msg, id); | 167 | fatal("%s: sshbuf_new failed", __func__); |
162 | buffer_put_string(&msg, s, len); | 168 | if ((r = sshbuf_put_u8(msg, code)) != 0 || |
163 | send_msg(conn, &msg); | 169 | (r = sshbuf_put_u32(msg, id)) != 0 || |
170 | (r = sshbuf_put_string(msg, s, len)) != 0) | ||
171 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
172 | send_msg(conn, msg); | ||
164 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); | 173 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); |
165 | buffer_free(&msg); | 174 | sshbuf_free(msg); |
166 | } | 175 | } |
167 | 176 | ||
168 | static void | 177 | static void |
169 | send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, | 178 | send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, |
170 | char *s, u_int len, Attrib *a) | 179 | const void *s, u_int len, Attrib *a) |
171 | { | 180 | { |
172 | Buffer msg; | 181 | struct sshbuf *msg; |
173 | 182 | int r; | |
174 | buffer_init(&msg); | 183 | |
175 | buffer_put_char(&msg, code); | 184 | if ((msg = sshbuf_new()) == NULL) |
176 | buffer_put_int(&msg, id); | 185 | fatal("%s: sshbuf_new failed", __func__); |
177 | buffer_put_string(&msg, s, len); | 186 | if ((r = sshbuf_put_u8(msg, code)) != 0 || |
178 | encode_attrib(&msg, a); | 187 | (r = sshbuf_put_u32(msg, id)) != 0 || |
179 | send_msg(conn, &msg); | 188 | (r = sshbuf_put_string(msg, s, len)) != 0 || |
189 | (r = encode_attrib(msg, a)) != 0) | ||
190 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
191 | send_msg(conn, msg); | ||
180 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); | 192 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); |
181 | buffer_free(&msg); | 193 | sshbuf_free(msg); |
182 | } | 194 | } |
183 | 195 | ||
184 | static u_int | 196 | static u_int |
185 | get_status(struct sftp_conn *conn, u_int expected_id) | 197 | get_status(struct sftp_conn *conn, u_int expected_id) |
186 | { | 198 | { |
187 | Buffer msg; | 199 | struct sshbuf *msg; |
188 | u_int type, id, status; | 200 | u_char type; |
201 | u_int id, status; | ||
202 | int r; | ||
189 | 203 | ||
190 | buffer_init(&msg); | 204 | if ((msg = sshbuf_new()) == NULL) |
191 | get_msg(conn, &msg); | 205 | fatal("%s: sshbuf_new failed", __func__); |
192 | type = buffer_get_char(&msg); | 206 | get_msg(conn, msg); |
193 | id = buffer_get_int(&msg); | 207 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
208 | (r = sshbuf_get_u32(msg, &id)) != 0) | ||
209 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
194 | 210 | ||
195 | if (id != expected_id) | 211 | if (id != expected_id) |
196 | fatal("ID mismatch (%u != %u)", id, expected_id); | 212 | fatal("ID mismatch (%u != %u)", id, expected_id); |
@@ -198,112 +214,136 @@ get_status(struct sftp_conn *conn, u_int expected_id) | |||
198 | fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", | 214 | fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", |
199 | SSH2_FXP_STATUS, type); | 215 | SSH2_FXP_STATUS, type); |
200 | 216 | ||
201 | status = buffer_get_int(&msg); | 217 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
202 | buffer_free(&msg); | 218 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
219 | sshbuf_free(msg); | ||
203 | 220 | ||
204 | debug3("SSH2_FXP_STATUS %u", status); | 221 | debug3("SSH2_FXP_STATUS %u", status); |
205 | 222 | ||
206 | return status; | 223 | return status; |
207 | } | 224 | } |
208 | 225 | ||
209 | static char * | 226 | static u_char * |
210 | get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, | 227 | get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, |
211 | const char *errfmt, ...) | 228 | const char *errfmt, ...) |
212 | { | 229 | { |
213 | Buffer msg; | 230 | struct sshbuf *msg; |
214 | u_int type, id; | 231 | u_int id, status; |
215 | char *handle, errmsg[256]; | 232 | u_char type; |
233 | u_char *handle; | ||
234 | char errmsg[256]; | ||
216 | va_list args; | 235 | va_list args; |
217 | int status; | 236 | int r; |
218 | 237 | ||
219 | va_start(args, errfmt); | 238 | va_start(args, errfmt); |
220 | if (errfmt != NULL) | 239 | if (errfmt != NULL) |
221 | vsnprintf(errmsg, sizeof(errmsg), errfmt, args); | 240 | vsnprintf(errmsg, sizeof(errmsg), errfmt, args); |
222 | va_end(args); | 241 | va_end(args); |
223 | 242 | ||
224 | buffer_init(&msg); | 243 | if ((msg = sshbuf_new()) == NULL) |
225 | get_msg(conn, &msg); | 244 | fatal("%s: sshbuf_new failed", __func__); |
226 | type = buffer_get_char(&msg); | 245 | get_msg(conn, msg); |
227 | id = buffer_get_int(&msg); | 246 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
247 | (r = sshbuf_get_u32(msg, &id)) != 0) | ||
248 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
228 | 249 | ||
229 | if (id != expected_id) | 250 | if (id != expected_id) |
230 | fatal("%s: ID mismatch (%u != %u)", | 251 | fatal("%s: ID mismatch (%u != %u)", |
231 | errfmt == NULL ? __func__ : errmsg, id, expected_id); | 252 | errfmt == NULL ? __func__ : errmsg, id, expected_id); |
232 | if (type == SSH2_FXP_STATUS) { | 253 | if (type == SSH2_FXP_STATUS) { |
233 | status = buffer_get_int(&msg); | 254 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
255 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
234 | if (errfmt != NULL) | 256 | if (errfmt != NULL) |
235 | error("%s: %s", errmsg, fx2txt(status)); | 257 | error("%s: %s", errmsg, fx2txt(status)); |
236 | buffer_free(&msg); | 258 | sshbuf_free(msg); |
237 | return(NULL); | 259 | return(NULL); |
238 | } else if (type != SSH2_FXP_HANDLE) | 260 | } else if (type != SSH2_FXP_HANDLE) |
239 | fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", | 261 | fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", |
240 | errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); | 262 | errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); |
241 | 263 | ||
242 | handle = buffer_get_string(&msg, len); | 264 | if ((r = sshbuf_get_string(msg, &handle, len)) != 0) |
243 | buffer_free(&msg); | 265 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
266 | sshbuf_free(msg); | ||
244 | 267 | ||
245 | return(handle); | 268 | return handle; |
246 | } | 269 | } |
247 | 270 | ||
248 | static Attrib * | 271 | static Attrib * |
249 | get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) | 272 | get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) |
250 | { | 273 | { |
251 | Buffer msg; | 274 | struct sshbuf *msg; |
252 | u_int type, id; | 275 | u_int id; |
253 | Attrib *a; | 276 | u_char type; |
277 | int r; | ||
278 | static Attrib a; | ||
254 | 279 | ||
255 | buffer_init(&msg); | 280 | if ((msg = sshbuf_new()) == NULL) |
256 | get_msg(conn, &msg); | 281 | fatal("%s: sshbuf_new failed", __func__); |
282 | get_msg(conn, msg); | ||
257 | 283 | ||
258 | type = buffer_get_char(&msg); | 284 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
259 | id = buffer_get_int(&msg); | 285 | (r = sshbuf_get_u32(msg, &id)) != 0) |
286 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
260 | 287 | ||
261 | debug3("Received stat reply T:%u I:%u", type, id); | 288 | debug3("Received stat reply T:%u I:%u", type, id); |
262 | if (id != expected_id) | 289 | if (id != expected_id) |
263 | fatal("ID mismatch (%u != %u)", id, expected_id); | 290 | fatal("ID mismatch (%u != %u)", id, expected_id); |
264 | if (type == SSH2_FXP_STATUS) { | 291 | if (type == SSH2_FXP_STATUS) { |
265 | int status = buffer_get_int(&msg); | 292 | u_int status; |
266 | 293 | ||
294 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
295 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
267 | if (quiet) | 296 | if (quiet) |
268 | debug("Couldn't stat remote file: %s", fx2txt(status)); | 297 | debug("Couldn't stat remote file: %s", fx2txt(status)); |
269 | else | 298 | else |
270 | error("Couldn't stat remote file: %s", fx2txt(status)); | 299 | error("Couldn't stat remote file: %s", fx2txt(status)); |
271 | buffer_free(&msg); | 300 | sshbuf_free(msg); |
272 | return(NULL); | 301 | return(NULL); |
273 | } else if (type != SSH2_FXP_ATTRS) { | 302 | } else if (type != SSH2_FXP_ATTRS) { |
274 | fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", | 303 | fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", |
275 | SSH2_FXP_ATTRS, type); | 304 | SSH2_FXP_ATTRS, type); |
276 | } | 305 | } |
277 | a = decode_attrib(&msg); | 306 | if ((r = decode_attrib(msg, &a)) != 0) { |
278 | buffer_free(&msg); | 307 | error("%s: couldn't decode attrib: %s", __func__, ssh_err(r)); |
308 | sshbuf_free(msg); | ||
309 | return NULL; | ||
310 | } | ||
311 | sshbuf_free(msg); | ||
279 | 312 | ||
280 | return(a); | 313 | return &a; |
281 | } | 314 | } |
282 | 315 | ||
283 | static int | 316 | static int |
284 | get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, | 317 | get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, |
285 | u_int expected_id, int quiet) | 318 | u_int expected_id, int quiet) |
286 | { | 319 | { |
287 | Buffer msg; | 320 | struct sshbuf *msg; |
288 | u_int type, id, flag; | 321 | u_char type; |
322 | u_int id; | ||
323 | u_int64_t flag; | ||
324 | int r; | ||
289 | 325 | ||
290 | buffer_init(&msg); | 326 | if ((msg = sshbuf_new()) == NULL) |
291 | get_msg(conn, &msg); | 327 | fatal("%s: sshbuf_new failed", __func__); |
328 | get_msg(conn, msg); | ||
292 | 329 | ||
293 | type = buffer_get_char(&msg); | 330 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
294 | id = buffer_get_int(&msg); | 331 | (r = sshbuf_get_u32(msg, &id)) != 0) |
332 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
295 | 333 | ||
296 | debug3("Received statvfs reply T:%u I:%u", type, id); | 334 | debug3("Received statvfs reply T:%u I:%u", type, id); |
297 | if (id != expected_id) | 335 | if (id != expected_id) |
298 | fatal("ID mismatch (%u != %u)", id, expected_id); | 336 | fatal("ID mismatch (%u != %u)", id, expected_id); |
299 | if (type == SSH2_FXP_STATUS) { | 337 | if (type == SSH2_FXP_STATUS) { |
300 | int status = buffer_get_int(&msg); | 338 | u_int status; |
301 | 339 | ||
340 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
341 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
302 | if (quiet) | 342 | if (quiet) |
303 | debug("Couldn't statvfs: %s", fx2txt(status)); | 343 | debug("Couldn't statvfs: %s", fx2txt(status)); |
304 | else | 344 | else |
305 | error("Couldn't statvfs: %s", fx2txt(status)); | 345 | error("Couldn't statvfs: %s", fx2txt(status)); |
306 | buffer_free(&msg); | 346 | sshbuf_free(msg); |
307 | return -1; | 347 | return -1; |
308 | } else if (type != SSH2_FXP_EXTENDED_REPLY) { | 348 | } else if (type != SSH2_FXP_EXTENDED_REPLY) { |
309 | fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", | 349 | fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", |
@@ -311,22 +351,23 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, | |||
311 | } | 351 | } |
312 | 352 | ||
313 | memset(st, 0, sizeof(*st)); | 353 | memset(st, 0, sizeof(*st)); |
314 | st->f_bsize = buffer_get_int64(&msg); | 354 | if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || |
315 | st->f_frsize = buffer_get_int64(&msg); | 355 | (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || |
316 | st->f_blocks = buffer_get_int64(&msg); | 356 | (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || |
317 | st->f_bfree = buffer_get_int64(&msg); | 357 | (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || |
318 | st->f_bavail = buffer_get_int64(&msg); | 358 | (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || |
319 | st->f_files = buffer_get_int64(&msg); | 359 | (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || |
320 | st->f_ffree = buffer_get_int64(&msg); | 360 | (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || |
321 | st->f_favail = buffer_get_int64(&msg); | 361 | (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || |
322 | st->f_fsid = buffer_get_int64(&msg); | 362 | (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || |
323 | flag = buffer_get_int64(&msg); | 363 | (r = sshbuf_get_u64(msg, &flag)) != 0 || |
324 | st->f_namemax = buffer_get_int64(&msg); | 364 | (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) |
365 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
325 | 366 | ||
326 | st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; | 367 | st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; |
327 | st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; | 368 | st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; |
328 | 369 | ||
329 | buffer_free(&msg); | 370 | sshbuf_free(msg); |
330 | 371 | ||
331 | return 0; | 372 | return 0; |
332 | } | 373 | } |
@@ -335,9 +376,10 @@ struct sftp_conn * | |||
335 | do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, | 376 | do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, |
336 | u_int64_t limit_kbps) | 377 | u_int64_t limit_kbps) |
337 | { | 378 | { |
338 | u_int type; | 379 | u_char type; |
339 | Buffer msg; | 380 | struct sshbuf *msg; |
340 | struct sftp_conn *ret; | 381 | struct sftp_conn *ret; |
382 | int r; | ||
341 | 383 | ||
342 | ret = xcalloc(1, sizeof(*ret)); | 384 | ret = xcalloc(1, sizeof(*ret)); |
343 | ret->msg_id = 1; | 385 | ret->msg_id = 1; |
@@ -348,52 +390,61 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, | |||
348 | ret->exts = 0; | 390 | ret->exts = 0; |
349 | ret->limit_kbps = 0; | 391 | ret->limit_kbps = 0; |
350 | 392 | ||
351 | buffer_init(&msg); | 393 | if ((msg = sshbuf_new()) == NULL) |
352 | buffer_put_char(&msg, SSH2_FXP_INIT); | 394 | fatal("%s: sshbuf_new failed", __func__); |
353 | buffer_put_int(&msg, SSH2_FILEXFER_VERSION); | 395 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || |
354 | send_msg(ret, &msg); | 396 | (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) |
397 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
398 | send_msg(ret, msg); | ||
355 | 399 | ||
356 | buffer_clear(&msg); | 400 | sshbuf_reset(msg); |
357 | 401 | ||
358 | get_msg(ret, &msg); | 402 | get_msg(ret, msg); |
359 | 403 | ||
360 | /* Expecting a VERSION reply */ | 404 | /* Expecting a VERSION reply */ |
361 | if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { | 405 | if ((r = sshbuf_get_u8(msg, &type)) != 0) |
406 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
407 | if (type != SSH2_FXP_VERSION) { | ||
362 | error("Invalid packet back from SSH2_FXP_INIT (type %u)", | 408 | error("Invalid packet back from SSH2_FXP_INIT (type %u)", |
363 | type); | 409 | type); |
364 | buffer_free(&msg); | 410 | sshbuf_free(msg); |
365 | return(NULL); | 411 | return(NULL); |
366 | } | 412 | } |
367 | ret->version = buffer_get_int(&msg); | 413 | if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) |
414 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
368 | 415 | ||
369 | debug2("Remote version: %u", ret->version); | 416 | debug2("Remote version: %u", ret->version); |
370 | 417 | ||
371 | /* Check for extensions */ | 418 | /* Check for extensions */ |
372 | while (buffer_len(&msg) > 0) { | 419 | while (sshbuf_len(msg) > 0) { |
373 | char *name = buffer_get_string(&msg, NULL); | 420 | char *name; |
374 | char *value = buffer_get_string(&msg, NULL); | 421 | u_char *value; |
422 | size_t vlen; | ||
375 | int known = 0; | 423 | int known = 0; |
376 | 424 | ||
425 | if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || | ||
426 | (r = sshbuf_get_string(msg, &value, &vlen)) != 0) | ||
427 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
377 | if (strcmp(name, "posix-rename@openssh.com") == 0 && | 428 | if (strcmp(name, "posix-rename@openssh.com") == 0 && |
378 | strcmp(value, "1") == 0) { | 429 | strcmp((char *)value, "1") == 0) { |
379 | ret->exts |= SFTP_EXT_POSIX_RENAME; | 430 | ret->exts |= SFTP_EXT_POSIX_RENAME; |
380 | known = 1; | 431 | known = 1; |
381 | } else if (strcmp(name, "statvfs@openssh.com") == 0 && | 432 | } else if (strcmp(name, "statvfs@openssh.com") == 0 && |
382 | strcmp(value, "2") == 0) { | 433 | strcmp((char *)value, "2") == 0) { |
383 | ret->exts |= SFTP_EXT_STATVFS; | 434 | ret->exts |= SFTP_EXT_STATVFS; |
384 | known = 1; | 435 | known = 1; |
385 | } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && | 436 | } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && |
386 | strcmp(value, "2") == 0) { | 437 | strcmp((char *)value, "2") == 0) { |
387 | ret->exts |= SFTP_EXT_FSTATVFS; | 438 | ret->exts |= SFTP_EXT_FSTATVFS; |
388 | known = 1; | 439 | known = 1; |
389 | } else if (strcmp(name, "hardlink@openssh.com") == 0 && | 440 | } else if (strcmp(name, "hardlink@openssh.com") == 0 && |
390 | strcmp(value, "1") == 0) { | 441 | strcmp((char *)value, "1") == 0) { |
391 | ret->exts |= SFTP_EXT_HARDLINK; | 442 | ret->exts |= SFTP_EXT_HARDLINK; |
392 | known = 1; | 443 | known = 1; |
393 | } else if (strcmp(name, "fsync@openssh.com") == 0 && | 444 | } else if (strcmp(name, "fsync@openssh.com") == 0 && |
394 | strcmp(value, "1") == 0) { | 445 | strcmp((char *)value, "1") == 0) { |
395 | ret->exts |= SFTP_EXT_FSYNC; | 446 | ret->exts |= SFTP_EXT_FSYNC; |
396 | known = 1; | 447 | known = 1; |
397 | } | 448 | } |
398 | if (known) { | 449 | if (known) { |
399 | debug2("Server supports extension \"%s\" revision %s", | 450 | debug2("Server supports extension \"%s\" revision %s", |
@@ -405,7 +456,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, | |||
405 | free(value); | 456 | free(value); |
406 | } | 457 | } |
407 | 458 | ||
408 | buffer_free(&msg); | 459 | sshbuf_free(msg); |
409 | 460 | ||
410 | /* Some filexfer v.0 servers don't support large packets */ | 461 | /* Some filexfer v.0 servers don't support large packets */ |
411 | if (ret->version == 0) | 462 | if (ret->version == 0) |
@@ -429,54 +480,62 @@ sftp_proto_version(struct sftp_conn *conn) | |||
429 | } | 480 | } |
430 | 481 | ||
431 | int | 482 | int |
432 | do_close(struct sftp_conn *conn, char *handle, u_int handle_len) | 483 | do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) |
433 | { | 484 | { |
434 | u_int id, status; | 485 | u_int id, status; |
435 | Buffer msg; | 486 | struct sshbuf *msg; |
487 | int r; | ||
436 | 488 | ||
437 | buffer_init(&msg); | 489 | if ((msg = sshbuf_new()) == NULL) |
490 | fatal("%s: sshbuf_new failed", __func__); | ||
438 | 491 | ||
439 | id = conn->msg_id++; | 492 | id = conn->msg_id++; |
440 | buffer_put_char(&msg, SSH2_FXP_CLOSE); | 493 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || |
441 | buffer_put_int(&msg, id); | 494 | (r = sshbuf_put_u32(msg, id)) != 0 || |
442 | buffer_put_string(&msg, handle, handle_len); | 495 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
443 | send_msg(conn, &msg); | 496 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
497 | send_msg(conn, msg); | ||
444 | debug3("Sent message SSH2_FXP_CLOSE I:%u", id); | 498 | debug3("Sent message SSH2_FXP_CLOSE I:%u", id); |
445 | 499 | ||
446 | status = get_status(conn, id); | 500 | status = get_status(conn, id); |
447 | if (status != SSH2_FX_OK) | 501 | if (status != SSH2_FX_OK) |
448 | error("Couldn't close file: %s", fx2txt(status)); | 502 | error("Couldn't close file: %s", fx2txt(status)); |
449 | 503 | ||
450 | buffer_free(&msg); | 504 | sshbuf_free(msg); |
451 | 505 | ||
452 | return status; | 506 | return status == SSH2_FX_OK ? 0 : -1; |
453 | } | 507 | } |
454 | 508 | ||
455 | 509 | ||
456 | static int | 510 | static int |
457 | do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | 511 | do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, |
458 | SFTP_DIRENT ***dir) | 512 | SFTP_DIRENT ***dir) |
459 | { | 513 | { |
460 | Buffer msg; | 514 | struct sshbuf *msg; |
461 | u_int count, type, id, handle_len, i, expected_id, ents = 0; | 515 | u_int count, id, i, expected_id, ents = 0; |
516 | size_t handle_len; | ||
517 | u_char type; | ||
462 | char *handle; | 518 | char *handle; |
463 | int status = SSH2_FX_FAILURE; | 519 | int status = SSH2_FX_FAILURE; |
520 | int r; | ||
464 | 521 | ||
465 | if (dir) | 522 | if (dir) |
466 | *dir = NULL; | 523 | *dir = NULL; |
467 | 524 | ||
468 | id = conn->msg_id++; | 525 | id = conn->msg_id++; |
469 | 526 | ||
470 | buffer_init(&msg); | 527 | if ((msg = sshbuf_new()) == NULL) |
471 | buffer_put_char(&msg, SSH2_FXP_OPENDIR); | 528 | fatal("%s: sshbuf_new failed", __func__); |
472 | buffer_put_int(&msg, id); | 529 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || |
473 | buffer_put_cstring(&msg, path); | 530 | (r = sshbuf_put_u32(msg, id)) != 0 || |
474 | send_msg(conn, &msg); | 531 | (r = sshbuf_put_cstring(msg, path)) != 0) |
532 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
533 | send_msg(conn, msg); | ||
475 | 534 | ||
476 | handle = get_handle(conn, id, &handle_len, | 535 | handle = get_handle(conn, id, &handle_len, |
477 | "remote readdir(\"%s\")", path); | 536 | "remote readdir(\"%s\")", path); |
478 | if (handle == NULL) { | 537 | if (handle == NULL) { |
479 | buffer_free(&msg); | 538 | sshbuf_free(msg); |
480 | return -1; | 539 | return -1; |
481 | } | 540 | } |
482 | 541 | ||
@@ -491,18 +550,20 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
491 | 550 | ||
492 | debug3("Sending SSH2_FXP_READDIR I:%u", id); | 551 | debug3("Sending SSH2_FXP_READDIR I:%u", id); |
493 | 552 | ||
494 | buffer_clear(&msg); | 553 | sshbuf_reset(msg); |
495 | buffer_put_char(&msg, SSH2_FXP_READDIR); | 554 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || |
496 | buffer_put_int(&msg, id); | 555 | (r = sshbuf_put_u32(msg, id)) != 0 || |
497 | buffer_put_string(&msg, handle, handle_len); | 556 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
498 | send_msg(conn, &msg); | 557 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
558 | send_msg(conn, msg); | ||
499 | 559 | ||
500 | buffer_clear(&msg); | 560 | sshbuf_reset(msg); |
501 | 561 | ||
502 | get_msg(conn, &msg); | 562 | get_msg(conn, msg); |
503 | 563 | ||
504 | type = buffer_get_char(&msg); | 564 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
505 | id = buffer_get_int(&msg); | 565 | (r = sshbuf_get_u32(msg, &id)) != 0) |
566 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
506 | 567 | ||
507 | debug3("Received reply T:%u I:%u", type, id); | 568 | debug3("Received reply T:%u I:%u", type, id); |
508 | 569 | ||
@@ -510,27 +571,43 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
510 | fatal("ID mismatch (%u != %u)", id, expected_id); | 571 | fatal("ID mismatch (%u != %u)", id, expected_id); |
511 | 572 | ||
512 | if (type == SSH2_FXP_STATUS) { | 573 | if (type == SSH2_FXP_STATUS) { |
513 | status = buffer_get_int(&msg); | 574 | u_int rstatus; |
514 | debug3("Received SSH2_FXP_STATUS %d", status); | 575 | |
515 | if (status == SSH2_FX_EOF) | 576 | if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) |
577 | fatal("%s: buffer error: %s", | ||
578 | __func__, ssh_err(r)); | ||
579 | debug3("Received SSH2_FXP_STATUS %d", rstatus); | ||
580 | if (rstatus == SSH2_FX_EOF) | ||
516 | break; | 581 | break; |
517 | error("Couldn't read directory: %s", fx2txt(status)); | 582 | error("Couldn't read directory: %s", fx2txt(rstatus)); |
518 | goto out; | 583 | goto out; |
519 | } else if (type != SSH2_FXP_NAME) | 584 | } else if (type != SSH2_FXP_NAME) |
520 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", | 585 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", |
521 | SSH2_FXP_NAME, type); | 586 | SSH2_FXP_NAME, type); |
522 | 587 | ||
523 | count = buffer_get_int(&msg); | 588 | if ((r = sshbuf_get_u32(msg, &count)) != 0) |
589 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
524 | if (count == 0) | 590 | if (count == 0) |
525 | break; | 591 | break; |
526 | debug3("Received %d SSH2_FXP_NAME responses", count); | 592 | debug3("Received %d SSH2_FXP_NAME responses", count); |
527 | for (i = 0; i < count; i++) { | 593 | for (i = 0; i < count; i++) { |
528 | char *filename, *longname; | 594 | char *filename, *longname; |
529 | Attrib *a; | 595 | Attrib a; |
530 | 596 | ||
531 | filename = buffer_get_string(&msg, NULL); | 597 | if ((r = sshbuf_get_cstring(msg, &filename, |
532 | longname = buffer_get_string(&msg, NULL); | 598 | NULL)) != 0 || |
533 | a = decode_attrib(&msg); | 599 | (r = sshbuf_get_cstring(msg, &longname, |
600 | NULL)) != 0) | ||
601 | fatal("%s: buffer error: %s", | ||
602 | __func__, ssh_err(r)); | ||
603 | if ((r = decode_attrib(msg, &a)) != 0) { | ||
604 | error("%s: couldn't decode attrib: %s", | ||
605 | __func__, ssh_err(r)); | ||
606 | free(filename); | ||
607 | free(longname); | ||
608 | sshbuf_free(msg); | ||
609 | return -1; | ||
610 | } | ||
534 | 611 | ||
535 | if (print_flag) | 612 | if (print_flag) |
536 | printf("%s\n", longname); | 613 | printf("%s\n", longname); |
@@ -548,7 +625,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
548 | (*dir)[ents] = xcalloc(1, sizeof(***dir)); | 625 | (*dir)[ents] = xcalloc(1, sizeof(***dir)); |
549 | (*dir)[ents]->filename = xstrdup(filename); | 626 | (*dir)[ents]->filename = xstrdup(filename); |
550 | (*dir)[ents]->longname = xstrdup(longname); | 627 | (*dir)[ents]->longname = xstrdup(longname); |
551 | memcpy(&(*dir)[ents]->a, a, sizeof(*a)); | 628 | memcpy(&(*dir)[ents]->a, &a, sizeof(a)); |
552 | (*dir)[++ents] = NULL; | 629 | (*dir)[++ents] = NULL; |
553 | } | 630 | } |
554 | free(filename); | 631 | free(filename); |
@@ -558,7 +635,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
558 | status = 0; | 635 | status = 0; |
559 | 636 | ||
560 | out: | 637 | out: |
561 | buffer_free(&msg); | 638 | sshbuf_free(msg); |
562 | do_close(conn, handle, handle_len); | 639 | do_close(conn, handle, handle_len); |
563 | free(handle); | 640 | free(handle); |
564 | 641 | ||
@@ -577,7 +654,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
577 | } | 654 | } |
578 | 655 | ||
579 | int | 656 | int |
580 | do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) | 657 | do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) |
581 | { | 658 | { |
582 | return(do_lsreaddir(conn, path, 0, dir)); | 659 | return(do_lsreaddir(conn, path, 0, dir)); |
583 | } | 660 | } |
@@ -597,7 +674,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) | |||
597 | } | 674 | } |
598 | 675 | ||
599 | int | 676 | int |
600 | do_rm(struct sftp_conn *conn, char *path) | 677 | do_rm(struct sftp_conn *conn, const char *path) |
601 | { | 678 | { |
602 | u_int status, id; | 679 | u_int status, id; |
603 | 680 | ||
@@ -608,11 +685,11 @@ do_rm(struct sftp_conn *conn, char *path) | |||
608 | status = get_status(conn, id); | 685 | status = get_status(conn, id); |
609 | if (status != SSH2_FX_OK) | 686 | if (status != SSH2_FX_OK) |
610 | error("Couldn't delete file: %s", fx2txt(status)); | 687 | error("Couldn't delete file: %s", fx2txt(status)); |
611 | return(status); | 688 | return status == SSH2_FX_OK ? 0 : -1; |
612 | } | 689 | } |
613 | 690 | ||
614 | int | 691 | int |
615 | do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) | 692 | do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) |
616 | { | 693 | { |
617 | u_int status, id; | 694 | u_int status, id; |
618 | 695 | ||
@@ -624,11 +701,11 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) | |||
624 | if (status != SSH2_FX_OK && print_flag) | 701 | if (status != SSH2_FX_OK && print_flag) |
625 | error("Couldn't create directory: %s", fx2txt(status)); | 702 | error("Couldn't create directory: %s", fx2txt(status)); |
626 | 703 | ||
627 | return(status); | 704 | return status == SSH2_FX_OK ? 0 : -1; |
628 | } | 705 | } |
629 | 706 | ||
630 | int | 707 | int |
631 | do_rmdir(struct sftp_conn *conn, char *path) | 708 | do_rmdir(struct sftp_conn *conn, const char *path) |
632 | { | 709 | { |
633 | u_int status, id; | 710 | u_int status, id; |
634 | 711 | ||
@@ -640,11 +717,11 @@ do_rmdir(struct sftp_conn *conn, char *path) | |||
640 | if (status != SSH2_FX_OK) | 717 | if (status != SSH2_FX_OK) |
641 | error("Couldn't remove directory: %s", fx2txt(status)); | 718 | error("Couldn't remove directory: %s", fx2txt(status)); |
642 | 719 | ||
643 | return(status); | 720 | return status == SSH2_FX_OK ? 0 : -1; |
644 | } | 721 | } |
645 | 722 | ||
646 | Attrib * | 723 | Attrib * |
647 | do_stat(struct sftp_conn *conn, char *path, int quiet) | 724 | do_stat(struct sftp_conn *conn, const char *path, int quiet) |
648 | { | 725 | { |
649 | u_int id; | 726 | u_int id; |
650 | 727 | ||
@@ -658,7 +735,7 @@ do_stat(struct sftp_conn *conn, char *path, int quiet) | |||
658 | } | 735 | } |
659 | 736 | ||
660 | Attrib * | 737 | Attrib * |
661 | do_lstat(struct sftp_conn *conn, char *path, int quiet) | 738 | do_lstat(struct sftp_conn *conn, const char *path, int quiet) |
662 | { | 739 | { |
663 | u_int id; | 740 | u_int id; |
664 | 741 | ||
@@ -679,7 +756,8 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet) | |||
679 | 756 | ||
680 | #ifdef notyet | 757 | #ifdef notyet |
681 | Attrib * | 758 | Attrib * |
682 | do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) | 759 | do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, |
760 | int quiet) | ||
683 | { | 761 | { |
684 | u_int id; | 762 | u_int id; |
685 | 763 | ||
@@ -692,7 +770,7 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) | |||
692 | #endif | 770 | #endif |
693 | 771 | ||
694 | int | 772 | int |
695 | do_setstat(struct sftp_conn *conn, char *path, Attrib *a) | 773 | do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) |
696 | { | 774 | { |
697 | u_int status, id; | 775 | u_int status, id; |
698 | 776 | ||
@@ -705,11 +783,11 @@ do_setstat(struct sftp_conn *conn, char *path, Attrib *a) | |||
705 | error("Couldn't setstat on \"%s\": %s", path, | 783 | error("Couldn't setstat on \"%s\": %s", path, |
706 | fx2txt(status)); | 784 | fx2txt(status)); |
707 | 785 | ||
708 | return(status); | 786 | return status == SSH2_FX_OK ? 0 : -1; |
709 | } | 787 | } |
710 | 788 | ||
711 | int | 789 | int |
712 | do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, | 790 | do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, |
713 | Attrib *a) | 791 | Attrib *a) |
714 | { | 792 | { |
715 | u_int status, id; | 793 | u_int status, id; |
@@ -722,181 +800,201 @@ do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, | |||
722 | if (status != SSH2_FX_OK) | 800 | if (status != SSH2_FX_OK) |
723 | error("Couldn't fsetstat: %s", fx2txt(status)); | 801 | error("Couldn't fsetstat: %s", fx2txt(status)); |
724 | 802 | ||
725 | return(status); | 803 | return status == SSH2_FX_OK ? 0 : -1; |
726 | } | 804 | } |
727 | 805 | ||
728 | char * | 806 | char * |
729 | do_realpath(struct sftp_conn *conn, char *path) | 807 | do_realpath(struct sftp_conn *conn, const char *path) |
730 | { | 808 | { |
731 | Buffer msg; | 809 | struct sshbuf *msg; |
732 | u_int type, expected_id, count, id; | 810 | u_int expected_id, count, id; |
733 | char *filename, *longname; | 811 | char *filename, *longname; |
734 | Attrib *a; | 812 | Attrib a; |
813 | u_char type; | ||
814 | int r; | ||
735 | 815 | ||
736 | expected_id = id = conn->msg_id++; | 816 | expected_id = id = conn->msg_id++; |
737 | send_string_request(conn, id, SSH2_FXP_REALPATH, path, | 817 | send_string_request(conn, id, SSH2_FXP_REALPATH, path, |
738 | strlen(path)); | 818 | strlen(path)); |
739 | 819 | ||
740 | buffer_init(&msg); | 820 | if ((msg = sshbuf_new()) == NULL) |
821 | fatal("%s: sshbuf_new failed", __func__); | ||
741 | 822 | ||
742 | get_msg(conn, &msg); | 823 | get_msg(conn, msg); |
743 | type = buffer_get_char(&msg); | 824 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
744 | id = buffer_get_int(&msg); | 825 | (r = sshbuf_get_u32(msg, &id)) != 0) |
826 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
745 | 827 | ||
746 | if (id != expected_id) | 828 | if (id != expected_id) |
747 | fatal("ID mismatch (%u != %u)", id, expected_id); | 829 | fatal("ID mismatch (%u != %u)", id, expected_id); |
748 | 830 | ||
749 | if (type == SSH2_FXP_STATUS) { | 831 | if (type == SSH2_FXP_STATUS) { |
750 | u_int status = buffer_get_int(&msg); | 832 | u_int status; |
751 | 833 | ||
834 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
835 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
752 | error("Couldn't canonicalize: %s", fx2txt(status)); | 836 | error("Couldn't canonicalize: %s", fx2txt(status)); |
753 | buffer_free(&msg); | 837 | sshbuf_free(msg); |
754 | return NULL; | 838 | return NULL; |
755 | } else if (type != SSH2_FXP_NAME) | 839 | } else if (type != SSH2_FXP_NAME) |
756 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", | 840 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", |
757 | SSH2_FXP_NAME, type); | 841 | SSH2_FXP_NAME, type); |
758 | 842 | ||
759 | count = buffer_get_int(&msg); | 843 | if ((r = sshbuf_get_u32(msg, &count)) != 0) |
844 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
760 | if (count != 1) | 845 | if (count != 1) |
761 | fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); | 846 | fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); |
762 | 847 | ||
763 | filename = buffer_get_string(&msg, NULL); | 848 | if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || |
764 | longname = buffer_get_string(&msg, NULL); | 849 | (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || |
765 | a = decode_attrib(&msg); | 850 | (r = decode_attrib(msg, &a)) != 0) |
851 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
766 | 852 | ||
767 | debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, | 853 | debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, |
768 | (unsigned long)a->size); | 854 | (unsigned long)a.size); |
769 | 855 | ||
770 | free(longname); | 856 | free(longname); |
771 | 857 | ||
772 | buffer_free(&msg); | 858 | sshbuf_free(msg); |
773 | 859 | ||
774 | return(filename); | 860 | return(filename); |
775 | } | 861 | } |
776 | 862 | ||
777 | int | 863 | int |
778 | do_rename(struct sftp_conn *conn, char *oldpath, char *newpath, | 864 | do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, |
779 | int force_legacy) | 865 | int force_legacy) |
780 | { | 866 | { |
781 | Buffer msg; | 867 | struct sshbuf *msg; |
782 | u_int status, id; | 868 | u_int status, id; |
783 | int use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; | 869 | int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; |
784 | 870 | ||
785 | buffer_init(&msg); | 871 | if ((msg = sshbuf_new()) == NULL) |
872 | fatal("%s: sshbuf_new failed", __func__); | ||
786 | 873 | ||
787 | /* Send rename request */ | 874 | /* Send rename request */ |
788 | id = conn->msg_id++; | 875 | id = conn->msg_id++; |
789 | if (use_ext) { | 876 | if (use_ext) { |
790 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 877 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
791 | buffer_put_int(&msg, id); | 878 | (r = sshbuf_put_u32(msg, id)) != 0 || |
792 | buffer_put_cstring(&msg, "posix-rename@openssh.com"); | 879 | (r = sshbuf_put_cstring(msg, |
880 | "posix-rename@openssh.com")) != 0) | ||
881 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
793 | } else { | 882 | } else { |
794 | buffer_put_char(&msg, SSH2_FXP_RENAME); | 883 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || |
795 | buffer_put_int(&msg, id); | 884 | (r = sshbuf_put_u32(msg, id)) != 0) |
885 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
796 | } | 886 | } |
797 | buffer_put_cstring(&msg, oldpath); | 887 | if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || |
798 | buffer_put_cstring(&msg, newpath); | 888 | (r = sshbuf_put_cstring(msg, newpath)) != 0) |
799 | send_msg(conn, &msg); | 889 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
890 | send_msg(conn, msg); | ||
800 | debug3("Sent message %s \"%s\" -> \"%s\"", | 891 | debug3("Sent message %s \"%s\" -> \"%s\"", |
801 | use_ext ? "posix-rename@openssh.com" : "SSH2_FXP_RENAME", | 892 | use_ext ? "posix-rename@openssh.com" : |
802 | oldpath, newpath); | 893 | "SSH2_FXP_RENAME", oldpath, newpath); |
803 | buffer_free(&msg); | 894 | sshbuf_free(msg); |
804 | 895 | ||
805 | status = get_status(conn, id); | 896 | status = get_status(conn, id); |
806 | if (status != SSH2_FX_OK) | 897 | if (status != SSH2_FX_OK) |
807 | error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, | 898 | error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, |
808 | newpath, fx2txt(status)); | 899 | newpath, fx2txt(status)); |
809 | 900 | ||
810 | return(status); | 901 | return status == SSH2_FX_OK ? 0 : -1; |
811 | } | 902 | } |
812 | 903 | ||
813 | int | 904 | int |
814 | do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) | 905 | do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) |
815 | { | 906 | { |
816 | Buffer msg; | 907 | struct sshbuf *msg; |
817 | u_int status, id; | 908 | u_int status, id; |
909 | int r; | ||
818 | 910 | ||
819 | if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { | 911 | if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { |
820 | error("Server does not support hardlink@openssh.com extension"); | 912 | error("Server does not support hardlink@openssh.com extension"); |
821 | return -1; | 913 | return -1; |
822 | } | 914 | } |
823 | 915 | ||
824 | buffer_init(&msg); | 916 | if ((msg = sshbuf_new()) == NULL) |
917 | fatal("%s: sshbuf_new failed", __func__); | ||
825 | 918 | ||
826 | /* Send link request */ | 919 | /* Send link request */ |
827 | id = conn->msg_id++; | 920 | id = conn->msg_id++; |
828 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 921 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
829 | buffer_put_int(&msg, id); | 922 | (r = sshbuf_put_u32(msg, id)) != 0 || |
830 | buffer_put_cstring(&msg, "hardlink@openssh.com"); | 923 | (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || |
831 | buffer_put_cstring(&msg, oldpath); | 924 | (r = sshbuf_put_cstring(msg, oldpath)) != 0 || |
832 | buffer_put_cstring(&msg, newpath); | 925 | (r = sshbuf_put_cstring(msg, newpath)) != 0) |
833 | send_msg(conn, &msg); | 926 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
927 | send_msg(conn, msg); | ||
834 | debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", | 928 | debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", |
835 | oldpath, newpath); | 929 | oldpath, newpath); |
836 | buffer_free(&msg); | 930 | sshbuf_free(msg); |
837 | 931 | ||
838 | status = get_status(conn, id); | 932 | status = get_status(conn, id); |
839 | if (status != SSH2_FX_OK) | 933 | if (status != SSH2_FX_OK) |
840 | error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, | 934 | error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, |
841 | newpath, fx2txt(status)); | 935 | newpath, fx2txt(status)); |
842 | 936 | ||
843 | return(status); | 937 | return status == SSH2_FX_OK ? 0 : -1; |
844 | } | 938 | } |
845 | 939 | ||
846 | int | 940 | int |
847 | do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) | 941 | do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) |
848 | { | 942 | { |
849 | Buffer msg; | 943 | struct sshbuf *msg; |
850 | u_int status, id; | 944 | u_int status, id; |
945 | int r; | ||
851 | 946 | ||
852 | if (conn->version < 3) { | 947 | if (conn->version < 3) { |
853 | error("This server does not support the symlink operation"); | 948 | error("This server does not support the symlink operation"); |
854 | return(SSH2_FX_OP_UNSUPPORTED); | 949 | return(SSH2_FX_OP_UNSUPPORTED); |
855 | } | 950 | } |
856 | 951 | ||
857 | buffer_init(&msg); | 952 | if ((msg = sshbuf_new()) == NULL) |
953 | fatal("%s: sshbuf_new failed", __func__); | ||
858 | 954 | ||
859 | /* Send symlink request */ | 955 | /* Send symlink request */ |
860 | id = conn->msg_id++; | 956 | id = conn->msg_id++; |
861 | buffer_put_char(&msg, SSH2_FXP_SYMLINK); | 957 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || |
862 | buffer_put_int(&msg, id); | 958 | (r = sshbuf_put_u32(msg, id)) != 0 || |
863 | buffer_put_cstring(&msg, oldpath); | 959 | (r = sshbuf_put_cstring(msg, oldpath)) != 0 || |
864 | buffer_put_cstring(&msg, newpath); | 960 | (r = sshbuf_put_cstring(msg, newpath)) != 0) |
865 | send_msg(conn, &msg); | 961 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
962 | send_msg(conn, msg); | ||
866 | debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, | 963 | debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, |
867 | newpath); | 964 | newpath); |
868 | buffer_free(&msg); | 965 | sshbuf_free(msg); |
869 | 966 | ||
870 | status = get_status(conn, id); | 967 | status = get_status(conn, id); |
871 | if (status != SSH2_FX_OK) | 968 | if (status != SSH2_FX_OK) |
872 | error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, | 969 | error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, |
873 | newpath, fx2txt(status)); | 970 | newpath, fx2txt(status)); |
874 | 971 | ||
875 | return(status); | 972 | return status == SSH2_FX_OK ? 0 : -1; |
876 | } | 973 | } |
877 | 974 | ||
878 | int | 975 | int |
879 | do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) | 976 | do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) |
880 | { | 977 | { |
881 | Buffer msg; | 978 | struct sshbuf *msg; |
882 | u_int status, id; | 979 | u_int status, id; |
980 | int r; | ||
883 | 981 | ||
884 | /* Silently return if the extension is not supported */ | 982 | /* Silently return if the extension is not supported */ |
885 | if ((conn->exts & SFTP_EXT_FSYNC) == 0) | 983 | if ((conn->exts & SFTP_EXT_FSYNC) == 0) |
886 | return -1; | 984 | return -1; |
887 | 985 | ||
888 | buffer_init(&msg); | ||
889 | |||
890 | /* Send fsync request */ | 986 | /* Send fsync request */ |
987 | if ((msg = sshbuf_new()) == NULL) | ||
988 | fatal("%s: sshbuf_new failed", __func__); | ||
891 | id = conn->msg_id++; | 989 | id = conn->msg_id++; |
892 | 990 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || | |
893 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 991 | (r = sshbuf_put_u32(msg, id)) != 0 || |
894 | buffer_put_int(&msg, id); | 992 | (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || |
895 | buffer_put_cstring(&msg, "fsync@openssh.com"); | 993 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
896 | buffer_put_string(&msg, handle, handle_len); | 994 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
897 | send_msg(conn, &msg); | 995 | send_msg(conn, msg); |
898 | debug3("Sent message fsync@openssh.com I:%u", id); | 996 | debug3("Sent message fsync@openssh.com I:%u", id); |
899 | buffer_free(&msg); | 997 | sshbuf_free(msg); |
900 | 998 | ||
901 | status = get_status(conn, id); | 999 | status = get_status(conn, id); |
902 | if (status != SSH2_FX_OK) | 1000 | if (status != SSH2_FX_OK) |
@@ -907,50 +1005,58 @@ do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) | |||
907 | 1005 | ||
908 | #ifdef notyet | 1006 | #ifdef notyet |
909 | char * | 1007 | char * |
910 | do_readlink(struct sftp_conn *conn, char *path) | 1008 | do_readlink(struct sftp_conn *conn, const char *path) |
911 | { | 1009 | { |
912 | Buffer msg; | 1010 | struct sshbuf *msg; |
913 | u_int type, expected_id, count, id; | 1011 | u_int expected_id, count, id; |
914 | char *filename, *longname; | 1012 | char *filename, *longname; |
915 | Attrib *a; | 1013 | Attrib a; |
1014 | u_char type; | ||
1015 | int r; | ||
916 | 1016 | ||
917 | expected_id = id = conn->msg_id++; | 1017 | expected_id = id = conn->msg_id++; |
918 | send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); | 1018 | send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); |
919 | 1019 | ||
920 | buffer_init(&msg); | 1020 | if ((msg = sshbuf_new()) == NULL) |
1021 | fatal("%s: sshbuf_new failed", __func__); | ||
921 | 1022 | ||
922 | get_msg(conn, &msg); | 1023 | get_msg(conn, msg); |
923 | type = buffer_get_char(&msg); | 1024 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
924 | id = buffer_get_int(&msg); | 1025 | (r = sshbuf_get_u32(msg, &id)) != 0) |
1026 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
925 | 1027 | ||
926 | if (id != expected_id) | 1028 | if (id != expected_id) |
927 | fatal("ID mismatch (%u != %u)", id, expected_id); | 1029 | fatal("ID mismatch (%u != %u)", id, expected_id); |
928 | 1030 | ||
929 | if (type == SSH2_FXP_STATUS) { | 1031 | if (type == SSH2_FXP_STATUS) { |
930 | u_int status = buffer_get_int(&msg); | 1032 | u_int status; |
931 | 1033 | ||
1034 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
1035 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
932 | error("Couldn't readlink: %s", fx2txt(status)); | 1036 | error("Couldn't readlink: %s", fx2txt(status)); |
933 | buffer_free(&msg); | 1037 | sshbuf_free(msg); |
934 | return(NULL); | 1038 | return(NULL); |
935 | } else if (type != SSH2_FXP_NAME) | 1039 | } else if (type != SSH2_FXP_NAME) |
936 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", | 1040 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", |
937 | SSH2_FXP_NAME, type); | 1041 | SSH2_FXP_NAME, type); |
938 | 1042 | ||
939 | count = buffer_get_int(&msg); | 1043 | if ((r = sshbuf_get_u32(msg, &count)) != 0) |
1044 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
940 | if (count != 1) | 1045 | if (count != 1) |
941 | fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); | 1046 | fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); |
942 | 1047 | ||
943 | filename = buffer_get_string(&msg, NULL); | 1048 | if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || |
944 | longname = buffer_get_string(&msg, NULL); | 1049 | (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || |
945 | a = decode_attrib(&msg); | 1050 | (r = decode_attrib(msg, &a)) != 0) |
1051 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
946 | 1052 | ||
947 | debug3("SSH_FXP_READLINK %s -> %s", path, filename); | 1053 | debug3("SSH_FXP_READLINK %s -> %s", path, filename); |
948 | 1054 | ||
949 | free(longname); | 1055 | free(longname); |
950 | 1056 | ||
951 | buffer_free(&msg); | 1057 | sshbuf_free(msg); |
952 | 1058 | ||
953 | return(filename); | 1059 | return filename; |
954 | } | 1060 | } |
955 | #endif | 1061 | #endif |
956 | 1062 | ||
@@ -958,8 +1064,9 @@ int | |||
958 | do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, | 1064 | do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, |
959 | int quiet) | 1065 | int quiet) |
960 | { | 1066 | { |
961 | Buffer msg; | 1067 | struct sshbuf *msg; |
962 | u_int id; | 1068 | u_int id; |
1069 | int r; | ||
963 | 1070 | ||
964 | if ((conn->exts & SFTP_EXT_STATVFS) == 0) { | 1071 | if ((conn->exts & SFTP_EXT_STATVFS) == 0) { |
965 | error("Server does not support statvfs@openssh.com extension"); | 1072 | error("Server does not support statvfs@openssh.com extension"); |
@@ -968,24 +1075,26 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, | |||
968 | 1075 | ||
969 | id = conn->msg_id++; | 1076 | id = conn->msg_id++; |
970 | 1077 | ||
971 | buffer_init(&msg); | 1078 | if ((msg = sshbuf_new()) == NULL) |
972 | buffer_clear(&msg); | 1079 | fatal("%s: sshbuf_new failed", __func__); |
973 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 1080 | sshbuf_reset(msg); |
974 | buffer_put_int(&msg, id); | 1081 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
975 | buffer_put_cstring(&msg, "statvfs@openssh.com"); | 1082 | (r = sshbuf_put_u32(msg, id)) != 0 || |
976 | buffer_put_cstring(&msg, path); | 1083 | (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || |
977 | send_msg(conn, &msg); | 1084 | (r = sshbuf_put_cstring(msg, path)) != 0) |
978 | buffer_free(&msg); | 1085 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1086 | send_msg(conn, msg); | ||
1087 | sshbuf_free(msg); | ||
979 | 1088 | ||
980 | return get_decode_statvfs(conn, st, id, quiet); | 1089 | return get_decode_statvfs(conn, st, id, quiet); |
981 | } | 1090 | } |
982 | 1091 | ||
983 | #ifdef notyet | 1092 | #ifdef notyet |
984 | int | 1093 | int |
985 | do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, | 1094 | do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, |
986 | struct sftp_statvfs *st, int quiet) | 1095 | struct sftp_statvfs *st, int quiet) |
987 | { | 1096 | { |
988 | Buffer msg; | 1097 | struct sshbuf *msg; |
989 | u_int id; | 1098 | u_int id; |
990 | 1099 | ||
991 | if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { | 1100 | if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { |
@@ -995,14 +1104,16 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, | |||
995 | 1104 | ||
996 | id = conn->msg_id++; | 1105 | id = conn->msg_id++; |
997 | 1106 | ||
998 | buffer_init(&msg); | 1107 | if ((msg = sshbuf_new()) == NULL) |
999 | buffer_clear(&msg); | 1108 | fatal("%s: sshbuf_new failed", __func__); |
1000 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 1109 | sshbuf_reset(msg); |
1001 | buffer_put_int(&msg, id); | 1110 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
1002 | buffer_put_cstring(&msg, "fstatvfs@openssh.com"); | 1111 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1003 | buffer_put_string(&msg, handle, handle_len); | 1112 | (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || |
1004 | send_msg(conn, &msg); | 1113 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
1005 | buffer_free(&msg); | 1114 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1115 | send_msg(conn, msg); | ||
1116 | sshbuf_free(msg); | ||
1006 | 1117 | ||
1007 | return get_decode_statvfs(conn, st, id, quiet); | 1118 | return get_decode_statvfs(conn, st, id, quiet); |
1008 | } | 1119 | } |
@@ -1010,42 +1121,48 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, | |||
1010 | 1121 | ||
1011 | static void | 1122 | static void |
1012 | send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, | 1123 | send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, |
1013 | u_int len, char *handle, u_int handle_len) | 1124 | u_int len, const u_char *handle, u_int handle_len) |
1014 | { | 1125 | { |
1015 | Buffer msg; | 1126 | struct sshbuf *msg; |
1016 | 1127 | int r; | |
1017 | buffer_init(&msg); | 1128 | |
1018 | buffer_clear(&msg); | 1129 | if ((msg = sshbuf_new()) == NULL) |
1019 | buffer_put_char(&msg, SSH2_FXP_READ); | 1130 | fatal("%s: sshbuf_new failed", __func__); |
1020 | buffer_put_int(&msg, id); | 1131 | sshbuf_reset(msg); |
1021 | buffer_put_string(&msg, handle, handle_len); | 1132 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || |
1022 | buffer_put_int64(&msg, offset); | 1133 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1023 | buffer_put_int(&msg, len); | 1134 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || |
1024 | send_msg(conn, &msg); | 1135 | (r = sshbuf_put_u64(msg, offset)) != 0 || |
1025 | buffer_free(&msg); | 1136 | (r = sshbuf_put_u32(msg, len)) != 0) |
1137 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1138 | send_msg(conn, msg); | ||
1139 | sshbuf_free(msg); | ||
1026 | } | 1140 | } |
1027 | 1141 | ||
1028 | int | 1142 | int |
1029 | do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | 1143 | do_download(struct sftp_conn *conn, const char *remote_path, |
1030 | Attrib *a, int preserve_flag, int resume_flag, int fsync_flag) | 1144 | const char *local_path, Attrib *a, int preserve_flag, int resume_flag, |
1145 | int fsync_flag) | ||
1031 | { | 1146 | { |
1032 | Attrib junk; | 1147 | Attrib junk; |
1033 | Buffer msg; | 1148 | struct sshbuf *msg; |
1034 | char *handle; | 1149 | u_char *handle; |
1035 | int local_fd = -1, status = 0, write_error; | 1150 | int local_fd = -1, write_error; |
1036 | int read_error, write_errno, reordered = 0; | 1151 | int read_error, write_errno, reordered = 0, r; |
1037 | u_int64_t offset = 0, size, highwater; | 1152 | u_int64_t offset = 0, size, highwater; |
1038 | u_int handle_len, mode, type, id, buflen, num_req, max_req; | 1153 | u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; |
1039 | off_t progress_counter; | 1154 | off_t progress_counter; |
1155 | size_t handle_len; | ||
1040 | struct stat st; | 1156 | struct stat st; |
1041 | struct request { | 1157 | struct request { |
1042 | u_int id; | 1158 | u_int id; |
1043 | u_int len; | 1159 | size_t len; |
1044 | u_int64_t offset; | 1160 | u_int64_t offset; |
1045 | TAILQ_ENTRY(request) tq; | 1161 | TAILQ_ENTRY(request) tq; |
1046 | }; | 1162 | }; |
1047 | TAILQ_HEAD(reqhead, request) requests; | 1163 | TAILQ_HEAD(reqhead, request) requests; |
1048 | struct request *req; | 1164 | struct request *req; |
1165 | u_char type; | ||
1049 | 1166 | ||
1050 | TAILQ_INIT(&requests); | 1167 | TAILQ_INIT(&requests); |
1051 | 1168 | ||
@@ -1070,23 +1187,26 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1070 | size = 0; | 1187 | size = 0; |
1071 | 1188 | ||
1072 | buflen = conn->transfer_buflen; | 1189 | buflen = conn->transfer_buflen; |
1073 | buffer_init(&msg); | 1190 | if ((msg = sshbuf_new()) == NULL) |
1191 | fatal("%s: sshbuf_new failed", __func__); | ||
1192 | |||
1193 | attrib_clear(&junk); /* Send empty attributes */ | ||
1074 | 1194 | ||
1075 | /* Send open request */ | 1195 | /* Send open request */ |
1076 | id = conn->msg_id++; | 1196 | id = conn->msg_id++; |
1077 | buffer_put_char(&msg, SSH2_FXP_OPEN); | 1197 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || |
1078 | buffer_put_int(&msg, id); | 1198 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1079 | buffer_put_cstring(&msg, remote_path); | 1199 | (r = sshbuf_put_cstring(msg, remote_path)) != 0 || |
1080 | buffer_put_int(&msg, SSH2_FXF_READ); | 1200 | (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || |
1081 | attrib_clear(&junk); /* Send empty attributes */ | 1201 | (r = encode_attrib(msg, &junk)) != 0) |
1082 | encode_attrib(&msg, &junk); | 1202 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1083 | send_msg(conn, &msg); | 1203 | send_msg(conn, msg); |
1084 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); | 1204 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); |
1085 | 1205 | ||
1086 | handle = get_handle(conn, id, &handle_len, | 1206 | handle = get_handle(conn, id, &handle_len, |
1087 | "remote open(\"%s\")", remote_path); | 1207 | "remote open(\"%s\")", remote_path); |
1088 | if (handle == NULL) { | 1208 | if (handle == NULL) { |
1089 | buffer_free(&msg); | 1209 | sshbuf_free(msg); |
1090 | return(-1); | 1210 | return(-1); |
1091 | } | 1211 | } |
1092 | 1212 | ||
@@ -1113,7 +1233,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1113 | "local file is larger than remote", local_path); | 1233 | "local file is larger than remote", local_path); |
1114 | fail: | 1234 | fail: |
1115 | do_close(conn, handle, handle_len); | 1235 | do_close(conn, handle, handle_len); |
1116 | buffer_free(&msg); | 1236 | sshbuf_free(msg); |
1117 | free(handle); | 1237 | free(handle); |
1118 | if (local_fd != -1) | 1238 | if (local_fd != -1) |
1119 | close(local_fd); | 1239 | close(local_fd); |
@@ -1131,8 +1251,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1131 | start_progress_meter(remote_path, size, &progress_counter); | 1251 | start_progress_meter(remote_path, size, &progress_counter); |
1132 | 1252 | ||
1133 | while (num_req > 0 || max_req > 0) { | 1253 | while (num_req > 0 || max_req > 0) { |
1134 | char *data; | 1254 | u_char *data; |
1135 | u_int len; | 1255 | size_t len; |
1136 | 1256 | ||
1137 | /* | 1257 | /* |
1138 | * Simulate EOF on interrupt: stop sending new requests and | 1258 | * Simulate EOF on interrupt: stop sending new requests and |
@@ -1161,10 +1281,11 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1161 | req->len, handle, handle_len); | 1281 | req->len, handle, handle_len); |
1162 | } | 1282 | } |
1163 | 1283 | ||
1164 | buffer_clear(&msg); | 1284 | sshbuf_reset(msg); |
1165 | get_msg(conn, &msg); | 1285 | get_msg(conn, msg); |
1166 | type = buffer_get_char(&msg); | 1286 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
1167 | id = buffer_get_int(&msg); | 1287 | (r = sshbuf_get_u32(msg, &id)) != 0) |
1288 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1168 | debug3("Received reply T:%u I:%u R:%d", type, id, max_req); | 1289 | debug3("Received reply T:%u I:%u R:%d", type, id, max_req); |
1169 | 1290 | ||
1170 | /* Find the request in our queue */ | 1291 | /* Find the request in our queue */ |
@@ -1177,7 +1298,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1177 | 1298 | ||
1178 | switch (type) { | 1299 | switch (type) { |
1179 | case SSH2_FXP_STATUS: | 1300 | case SSH2_FXP_STATUS: |
1180 | status = buffer_get_int(&msg); | 1301 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
1302 | fatal("%s: buffer error: %s", | ||
1303 | __func__, ssh_err(r)); | ||
1181 | if (status != SSH2_FX_EOF) | 1304 | if (status != SSH2_FX_EOF) |
1182 | read_error = 1; | 1305 | read_error = 1; |
1183 | max_req = 0; | 1306 | max_req = 0; |
@@ -1186,13 +1309,15 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1186 | num_req--; | 1309 | num_req--; |
1187 | break; | 1310 | break; |
1188 | case SSH2_FXP_DATA: | 1311 | case SSH2_FXP_DATA: |
1189 | data = buffer_get_string(&msg, &len); | 1312 | if ((r = sshbuf_get_string(msg, &data, &len)) != 0) |
1313 | fatal("%s: buffer error: %s", | ||
1314 | __func__, ssh_err(r)); | ||
1190 | debug3("Received data %llu -> %llu", | 1315 | debug3("Received data %llu -> %llu", |
1191 | (unsigned long long)req->offset, | 1316 | (unsigned long long)req->offset, |
1192 | (unsigned long long)req->offset + len - 1); | 1317 | (unsigned long long)req->offset + len - 1); |
1193 | if (len > req->len) | 1318 | if (len > req->len) |
1194 | fatal("Received more data than asked for " | 1319 | fatal("Received more data than asked for " |
1195 | "%u > %u", len, req->len); | 1320 | "%zu > %zu", len, req->len); |
1196 | if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || | 1321 | if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || |
1197 | atomicio(vwrite, local_fd, data, len) != len) && | 1322 | atomicio(vwrite, local_fd, data, len) != len) && |
1198 | !write_error) { | 1323 | !write_error) { |
@@ -1269,12 +1394,13 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1269 | } else if (write_error) { | 1394 | } else if (write_error) { |
1270 | error("Couldn't write to \"%s\": %s", local_path, | 1395 | error("Couldn't write to \"%s\": %s", local_path, |
1271 | strerror(write_errno)); | 1396 | strerror(write_errno)); |
1272 | status = -1; | 1397 | status = SSH2_FX_FAILURE; |
1273 | do_close(conn, handle, handle_len); | 1398 | do_close(conn, handle, handle_len); |
1274 | } else { | 1399 | } else { |
1275 | status = do_close(conn, handle, handle_len); | 1400 | if (do_close(conn, handle, handle_len) != 0 || interrupted) |
1276 | if (interrupted || status != SSH2_FX_OK) | 1401 | status = SSH2_FX_FAILURE; |
1277 | status = -1; | 1402 | else |
1403 | status = SSH2_FX_OK; | ||
1278 | /* Override umask and utimes if asked */ | 1404 | /* Override umask and utimes if asked */ |
1279 | #ifdef HAVE_FCHMOD | 1405 | #ifdef HAVE_FCHMOD |
1280 | if (preserve_flag && fchmod(local_fd, mode) == -1) | 1406 | if (preserve_flag && fchmod(local_fd, mode) == -1) |
@@ -1301,16 +1427,16 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1301 | } | 1427 | } |
1302 | } | 1428 | } |
1303 | close(local_fd); | 1429 | close(local_fd); |
1304 | buffer_free(&msg); | 1430 | sshbuf_free(msg); |
1305 | free(handle); | 1431 | free(handle); |
1306 | 1432 | ||
1307 | return(status); | 1433 | return(status); |
1308 | } | 1434 | } |
1309 | 1435 | ||
1310 | static int | 1436 | static int |
1311 | download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | 1437 | download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, |
1312 | Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, | 1438 | int depth, Attrib *dirattrib, int preserve_flag, int print_flag, |
1313 | int fsync_flag) | 1439 | int resume_flag, int fsync_flag) |
1314 | { | 1440 | { |
1315 | int i, ret = 0; | 1441 | int i, ret = 0; |
1316 | SFTP_DIRENT **dir_entries; | 1442 | SFTP_DIRENT **dir_entries; |
@@ -1400,9 +1526,9 @@ download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | |||
1400 | } | 1526 | } |
1401 | 1527 | ||
1402 | int | 1528 | int |
1403 | download_dir(struct sftp_conn *conn, char *src, char *dst, | 1529 | download_dir(struct sftp_conn *conn, const char *src, const char *dst, |
1404 | Attrib *dirattrib, int preserve_flag, int print_flag, | 1530 | Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, |
1405 | int resume_flag, int fsync_flag) | 1531 | int fsync_flag) |
1406 | { | 1532 | { |
1407 | char *src_canon; | 1533 | char *src_canon; |
1408 | int ret; | 1534 | int ret; |
@@ -1419,15 +1545,16 @@ download_dir(struct sftp_conn *conn, char *src, char *dst, | |||
1419 | } | 1545 | } |
1420 | 1546 | ||
1421 | int | 1547 | int |
1422 | do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | 1548 | do_upload(struct sftp_conn *conn, const char *local_path, |
1423 | int preserve_flag, int resume, int fsync_flag) | 1549 | const char *remote_path, int preserve_flag, int resume, int fsync_flag) |
1424 | { | 1550 | { |
1425 | int local_fd; | 1551 | int r, local_fd; |
1426 | int status = SSH2_FX_OK; | 1552 | u_int status = SSH2_FX_OK; |
1427 | u_int handle_len, id, type; | 1553 | u_int id; |
1554 | u_char type; | ||
1428 | off_t offset, progress_counter; | 1555 | off_t offset, progress_counter; |
1429 | char *handle, *data; | 1556 | u_char *handle, *data; |
1430 | Buffer msg; | 1557 | struct sshbuf *msg; |
1431 | struct stat sb; | 1558 | struct stat sb; |
1432 | Attrib a, *c = NULL; | 1559 | Attrib a, *c = NULL; |
1433 | u_int32_t startid; | 1560 | u_int32_t startid; |
@@ -1440,6 +1567,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1440 | }; | 1567 | }; |
1441 | TAILQ_HEAD(ackhead, outstanding_ack) acks; | 1568 | TAILQ_HEAD(ackhead, outstanding_ack) acks; |
1442 | struct outstanding_ack *ack = NULL; | 1569 | struct outstanding_ack *ack = NULL; |
1570 | size_t handle_len; | ||
1443 | 1571 | ||
1444 | TAILQ_INIT(&acks); | 1572 | TAILQ_INIT(&acks); |
1445 | 1573 | ||
@@ -1487,26 +1615,28 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1487 | } | 1615 | } |
1488 | } | 1616 | } |
1489 | 1617 | ||
1490 | buffer_init(&msg); | 1618 | if ((msg = sshbuf_new()) == NULL) |
1619 | fatal("%s: sshbuf_new failed", __func__); | ||
1491 | 1620 | ||
1492 | /* Send open request */ | 1621 | /* Send open request */ |
1493 | id = conn->msg_id++; | 1622 | id = conn->msg_id++; |
1494 | buffer_put_char(&msg, SSH2_FXP_OPEN); | 1623 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || |
1495 | buffer_put_int(&msg, id); | 1624 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1496 | buffer_put_cstring(&msg, remote_path); | 1625 | (r = sshbuf_put_cstring(msg, remote_path)) != 0 || |
1497 | buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| | 1626 | (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| |
1498 | (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC)); | 1627 | (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 || |
1499 | encode_attrib(&msg, &a); | 1628 | (r = encode_attrib(msg, &a)) != 0) |
1500 | send_msg(conn, &msg); | 1629 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1630 | send_msg(conn, msg); | ||
1501 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); | 1631 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); |
1502 | 1632 | ||
1503 | buffer_clear(&msg); | 1633 | sshbuf_reset(msg); |
1504 | 1634 | ||
1505 | handle = get_handle(conn, id, &handle_len, | 1635 | handle = get_handle(conn, id, &handle_len, |
1506 | "remote open(\"%s\")", remote_path); | 1636 | "remote open(\"%s\")", remote_path); |
1507 | if (handle == NULL) { | 1637 | if (handle == NULL) { |
1508 | close(local_fd); | 1638 | close(local_fd); |
1509 | buffer_free(&msg); | 1639 | sshbuf_free(msg); |
1510 | return -1; | 1640 | return -1; |
1511 | } | 1641 | } |
1512 | 1642 | ||
@@ -1546,13 +1676,16 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1546 | ack->len = len; | 1676 | ack->len = len; |
1547 | TAILQ_INSERT_TAIL(&acks, ack, tq); | 1677 | TAILQ_INSERT_TAIL(&acks, ack, tq); |
1548 | 1678 | ||
1549 | buffer_clear(&msg); | 1679 | sshbuf_reset(msg); |
1550 | buffer_put_char(&msg, SSH2_FXP_WRITE); | 1680 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || |
1551 | buffer_put_int(&msg, ack->id); | 1681 | (r = sshbuf_put_u32(msg, ack->id)) != 0 || |
1552 | buffer_put_string(&msg, handle, handle_len); | 1682 | (r = sshbuf_put_string(msg, handle, |
1553 | buffer_put_int64(&msg, offset); | 1683 | handle_len)) != 0 || |
1554 | buffer_put_string(&msg, data, len); | 1684 | (r = sshbuf_put_u64(msg, offset)) != 0 || |
1555 | send_msg(conn, &msg); | 1685 | (r = sshbuf_put_string(msg, data, len)) != 0) |
1686 | fatal("%s: buffer error: %s", | ||
1687 | __func__, ssh_err(r)); | ||
1688 | send_msg(conn, msg); | ||
1556 | debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", | 1689 | debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", |
1557 | id, (unsigned long long)offset, len); | 1690 | id, (unsigned long long)offset, len); |
1558 | } else if (TAILQ_FIRST(&acks) == NULL) | 1691 | } else if (TAILQ_FIRST(&acks) == NULL) |
@@ -1563,27 +1696,31 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1563 | 1696 | ||
1564 | if (id == startid || len == 0 || | 1697 | if (id == startid || len == 0 || |
1565 | id - ackid >= conn->num_requests) { | 1698 | id - ackid >= conn->num_requests) { |
1566 | u_int r_id; | 1699 | u_int rid; |
1567 | 1700 | ||
1568 | buffer_clear(&msg); | 1701 | sshbuf_reset(msg); |
1569 | get_msg(conn, &msg); | 1702 | get_msg(conn, msg); |
1570 | type = buffer_get_char(&msg); | 1703 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
1571 | r_id = buffer_get_int(&msg); | 1704 | (r = sshbuf_get_u32(msg, &rid)) != 0) |
1705 | fatal("%s: buffer error: %s", | ||
1706 | __func__, ssh_err(r)); | ||
1572 | 1707 | ||
1573 | if (type != SSH2_FXP_STATUS) | 1708 | if (type != SSH2_FXP_STATUS) |
1574 | fatal("Expected SSH2_FXP_STATUS(%d) packet, " | 1709 | fatal("Expected SSH2_FXP_STATUS(%d) packet, " |
1575 | "got %d", SSH2_FXP_STATUS, type); | 1710 | "got %d", SSH2_FXP_STATUS, type); |
1576 | 1711 | ||
1577 | status = buffer_get_int(&msg); | 1712 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
1578 | debug3("SSH2_FXP_STATUS %d", status); | 1713 | fatal("%s: buffer error: %s", |
1714 | __func__, ssh_err(r)); | ||
1715 | debug3("SSH2_FXP_STATUS %u", status); | ||
1579 | 1716 | ||
1580 | /* Find the request in our queue */ | 1717 | /* Find the request in our queue */ |
1581 | for (ack = TAILQ_FIRST(&acks); | 1718 | for (ack = TAILQ_FIRST(&acks); |
1582 | ack != NULL && ack->id != r_id; | 1719 | ack != NULL && ack->id != rid; |
1583 | ack = TAILQ_NEXT(ack, tq)) | 1720 | ack = TAILQ_NEXT(ack, tq)) |
1584 | ; | 1721 | ; |
1585 | if (ack == NULL) | 1722 | if (ack == NULL) |
1586 | fatal("Can't find request for ID %u", r_id); | 1723 | fatal("Can't find request for ID %u", rid); |
1587 | TAILQ_REMOVE(&acks, ack, tq); | 1724 | TAILQ_REMOVE(&acks, ack, tq); |
1588 | debug3("In write loop, ack for %u %u bytes at %lld", | 1725 | debug3("In write loop, ack for %u %u bytes at %lld", |
1589 | ack->id, ack->len, (long long)ack->offset); | 1726 | ack->id, ack->len, (long long)ack->offset); |
@@ -1595,7 +1732,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1595 | if (offset < 0) | 1732 | if (offset < 0) |
1596 | fatal("%s: offset < 0", __func__); | 1733 | fatal("%s: offset < 0", __func__); |
1597 | } | 1734 | } |
1598 | buffer_free(&msg); | 1735 | sshbuf_free(msg); |
1599 | 1736 | ||
1600 | if (showprogress) | 1737 | if (showprogress) |
1601 | stop_progress_meter(); | 1738 | stop_progress_meter(); |
@@ -1604,13 +1741,13 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1604 | if (status != SSH2_FX_OK) { | 1741 | if (status != SSH2_FX_OK) { |
1605 | error("Couldn't write to remote file \"%s\": %s", | 1742 | error("Couldn't write to remote file \"%s\": %s", |
1606 | remote_path, fx2txt(status)); | 1743 | remote_path, fx2txt(status)); |
1607 | status = -1; | 1744 | status = SSH2_FX_FAILURE; |
1608 | } | 1745 | } |
1609 | 1746 | ||
1610 | if (close(local_fd) == -1) { | 1747 | if (close(local_fd) == -1) { |
1611 | error("Couldn't close local file \"%s\": %s", local_path, | 1748 | error("Couldn't close local file \"%s\": %s", local_path, |
1612 | strerror(errno)); | 1749 | strerror(errno)); |
1613 | status = -1; | 1750 | status = SSH2_FX_FAILURE; |
1614 | } | 1751 | } |
1615 | 1752 | ||
1616 | /* Override umask and utimes if asked */ | 1753 | /* Override umask and utimes if asked */ |
@@ -1621,17 +1758,19 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1621 | (void)do_fsync(conn, handle, handle_len); | 1758 | (void)do_fsync(conn, handle, handle_len); |
1622 | 1759 | ||
1623 | if (do_close(conn, handle, handle_len) != SSH2_FX_OK) | 1760 | if (do_close(conn, handle, handle_len) != SSH2_FX_OK) |
1624 | status = -1; | 1761 | status = SSH2_FX_FAILURE; |
1762 | |||
1625 | free(handle); | 1763 | free(handle); |
1626 | 1764 | ||
1627 | return status; | 1765 | return status == SSH2_FX_OK ? 0 : -1; |
1628 | } | 1766 | } |
1629 | 1767 | ||
1630 | static int | 1768 | static int |
1631 | upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | 1769 | upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, |
1632 | int preserve_flag, int print_flag, int resume, int fsync_flag) | 1770 | int depth, int preserve_flag, int print_flag, int resume, int fsync_flag) |
1633 | { | 1771 | { |
1634 | int ret = 0, status; | 1772 | int ret = 0; |
1773 | u_int status; | ||
1635 | DIR *dirp; | 1774 | DIR *dirp; |
1636 | struct dirent *dp; | 1775 | struct dirent *dp; |
1637 | char *filename, *new_src, *new_dst; | 1776 | char *filename, *new_src, *new_dst; |
@@ -1721,8 +1860,8 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | |||
1721 | } | 1860 | } |
1722 | 1861 | ||
1723 | int | 1862 | int |
1724 | upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, | 1863 | upload_dir(struct sftp_conn *conn, const char *src, const char *dst, |
1725 | int print_flag, int resume, int fsync_flag) | 1864 | int preserve_flag, int print_flag, int resume, int fsync_flag) |
1726 | { | 1865 | { |
1727 | char *dst_canon; | 1866 | char *dst_canon; |
1728 | int ret; | 1867 | int ret; |
@@ -1740,7 +1879,7 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, | |||
1740 | } | 1879 | } |
1741 | 1880 | ||
1742 | char * | 1881 | char * |
1743 | path_append(char *p1, char *p2) | 1882 | path_append(const char *p1, const char *p2) |
1744 | { | 1883 | { |
1745 | char *ret; | 1884 | char *ret; |
1746 | size_t len = strlen(p1) + strlen(p2) + 2; | 1885 | size_t len = strlen(p1) + strlen(p2) + 2; |
diff --git a/sftp-client.h b/sftp-client.h index 967840b9c..507d763ea 100644 --- a/sftp-client.h +++ b/sftp-client.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-client.h,v 1.25 2014/04/21 14:36:16 logan Exp $ */ | 1 | /* $OpenBSD: sftp-client.h,v 1.26 2015/01/14 13:54:13 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 4 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
@@ -56,79 +56,81 @@ struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t); | |||
56 | u_int sftp_proto_version(struct sftp_conn *); | 56 | u_int sftp_proto_version(struct sftp_conn *); |
57 | 57 | ||
58 | /* Close file referred to by 'handle' */ | 58 | /* Close file referred to by 'handle' */ |
59 | int do_close(struct sftp_conn *, char *, u_int); | 59 | int do_close(struct sftp_conn *, const u_char *, u_int); |
60 | 60 | ||
61 | /* Read contents of 'path' to NULL-terminated array 'dir' */ | 61 | /* Read contents of 'path' to NULL-terminated array 'dir' */ |
62 | int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); | 62 | int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); |
63 | 63 | ||
64 | /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ | 64 | /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ |
65 | void free_sftp_dirents(SFTP_DIRENT **); | 65 | void free_sftp_dirents(SFTP_DIRENT **); |
66 | 66 | ||
67 | /* Delete file 'path' */ | 67 | /* Delete file 'path' */ |
68 | int do_rm(struct sftp_conn *, char *); | 68 | int do_rm(struct sftp_conn *, const char *); |
69 | 69 | ||
70 | /* Create directory 'path' */ | 70 | /* Create directory 'path' */ |
71 | int do_mkdir(struct sftp_conn *, char *, Attrib *, int); | 71 | int do_mkdir(struct sftp_conn *, const char *, Attrib *, int); |
72 | 72 | ||
73 | /* Remove directory 'path' */ | 73 | /* Remove directory 'path' */ |
74 | int do_rmdir(struct sftp_conn *, char *); | 74 | int do_rmdir(struct sftp_conn *, const char *); |
75 | 75 | ||
76 | /* Get file attributes of 'path' (follows symlinks) */ | 76 | /* Get file attributes of 'path' (follows symlinks) */ |
77 | Attrib *do_stat(struct sftp_conn *, char *, int); | 77 | Attrib *do_stat(struct sftp_conn *, const char *, int); |
78 | 78 | ||
79 | /* Get file attributes of 'path' (does not follow symlinks) */ | 79 | /* Get file attributes of 'path' (does not follow symlinks) */ |
80 | Attrib *do_lstat(struct sftp_conn *, char *, int); | 80 | Attrib *do_lstat(struct sftp_conn *, const char *, int); |
81 | 81 | ||
82 | /* Set file attributes of 'path' */ | 82 | /* Set file attributes of 'path' */ |
83 | int do_setstat(struct sftp_conn *, char *, Attrib *); | 83 | int do_setstat(struct sftp_conn *, const char *, Attrib *); |
84 | 84 | ||
85 | /* Set file attributes of open file 'handle' */ | 85 | /* Set file attributes of open file 'handle' */ |
86 | int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); | 86 | int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); |
87 | 87 | ||
88 | /* Canonicalise 'path' - caller must free result */ | 88 | /* Canonicalise 'path' - caller must free result */ |
89 | char *do_realpath(struct sftp_conn *, char *); | 89 | char *do_realpath(struct sftp_conn *, const char *); |
90 | 90 | ||
91 | /* Get statistics for filesystem hosting file at "path" */ | 91 | /* Get statistics for filesystem hosting file at "path" */ |
92 | int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); | 92 | int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); |
93 | 93 | ||
94 | /* Rename 'oldpath' to 'newpath' */ | 94 | /* Rename 'oldpath' to 'newpath' */ |
95 | int do_rename(struct sftp_conn *, char *, char *m, int force_legacy); | 95 | int do_rename(struct sftp_conn *, const char *, const char *, int force_legacy); |
96 | 96 | ||
97 | /* Link 'oldpath' to 'newpath' */ | 97 | /* Link 'oldpath' to 'newpath' */ |
98 | int do_hardlink(struct sftp_conn *, char *, char *); | 98 | int do_hardlink(struct sftp_conn *, const char *, const char *); |
99 | 99 | ||
100 | /* Rename 'oldpath' to 'newpath' */ | 100 | /* Rename 'oldpath' to 'newpath' */ |
101 | int do_symlink(struct sftp_conn *, char *, char *); | 101 | int do_symlink(struct sftp_conn *, const char *, const char *); |
102 | 102 | ||
103 | /* Call fsync() on open file 'handle' */ | 103 | /* Call fsync() on open file 'handle' */ |
104 | int do_fsync(struct sftp_conn *conn, char *, u_int); | 104 | int do_fsync(struct sftp_conn *conn, u_char *, u_int); |
105 | 105 | ||
106 | /* | 106 | /* |
107 | * Download 'remote_path' to 'local_path'. Preserve permissions and times | 107 | * Download 'remote_path' to 'local_path'. Preserve permissions and times |
108 | * if 'pflag' is set | 108 | * if 'pflag' is set |
109 | */ | 109 | */ |
110 | int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int, int); | 110 | int do_download(struct sftp_conn *, const char *, const char *, |
111 | Attrib *, int, int, int); | ||
111 | 112 | ||
112 | /* | 113 | /* |
113 | * Recursively download 'remote_directory' to 'local_directory'. Preserve | 114 | * Recursively download 'remote_directory' to 'local_directory'. Preserve |
114 | * times if 'pflag' is set | 115 | * times if 'pflag' is set |
115 | */ | 116 | */ |
116 | int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, | 117 | int download_dir(struct sftp_conn *, const char *, const char *, |
117 | int, int, int); | 118 | Attrib *, int, int, int, int); |
118 | 119 | ||
119 | /* | 120 | /* |
120 | * Upload 'local_path' to 'remote_path'. Preserve permissions and times | 121 | * Upload 'local_path' to 'remote_path'. Preserve permissions and times |
121 | * if 'pflag' is set | 122 | * if 'pflag' is set |
122 | */ | 123 | */ |
123 | int do_upload(struct sftp_conn *, char *, char *, int, int, int); | 124 | int do_upload(struct sftp_conn *, const char *, const char *, int, int, int); |
124 | 125 | ||
125 | /* | 126 | /* |
126 | * Recursively upload 'local_directory' to 'remote_directory'. Preserve | 127 | * Recursively upload 'local_directory' to 'remote_directory'. Preserve |
127 | * times if 'pflag' is set | 128 | * times if 'pflag' is set |
128 | */ | 129 | */ |
129 | int upload_dir(struct sftp_conn *, char *, char *, int, int, int, int); | 130 | int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, |
131 | int); | ||
130 | 132 | ||
131 | /* Concatenate paths, taking care of slashes. Caller must free result. */ | 133 | /* Concatenate paths, taking care of slashes. Caller must free result. */ |
132 | char *path_append(char *, char *); | 134 | char *path_append(const char *, const char *); |
133 | 135 | ||
134 | #endif | 136 | #endif |
diff --git a/sftp-common.c b/sftp-common.c index 70a929ccc..9c54d5c6b 100644 --- a/sftp-common.c +++ b/sftp-common.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-common.c,v 1.26 2014/01/09 03:26:00 guenther Exp $ */ | 1 | /* $OpenBSD: sftp-common.c,v 1.27 2015/01/14 13:54:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2001 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2001 Damien Miller. All rights reserved. |
@@ -42,7 +42,8 @@ | |||
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #include "xmalloc.h" | 44 | #include "xmalloc.h" |
45 | #include "buffer.h" | 45 | #include "ssherr.h" |
46 | #include "sshbuf.h" | ||
46 | #include "log.h" | 47 | #include "log.h" |
47 | 48 | ||
48 | #include "sftp.h" | 49 | #include "sftp.h" |
@@ -100,59 +101,81 @@ attrib_to_stat(const Attrib *a, struct stat *st) | |||
100 | } | 101 | } |
101 | 102 | ||
102 | /* Decode attributes in buffer */ | 103 | /* Decode attributes in buffer */ |
103 | Attrib * | 104 | int |
104 | decode_attrib(Buffer *b) | 105 | decode_attrib(struct sshbuf *b, Attrib *a) |
105 | { | 106 | { |
106 | static Attrib a; | 107 | int r; |
107 | 108 | ||
108 | attrib_clear(&a); | 109 | attrib_clear(a); |
109 | a.flags = buffer_get_int(b); | 110 | if ((r = sshbuf_get_u32(b, &a->flags)) != 0) |
110 | if (a.flags & SSH2_FILEXFER_ATTR_SIZE) | 111 | return r; |
111 | a.size = buffer_get_int64(b); | 112 | if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
112 | if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { | 113 | if ((r = sshbuf_get_u64(b, &a->size)) != 0) |
113 | a.uid = buffer_get_int(b); | 114 | return r; |
114 | a.gid = buffer_get_int(b); | 115 | } |
115 | } | 116 | if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
116 | if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) | 117 | if ((r = sshbuf_get_u32(b, &a->uid)) != 0 || |
117 | a.perm = buffer_get_int(b); | 118 | (r = sshbuf_get_u32(b, &a->gid)) != 0) |
118 | if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { | 119 | return r; |
119 | a.atime = buffer_get_int(b); | 120 | } |
120 | a.mtime = buffer_get_int(b); | 121 | if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
122 | if ((r = sshbuf_get_u32(b, &a->perm)) != 0) | ||
123 | return r; | ||
124 | } | ||
125 | if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { | ||
126 | if ((r = sshbuf_get_u32(b, &a->atime)) != 0 || | ||
127 | (r = sshbuf_get_u32(b, &a->mtime)) != 0) | ||
128 | return r; | ||
121 | } | 129 | } |
122 | /* vendor-specific extensions */ | 130 | /* vendor-specific extensions */ |
123 | if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) { | 131 | if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) { |
124 | char *type, *data; | 132 | char *type; |
125 | int i, count; | 133 | u_char *data; |
134 | size_t dlen; | ||
135 | u_int i, count; | ||
126 | 136 | ||
127 | count = buffer_get_int(b); | 137 | if ((r = sshbuf_get_u32(b, &count)) != 0) |
138 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
128 | for (i = 0; i < count; i++) { | 139 | for (i = 0; i < count; i++) { |
129 | type = buffer_get_string(b, NULL); | 140 | if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 || |
130 | data = buffer_get_string(b, NULL); | 141 | (r = sshbuf_get_string(b, &data, &dlen)) != 0) |
131 | debug3("Got file attribute \"%s\"", type); | 142 | return r; |
143 | debug3("Got file attribute \"%.100s\" len %zu", | ||
144 | type, dlen); | ||
132 | free(type); | 145 | free(type); |
133 | free(data); | 146 | free(data); |
134 | } | 147 | } |
135 | } | 148 | } |
136 | return &a; | 149 | return 0; |
137 | } | 150 | } |
138 | 151 | ||
139 | /* Encode attributes to buffer */ | 152 | /* Encode attributes to buffer */ |
140 | void | 153 | int |
141 | encode_attrib(Buffer *b, const Attrib *a) | 154 | encode_attrib(struct sshbuf *b, const Attrib *a) |
142 | { | 155 | { |
143 | buffer_put_int(b, a->flags); | 156 | int r; |
144 | if (a->flags & SSH2_FILEXFER_ATTR_SIZE) | 157 | |
145 | buffer_put_int64(b, a->size); | 158 | if ((r = sshbuf_put_u32(b, a->flags)) != 0) |
159 | return r; | ||
160 | if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { | ||
161 | if ((r = sshbuf_put_u64(b, a->size)) != 0) | ||
162 | return r; | ||
163 | } | ||
146 | if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { | 164 | if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { |
147 | buffer_put_int(b, a->uid); | 165 | if ((r = sshbuf_put_u32(b, a->uid)) != 0 || |
148 | buffer_put_int(b, a->gid); | 166 | (r = sshbuf_put_u32(b, a->gid)) != 0) |
167 | return r; | ||
168 | } | ||
169 | if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { | ||
170 | if ((r = sshbuf_put_u32(b, a->perm)) != 0) | ||
171 | return r; | ||
149 | } | 172 | } |
150 | if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) | ||
151 | buffer_put_int(b, a->perm); | ||
152 | if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { | 173 | if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
153 | buffer_put_int(b, a->atime); | 174 | if ((r = sshbuf_put_u32(b, a->atime)) != 0 || |
154 | buffer_put_int(b, a->mtime); | 175 | (r = sshbuf_put_u32(b, a->mtime)) != 0) |
176 | return r; | ||
155 | } | 177 | } |
178 | return 0; | ||
156 | } | 179 | } |
157 | 180 | ||
158 | /* Convert from SSH2_FX_ status to text error message */ | 181 | /* Convert from SSH2_FX_ status to text error message */ |
diff --git a/sftp-common.h b/sftp-common.h index 9ed86c070..2e778a9ca 100644 --- a/sftp-common.h +++ b/sftp-common.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-common.h,v 1.11 2010/01/13 01:40:16 djm Exp $ */ | 1 | /* $OpenBSD: sftp-common.h,v 1.12 2015/01/14 13:54:13 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
@@ -28,6 +28,7 @@ | |||
28 | /* Maximum packet that we are willing to send/accept */ | 28 | /* Maximum packet that we are willing to send/accept */ |
29 | #define SFTP_MAX_MSG_LENGTH (256 * 1024) | 29 | #define SFTP_MAX_MSG_LENGTH (256 * 1024) |
30 | 30 | ||
31 | struct sshbuf; | ||
31 | typedef struct Attrib Attrib; | 32 | typedef struct Attrib Attrib; |
32 | 33 | ||
33 | /* File attributes */ | 34 | /* File attributes */ |
@@ -44,8 +45,8 @@ struct Attrib { | |||
44 | void attrib_clear(Attrib *); | 45 | void attrib_clear(Attrib *); |
45 | void stat_to_attrib(const struct stat *, Attrib *); | 46 | void stat_to_attrib(const struct stat *, Attrib *); |
46 | void attrib_to_stat(const Attrib *, struct stat *); | 47 | void attrib_to_stat(const Attrib *, struct stat *); |
47 | Attrib *decode_attrib(Buffer *); | 48 | int decode_attrib(struct sshbuf *, Attrib *); |
48 | void encode_attrib(Buffer *, const Attrib *); | 49 | int encode_attrib(struct sshbuf *, const Attrib *); |
49 | char *ls_file(const char *, const struct stat *, int, int); | 50 | char *ls_file(const char *, const struct stat *, int, int); |
50 | 51 | ||
51 | const char *fx2txt(int); | 52 | const char *fx2txt(int); |
diff --git a/sftp-glob.c b/sftp-glob.c index d85aecc9a..43a1bebad 100644 --- a/sftp-glob.c +++ b/sftp-glob.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-glob.c,v 1.26 2013/11/08 11:15:19 dtucker Exp $ */ | 1 | /* $OpenBSD: sftp-glob.c,v 1.27 2015/01/14 13:54:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -25,10 +25,10 @@ | |||
25 | #include <dirent.h> | 25 | #include <dirent.h> |
26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
27 | #include <string.h> | 27 | #include <string.h> |
28 | #include <stdlib.h> | ||
28 | 29 | ||
29 | #include "xmalloc.h" | 30 | #include "xmalloc.h" |
30 | #include "sftp.h" | 31 | #include "sftp.h" |
31 | #include "buffer.h" | ||
32 | #include "sftp-common.h" | 32 | #include "sftp-common.h" |
33 | #include "sftp-client.h" | 33 | #include "sftp-client.h" |
34 | 34 | ||
diff --git a/sftp-server.c b/sftp-server.c index 0177130cf..aeff1aa17 100644 --- a/sftp-server.c +++ b/sftp-server.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-server.c,v 1.103 2014/01/17 06:23:24 dtucker Exp $ */ | 1 | /* $OpenBSD: sftp-server.c,v 1.104 2015/01/14 13:54:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -46,7 +46,8 @@ | |||
46 | #include <stdarg.h> | 46 | #include <stdarg.h> |
47 | 47 | ||
48 | #include "xmalloc.h" | 48 | #include "xmalloc.h" |
49 | #include "buffer.h" | 49 | #include "sshbuf.h" |
50 | #include "ssherr.h" | ||
50 | #include "log.h" | 51 | #include "log.h" |
51 | #include "misc.h" | 52 | #include "misc.h" |
52 | #include "match.h" | 53 | #include "match.h" |
@@ -55,11 +56,6 @@ | |||
55 | #include "sftp.h" | 56 | #include "sftp.h" |
56 | #include "sftp-common.h" | 57 | #include "sftp-common.h" |
57 | 58 | ||
58 | /* helper */ | ||
59 | #define get_int64() buffer_get_int64(&iqueue); | ||
60 | #define get_int() buffer_get_int(&iqueue); | ||
61 | #define get_string(lenp) buffer_get_string(&iqueue, lenp); | ||
62 | |||
63 | /* Our verbosity */ | 59 | /* Our verbosity */ |
64 | static LogLevel log_level = SYSLOG_LEVEL_ERROR; | 60 | static LogLevel log_level = SYSLOG_LEVEL_ERROR; |
65 | 61 | ||
@@ -68,8 +64,8 @@ static struct passwd *pw = NULL; | |||
68 | static char *client_addr = NULL; | 64 | static char *client_addr = NULL; |
69 | 65 | ||
70 | /* input and output queue */ | 66 | /* input and output queue */ |
71 | static Buffer iqueue; | 67 | struct sshbuf *iqueue; |
72 | static Buffer oqueue; | 68 | struct sshbuf *oqueue; |
73 | 69 | ||
74 | /* Version of client */ | 70 | /* Version of client */ |
75 | static u_int version; | 71 | static u_int version; |
@@ -275,12 +271,6 @@ string_from_portable(int pflags) | |||
275 | return ret; | 271 | return ret; |
276 | } | 272 | } |
277 | 273 | ||
278 | static Attrib * | ||
279 | get_attrib(void) | ||
280 | { | ||
281 | return decode_attrib(&iqueue); | ||
282 | } | ||
283 | |||
284 | /* handle handles */ | 274 | /* handle handles */ |
285 | 275 | ||
286 | typedef struct Handle Handle; | 276 | typedef struct Handle Handle; |
@@ -344,7 +334,7 @@ handle_is_ok(int i, int type) | |||
344 | } | 334 | } |
345 | 335 | ||
346 | static int | 336 | static int |
347 | handle_to_string(int handle, char **stringp, int *hlenp) | 337 | handle_to_string(int handle, u_char **stringp, int *hlenp) |
348 | { | 338 | { |
349 | if (stringp == NULL || hlenp == NULL) | 339 | if (stringp == NULL || hlenp == NULL) |
350 | return -1; | 340 | return -1; |
@@ -355,7 +345,7 @@ handle_to_string(int handle, char **stringp, int *hlenp) | |||
355 | } | 345 | } |
356 | 346 | ||
357 | static int | 347 | static int |
358 | handle_from_string(const char *handle, u_int hlen) | 348 | handle_from_string(const u_char *handle, u_int hlen) |
359 | { | 349 | { |
360 | int val; | 350 | int val; |
361 | 351 | ||
@@ -477,29 +467,31 @@ handle_log_exit(void) | |||
477 | } | 467 | } |
478 | 468 | ||
479 | static int | 469 | static int |
480 | get_handle(void) | 470 | get_handle(struct sshbuf *queue, int *hp) |
481 | { | 471 | { |
482 | char *handle; | 472 | u_char *handle; |
483 | int val = -1; | 473 | int r; |
484 | u_int hlen; | 474 | size_t hlen; |
485 | 475 | ||
486 | handle = get_string(&hlen); | 476 | *hp = -1; |
477 | if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0) | ||
478 | return r; | ||
487 | if (hlen < 256) | 479 | if (hlen < 256) |
488 | val = handle_from_string(handle, hlen); | 480 | *hp = handle_from_string(handle, hlen); |
489 | free(handle); | 481 | free(handle); |
490 | return val; | 482 | return 0; |
491 | } | 483 | } |
492 | 484 | ||
493 | /* send replies */ | 485 | /* send replies */ |
494 | 486 | ||
495 | static void | 487 | static void |
496 | send_msg(Buffer *m) | 488 | send_msg(struct sshbuf *m) |
497 | { | 489 | { |
498 | int mlen = buffer_len(m); | 490 | int r; |
499 | 491 | ||
500 | buffer_put_int(&oqueue, mlen); | 492 | if ((r = sshbuf_put_stringb(oqueue, m)) != 0) |
501 | buffer_append(&oqueue, buffer_ptr(m), mlen); | 493 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
502 | buffer_consume(m, mlen); | 494 | sshbuf_reset(m); |
503 | } | 495 | } |
504 | 496 | ||
505 | static const char * | 497 | static const char * |
@@ -523,38 +515,46 @@ status_to_message(u_int32_t status) | |||
523 | static void | 515 | static void |
524 | send_status(u_int32_t id, u_int32_t status) | 516 | send_status(u_int32_t id, u_int32_t status) |
525 | { | 517 | { |
526 | Buffer msg; | 518 | struct sshbuf *msg; |
519 | int r; | ||
527 | 520 | ||
528 | debug3("request %u: sent status %u", id, status); | 521 | debug3("request %u: sent status %u", id, status); |
529 | if (log_level > SYSLOG_LEVEL_VERBOSE || | 522 | if (log_level > SYSLOG_LEVEL_VERBOSE || |
530 | (status != SSH2_FX_OK && status != SSH2_FX_EOF)) | 523 | (status != SSH2_FX_OK && status != SSH2_FX_EOF)) |
531 | logit("sent status %s", status_to_message(status)); | 524 | logit("sent status %s", status_to_message(status)); |
532 | buffer_init(&msg); | 525 | if ((msg = sshbuf_new()) == NULL) |
533 | buffer_put_char(&msg, SSH2_FXP_STATUS); | 526 | fatal("%s: sshbuf_new failed", __func__); |
534 | buffer_put_int(&msg, id); | 527 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 || |
535 | buffer_put_int(&msg, status); | 528 | (r = sshbuf_put_u32(msg, id)) != 0 || |
529 | (r = sshbuf_put_u32(msg, status)) != 0) | ||
530 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
536 | if (version >= 3) { | 531 | if (version >= 3) { |
537 | buffer_put_cstring(&msg, status_to_message(status)); | 532 | if ((r = sshbuf_put_cstring(msg, |
538 | buffer_put_cstring(&msg, ""); | 533 | status_to_message(status))) != 0 || |
534 | (r = sshbuf_put_cstring(msg, "")) != 0) | ||
535 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
539 | } | 536 | } |
540 | send_msg(&msg); | 537 | send_msg(msg); |
541 | buffer_free(&msg); | 538 | sshbuf_free(msg); |
542 | } | 539 | } |
543 | static void | 540 | static void |
544 | send_data_or_handle(char type, u_int32_t id, const char *data, int dlen) | 541 | send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen) |
545 | { | 542 | { |
546 | Buffer msg; | 543 | struct sshbuf *msg; |
547 | 544 | int r; | |
548 | buffer_init(&msg); | 545 | |
549 | buffer_put_char(&msg, type); | 546 | if ((msg = sshbuf_new()) == NULL) |
550 | buffer_put_int(&msg, id); | 547 | fatal("%s: sshbuf_new failed", __func__); |
551 | buffer_put_string(&msg, data, dlen); | 548 | if ((r = sshbuf_put_u8(msg, type)) != 0 || |
552 | send_msg(&msg); | 549 | (r = sshbuf_put_u32(msg, id)) != 0 || |
553 | buffer_free(&msg); | 550 | (r = sshbuf_put_string(msg, data, dlen)) != 0) |
551 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
552 | send_msg(msg); | ||
553 | sshbuf_free(msg); | ||
554 | } | 554 | } |
555 | 555 | ||
556 | static void | 556 | static void |
557 | send_data(u_int32_t id, const char *data, int dlen) | 557 | send_data(u_int32_t id, const u_char *data, int dlen) |
558 | { | 558 | { |
559 | debug("request %u: sent data len %d", id, dlen); | 559 | debug("request %u: sent data len %d", id, dlen); |
560 | send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); | 560 | send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); |
@@ -563,7 +563,7 @@ send_data(u_int32_t id, const char *data, int dlen) | |||
563 | static void | 563 | static void |
564 | send_handle(u_int32_t id, int handle) | 564 | send_handle(u_int32_t id, int handle) |
565 | { | 565 | { |
566 | char *string; | 566 | u_char *string; |
567 | int hlen; | 567 | int hlen; |
568 | 568 | ||
569 | handle_to_string(handle, &string, &hlen); | 569 | handle_to_string(handle, &string, &hlen); |
@@ -575,62 +575,71 @@ send_handle(u_int32_t id, int handle) | |||
575 | static void | 575 | static void |
576 | send_names(u_int32_t id, int count, const Stat *stats) | 576 | send_names(u_int32_t id, int count, const Stat *stats) |
577 | { | 577 | { |
578 | Buffer msg; | 578 | struct sshbuf *msg; |
579 | int i; | 579 | int i, r; |
580 | 580 | ||
581 | buffer_init(&msg); | 581 | if ((msg = sshbuf_new()) == NULL) |
582 | buffer_put_char(&msg, SSH2_FXP_NAME); | 582 | fatal("%s: sshbuf_new failed", __func__); |
583 | buffer_put_int(&msg, id); | 583 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 || |
584 | buffer_put_int(&msg, count); | 584 | (r = sshbuf_put_u32(msg, id)) != 0 || |
585 | (r = sshbuf_put_u32(msg, count)) != 0) | ||
586 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
585 | debug("request %u: sent names count %d", id, count); | 587 | debug("request %u: sent names count %d", id, count); |
586 | for (i = 0; i < count; i++) { | 588 | for (i = 0; i < count; i++) { |
587 | buffer_put_cstring(&msg, stats[i].name); | 589 | if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 || |
588 | buffer_put_cstring(&msg, stats[i].long_name); | 590 | (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 || |
589 | encode_attrib(&msg, &stats[i].attrib); | 591 | (r = encode_attrib(msg, &stats[i].attrib)) != 0) |
592 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
590 | } | 593 | } |
591 | send_msg(&msg); | 594 | send_msg(msg); |
592 | buffer_free(&msg); | 595 | sshbuf_free(msg); |
593 | } | 596 | } |
594 | 597 | ||
595 | static void | 598 | static void |
596 | send_attrib(u_int32_t id, const Attrib *a) | 599 | send_attrib(u_int32_t id, const Attrib *a) |
597 | { | 600 | { |
598 | Buffer msg; | 601 | struct sshbuf *msg; |
602 | int r; | ||
599 | 603 | ||
600 | debug("request %u: sent attrib have 0x%x", id, a->flags); | 604 | debug("request %u: sent attrib have 0x%x", id, a->flags); |
601 | buffer_init(&msg); | 605 | if ((msg = sshbuf_new()) == NULL) |
602 | buffer_put_char(&msg, SSH2_FXP_ATTRS); | 606 | fatal("%s: sshbuf_new failed", __func__); |
603 | buffer_put_int(&msg, id); | 607 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 || |
604 | encode_attrib(&msg, a); | 608 | (r = sshbuf_put_u32(msg, id)) != 0 || |
605 | send_msg(&msg); | 609 | (r = encode_attrib(msg, a)) != 0) |
606 | buffer_free(&msg); | 610 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
611 | send_msg(msg); | ||
612 | sshbuf_free(msg); | ||
607 | } | 613 | } |
608 | 614 | ||
609 | static void | 615 | static void |
610 | send_statvfs(u_int32_t id, struct statvfs *st) | 616 | send_statvfs(u_int32_t id, struct statvfs *st) |
611 | { | 617 | { |
612 | Buffer msg; | 618 | struct sshbuf *msg; |
613 | u_int64_t flag; | 619 | u_int64_t flag; |
620 | int r; | ||
614 | 621 | ||
615 | flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; | 622 | flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; |
616 | flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; | 623 | flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; |
617 | 624 | ||
618 | buffer_init(&msg); | 625 | if ((msg = sshbuf_new()) == NULL) |
619 | buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY); | 626 | fatal("%s: sshbuf_new failed", __func__); |
620 | buffer_put_int(&msg, id); | 627 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || |
621 | buffer_put_int64(&msg, st->f_bsize); | 628 | (r = sshbuf_put_u32(msg, id)) != 0 || |
622 | buffer_put_int64(&msg, st->f_frsize); | 629 | (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 || |
623 | buffer_put_int64(&msg, st->f_blocks); | 630 | (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 || |
624 | buffer_put_int64(&msg, st->f_bfree); | 631 | (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 || |
625 | buffer_put_int64(&msg, st->f_bavail); | 632 | (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 || |
626 | buffer_put_int64(&msg, st->f_files); | 633 | (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 || |
627 | buffer_put_int64(&msg, st->f_ffree); | 634 | (r = sshbuf_put_u64(msg, st->f_files)) != 0 || |
628 | buffer_put_int64(&msg, st->f_favail); | 635 | (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 || |
629 | buffer_put_int64(&msg, FSID_TO_ULONG(st->f_fsid)); | 636 | (r = sshbuf_put_u64(msg, st->f_favail)) != 0 || |
630 | buffer_put_int64(&msg, flag); | 637 | (r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 || |
631 | buffer_put_int64(&msg, st->f_namemax); | 638 | (r = sshbuf_put_u64(msg, flag)) != 0 || |
632 | send_msg(&msg); | 639 | (r = sshbuf_put_u64(msg, st->f_namemax)) != 0) |
633 | buffer_free(&msg); | 640 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
641 | send_msg(msg); | ||
642 | sshbuf_free(msg); | ||
634 | } | 643 | } |
635 | 644 | ||
636 | /* parse incoming */ | 645 | /* parse incoming */ |
@@ -638,53 +647,59 @@ send_statvfs(u_int32_t id, struct statvfs *st) | |||
638 | static void | 647 | static void |
639 | process_init(void) | 648 | process_init(void) |
640 | { | 649 | { |
641 | Buffer msg; | 650 | struct sshbuf *msg; |
651 | int r; | ||
642 | 652 | ||
643 | version = get_int(); | 653 | if ((r = sshbuf_get_u32(iqueue, &version)) != 0) |
654 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
644 | verbose("received client version %u", version); | 655 | verbose("received client version %u", version); |
645 | buffer_init(&msg); | 656 | if ((msg = sshbuf_new()) == NULL) |
646 | buffer_put_char(&msg, SSH2_FXP_VERSION); | 657 | fatal("%s: sshbuf_new failed", __func__); |
647 | buffer_put_int(&msg, SSH2_FILEXFER_VERSION); | 658 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 || |
648 | /* POSIX rename extension */ | 659 | (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 || |
649 | buffer_put_cstring(&msg, "posix-rename@openssh.com"); | 660 | /* POSIX rename extension */ |
650 | buffer_put_cstring(&msg, "1"); /* version */ | 661 | (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0 || |
651 | /* statvfs extension */ | 662 | (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ |
652 | buffer_put_cstring(&msg, "statvfs@openssh.com"); | 663 | /* statvfs extension */ |
653 | buffer_put_cstring(&msg, "2"); /* version */ | 664 | (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || |
654 | /* fstatvfs extension */ | 665 | (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ |
655 | buffer_put_cstring(&msg, "fstatvfs@openssh.com"); | 666 | /* fstatvfs extension */ |
656 | buffer_put_cstring(&msg, "2"); /* version */ | 667 | (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || |
657 | /* hardlink extension */ | 668 | (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ |
658 | buffer_put_cstring(&msg, "hardlink@openssh.com"); | 669 | /* hardlink extension */ |
659 | buffer_put_cstring(&msg, "1"); /* version */ | 670 | (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || |
660 | /* fsync extension */ | 671 | (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ |
661 | buffer_put_cstring(&msg, "fsync@openssh.com"); | 672 | /* fsync extension */ |
662 | buffer_put_cstring(&msg, "1"); /* version */ | 673 | (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || |
663 | send_msg(&msg); | 674 | (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ |
664 | buffer_free(&msg); | 675 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
676 | send_msg(msg); | ||
677 | sshbuf_free(msg); | ||
665 | } | 678 | } |
666 | 679 | ||
667 | static void | 680 | static void |
668 | process_open(u_int32_t id) | 681 | process_open(u_int32_t id) |
669 | { | 682 | { |
670 | u_int32_t pflags; | 683 | u_int32_t pflags; |
671 | Attrib *a; | 684 | Attrib a; |
672 | char *name; | 685 | char *name; |
673 | int handle, fd, flags, mode, status = SSH2_FX_FAILURE; | 686 | int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; |
687 | |||
688 | if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || | ||
689 | (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ | ||
690 | (r = decode_attrib(iqueue, &a)) != 0) | ||
691 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
674 | 692 | ||
675 | name = get_string(NULL); | ||
676 | pflags = get_int(); /* portable flags */ | ||
677 | debug3("request %u: open flags %d", id, pflags); | 693 | debug3("request %u: open flags %d", id, pflags); |
678 | a = get_attrib(); | ||
679 | flags = flags_from_portable(pflags); | 694 | flags = flags_from_portable(pflags); |
680 | mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; | 695 | mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; |
681 | logit("open \"%s\" flags %s mode 0%o", | 696 | logit("open \"%s\" flags %s mode 0%o", |
682 | name, string_from_portable(pflags), mode); | 697 | name, string_from_portable(pflags), mode); |
683 | if (readonly && | 698 | if (readonly && |
684 | ((flags & O_ACCMODE) == O_WRONLY || | 699 | ((flags & O_ACCMODE) == O_WRONLY || |
685 | (flags & O_ACCMODE) == O_RDWR)) { | 700 | (flags & O_ACCMODE) == O_RDWR)) { |
686 | verbose("Refusing open request in read-only mode"); | 701 | verbose("Refusing open request in read-only mode"); |
687 | status = SSH2_FX_PERMISSION_DENIED; | 702 | status = SSH2_FX_PERMISSION_DENIED; |
688 | } else { | 703 | } else { |
689 | fd = open(name, flags, mode); | 704 | fd = open(name, flags, mode); |
690 | if (fd < 0) { | 705 | if (fd < 0) { |
@@ -707,9 +722,11 @@ process_open(u_int32_t id) | |||
707 | static void | 722 | static void |
708 | process_close(u_int32_t id) | 723 | process_close(u_int32_t id) |
709 | { | 724 | { |
710 | int handle, ret, status = SSH2_FX_FAILURE; | 725 | int r, handle, ret, status = SSH2_FX_FAILURE; |
726 | |||
727 | if ((r = get_handle(iqueue, &handle)) != 0) | ||
728 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
711 | 729 | ||
712 | handle = get_handle(); | ||
713 | debug3("request %u: close handle %u", id, handle); | 730 | debug3("request %u: close handle %u", id, handle); |
714 | handle_log_close(handle, NULL); | 731 | handle_log_close(handle, NULL); |
715 | ret = handle_close(handle); | 732 | ret = handle_close(handle); |
@@ -720,14 +737,15 @@ process_close(u_int32_t id) | |||
720 | static void | 737 | static void |
721 | process_read(u_int32_t id) | 738 | process_read(u_int32_t id) |
722 | { | 739 | { |
723 | char buf[64*1024]; | 740 | u_char buf[64*1024]; |
724 | u_int32_t len; | 741 | u_int32_t len; |
725 | int handle, fd, ret, status = SSH2_FX_FAILURE; | 742 | int r, handle, fd, ret, status = SSH2_FX_FAILURE; |
726 | u_int64_t off; | 743 | u_int64_t off; |
727 | 744 | ||
728 | handle = get_handle(); | 745 | if ((r = get_handle(iqueue, &handle)) != 0 || |
729 | off = get_int64(); | 746 | (r = sshbuf_get_u64(iqueue, &off)) != 0 || |
730 | len = get_int(); | 747 | (r = sshbuf_get_u32(iqueue, &len)) != 0) |
748 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
731 | 749 | ||
732 | debug("request %u: read \"%s\" (handle %d) off %llu len %d", | 750 | debug("request %u: read \"%s\" (handle %d) off %llu len %d", |
733 | id, handle_to_name(handle), handle, (unsigned long long)off, len); | 751 | id, handle_to_name(handle), handle, (unsigned long long)off, len); |
@@ -761,18 +779,19 @@ static void | |||
761 | process_write(u_int32_t id) | 779 | process_write(u_int32_t id) |
762 | { | 780 | { |
763 | u_int64_t off; | 781 | u_int64_t off; |
764 | u_int len; | 782 | size_t len; |
765 | int handle, fd, ret, status; | 783 | int r, handle, fd, ret, status; |
766 | char *data; | 784 | u_char *data; |
767 | 785 | ||
768 | handle = get_handle(); | 786 | if ((r = get_handle(iqueue, &handle)) != 0 || |
769 | off = get_int64(); | 787 | (r = sshbuf_get_u64(iqueue, &off)) != 0 || |
770 | data = get_string(&len); | 788 | (r = sshbuf_get_string(iqueue, &data, &len)) != 0) |
789 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
771 | 790 | ||
772 | debug("request %u: write \"%s\" (handle %d) off %llu len %d", | 791 | debug("request %u: write \"%s\" (handle %d) off %llu len %zu", |
773 | id, handle_to_name(handle), handle, (unsigned long long)off, len); | 792 | id, handle_to_name(handle), handle, (unsigned long long)off, len); |
774 | fd = handle_to_fd(handle); | 793 | fd = handle_to_fd(handle); |
775 | 794 | ||
776 | if (fd < 0) | 795 | if (fd < 0) |
777 | status = SSH2_FX_FAILURE; | 796 | status = SSH2_FX_FAILURE; |
778 | else { | 797 | else { |
@@ -805,13 +824,15 @@ process_do_stat(u_int32_t id, int do_lstat) | |||
805 | Attrib a; | 824 | Attrib a; |
806 | struct stat st; | 825 | struct stat st; |
807 | char *name; | 826 | char *name; |
808 | int ret, status = SSH2_FX_FAILURE; | 827 | int r, status = SSH2_FX_FAILURE; |
828 | |||
829 | if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) | ||
830 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
809 | 831 | ||
810 | name = get_string(NULL); | ||
811 | debug3("request %u: %sstat", id, do_lstat ? "l" : ""); | 832 | debug3("request %u: %sstat", id, do_lstat ? "l" : ""); |
812 | verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); | 833 | verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); |
813 | ret = do_lstat ? lstat(name, &st) : stat(name, &st); | 834 | r = do_lstat ? lstat(name, &st) : stat(name, &st); |
814 | if (ret < 0) { | 835 | if (r < 0) { |
815 | status = errno_to_portable(errno); | 836 | status = errno_to_portable(errno); |
816 | } else { | 837 | } else { |
817 | stat_to_attrib(&st, &a); | 838 | stat_to_attrib(&st, &a); |
@@ -840,15 +861,16 @@ process_fstat(u_int32_t id) | |||
840 | { | 861 | { |
841 | Attrib a; | 862 | Attrib a; |
842 | struct stat st; | 863 | struct stat st; |
843 | int fd, ret, handle, status = SSH2_FX_FAILURE; | 864 | int fd, r, handle, status = SSH2_FX_FAILURE; |
844 | 865 | ||
845 | handle = get_handle(); | 866 | if ((r = get_handle(iqueue, &handle)) != 0) |
867 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
846 | debug("request %u: fstat \"%s\" (handle %u)", | 868 | debug("request %u: fstat \"%s\" (handle %u)", |
847 | id, handle_to_name(handle), handle); | 869 | id, handle_to_name(handle), handle); |
848 | fd = handle_to_fd(handle); | 870 | fd = handle_to_fd(handle); |
849 | if (fd >= 0) { | 871 | if (fd >= 0) { |
850 | ret = fstat(fd, &st); | 872 | r = fstat(fd, &st); |
851 | if (ret < 0) { | 873 | if (r < 0) { |
852 | status = errno_to_portable(errno); | 874 | status = errno_to_portable(errno); |
853 | } else { | 875 | } else { |
854 | stat_to_attrib(&st, &a); | 876 | stat_to_attrib(&st, &a); |
@@ -875,42 +897,44 @@ attrib_to_tv(const Attrib *a) | |||
875 | static void | 897 | static void |
876 | process_setstat(u_int32_t id) | 898 | process_setstat(u_int32_t id) |
877 | { | 899 | { |
878 | Attrib *a; | 900 | Attrib a; |
879 | char *name; | 901 | char *name; |
880 | int status = SSH2_FX_OK, ret; | 902 | int r, status = SSH2_FX_OK; |
903 | |||
904 | if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || | ||
905 | (r = decode_attrib(iqueue, &a)) != 0) | ||
906 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
881 | 907 | ||
882 | name = get_string(NULL); | ||
883 | a = get_attrib(); | ||
884 | debug("request %u: setstat name \"%s\"", id, name); | 908 | debug("request %u: setstat name \"%s\"", id, name); |
885 | if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { | 909 | if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { |
886 | logit("set \"%s\" size %llu", | 910 | logit("set \"%s\" size %llu", |
887 | name, (unsigned long long)a->size); | 911 | name, (unsigned long long)a.size); |
888 | ret = truncate(name, a->size); | 912 | r = truncate(name, a.size); |
889 | if (ret == -1) | 913 | if (r == -1) |
890 | status = errno_to_portable(errno); | 914 | status = errno_to_portable(errno); |
891 | } | 915 | } |
892 | if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { | 916 | if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { |
893 | logit("set \"%s\" mode %04o", name, a->perm); | 917 | logit("set \"%s\" mode %04o", name, a.perm); |
894 | ret = chmod(name, a->perm & 07777); | 918 | r = chmod(name, a.perm & 07777); |
895 | if (ret == -1) | 919 | if (r == -1) |
896 | status = errno_to_portable(errno); | 920 | status = errno_to_portable(errno); |
897 | } | 921 | } |
898 | if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { | 922 | if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { |
899 | char buf[64]; | 923 | char buf[64]; |
900 | time_t t = a->mtime; | 924 | time_t t = a.mtime; |
901 | 925 | ||
902 | strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", | 926 | strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", |
903 | localtime(&t)); | 927 | localtime(&t)); |
904 | logit("set \"%s\" modtime %s", name, buf); | 928 | logit("set \"%s\" modtime %s", name, buf); |
905 | ret = utimes(name, attrib_to_tv(a)); | 929 | r = utimes(name, attrib_to_tv(&a)); |
906 | if (ret == -1) | 930 | if (r == -1) |
907 | status = errno_to_portable(errno); | 931 | status = errno_to_portable(errno); |
908 | } | 932 | } |
909 | if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { | 933 | if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { |
910 | logit("set \"%s\" owner %lu group %lu", name, | 934 | logit("set \"%s\" owner %lu group %lu", name, |
911 | (u_long)a->uid, (u_long)a->gid); | 935 | (u_long)a.uid, (u_long)a.gid); |
912 | ret = chown(name, a->uid, a->gid); | 936 | r = chown(name, a.uid, a.gid); |
913 | if (ret == -1) | 937 | if (r == -1) |
914 | status = errno_to_portable(errno); | 938 | status = errno_to_portable(errno); |
915 | } | 939 | } |
916 | send_status(id, status); | 940 | send_status(id, status); |
@@ -920,12 +944,78 @@ process_setstat(u_int32_t id) | |||
920 | static void | 944 | static void |
921 | process_fsetstat(u_int32_t id) | 945 | process_fsetstat(u_int32_t id) |
922 | { | 946 | { |
923 | Attrib *a; | 947 | Attrib a; |
924 | int handle, fd, ret; | 948 | int handle, fd, r; |
949 | int status = SSH2_FX_OK; | ||
950 | |||
951 | if ((r = get_handle(iqueue, &handle)) != 0 || | ||
952 | (r = decode_attrib(iqueue, &a)) != 0) | ||
953 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
954 | |||
955 | debug("request %u: fsetstat handle %d", id, handle); | ||
956 | fd = handle_to_fd(handle); | ||
957 | if (fd < 0) | ||
958 | status = SSH2_FX_FAILURE; | ||
959 | else { | ||
960 | char *name = handle_to_name(handle); | ||
961 | |||
962 | if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { | ||
963 | logit("set \"%s\" size %llu", | ||
964 | name, (unsigned long long)a.size); | ||
965 | r = ftruncate(fd, a.size); | ||
966 | if (r == -1) | ||
967 | status = errno_to_portable(errno); | ||
968 | } | ||
969 | if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { | ||
970 | logit("set \"%s\" mode %04o", name, a.perm); | ||
971 | #ifdef HAVE_FCHMOD | ||
972 | ret = fchmod(fd, a->perm & 07777); | ||
973 | #else | ||
974 | ret = chmod(name, a->perm & 07777); | ||
975 | #endif | ||
976 | if (r == -1) | ||
977 | status = errno_to_portable(errno); | ||
978 | } | ||
979 | if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { | ||
980 | char buf[64]; | ||
981 | time_t t = a.mtime; | ||
982 | |||
983 | strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", | ||
984 | localtime(&t)); | ||
985 | logit("set \"%s\" modtime %s", name, buf); | ||
986 | #ifdef HAVE_FUTIMES | ||
987 | ret = futimes(fd, attrib_to_tv(a)); | ||
988 | #else | ||
989 | ret = utimes(name, attrib_to_tv(a)); | ||
990 | #endif | ||
991 | if (r == -1) | ||
992 | status = errno_to_portable(errno); | ||
993 | } | ||
994 | if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { | ||
995 | logit("set \"%s\" owner %lu group %lu", name, | ||
996 | (u_long)a.uid, (u_long)a.gid); | ||
997 | #ifdef HAVE_FCHOWN | ||
998 | ret = fchown(fd, a->uid, a->gid); | ||
999 | #else | ||
1000 | ret = chown(name, a->uid, a->gid); | ||
1001 | #endif | ||
1002 | if (r == -1) | ||
1003 | status = errno_to_portable(errno); | ||
1004 | } | ||
1005 | } | ||
1006 | send_status(id, status); | ||
1007 | } | ||
1008 | static void | ||
1009 | process_fsetstat(u_int32_t id) | ||
1010 | { | ||
1011 | Attrib a; | ||
1012 | int handle, fd, r; | ||
925 | int status = SSH2_FX_OK; | 1013 | int status = SSH2_FX_OK; |
926 | 1014 | ||
927 | handle = get_handle(); | 1015 | if ((r = get_handle(iqueue, &handle)) != 0 || |
928 | a = get_attrib(); | 1016 | (r = decode_attrib(iqueue, &a)) != 0) |
1017 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1018 | |||
929 | debug("request %u: fsetstat handle %d", id, handle); | 1019 | debug("request %u: fsetstat handle %d", id, handle); |
930 | fd = handle_to_fd(handle); | 1020 | fd = handle_to_fd(handle); |
931 | if (fd < 0) | 1021 | if (fd < 0) |
@@ -985,9 +1075,11 @@ process_opendir(u_int32_t id) | |||
985 | { | 1075 | { |
986 | DIR *dirp = NULL; | 1076 | DIR *dirp = NULL; |
987 | char *path; | 1077 | char *path; |
988 | int handle, status = SSH2_FX_FAILURE; | 1078 | int r, handle, status = SSH2_FX_FAILURE; |
1079 | |||
1080 | if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) | ||
1081 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
989 | 1082 | ||
990 | path = get_string(NULL); | ||
991 | debug3("request %u: opendir", id); | 1083 | debug3("request %u: opendir", id); |
992 | logit("opendir \"%s\"", path); | 1084 | logit("opendir \"%s\"", path); |
993 | dirp = opendir(path); | 1085 | dirp = opendir(path); |
@@ -1014,9 +1106,11 @@ process_readdir(u_int32_t id) | |||
1014 | DIR *dirp; | 1106 | DIR *dirp; |
1015 | struct dirent *dp; | 1107 | struct dirent *dp; |
1016 | char *path; | 1108 | char *path; |
1017 | int handle; | 1109 | int r, handle; |
1110 | |||
1111 | if ((r = get_handle(iqueue, &handle)) != 0) | ||
1112 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1018 | 1113 | ||
1019 | handle = get_handle(); | ||
1020 | debug("request %u: readdir \"%s\" (handle %d)", id, | 1114 | debug("request %u: readdir \"%s\" (handle %d)", id, |
1021 | handle_to_name(handle), handle); | 1115 | handle_to_name(handle), handle); |
1022 | dirp = handle_to_dir(handle); | 1116 | dirp = handle_to_dir(handle); |
@@ -1066,14 +1160,15 @@ static void | |||
1066 | process_remove(u_int32_t id) | 1160 | process_remove(u_int32_t id) |
1067 | { | 1161 | { |
1068 | char *name; | 1162 | char *name; |
1069 | int status = SSH2_FX_FAILURE; | 1163 | int r, status = SSH2_FX_FAILURE; |
1070 | int ret; | 1164 | |
1165 | if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) | ||
1166 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1071 | 1167 | ||
1072 | name = get_string(NULL); | ||
1073 | debug3("request %u: remove", id); | 1168 | debug3("request %u: remove", id); |
1074 | logit("remove name \"%s\"", name); | 1169 | logit("remove name \"%s\"", name); |
1075 | ret = unlink(name); | 1170 | r = unlink(name); |
1076 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | 1171 | status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1077 | send_status(id, status); | 1172 | send_status(id, status); |
1078 | free(name); | 1173 | free(name); |
1079 | } | 1174 | } |
@@ -1081,18 +1176,20 @@ process_remove(u_int32_t id) | |||
1081 | static void | 1176 | static void |
1082 | process_mkdir(u_int32_t id) | 1177 | process_mkdir(u_int32_t id) |
1083 | { | 1178 | { |
1084 | Attrib *a; | 1179 | Attrib a; |
1085 | char *name; | 1180 | char *name; |
1086 | int ret, mode, status = SSH2_FX_FAILURE; | 1181 | int r, mode, status = SSH2_FX_FAILURE; |
1182 | |||
1183 | if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || | ||
1184 | (r = decode_attrib(iqueue, &a)) != 0) | ||
1185 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1087 | 1186 | ||
1088 | name = get_string(NULL); | 1187 | mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? |
1089 | a = get_attrib(); | 1188 | a.perm & 07777 : 0777; |
1090 | mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? | ||
1091 | a->perm & 07777 : 0777; | ||
1092 | debug3("request %u: mkdir", id); | 1189 | debug3("request %u: mkdir", id); |
1093 | logit("mkdir name \"%s\" mode 0%o", name, mode); | 1190 | logit("mkdir name \"%s\" mode 0%o", name, mode); |
1094 | ret = mkdir(name, mode); | 1191 | r = mkdir(name, mode); |
1095 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | 1192 | status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1096 | send_status(id, status); | 1193 | send_status(id, status); |
1097 | free(name); | 1194 | free(name); |
1098 | } | 1195 | } |
@@ -1101,13 +1198,15 @@ static void | |||
1101 | process_rmdir(u_int32_t id) | 1198 | process_rmdir(u_int32_t id) |
1102 | { | 1199 | { |
1103 | char *name; | 1200 | char *name; |
1104 | int ret, status; | 1201 | int r, status; |
1202 | |||
1203 | if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) | ||
1204 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1105 | 1205 | ||
1106 | name = get_string(NULL); | ||
1107 | debug3("request %u: rmdir", id); | 1206 | debug3("request %u: rmdir", id); |
1108 | logit("rmdir name \"%s\"", name); | 1207 | logit("rmdir name \"%s\"", name); |
1109 | ret = rmdir(name); | 1208 | r = rmdir(name); |
1110 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | 1209 | status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1111 | send_status(id, status); | 1210 | send_status(id, status); |
1112 | free(name); | 1211 | free(name); |
1113 | } | 1212 | } |
@@ -1117,8 +1216,11 @@ process_realpath(u_int32_t id) | |||
1117 | { | 1216 | { |
1118 | char resolvedname[MAXPATHLEN]; | 1217 | char resolvedname[MAXPATHLEN]; |
1119 | char *path; | 1218 | char *path; |
1219 | int r; | ||
1220 | |||
1221 | if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) | ||
1222 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1120 | 1223 | ||
1121 | path = get_string(NULL); | ||
1122 | if (path[0] == '\0') { | 1224 | if (path[0] == '\0') { |
1123 | free(path); | 1225 | free(path); |
1124 | path = xstrdup("."); | 1226 | path = xstrdup("."); |
@@ -1140,11 +1242,13 @@ static void | |||
1140 | process_rename(u_int32_t id) | 1242 | process_rename(u_int32_t id) |
1141 | { | 1243 | { |
1142 | char *oldpath, *newpath; | 1244 | char *oldpath, *newpath; |
1143 | int status; | 1245 | int r, status; |
1144 | struct stat sb; | 1246 | struct stat sb; |
1145 | 1247 | ||
1146 | oldpath = get_string(NULL); | 1248 | if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || |
1147 | newpath = get_string(NULL); | 1249 | (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) |
1250 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1251 | |||
1148 | debug3("request %u: rename", id); | 1252 | debug3("request %u: rename", id); |
1149 | logit("rename old \"%s\" new \"%s\"", oldpath, newpath); | 1253 | logit("rename old \"%s\" new \"%s\"", oldpath, newpath); |
1150 | status = SSH2_FX_FAILURE; | 1254 | status = SSH2_FX_FAILURE; |
@@ -1197,11 +1301,13 @@ process_rename(u_int32_t id) | |||
1197 | static void | 1301 | static void |
1198 | process_readlink(u_int32_t id) | 1302 | process_readlink(u_int32_t id) |
1199 | { | 1303 | { |
1200 | int len; | 1304 | int r, len; |
1201 | char buf[MAXPATHLEN]; | 1305 | char buf[MAXPATHLEN]; |
1202 | char *path; | 1306 | char *path; |
1203 | 1307 | ||
1204 | path = get_string(NULL); | 1308 | if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) |
1309 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1310 | |||
1205 | debug3("request %u: readlink", id); | 1311 | debug3("request %u: readlink", id); |
1206 | verbose("readlink \"%s\"", path); | 1312 | verbose("readlink \"%s\"", path); |
1207 | if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) | 1313 | if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) |
@@ -1221,15 +1327,17 @@ static void | |||
1221 | process_symlink(u_int32_t id) | 1327 | process_symlink(u_int32_t id) |
1222 | { | 1328 | { |
1223 | char *oldpath, *newpath; | 1329 | char *oldpath, *newpath; |
1224 | int ret, status; | 1330 | int r, status; |
1331 | |||
1332 | if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || | ||
1333 | (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) | ||
1334 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1225 | 1335 | ||
1226 | oldpath = get_string(NULL); | ||
1227 | newpath = get_string(NULL); | ||
1228 | debug3("request %u: symlink", id); | 1336 | debug3("request %u: symlink", id); |
1229 | logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); | 1337 | logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); |
1230 | /* this will fail if 'newpath' exists */ | 1338 | /* this will fail if 'newpath' exists */ |
1231 | ret = symlink(oldpath, newpath); | 1339 | r = symlink(oldpath, newpath); |
1232 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | 1340 | status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1233 | send_status(id, status); | 1341 | send_status(id, status); |
1234 | free(oldpath); | 1342 | free(oldpath); |
1235 | free(newpath); | 1343 | free(newpath); |
@@ -1239,14 +1347,16 @@ static void | |||
1239 | process_extended_posix_rename(u_int32_t id) | 1347 | process_extended_posix_rename(u_int32_t id) |
1240 | { | 1348 | { |
1241 | char *oldpath, *newpath; | 1349 | char *oldpath, *newpath; |
1242 | int ret, status; | 1350 | int r, status; |
1351 | |||
1352 | if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || | ||
1353 | (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) | ||
1354 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1243 | 1355 | ||
1244 | oldpath = get_string(NULL); | ||
1245 | newpath = get_string(NULL); | ||
1246 | debug3("request %u: posix-rename", id); | 1356 | debug3("request %u: posix-rename", id); |
1247 | logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); | 1357 | logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); |
1248 | ret = rename(oldpath, newpath); | 1358 | r = rename(oldpath, newpath); |
1249 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | 1359 | status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1250 | send_status(id, status); | 1360 | send_status(id, status); |
1251 | free(oldpath); | 1361 | free(oldpath); |
1252 | free(newpath); | 1362 | free(newpath); |
@@ -1257,8 +1367,10 @@ process_extended_statvfs(u_int32_t id) | |||
1257 | { | 1367 | { |
1258 | char *path; | 1368 | char *path; |
1259 | struct statvfs st; | 1369 | struct statvfs st; |
1370 | int r; | ||
1260 | 1371 | ||
1261 | path = get_string(NULL); | 1372 | if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) |
1373 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1262 | debug3("request %u: statvfs", id); | 1374 | debug3("request %u: statvfs", id); |
1263 | logit("statvfs \"%s\"", path); | 1375 | logit("statvfs \"%s\"", path); |
1264 | 1376 | ||
@@ -1272,10 +1384,11 @@ process_extended_statvfs(u_int32_t id) | |||
1272 | static void | 1384 | static void |
1273 | process_extended_fstatvfs(u_int32_t id) | 1385 | process_extended_fstatvfs(u_int32_t id) |
1274 | { | 1386 | { |
1275 | int handle, fd; | 1387 | int r, handle, fd; |
1276 | struct statvfs st; | 1388 | struct statvfs st; |
1277 | 1389 | ||
1278 | handle = get_handle(); | 1390 | if ((r = get_handle(iqueue, &handle)) != 0) |
1391 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1279 | debug("request %u: fstatvfs \"%s\" (handle %u)", | 1392 | debug("request %u: fstatvfs \"%s\" (handle %u)", |
1280 | id, handle_to_name(handle), handle); | 1393 | id, handle_to_name(handle), handle); |
1281 | if ((fd = handle_to_fd(handle)) < 0) { | 1394 | if ((fd = handle_to_fd(handle)) < 0) { |
@@ -1292,14 +1405,16 @@ static void | |||
1292 | process_extended_hardlink(u_int32_t id) | 1405 | process_extended_hardlink(u_int32_t id) |
1293 | { | 1406 | { |
1294 | char *oldpath, *newpath; | 1407 | char *oldpath, *newpath; |
1295 | int ret, status; | 1408 | int r, status; |
1409 | |||
1410 | if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || | ||
1411 | (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) | ||
1412 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1296 | 1413 | ||
1297 | oldpath = get_string(NULL); | ||
1298 | newpath = get_string(NULL); | ||
1299 | debug3("request %u: hardlink", id); | 1414 | debug3("request %u: hardlink", id); |
1300 | logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); | 1415 | logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); |
1301 | ret = link(oldpath, newpath); | 1416 | r = link(oldpath, newpath); |
1302 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | 1417 | status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1303 | send_status(id, status); | 1418 | send_status(id, status); |
1304 | free(oldpath); | 1419 | free(oldpath); |
1305 | free(newpath); | 1420 | free(newpath); |
@@ -1308,16 +1423,17 @@ process_extended_hardlink(u_int32_t id) | |||
1308 | static void | 1423 | static void |
1309 | process_extended_fsync(u_int32_t id) | 1424 | process_extended_fsync(u_int32_t id) |
1310 | { | 1425 | { |
1311 | int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED; | 1426 | int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED; |
1312 | 1427 | ||
1313 | handle = get_handle(); | 1428 | if ((r = get_handle(iqueue, &handle)) != 0) |
1429 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1314 | debug3("request %u: fsync (handle %u)", id, handle); | 1430 | debug3("request %u: fsync (handle %u)", id, handle); |
1315 | verbose("fsync \"%s\"", handle_to_name(handle)); | 1431 | verbose("fsync \"%s\"", handle_to_name(handle)); |
1316 | if ((fd = handle_to_fd(handle)) < 0) | 1432 | if ((fd = handle_to_fd(handle)) < 0) |
1317 | status = SSH2_FX_NO_SUCH_FILE; | 1433 | status = SSH2_FX_NO_SUCH_FILE; |
1318 | else if (handle_is_ok(handle, HANDLE_FILE)) { | 1434 | else if (handle_is_ok(handle, HANDLE_FILE)) { |
1319 | ret = fsync(fd); | 1435 | r = fsync(fd); |
1320 | status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; | 1436 | status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1321 | } | 1437 | } |
1322 | send_status(id, status); | 1438 | send_status(id, status); |
1323 | } | 1439 | } |
@@ -1326,9 +1442,10 @@ static void | |||
1326 | process_extended(u_int32_t id) | 1442 | process_extended(u_int32_t id) |
1327 | { | 1443 | { |
1328 | char *request; | 1444 | char *request; |
1329 | u_int i; | 1445 | int i, r; |
1330 | 1446 | ||
1331 | request = get_string(NULL); | 1447 | if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0) |
1448 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1332 | for (i = 0; extended_handlers[i].handler != NULL; i++) { | 1449 | for (i = 0; extended_handlers[i].handler != NULL; i++) { |
1333 | if (strcmp(request, extended_handlers[i].ext_name) == 0) { | 1450 | if (strcmp(request, extended_handlers[i].ext_name) == 0) { |
1334 | if (!request_permitted(&extended_handlers[i])) | 1451 | if (!request_permitted(&extended_handlers[i])) |
@@ -1350,14 +1467,18 @@ process_extended(u_int32_t id) | |||
1350 | static void | 1467 | static void |
1351 | process(void) | 1468 | process(void) |
1352 | { | 1469 | { |
1353 | u_int msg_len, buf_len, consumed, type, i; | 1470 | u_int msg_len; |
1354 | u_char *cp; | 1471 | u_int buf_len; |
1472 | u_int consumed; | ||
1473 | u_char type; | ||
1474 | const u_char *cp; | ||
1475 | int i, r; | ||
1355 | u_int32_t id; | 1476 | u_int32_t id; |
1356 | 1477 | ||
1357 | buf_len = buffer_len(&iqueue); | 1478 | buf_len = sshbuf_len(iqueue); |
1358 | if (buf_len < 5) | 1479 | if (buf_len < 5) |
1359 | return; /* Incomplete message. */ | 1480 | return; /* Incomplete message. */ |
1360 | cp = buffer_ptr(&iqueue); | 1481 | cp = sshbuf_ptr(iqueue); |
1361 | msg_len = get_u32(cp); | 1482 | msg_len = get_u32(cp); |
1362 | if (msg_len > SFTP_MAX_MSG_LENGTH) { | 1483 | if (msg_len > SFTP_MAX_MSG_LENGTH) { |
1363 | error("bad message from %s local user %s", | 1484 | error("bad message from %s local user %s", |
@@ -1366,9 +1487,11 @@ process(void) | |||
1366 | } | 1487 | } |
1367 | if (buf_len < msg_len + 4) | 1488 | if (buf_len < msg_len + 4) |
1368 | return; | 1489 | return; |
1369 | buffer_consume(&iqueue, 4); | 1490 | if ((r = sshbuf_consume(iqueue, 4)) != 0) |
1491 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1370 | buf_len -= 4; | 1492 | buf_len -= 4; |
1371 | type = buffer_get_char(&iqueue); | 1493 | if ((r = sshbuf_get_u8(iqueue, &type)) != 0) |
1494 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1372 | 1495 | ||
1373 | switch (type) { | 1496 | switch (type) { |
1374 | case SSH2_FXP_INIT: | 1497 | case SSH2_FXP_INIT: |
@@ -1378,13 +1501,15 @@ process(void) | |||
1378 | case SSH2_FXP_EXTENDED: | 1501 | case SSH2_FXP_EXTENDED: |
1379 | if (!init_done) | 1502 | if (!init_done) |
1380 | fatal("Received extended request before init"); | 1503 | fatal("Received extended request before init"); |
1381 | id = get_int(); | 1504 | if ((r = sshbuf_get_u32(iqueue, &id)) != 0) |
1505 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1382 | process_extended(id); | 1506 | process_extended(id); |
1383 | break; | 1507 | break; |
1384 | default: | 1508 | default: |
1385 | if (!init_done) | 1509 | if (!init_done) |
1386 | fatal("Received %u request before init", type); | 1510 | fatal("Received %u request before init", type); |
1387 | id = get_int(); | 1511 | if ((r = sshbuf_get_u32(iqueue, &id)) != 0) |
1512 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1388 | for (i = 0; handlers[i].handler != NULL; i++) { | 1513 | for (i = 0; handlers[i].handler != NULL; i++) { |
1389 | if (type == handlers[i].type) { | 1514 | if (type == handlers[i].type) { |
1390 | if (!request_permitted(&handlers[i])) { | 1515 | if (!request_permitted(&handlers[i])) { |
@@ -1400,17 +1525,18 @@ process(void) | |||
1400 | error("Unknown message %u", type); | 1525 | error("Unknown message %u", type); |
1401 | } | 1526 | } |
1402 | /* discard the remaining bytes from the current packet */ | 1527 | /* discard the remaining bytes from the current packet */ |
1403 | if (buf_len < buffer_len(&iqueue)) { | 1528 | if (buf_len < sshbuf_len(iqueue)) { |
1404 | error("iqueue grew unexpectedly"); | 1529 | error("iqueue grew unexpectedly"); |
1405 | sftp_server_cleanup_exit(255); | 1530 | sftp_server_cleanup_exit(255); |
1406 | } | 1531 | } |
1407 | consumed = buf_len - buffer_len(&iqueue); | 1532 | consumed = buf_len - sshbuf_len(iqueue); |
1408 | if (msg_len < consumed) { | 1533 | if (msg_len < consumed) { |
1409 | error("msg_len %u < consumed %u", msg_len, consumed); | 1534 | error("msg_len %u < consumed %u", msg_len, consumed); |
1410 | sftp_server_cleanup_exit(255); | 1535 | sftp_server_cleanup_exit(255); |
1411 | } | 1536 | } |
1412 | if (msg_len > consumed) | 1537 | if (msg_len > consumed && |
1413 | buffer_consume(&iqueue, msg_len - consumed); | 1538 | (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) |
1539 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1414 | } | 1540 | } |
1415 | 1541 | ||
1416 | /* Cleanup handler that logs active handles upon normal exit */ | 1542 | /* Cleanup handler that logs active handles upon normal exit */ |
@@ -1443,7 +1569,7 @@ int | |||
1443 | sftp_server_main(int argc, char **argv, struct passwd *user_pw) | 1569 | sftp_server_main(int argc, char **argv, struct passwd *user_pw) |
1444 | { | 1570 | { |
1445 | fd_set *rset, *wset; | 1571 | fd_set *rset, *wset; |
1446 | int i, in, out, max, ch, skipargs = 0, log_stderr = 0; | 1572 | int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; |
1447 | ssize_t len, olen, set_size; | 1573 | ssize_t len, olen, set_size; |
1448 | SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; | 1574 | SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; |
1449 | char *cp, *homedir = NULL, buf[4*4096]; | 1575 | char *cp, *homedir = NULL, buf[4*4096]; |
@@ -1565,8 +1691,10 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) | |||
1565 | if (out > max) | 1691 | if (out > max) |
1566 | max = out; | 1692 | max = out; |
1567 | 1693 | ||
1568 | buffer_init(&iqueue); | 1694 | if ((iqueue = sshbuf_new()) == NULL) |
1569 | buffer_init(&oqueue); | 1695 | fatal("%s: sshbuf_new failed", __func__); |
1696 | if ((oqueue = sshbuf_new()) == NULL) | ||
1697 | fatal("%s: sshbuf_new failed", __func__); | ||
1570 | 1698 | ||
1571 | set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); | 1699 | set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); |
1572 | rset = (fd_set *)xmalloc(set_size); | 1700 | rset = (fd_set *)xmalloc(set_size); |
@@ -1588,11 +1716,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) | |||
1588 | * the worst-case length packet it can generate, | 1716 | * the worst-case length packet it can generate, |
1589 | * otherwise apply backpressure by stopping reads. | 1717 | * otherwise apply backpressure by stopping reads. |
1590 | */ | 1718 | */ |
1591 | if (buffer_check_alloc(&iqueue, sizeof(buf)) && | 1719 | if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && |
1592 | buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) | 1720 | (r = sshbuf_check_reserve(oqueue, |
1721 | SFTP_MAX_MSG_LENGTH)) == 0) | ||
1593 | FD_SET(in, rset); | 1722 | FD_SET(in, rset); |
1723 | else if (r != SSH_ERR_NO_BUFFER_SPACE) | ||
1724 | fatal("%s: sshbuf_check_reserve failed: %s", | ||
1725 | __func__, ssh_err(r)); | ||
1594 | 1726 | ||
1595 | olen = buffer_len(&oqueue); | 1727 | olen = sshbuf_len(oqueue); |
1596 | if (olen > 0) | 1728 | if (olen > 0) |
1597 | FD_SET(out, wset); | 1729 | FD_SET(out, wset); |
1598 | 1730 | ||
@@ -1612,18 +1744,20 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) | |||
1612 | } else if (len < 0) { | 1744 | } else if (len < 0) { |
1613 | error("read: %s", strerror(errno)); | 1745 | error("read: %s", strerror(errno)); |
1614 | sftp_server_cleanup_exit(1); | 1746 | sftp_server_cleanup_exit(1); |
1615 | } else { | 1747 | } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) { |
1616 | buffer_append(&iqueue, buf, len); | 1748 | fatal("%s: buffer error: %s", |
1749 | __func__, ssh_err(r)); | ||
1617 | } | 1750 | } |
1618 | } | 1751 | } |
1619 | /* send oqueue to stdout */ | 1752 | /* send oqueue to stdout */ |
1620 | if (FD_ISSET(out, wset)) { | 1753 | if (FD_ISSET(out, wset)) { |
1621 | len = write(out, buffer_ptr(&oqueue), olen); | 1754 | len = write(out, sshbuf_ptr(oqueue), olen); |
1622 | if (len < 0) { | 1755 | if (len < 0) { |
1623 | error("write: %s", strerror(errno)); | 1756 | error("write: %s", strerror(errno)); |
1624 | sftp_server_cleanup_exit(1); | 1757 | sftp_server_cleanup_exit(1); |
1625 | } else { | 1758 | } else if ((r = sshbuf_consume(oqueue, len)) != 0) { |
1626 | buffer_consume(&oqueue, len); | 1759 | fatal("%s: buffer error: %s", |
1760 | __func__, ssh_err(r)); | ||
1627 | } | 1761 | } |
1628 | } | 1762 | } |
1629 | 1763 | ||
@@ -1632,7 +1766,11 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) | |||
1632 | * into the output buffer, otherwise stop processing input | 1766 | * into the output buffer, otherwise stop processing input |
1633 | * and let the output queue drain. | 1767 | * and let the output queue drain. |
1634 | */ | 1768 | */ |
1635 | if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) | 1769 | r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH); |
1770 | if (r == 0) | ||
1636 | process(); | 1771 | process(); |
1772 | else if (r != SSH_ERR_NO_BUFFER_SPACE) | ||
1773 | fatal("%s: sshbuf_check_reserve: %s", | ||
1774 | __func__, ssh_err(r)); | ||
1637 | } | 1775 | } |
1638 | } | 1776 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp.c,v 1.168 2014/11/26 18:34:51 millert Exp $ */ | 1 | /* $OpenBSD: sftp.c,v 1.169 2015/01/14 13:54:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -63,7 +63,8 @@ typedef void EditLine; | |||
63 | #include "misc.h" | 63 | #include "misc.h" |
64 | 64 | ||
65 | #include "sftp.h" | 65 | #include "sftp.h" |
66 | #include "buffer.h" | 66 | #include "ssherr.h" |
67 | #include "sshbuf.h" | ||
67 | #include "sftp-common.h" | 68 | #include "sftp-common.h" |
68 | #include "sftp-client.h" | 69 | #include "sftp-client.h" |
69 | 70 | ||