summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2015-01-14 13:54:13 +0000
committerDamien Miller <djm@mindrot.org>2015-01-15 02:22:18 +1100
commit7d845f4a0b7ec97887be204c3760e44de8bf1f32 (patch)
treec7f7271203627c22594cc86381745acce479d250 /sftp-client.c
parent139ca81866ec1b219c717d17061e5e7ad1059e2a (diff)
upstream commit
update sftp client and server to new buffer API. pretty much just mechanical changes; with & ok markus
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c861
1 files changed, 500 insertions, 361 deletions
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
86static char * 87static u_char *
87get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, 88get_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
100static void 101static void
101send_msg(struct sftp_conn *conn, Buffer *m) 102send_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
124static void 125static void
125get_msg(struct sftp_conn *conn, Buffer *m) 126get_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
153static void 159static void
154send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, 160send_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
168static void 177static void
169send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, 178send_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
184static u_int 196static u_int
185get_status(struct sftp_conn *conn, u_int expected_id) 197get_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
209static char * 226static u_char *
210get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, 227get_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
248static Attrib * 271static Attrib *
249get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) 272get_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
283static int 316static int
284get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, 317get_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 *
335do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, 376do_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
431int 482int
432do_close(struct sftp_conn *conn, char *handle, u_int handle_len) 483do_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
456static int 510static int
457do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, 511do_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
579int 656int
580do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) 657do_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
599int 676int
600do_rm(struct sftp_conn *conn, char *path) 677do_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
614int 691int
615do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) 692do_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
630int 707int
631do_rmdir(struct sftp_conn *conn, char *path) 708do_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
646Attrib * 723Attrib *
647do_stat(struct sftp_conn *conn, char *path, int quiet) 724do_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
660Attrib * 737Attrib *
661do_lstat(struct sftp_conn *conn, char *path, int quiet) 738do_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
681Attrib * 758Attrib *
682do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) 759do_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
694int 772int
695do_setstat(struct sftp_conn *conn, char *path, Attrib *a) 773do_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
711int 789int
712do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, 790do_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
728char * 806char *
729do_realpath(struct sftp_conn *conn, char *path) 807do_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
777int 863int
778do_rename(struct sftp_conn *conn, char *oldpath, char *newpath, 864do_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
813int 904int
814do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) 905do_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
846int 940int
847do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) 941do_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
878int 975int
879do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) 976do_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
909char * 1007char *
910do_readlink(struct sftp_conn *conn, char *path) 1008do_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
958do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, 1064do_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
984int 1093int
985do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, 1094do_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
1011static void 1122static void
1012send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1123send_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
1028int 1142int
1029do_download(struct sftp_conn *conn, char *remote_path, char *local_path, 1143do_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
1310static int 1436static int
1311download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, 1437download_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
1402int 1528int
1403download_dir(struct sftp_conn *conn, char *src, char *dst, 1529download_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
1421int 1547int
1422do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, 1548do_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
1630static int 1768static int
1631upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, 1769upload_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
1723int 1862int
1724upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, 1863upload_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
1742char * 1881char *
1743path_append(char *p1, char *p2) 1882path_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;