summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2011-01-24 12:43:25 +0000
committerColin Watson <cjwatson@debian.org>2011-01-24 12:43:25 +0000
commit626f1d986ff72aa514da63e34744e1de9cf21b9a (patch)
treed215a5280bc2e57251e4a9e08bfd3674ad824a94 /sftp-client.c
parent6ed622cb6fe8f71bbe0d998cdd12280410bfb420 (diff)
parent0970072c89b079b022538e3c366fbfa2c53fc821 (diff)
* New upstream release (http://www.openssh.org/txt/release-5.7):
- Implement Elliptic Curve Cryptography modes for key exchange (ECDH) and host/user keys (ECDSA) as specified by RFC5656. ECDH and ECDSA offer better performance than plain DH and DSA at the same equivalent symmetric key length, as well as much shorter keys. - sftp(1)/sftp-server(8): add a protocol extension to support a hard link operation. It is available through the "ln" command in the client. The old "ln" behaviour of creating a symlink is available using its "-s" option or through the preexisting "symlink" command. - scp(1): Add a new -3 option to scp: Copies between two remote hosts are transferred through the local host (closes: #508613). - ssh(1): "atomically" create the listening mux socket by binding it on a temporary name and then linking it into position after listen() has succeeded. This allows the mux clients to determine that the server socket is either ready or stale without races (closes: #454784). Stale server sockets are now automatically removed (closes: #523250). - ssh(1): install a SIGCHLD handler to reap expired child process (closes: #594687). - ssh(1)/ssh-agent(1): honour $TMPDIR for client xauth and ssh-agent temporary directories (closes: #357469, although only if you arrange for ssh-agent to actually see $TMPDIR since the setgid bit will cause it to be stripped off).
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c259
1 files changed, 160 insertions, 99 deletions
diff --git a/sftp-client.c b/sftp-client.c
index 9dab47780..caa384b4e 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.92 2010/07/19 03:16:33 djm Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.94 2010/12/04 00:18:01 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 *
@@ -75,15 +75,28 @@ struct sftp_conn {
75#define SFTP_EXT_POSIX_RENAME 0x00000001 75#define SFTP_EXT_POSIX_RENAME 0x00000001
76#define SFTP_EXT_STATVFS 0x00000002 76#define SFTP_EXT_STATVFS 0x00000002
77#define SFTP_EXT_FSTATVFS 0x00000004 77#define SFTP_EXT_FSTATVFS 0x00000004
78#define SFTP_EXT_HARDLINK 0x00000008
78 u_int exts; 79 u_int exts;
80 u_int64_t limit_kbps;
81 struct bwlimit bwlimit_in, bwlimit_out;
79}; 82};
80 83
81static char * 84static char *
82get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...) 85get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
83 __attribute__((format(printf, 4, 5))); 86 const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
87
88/* ARGSUSED */
89static int
90sftpio(void *_bwlimit, size_t amount)
91{
92 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
93
94 bandwidth_limit(bwlimit, amount);
95 return 0;
96}
84 97
85static void 98static void
86send_msg(int fd, Buffer *m) 99send_msg(struct sftp_conn *conn, Buffer *m)
87{ 100{
88 u_char mlen[4]; 101 u_char mlen[4];
89 struct iovec iov[2]; 102 struct iovec iov[2];
@@ -98,19 +111,22 @@ send_msg(int fd, Buffer *m)
98 iov[1].iov_base = buffer_ptr(m); 111 iov[1].iov_base = buffer_ptr(m);
99 iov[1].iov_len = buffer_len(m); 112 iov[1].iov_len = buffer_len(m);
100 113
101 if (atomiciov(writev, fd, iov, 2) != buffer_len(m) + sizeof(mlen)) 114 if (atomiciov6(writev, conn->fd_out, iov, 2,
115 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
116 buffer_len(m) + sizeof(mlen))
102 fatal("Couldn't send packet: %s", strerror(errno)); 117 fatal("Couldn't send packet: %s", strerror(errno));
103 118
104 buffer_clear(m); 119 buffer_clear(m);
105} 120}
106 121
107static void 122static void
108get_msg(int fd, Buffer *m) 123get_msg(struct sftp_conn *conn, Buffer *m)
109{ 124{
110 u_int msg_len; 125 u_int msg_len;
111 126
112 buffer_append_space(m, 4); 127 buffer_append_space(m, 4);
113 if (atomicio(read, fd, buffer_ptr(m), 4) != 4) { 128 if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4,
129 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
114 if (errno == EPIPE) 130 if (errno == EPIPE)
115 fatal("Connection closed"); 131 fatal("Connection closed");
116 else 132 else
@@ -122,7 +138,9 @@ get_msg(int fd, Buffer *m)
122 fatal("Received message too long %u", msg_len); 138 fatal("Received message too long %u", msg_len);
123 139
124 buffer_append_space(m, msg_len); 140 buffer_append_space(m, msg_len);
125 if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) { 141 if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len,
142 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
143 != msg_len) {
126 if (errno == EPIPE) 144 if (errno == EPIPE)
127 fatal("Connection closed"); 145 fatal("Connection closed");
128 else 146 else
@@ -131,7 +149,7 @@ get_msg(int fd, Buffer *m)
131} 149}
132 150
133static void 151static void
134send_string_request(int fd, u_int id, u_int code, char *s, 152send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s,
135 u_int len) 153 u_int len)
136{ 154{
137 Buffer msg; 155 Buffer msg;
@@ -140,14 +158,14 @@ send_string_request(int fd, u_int id, u_int code, char *s,
140 buffer_put_char(&msg, code); 158 buffer_put_char(&msg, code);
141 buffer_put_int(&msg, id); 159 buffer_put_int(&msg, id);
142 buffer_put_string(&msg, s, len); 160 buffer_put_string(&msg, s, len);
143 send_msg(fd, &msg); 161 send_msg(conn, &msg);
144 debug3("Sent message fd %d T:%u I:%u", fd, code, id); 162 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
145 buffer_free(&msg); 163 buffer_free(&msg);
146} 164}
147 165
148static void 166static void
149send_string_attrs_request(int fd, u_int id, u_int code, char *s, 167send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
150 u_int len, Attrib *a) 168 char *s, u_int len, Attrib *a)
151{ 169{
152 Buffer msg; 170 Buffer msg;
153 171
@@ -156,19 +174,19 @@ send_string_attrs_request(int fd, u_int id, u_int code, char *s,
156 buffer_put_int(&msg, id); 174 buffer_put_int(&msg, id);
157 buffer_put_string(&msg, s, len); 175 buffer_put_string(&msg, s, len);
158 encode_attrib(&msg, a); 176 encode_attrib(&msg, a);
159 send_msg(fd, &msg); 177 send_msg(conn, &msg);
160 debug3("Sent message fd %d T:%u I:%u", fd, code, id); 178 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
161 buffer_free(&msg); 179 buffer_free(&msg);
162} 180}
163 181
164static u_int 182static u_int
165get_status(int fd, u_int expected_id) 183get_status(struct sftp_conn *conn, u_int expected_id)
166{ 184{
167 Buffer msg; 185 Buffer msg;
168 u_int type, id, status; 186 u_int type, id, status;
169 187
170 buffer_init(&msg); 188 buffer_init(&msg);
171 get_msg(fd, &msg); 189 get_msg(conn, &msg);
172 type = buffer_get_char(&msg); 190 type = buffer_get_char(&msg);
173 id = buffer_get_int(&msg); 191 id = buffer_get_int(&msg);
174 192
@@ -183,11 +201,12 @@ get_status(int fd, u_int expected_id)
183 201
184 debug3("SSH2_FXP_STATUS %u", status); 202 debug3("SSH2_FXP_STATUS %u", status);
185 203
186 return(status); 204 return status;
187} 205}
188 206
189static char * 207static char *
190get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...) 208get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
209 const char *errfmt, ...)
191{ 210{
192 Buffer msg; 211 Buffer msg;
193 u_int type, id; 212 u_int type, id;
@@ -201,7 +220,7 @@ get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
201 va_end(args); 220 va_end(args);
202 221
203 buffer_init(&msg); 222 buffer_init(&msg);
204 get_msg(fd, &msg); 223 get_msg(conn, &msg);
205 type = buffer_get_char(&msg); 224 type = buffer_get_char(&msg);
206 id = buffer_get_int(&msg); 225 id = buffer_get_int(&msg);
207 226
@@ -225,14 +244,14 @@ get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
225} 244}
226 245
227static Attrib * 246static Attrib *
228get_decode_stat(int fd, u_int expected_id, int quiet) 247get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
229{ 248{
230 Buffer msg; 249 Buffer msg;
231 u_int type, id; 250 u_int type, id;
232 Attrib *a; 251 Attrib *a;
233 252
234 buffer_init(&msg); 253 buffer_init(&msg);
235 get_msg(fd, &msg); 254 get_msg(conn, &msg);
236 255
237 type = buffer_get_char(&msg); 256 type = buffer_get_char(&msg);
238 id = buffer_get_int(&msg); 257 id = buffer_get_int(&msg);
@@ -260,14 +279,14 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
260} 279}
261 280
262static int 281static int
263get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id, 282get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
264 int quiet) 283 u_int expected_id, int quiet)
265{ 284{
266 Buffer msg; 285 Buffer msg;
267 u_int type, id, flag; 286 u_int type, id, flag;
268 287
269 buffer_init(&msg); 288 buffer_init(&msg);
270 get_msg(fd, &msg); 289 get_msg(conn, &msg);
271 290
272 type = buffer_get_char(&msg); 291 type = buffer_get_char(&msg);
273 id = buffer_get_int(&msg); 292 id = buffer_get_int(&msg);
@@ -311,21 +330,29 @@ get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
311} 330}
312 331
313struct sftp_conn * 332struct sftp_conn *
314do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) 333do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
334 u_int64_t limit_kbps)
315{ 335{
316 u_int type, exts = 0; 336 u_int type;
317 int version;
318 Buffer msg; 337 Buffer msg;
319 struct sftp_conn *ret; 338 struct sftp_conn *ret;
320 339
340 ret = xmalloc(sizeof(*ret));
341 ret->fd_in = fd_in;
342 ret->fd_out = fd_out;
343 ret->transfer_buflen = transfer_buflen;
344 ret->num_requests = num_requests;
345 ret->exts = 0;
346 ret->limit_kbps = 0;
347
321 buffer_init(&msg); 348 buffer_init(&msg);
322 buffer_put_char(&msg, SSH2_FXP_INIT); 349 buffer_put_char(&msg, SSH2_FXP_INIT);
323 buffer_put_int(&msg, SSH2_FILEXFER_VERSION); 350 buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
324 send_msg(fd_out, &msg); 351 send_msg(ret, &msg);
325 352
326 buffer_clear(&msg); 353 buffer_clear(&msg);
327 354
328 get_msg(fd_in, &msg); 355 get_msg(ret, &msg);
329 356
330 /* Expecting a VERSION reply */ 357 /* Expecting a VERSION reply */
331 if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { 358 if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) {
@@ -334,9 +361,9 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
334 buffer_free(&msg); 361 buffer_free(&msg);
335 return(NULL); 362 return(NULL);
336 } 363 }
337 version = buffer_get_int(&msg); 364 ret->version = buffer_get_int(&msg);
338 365
339 debug2("Remote version: %d", version); 366 debug2("Remote version: %u", ret->version);
340 367
341 /* Check for extensions */ 368 /* Check for extensions */
342 while (buffer_len(&msg) > 0) { 369 while (buffer_len(&msg) > 0) {
@@ -346,15 +373,19 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
346 373
347 if (strcmp(name, "posix-rename@openssh.com") == 0 && 374 if (strcmp(name, "posix-rename@openssh.com") == 0 &&
348 strcmp(value, "1") == 0) { 375 strcmp(value, "1") == 0) {
349 exts |= SFTP_EXT_POSIX_RENAME; 376 ret->exts |= SFTP_EXT_POSIX_RENAME;
350 known = 1; 377 known = 1;
351 } else if (strcmp(name, "statvfs@openssh.com") == 0 && 378 } else if (strcmp(name, "statvfs@openssh.com") == 0 &&
352 strcmp(value, "2") == 0) { 379 strcmp(value, "2") == 0) {
353 exts |= SFTP_EXT_STATVFS; 380 ret->exts |= SFTP_EXT_STATVFS;
354 known = 1; 381 known = 1;
355 } if (strcmp(name, "fstatvfs@openssh.com") == 0 && 382 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
356 strcmp(value, "2") == 0) { 383 strcmp(value, "2") == 0) {
357 exts |= SFTP_EXT_FSTATVFS; 384 ret->exts |= SFTP_EXT_FSTATVFS;
385 known = 1;
386 } else if (strcmp(name, "hardlink@openssh.com") == 0 &&
387 strcmp(value, "1") == 0) {
388 ret->exts |= SFTP_EXT_HARDLINK;
358 known = 1; 389 known = 1;
359 } 390 }
360 if (known) { 391 if (known) {
@@ -369,26 +400,25 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
369 400
370 buffer_free(&msg); 401 buffer_free(&msg);
371 402
372 ret = xmalloc(sizeof(*ret));
373 ret->fd_in = fd_in;
374 ret->fd_out = fd_out;
375 ret->transfer_buflen = transfer_buflen;
376 ret->num_requests = num_requests;
377 ret->version = version;
378 ret->msg_id = 1;
379 ret->exts = exts;
380
381 /* Some filexfer v.0 servers don't support large packets */ 403 /* Some filexfer v.0 servers don't support large packets */
382 if (version == 0) 404 if (ret->version == 0)
383 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480); 405 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
384 406
385 return(ret); 407 ret->limit_kbps = limit_kbps;
408 if (ret->limit_kbps > 0) {
409 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
410 ret->transfer_buflen);
411 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
412 ret->transfer_buflen);
413 }
414
415 return ret;
386} 416}
387 417
388u_int 418u_int
389sftp_proto_version(struct sftp_conn *conn) 419sftp_proto_version(struct sftp_conn *conn)
390{ 420{
391 return(conn->version); 421 return conn->version;
392} 422}
393 423
394int 424int
@@ -403,16 +433,16 @@ do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
403 buffer_put_char(&msg, SSH2_FXP_CLOSE); 433 buffer_put_char(&msg, SSH2_FXP_CLOSE);
404 buffer_put_int(&msg, id); 434 buffer_put_int(&msg, id);
405 buffer_put_string(&msg, handle, handle_len); 435 buffer_put_string(&msg, handle, handle_len);
406 send_msg(conn->fd_out, &msg); 436 send_msg(conn, &msg);
407 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 437 debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
408 438
409 status = get_status(conn->fd_in, id); 439 status = get_status(conn, id);
410 if (status != SSH2_FX_OK) 440 if (status != SSH2_FX_OK)
411 error("Couldn't close file: %s", fx2txt(status)); 441 error("Couldn't close file: %s", fx2txt(status));
412 442
413 buffer_free(&msg); 443 buffer_free(&msg);
414 444
415 return(status); 445 return status;
416} 446}
417 447
418 448
@@ -430,14 +460,14 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
430 buffer_put_char(&msg, SSH2_FXP_OPENDIR); 460 buffer_put_char(&msg, SSH2_FXP_OPENDIR);
431 buffer_put_int(&msg, id); 461 buffer_put_int(&msg, id);
432 buffer_put_cstring(&msg, path); 462 buffer_put_cstring(&msg, path);
433 send_msg(conn->fd_out, &msg); 463 send_msg(conn, &msg);
434 464
435 buffer_clear(&msg); 465 buffer_clear(&msg);
436 466
437 handle = get_handle(conn->fd_in, id, &handle_len, 467 handle = get_handle(conn, id, &handle_len,
438 "remote readdir(\"%s\")", path); 468 "remote readdir(\"%s\")", path);
439 if (handle == NULL) 469 if (handle == NULL)
440 return(-1); 470 return -1;
441 471
442 if (dir) { 472 if (dir) {
443 ents = 0; 473 ents = 0;
@@ -454,11 +484,11 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
454 buffer_put_char(&msg, SSH2_FXP_READDIR); 484 buffer_put_char(&msg, SSH2_FXP_READDIR);
455 buffer_put_int(&msg, id); 485 buffer_put_int(&msg, id);
456 buffer_put_string(&msg, handle, handle_len); 486 buffer_put_string(&msg, handle, handle_len);
457 send_msg(conn->fd_out, &msg); 487 send_msg(conn, &msg);
458 488
459 buffer_clear(&msg); 489 buffer_clear(&msg);
460 490
461 get_msg(conn->fd_in, &msg); 491 get_msg(conn, &msg);
462 492
463 type = buffer_get_char(&msg); 493 type = buffer_get_char(&msg);
464 id = buffer_get_int(&msg); 494 id = buffer_get_int(&msg);
@@ -537,7 +567,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
537 **dir = NULL; 567 **dir = NULL;
538 } 568 }
539 569
540 return(0); 570 return 0;
541} 571}
542 572
543int 573int
@@ -566,9 +596,8 @@ do_rm(struct sftp_conn *conn, char *path)
566 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 596 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
567 597
568 id = conn->msg_id++; 598 id = conn->msg_id++;
569 send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path, 599 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
570 strlen(path)); 600 status = get_status(conn, id);
571 status = get_status(conn->fd_in, id);
572 if (status != SSH2_FX_OK) 601 if (status != SSH2_FX_OK)
573 error("Couldn't delete file: %s", fx2txt(status)); 602 error("Couldn't delete file: %s", fx2txt(status));
574 return(status); 603 return(status);
@@ -580,10 +609,10 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag)
580 u_int status, id; 609 u_int status, id;
581 610
582 id = conn->msg_id++; 611 id = conn->msg_id++;
583 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path, 612 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
584 strlen(path), a); 613 strlen(path), a);
585 614
586 status = get_status(conn->fd_in, id); 615 status = get_status(conn, id);
587 if (status != SSH2_FX_OK && printflag) 616 if (status != SSH2_FX_OK && printflag)
588 error("Couldn't create directory: %s", fx2txt(status)); 617 error("Couldn't create directory: %s", fx2txt(status));
589 618
@@ -596,10 +625,10 @@ do_rmdir(struct sftp_conn *conn, char *path)
596 u_int status, id; 625 u_int status, id;
597 626
598 id = conn->msg_id++; 627 id = conn->msg_id++;
599 send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path, 628 send_string_request(conn, id, SSH2_FXP_RMDIR, path,
600 strlen(path)); 629 strlen(path));
601 630
602 status = get_status(conn->fd_in, id); 631 status = get_status(conn, id);
603 if (status != SSH2_FX_OK) 632 if (status != SSH2_FX_OK)
604 error("Couldn't remove directory: %s", fx2txt(status)); 633 error("Couldn't remove directory: %s", fx2txt(status));
605 634
@@ -613,11 +642,11 @@ do_stat(struct sftp_conn *conn, char *path, int quiet)
613 642
614 id = conn->msg_id++; 643 id = conn->msg_id++;
615 644
616 send_string_request(conn->fd_out, id, 645 send_string_request(conn, id,
617 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 646 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
618 path, strlen(path)); 647 path, strlen(path));
619 648
620 return(get_decode_stat(conn->fd_in, id, quiet)); 649 return(get_decode_stat(conn, id, quiet));
621} 650}
622 651
623Attrib * 652Attrib *
@@ -634,10 +663,10 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet)
634 } 663 }
635 664
636 id = conn->msg_id++; 665 id = conn->msg_id++;
637 send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path, 666 send_string_request(conn, id, SSH2_FXP_LSTAT, path,
638 strlen(path)); 667 strlen(path));
639 668
640 return(get_decode_stat(conn->fd_in, id, quiet)); 669 return(get_decode_stat(conn, id, quiet));
641} 670}
642 671
643#ifdef notyet 672#ifdef notyet
@@ -647,10 +676,10 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
647 u_int id; 676 u_int id;
648 677
649 id = conn->msg_id++; 678 id = conn->msg_id++;
650 send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle, 679 send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
651 handle_len); 680 handle_len);
652 681
653 return(get_decode_stat(conn->fd_in, id, quiet)); 682 return(get_decode_stat(conn, id, quiet));
654} 683}
655#endif 684#endif
656 685
@@ -660,10 +689,10 @@ do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
660 u_int status, id; 689 u_int status, id;
661 690
662 id = conn->msg_id++; 691 id = conn->msg_id++;
663 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path, 692 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
664 strlen(path), a); 693 strlen(path), a);
665 694
666 status = get_status(conn->fd_in, id); 695 status = get_status(conn, id);
667 if (status != SSH2_FX_OK) 696 if (status != SSH2_FX_OK)
668 error("Couldn't setstat on \"%s\": %s", path, 697 error("Couldn't setstat on \"%s\": %s", path,
669 fx2txt(status)); 698 fx2txt(status));
@@ -678,10 +707,10 @@ do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
678 u_int status, id; 707 u_int status, id;
679 708
680 id = conn->msg_id++; 709 id = conn->msg_id++;
681 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle, 710 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
682 handle_len, a); 711 handle_len, a);
683 712
684 status = get_status(conn->fd_in, id); 713 status = get_status(conn, id);
685 if (status != SSH2_FX_OK) 714 if (status != SSH2_FX_OK)
686 error("Couldn't fsetstat: %s", fx2txt(status)); 715 error("Couldn't fsetstat: %s", fx2txt(status));
687 716
@@ -697,12 +726,12 @@ do_realpath(struct sftp_conn *conn, char *path)
697 Attrib *a; 726 Attrib *a;
698 727
699 expected_id = id = conn->msg_id++; 728 expected_id = id = conn->msg_id++;
700 send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path, 729 send_string_request(conn, id, SSH2_FXP_REALPATH, path,
701 strlen(path)); 730 strlen(path));
702 731
703 buffer_init(&msg); 732 buffer_init(&msg);
704 733
705 get_msg(conn->fd_in, &msg); 734 get_msg(conn, &msg);
706 type = buffer_get_char(&msg); 735 type = buffer_get_char(&msg);
707 id = buffer_get_int(&msg); 736 id = buffer_get_int(&msg);
708 737
@@ -756,13 +785,13 @@ do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
756 } 785 }
757 buffer_put_cstring(&msg, oldpath); 786 buffer_put_cstring(&msg, oldpath);
758 buffer_put_cstring(&msg, newpath); 787 buffer_put_cstring(&msg, newpath);
759 send_msg(conn->fd_out, &msg); 788 send_msg(conn, &msg);
760 debug3("Sent message %s \"%s\" -> \"%s\"", 789 debug3("Sent message %s \"%s\" -> \"%s\"",
761 (conn->exts & SFTP_EXT_POSIX_RENAME) ? "posix-rename@openssh.com" : 790 (conn->exts & SFTP_EXT_POSIX_RENAME) ? "posix-rename@openssh.com" :
762 "SSH2_FXP_RENAME", oldpath, newpath); 791 "SSH2_FXP_RENAME", oldpath, newpath);
763 buffer_free(&msg); 792 buffer_free(&msg);
764 793
765 status = get_status(conn->fd_in, id); 794 status = get_status(conn, id);
766 if (status != SSH2_FX_OK) 795 if (status != SSH2_FX_OK)
767 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 796 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
768 newpath, fx2txt(status)); 797 newpath, fx2txt(status));
@@ -771,6 +800,39 @@ do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
771} 800}
772 801
773int 802int
803do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath)
804{
805 Buffer msg;
806 u_int status, id;
807
808 buffer_init(&msg);
809
810 /* Send link request */
811 id = conn->msg_id++;
812 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
813 error("Server does not support hardlink@openssh.com extension");
814 return -1;
815 }
816
817 buffer_put_char(&msg, SSH2_FXP_EXTENDED);
818 buffer_put_int(&msg, id);
819 buffer_put_cstring(&msg, "hardlink@openssh.com");
820 buffer_put_cstring(&msg, oldpath);
821 buffer_put_cstring(&msg, newpath);
822 send_msg(conn, &msg);
823 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
824 oldpath, newpath);
825 buffer_free(&msg);
826
827 status = get_status(conn, id);
828 if (status != SSH2_FX_OK)
829 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
830 newpath, fx2txt(status));
831
832 return(status);
833}
834
835int
774do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) 836do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
775{ 837{
776 Buffer msg; 838 Buffer msg;
@@ -789,12 +851,12 @@ do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
789 buffer_put_int(&msg, id); 851 buffer_put_int(&msg, id);
790 buffer_put_cstring(&msg, oldpath); 852 buffer_put_cstring(&msg, oldpath);
791 buffer_put_cstring(&msg, newpath); 853 buffer_put_cstring(&msg, newpath);
792 send_msg(conn->fd_out, &msg); 854 send_msg(conn, &msg);
793 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 855 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
794 newpath); 856 newpath);
795 buffer_free(&msg); 857 buffer_free(&msg);
796 858
797 status = get_status(conn->fd_in, id); 859 status = get_status(conn, id);
798 if (status != SSH2_FX_OK) 860 if (status != SSH2_FX_OK)
799 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 861 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
800 newpath, fx2txt(status)); 862 newpath, fx2txt(status));
@@ -812,12 +874,11 @@ do_readlink(struct sftp_conn *conn, char *path)
812 Attrib *a; 874 Attrib *a;
813 875
814 expected_id = id = conn->msg_id++; 876 expected_id = id = conn->msg_id++;
815 send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path, 877 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
816 strlen(path));
817 878
818 buffer_init(&msg); 879 buffer_init(&msg);
819 880
820 get_msg(conn->fd_in, &msg); 881 get_msg(conn, &msg);
821 type = buffer_get_char(&msg); 882 type = buffer_get_char(&msg);
822 id = buffer_get_int(&msg); 883 id = buffer_get_int(&msg);
823 884
@@ -871,10 +932,10 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
871 buffer_put_int(&msg, id); 932 buffer_put_int(&msg, id);
872 buffer_put_cstring(&msg, "statvfs@openssh.com"); 933 buffer_put_cstring(&msg, "statvfs@openssh.com");
873 buffer_put_cstring(&msg, path); 934 buffer_put_cstring(&msg, path);
874 send_msg(conn->fd_out, &msg); 935 send_msg(conn, &msg);
875 buffer_free(&msg); 936 buffer_free(&msg);
876 937
877 return get_decode_statvfs(conn->fd_in, st, id, quiet); 938 return get_decode_statvfs(conn, st, id, quiet);
878} 939}
879 940
880#ifdef notyet 941#ifdef notyet
@@ -898,16 +959,16 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
898 buffer_put_int(&msg, id); 959 buffer_put_int(&msg, id);
899 buffer_put_cstring(&msg, "fstatvfs@openssh.com"); 960 buffer_put_cstring(&msg, "fstatvfs@openssh.com");
900 buffer_put_string(&msg, handle, handle_len); 961 buffer_put_string(&msg, handle, handle_len);
901 send_msg(conn->fd_out, &msg); 962 send_msg(conn, &msg);
902 buffer_free(&msg); 963 buffer_free(&msg);
903 964
904 return get_decode_statvfs(conn->fd_in, st, id, quiet); 965 return get_decode_statvfs(conn, st, id, quiet);
905} 966}
906#endif 967#endif
907 968
908static void 969static void
909send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, 970send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
910 char *handle, u_int handle_len) 971 u_int len, char *handle, u_int handle_len)
911{ 972{
912 Buffer msg; 973 Buffer msg;
913 974
@@ -918,7 +979,7 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
918 buffer_put_string(&msg, handle, handle_len); 979 buffer_put_string(&msg, handle, handle_len);
919 buffer_put_int64(&msg, offset); 980 buffer_put_int64(&msg, offset);
920 buffer_put_int(&msg, len); 981 buffer_put_int(&msg, len);
921 send_msg(fd_out, &msg); 982 send_msg(conn, &msg);
922 buffer_free(&msg); 983 buffer_free(&msg);
923} 984}
924 985
@@ -976,10 +1037,10 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
976 buffer_put_int(&msg, SSH2_FXF_READ); 1037 buffer_put_int(&msg, SSH2_FXF_READ);
977 attrib_clear(&junk); /* Send empty attributes */ 1038 attrib_clear(&junk); /* Send empty attributes */
978 encode_attrib(&msg, &junk); 1039 encode_attrib(&msg, &junk);
979 send_msg(conn->fd_out, &msg); 1040 send_msg(conn, &msg);
980 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1041 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
981 1042
982 handle = get_handle(conn->fd_in, id, &handle_len, 1043 handle = get_handle(conn, id, &handle_len,
983 "remote open(\"%s\")", remote_path); 1044 "remote open(\"%s\")", remote_path);
984 if (handle == NULL) { 1045 if (handle == NULL) {
985 buffer_free(&msg); 1046 buffer_free(&msg);
@@ -1032,12 +1093,12 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
1032 offset += buflen; 1093 offset += buflen;
1033 num_req++; 1094 num_req++;
1034 TAILQ_INSERT_TAIL(&requests, req, tq); 1095 TAILQ_INSERT_TAIL(&requests, req, tq);
1035 send_read_request(conn->fd_out, req->id, req->offset, 1096 send_read_request(conn, req->id, req->offset,
1036 req->len, handle, handle_len); 1097 req->len, handle, handle_len);
1037 } 1098 }
1038 1099
1039 buffer_clear(&msg); 1100 buffer_clear(&msg);
1040 get_msg(conn->fd_in, &msg); 1101 get_msg(conn, &msg);
1041 type = buffer_get_char(&msg); 1102 type = buffer_get_char(&msg);
1042 id = buffer_get_int(&msg); 1103 id = buffer_get_int(&msg);
1043 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1104 debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
@@ -1092,7 +1153,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
1092 req->id = conn->msg_id++; 1153 req->id = conn->msg_id++;
1093 req->len -= len; 1154 req->len -= len;
1094 req->offset += len; 1155 req->offset += len;
1095 send_read_request(conn->fd_out, req->id, 1156 send_read_request(conn, req->id,
1096 req->offset, req->len, handle, handle_len); 1157 req->offset, req->len, handle, handle_len);
1097 /* Reduce the request size */ 1158 /* Reduce the request size */
1098 if (len < buflen) 1159 if (len < buflen)
@@ -1327,12 +1388,12 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1327 buffer_put_cstring(&msg, remote_path); 1388 buffer_put_cstring(&msg, remote_path);
1328 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1389 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
1329 encode_attrib(&msg, &a); 1390 encode_attrib(&msg, &a);
1330 send_msg(conn->fd_out, &msg); 1391 send_msg(conn, &msg);
1331 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1392 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1332 1393
1333 buffer_clear(&msg); 1394 buffer_clear(&msg);
1334 1395
1335 handle = get_handle(conn->fd_in, id, &handle_len, 1396 handle = get_handle(conn, id, &handle_len,
1336 "remote open(\"%s\")", remote_path); 1397 "remote open(\"%s\")", remote_path);
1337 if (handle == NULL) { 1398 if (handle == NULL) {
1338 close(local_fd); 1399 close(local_fd);
@@ -1381,7 +1442,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1381 buffer_put_string(&msg, handle, handle_len); 1442 buffer_put_string(&msg, handle, handle_len);
1382 buffer_put_int64(&msg, offset); 1443 buffer_put_int64(&msg, offset);
1383 buffer_put_string(&msg, data, len); 1444 buffer_put_string(&msg, data, len);
1384 send_msg(conn->fd_out, &msg); 1445 send_msg(conn, &msg);
1385 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1446 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
1386 id, (unsigned long long)offset, len); 1447 id, (unsigned long long)offset, len);
1387 } else if (TAILQ_FIRST(&acks) == NULL) 1448 } else if (TAILQ_FIRST(&acks) == NULL)
@@ -1395,7 +1456,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1395 u_int r_id; 1456 u_int r_id;
1396 1457
1397 buffer_clear(&msg); 1458 buffer_clear(&msg);
1398 get_msg(conn->fd_in, &msg); 1459 get_msg(conn, &msg);
1399 type = buffer_get_char(&msg); 1460 type = buffer_get_char(&msg);
1400 r_id = buffer_get_int(&msg); 1461 r_id = buffer_get_int(&msg);
1401 1462