summaryrefslogtreecommitdiff
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
parent139ca81866ec1b219c717d17061e5e7ad1059e2a (diff)
upstream commit
update sftp client and server to new buffer API. pretty much just mechanical changes; with & ok markus
-rw-r--r--progressmeter.c6
-rw-r--r--progressmeter.h4
-rw-r--r--sftp-client.c861
-rw-r--r--sftp-client.h44
-rw-r--r--sftp-common.c99
-rw-r--r--sftp-common.h7
-rw-r--r--sftp-glob.c4
-rw-r--r--sftp-server.c610
-rw-r--r--sftp.c5
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
66static time_t start; /* start progress */ 66static time_t start; /* start progress */
67static time_t last_update; /* last progress update */ 67static time_t last_update; /* last progress update */
68static char *file; /* name of the file being transferred */ 68static const char *file; /* name of the file being transferred */
69static off_t start_pos; /* initial position of transfer */ 69static off_t start_pos; /* initial position of transfer */
70static off_t end_pos; /* ending position of transfer */ 70static off_t end_pos; /* ending position of transfer */
71static off_t cur_pos; /* transfer position as of last refresh */ 71static off_t cur_pos; /* transfer position as of last refresh */
@@ -248,7 +248,7 @@ update_progress_meter(int ignore)
248} 248}
249 249
250void 250void
251start_progress_meter(char *f, off_t filesize, off_t *ctr) 251start_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
26void start_progress_meter(char *, off_t, off_t *); 26void start_progress_meter(const char *, off_t, off_t *);
27void stop_progress_meter(void); 27void 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
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;
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);
56u_int sftp_proto_version(struct sftp_conn *); 56u_int sftp_proto_version(struct sftp_conn *);
57 57
58/* Close file referred to by 'handle' */ 58/* Close file referred to by 'handle' */
59int do_close(struct sftp_conn *, char *, u_int); 59int 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' */
62int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); 62int 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) */
65void free_sftp_dirents(SFTP_DIRENT **); 65void free_sftp_dirents(SFTP_DIRENT **);
66 66
67/* Delete file 'path' */ 67/* Delete file 'path' */
68int do_rm(struct sftp_conn *, char *); 68int do_rm(struct sftp_conn *, const char *);
69 69
70/* Create directory 'path' */ 70/* Create directory 'path' */
71int do_mkdir(struct sftp_conn *, char *, Attrib *, int); 71int do_mkdir(struct sftp_conn *, const char *, Attrib *, int);
72 72
73/* Remove directory 'path' */ 73/* Remove directory 'path' */
74int do_rmdir(struct sftp_conn *, char *); 74int 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) */
77Attrib *do_stat(struct sftp_conn *, char *, int); 77Attrib *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) */
80Attrib *do_lstat(struct sftp_conn *, char *, int); 80Attrib *do_lstat(struct sftp_conn *, const char *, int);
81 81
82/* Set file attributes of 'path' */ 82/* Set file attributes of 'path' */
83int do_setstat(struct sftp_conn *, char *, Attrib *); 83int 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' */
86int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); 86int 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 */
89char *do_realpath(struct sftp_conn *, char *); 89char *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" */
92int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); 92int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
93 93
94/* Rename 'oldpath' to 'newpath' */ 94/* Rename 'oldpath' to 'newpath' */
95int do_rename(struct sftp_conn *, char *, char *m, int force_legacy); 95int do_rename(struct sftp_conn *, const char *, const char *, int force_legacy);
96 96
97/* Link 'oldpath' to 'newpath' */ 97/* Link 'oldpath' to 'newpath' */
98int do_hardlink(struct sftp_conn *, char *, char *); 98int do_hardlink(struct sftp_conn *, const char *, const char *);
99 99
100/* Rename 'oldpath' to 'newpath' */ 100/* Rename 'oldpath' to 'newpath' */
101int do_symlink(struct sftp_conn *, char *, char *); 101int 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' */
104int do_fsync(struct sftp_conn *conn, char *, u_int); 104int 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 */
110int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int, int); 110int 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 */
116int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, 117int 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 */
123int do_upload(struct sftp_conn *, char *, char *, int, int, int); 124int 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 */
129int upload_dir(struct sftp_conn *, char *, char *, int, int, int, int); 130int 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. */
132char *path_append(char *, char *); 134char *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 */
103Attrib * 104int
104decode_attrib(Buffer *b) 105decode_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 */
140void 153int
141encode_attrib(Buffer *b, const Attrib *a) 154encode_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
31struct sshbuf;
31typedef struct Attrib Attrib; 32typedef struct Attrib Attrib;
32 33
33/* File attributes */ 34/* File attributes */
@@ -44,8 +45,8 @@ struct Attrib {
44void attrib_clear(Attrib *); 45void attrib_clear(Attrib *);
45void stat_to_attrib(const struct stat *, Attrib *); 46void stat_to_attrib(const struct stat *, Attrib *);
46void attrib_to_stat(const Attrib *, struct stat *); 47void attrib_to_stat(const Attrib *, struct stat *);
47Attrib *decode_attrib(Buffer *); 48int decode_attrib(struct sshbuf *, Attrib *);
48void encode_attrib(Buffer *, const Attrib *); 49int encode_attrib(struct sshbuf *, const Attrib *);
49char *ls_file(const char *, const struct stat *, int, int); 50char *ls_file(const char *, const struct stat *, int, int);
50 51
51const char *fx2txt(int); 52const 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 */
64static LogLevel log_level = SYSLOG_LEVEL_ERROR; 60static LogLevel log_level = SYSLOG_LEVEL_ERROR;
65 61
@@ -68,8 +64,8 @@ static struct passwd *pw = NULL;
68static char *client_addr = NULL; 64static char *client_addr = NULL;
69 65
70/* input and output queue */ 66/* input and output queue */
71static Buffer iqueue; 67struct sshbuf *iqueue;
72static Buffer oqueue; 68struct sshbuf *oqueue;
73 69
74/* Version of client */ 70/* Version of client */
75static u_int version; 71static u_int version;
@@ -275,12 +271,6 @@ string_from_portable(int pflags)
275 return ret; 271 return ret;
276} 272}
277 273
278static Attrib *
279get_attrib(void)
280{
281 return decode_attrib(&iqueue);
282}
283
284/* handle handles */ 274/* handle handles */
285 275
286typedef struct Handle Handle; 276typedef struct Handle Handle;
@@ -344,7 +334,7 @@ handle_is_ok(int i, int type)
344} 334}
345 335
346static int 336static int
347handle_to_string(int handle, char **stringp, int *hlenp) 337handle_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
357static int 347static int
358handle_from_string(const char *handle, u_int hlen) 348handle_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
479static int 469static int
480get_handle(void) 470get_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
495static void 487static void
496send_msg(Buffer *m) 488send_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
505static const char * 497static const char *
@@ -523,38 +515,46 @@ status_to_message(u_int32_t status)
523static void 515static void
524send_status(u_int32_t id, u_int32_t status) 516send_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}
543static void 540static void
544send_data_or_handle(char type, u_int32_t id, const char *data, int dlen) 541send_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
556static void 556static void
557send_data(u_int32_t id, const char *data, int dlen) 557send_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)
563static void 563static void
564send_handle(u_int32_t id, int handle) 564send_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)
575static void 575static void
576send_names(u_int32_t id, int count, const Stat *stats) 576send_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
595static void 598static void
596send_attrib(u_int32_t id, const Attrib *a) 599send_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
609static void 615static void
610send_statvfs(u_int32_t id, struct statvfs *st) 616send_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)
638static void 647static void
639process_init(void) 648process_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
667static void 680static void
668process_open(u_int32_t id) 681process_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)
707static void 722static void
708process_close(u_int32_t id) 723process_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)
720static void 737static void
721process_read(u_int32_t id) 738process_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
761process_write(u_int32_t id) 779process_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)
875static void 897static void
876process_setstat(u_int32_t id) 898process_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)
920static void 944static void
921process_fsetstat(u_int32_t id) 945process_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}
1008static void
1009process_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
1066process_remove(u_int32_t id) 1160process_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)
1081static void 1176static void
1082process_mkdir(u_int32_t id) 1177process_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
1101process_rmdir(u_int32_t id) 1198process_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
1140process_rename(u_int32_t id) 1242process_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)
1197static void 1301static void
1198process_readlink(u_int32_t id) 1302process_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
1221process_symlink(u_int32_t id) 1327process_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
1239process_extended_posix_rename(u_int32_t id) 1347process_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)
1272static void 1384static void
1273process_extended_fstatvfs(u_int32_t id) 1385process_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
1292process_extended_hardlink(u_int32_t id) 1405process_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)
1308static void 1423static void
1309process_extended_fsync(u_int32_t id) 1424process_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
1326process_extended(u_int32_t id) 1442process_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)
1350static void 1467static void
1351process(void) 1468process(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
1443sftp_server_main(int argc, char **argv, struct passwd *user_pw) 1569sftp_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}
diff --git a/sftp.c b/sftp.c
index 98a146ed4..eee472d08 100644
--- a/sftp.c
+++ b/sftp.c
@@ -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