1 /* 2 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /* XXX: memleaks */ 18 /* XXX: signed vs unsigned */ 19 /* XXX: remove all logging, only return status codes */ 20 /* XXX: copy between two remote sites */ 21 22 #include "includes.h" 23 RCSID("$OpenBSD: sftp-client.c,v 1.51 2004/07/11 17:48:47 deraadt Exp $"); 24 25 #include "openbsd-compat/sys-queue.h" 26 27 #include "buffer.h" 28 #include "bufaux.h" 29 #include "getput.h" 30 #include "xmalloc.h" 31 #include "log.h" 32 #include "atomicio.h" 33 #include "progressmeter.h" 34 35 #include "sftp.h" 36 #include "sftp-common.h" 37 #include "sftp-client.h" 38 39 extern volatile sig_atomic_t interrupted; 40 extern int showprogress; 41 42 /* Minimum amount of data to read at at time */ 43 #define MIN_READ_SIZE 512 44 45 /* Maximum packet size */ 46 #define MAX_MSG_LENGTH (256 * 1024) 47 48 struct sftp_conn { 49 int fd_in; 50 int fd_out; 51 u_int transfer_buflen; 52 u_int num_requests; 53 u_int version; 54 u_int msg_id; 55 }; 56 57 static void 58 send_msg(int fd, Buffer *m) 59 { 60 u_char mlen[4]; 61 62 if (buffer_len(m) > MAX_MSG_LENGTH) 63 fatal("Outbound message too long %u", buffer_len(m)); 64 65 /* Send length first */ 66 PUT_32BIT(mlen, buffer_len(m)); 67 if (atomicio(vwrite, fd, mlen, sizeof(mlen)) <= 0) 68 fatal("Couldn't send packet: %s", strerror(errno)); 69 70 if (atomicio(vwrite, fd, buffer_ptr(m), buffer_len(m)) <= 0) 71 fatal("Couldn't send packet: %s", strerror(errno)); 72 73 buffer_clear(m); 74 } 75 76 static void 77 get_msg(int fd, Buffer *m) 78 { 79 ssize_t len; 80 u_int msg_len; 81 82 buffer_append_space(m, 4); 83 len = atomicio(read, fd, buffer_ptr(m), 4); 84 if (len == 0) 85 fatal("Connection closed"); 86 else if (len == -1) 87 fatal("Couldn't read packet: %s", strerror(errno)); 88 89 msg_len = buffer_get_int(m); 90 if (msg_len > MAX_MSG_LENGTH) 91 fatal("Received message too long %u", msg_len); 92 93 buffer_append_space(m, msg_len); 94 len = atomicio(read, fd, buffer_ptr(m), msg_len); 95 if (len == 0) 96 fatal("Connection closed"); 97 else if (len == -1) 98 fatal("Read packet: %s", strerror(errno)); 99 } 100 101 static void 102 send_string_request(int fd, u_int id, u_int code, char *s, 103 u_int len) 104 { 105 Buffer msg; 106 107 buffer_init(&msg); 108 buffer_put_char(&msg, code); 109 buffer_put_int(&msg, id); 110 buffer_put_string(&msg, s, len); 111 send_msg(fd, &msg); 112 debug3("Sent message fd %d T:%u I:%u", fd, code, id); 113 buffer_free(&msg); 114 } 115 116 static void 117 send_string_attrs_request(int fd, u_int id, u_int code, char *s, 118 u_int len, Attrib *a) 119 { 120 Buffer msg; 121 122 buffer_init(&msg); 123 buffer_put_char(&msg, code); 124 buffer_put_int(&msg, id); 125 buffer_put_string(&msg, s, len); 126 encode_attrib(&msg, a); 127 send_msg(fd, &msg); 128 debug3("Sent message fd %d T:%u I:%u", fd, code, id); 129 buffer_free(&msg); 130 } 131 132 static u_int 133 get_status(int fd, u_int expected_id) 134 { 135 Buffer msg; 136 u_int type, id, status; 137 138 buffer_init(&msg); 139 get_msg(fd, &msg); 140 type = buffer_get_char(&msg); 141 id = buffer_get_int(&msg); 142 143 if (id != expected_id) 144 fatal("ID mismatch (%u != %u)", id, expected_id); 145 if (type != SSH2_FXP_STATUS) 146 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", 147 SSH2_FXP_STATUS, type); 148 149 status = buffer_get_int(&msg); 150 buffer_free(&msg); 151 152 debug3("SSH2_FXP_STATUS %u", status); 153 154 return(status); 155 } 156 157 static char * 158 get_handle(int fd, u_int expected_id, u_int *len) 159 { 160 Buffer msg; 161 u_int type, id; 162 char *handle; 163 164 buffer_init(&msg); 165 get_msg(fd, &msg); 166 type = buffer_get_char(&msg); 167 id = buffer_get_int(&msg); 168 169 if (id != expected_id) 170 fatal("ID mismatch (%u != %u)", id, expected_id); 171 if (type == SSH2_FXP_STATUS) { 172 int status = buffer_get_int(&msg); 173 174 error("Couldn't get handle: %s", fx2txt(status)); 175 return(NULL); 176 } else if (type != SSH2_FXP_HANDLE) 177 fatal("Expected SSH2_FXP_HANDLE(%u) packet, got %u", 178 SSH2_FXP_HANDLE, type); 179 180 handle = buffer_get_string(&msg, len); 181 buffer_free(&msg); 182 183 return(handle); 184 } 185 186 static Attrib * 187 get_decode_stat(int fd, u_int expected_id, int quiet) 188 { 189 Buffer msg; 190 u_int type, id; 191 Attrib *a; 192 193 buffer_init(&msg); 194 get_msg(fd, &msg); 195 196 type = buffer_get_char(&msg); 197 id = buffer_get_int(&msg); 198 199 debug3("Received stat reply T:%u I:%u", type, id); 200 if (id != expected_id) 201 fatal("ID mismatch (%u != %u)", id, expected_id); 202 if (type == SSH2_FXP_STATUS) { 203 int status = buffer_get_int(&msg); 204 205 if (quiet) 206 debug("Couldn't stat remote file: %s", fx2txt(status)); 207 else 208 error("Couldn't stat remote file: %s", fx2txt(status)); 209 return(NULL); 210 } else if (type != SSH2_FXP_ATTRS) { 211 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", 212 SSH2_FXP_ATTRS, type); 213 } 214 a = decode_attrib(&msg); 215 buffer_free(&msg); 216 217 return(a); 218 } 219 220 struct sftp_conn * 221 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) 222 { 223 u_int type; 224 int version; 225 Buffer msg; 226 struct sftp_conn *ret; 227 228 buffer_init(&msg); 229 buffer_put_char(&msg, SSH2_FXP_INIT); 230 buffer_put_int(&msg, SSH2_FILEXFER_VERSION); 231 send_msg(fd_out, &msg); 232 233 buffer_clear(&msg); 234 235 get_msg(fd_in, &msg); 236 237 /* Expecting a VERSION reply */ 238 if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { 239 error("Invalid packet back from SSH2_FXP_INIT (type %u)", 240 type); 241 buffer_free(&msg); 242 return(NULL); 243 } 244 version = buffer_get_int(&msg); 245 246 debug2("Remote version: %d", version); 247 248 /* Check for extensions */ 249 while (buffer_len(&msg) > 0) { 250 char *name = buffer_get_string(&msg, NULL); 251 char *value = buffer_get_string(&msg, NULL); 252 253 debug2("Init extension: \"%s\"", name); 254 xfree(name); 255 xfree(value); 256 } 257 258 buffer_free(&msg); 259 260 ret = xmalloc(sizeof(*ret)); 261 ret->fd_in = fd_in; 262 ret->fd_out = fd_out; 263 ret->transfer_buflen = transfer_buflen; 264 ret->num_requests = num_requests; 265 ret->version = version; 266 ret->msg_id = 1; 267 268 /* Some filexfer v.0 servers don't support large packets */ 269 if (version == 0) 270 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480); 271 272 return(ret); 273 } 274 275 u_int 276 sftp_proto_version(struct sftp_conn *conn) 277 { 278 return(conn->version); 279 } 280 281 int 282 do_close(struct sftp_conn *conn, char *handle, u_int handle_len) 283 { 284 u_int id, status; 285 Buffer msg; 286 287 buffer_init(&msg); 288 289 id = conn->msg_id++; 290 buffer_put_char(&msg, SSH2_FXP_CLOSE); 291 buffer_put_int(&msg, id); 292 buffer_put_string(&msg, handle, handle_len); 293 send_msg(conn->fd_out, &msg); 294 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 295 296 status = get_status(conn->fd_in, id); 297 if (status != SSH2_FX_OK) 298 error("Couldn't close file: %s", fx2txt(status)); 299 300 buffer_free(&msg); 301 302 return(status); 303 } 304 305 306 static int 307 do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, 308 SFTP_DIRENT ***dir) 309 { 310 Buffer msg; 311 u_int type, id, handle_len, i, expected_id, ents = 0; 312 char *handle; 313 314 id = conn->msg_id++; 315 316 buffer_init(&msg); 317 buffer_put_char(&msg, SSH2_FXP_OPENDIR); 318 buffer_put_int(&msg, id); 319 buffer_put_cstring(&msg, path); 320 send_msg(conn->fd_out, &msg); 321 322 buffer_clear(&msg); 323 324 handle = get_handle(conn->fd_in, id, &handle_len); 325 if (handle == NULL) 326 return(-1); 327 328 if (dir) { 329 ents = 0; 330 *dir = xmalloc(sizeof(**dir)); 331 (*dir)[0] = NULL; 332 } 333 334 for (; !interrupted;) { 335 int count; 336 337 id = expected_id = conn->msg_id++; 338 339 debug3("Sending SSH2_FXP_READDIR I:%u", id); 340 341 buffer_clear(&msg); 342 buffer_put_char(&msg, SSH2_FXP_READDIR); 343 buffer_put_int(&msg, id); 344 buffer_put_string(&msg, handle, handle_len); 345 send_msg(conn->fd_out, &msg); 346 347 buffer_clear(&msg); 348 349 get_msg(conn->fd_in, &msg); 350 351 type = buffer_get_char(&msg); 352 id = buffer_get_int(&msg); 353 354 debug3("Received reply T:%u I:%u", type, id); 355 356 if (id != expected_id) 357 fatal("ID mismatch (%u != %u)", id, expected_id); 358 359 if (type == SSH2_FXP_STATUS) { 360 int status = buffer_get_int(&msg); 361 362 debug3("Received SSH2_FXP_STATUS %d", status); 363 364 if (status == SSH2_FX_EOF) { 365 break; 366 } else { 367 error("Couldn't read directory: %s", 368 fx2txt(status)); 369 do_close(conn, handle, handle_len); 370 xfree(handle); 371 return(status); 372 } 373 } else if (type != SSH2_FXP_NAME) 374 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 375 SSH2_FXP_NAME, type); 376 377 count = buffer_get_int(&msg); 378 if (count == 0) 379 break; 380 debug3("Received %d SSH2_FXP_NAME responses", count); 381 for (i = 0; i < count; i++) { 382 char *filename, *longname; 383 Attrib *a; 384 385 filename = buffer_get_string(&msg, NULL); 386 longname = buffer_get_string(&msg, NULL); 387 a = decode_attrib(&msg); 388 389 if (printflag) 390 printf("%s\n", longname); 391 392 if (dir) { 393 *dir = xrealloc(*dir, sizeof(**dir) * 394 (ents + 2)); 395 (*dir)[ents] = xmalloc(sizeof(***dir)); 396 (*dir)[ents]->filename = xstrdup(filename); 397 (*dir)[ents]->longname = xstrdup(longname); 398 memcpy(&(*dir)[ents]->a, a, sizeof(*a)); 399 (*dir)[++ents] = NULL; 400 } 401 402 xfree(filename); 403 xfree(longname); 404 } 405 } 406 407 buffer_free(&msg); 408 do_close(conn, handle, handle_len); 409 xfree(handle); 410 411 /* Don't return partial matches on interrupt */ 412 if (interrupted && dir != NULL && *dir != NULL) { 413 free_sftp_dirents(*dir); 414 *dir = xmalloc(sizeof(**dir)); 415 **dir = NULL; 416 } 417 418 return(0); 419 } 420 421 int 422 do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) 423 { 424 return(do_lsreaddir(conn, path, 0, dir)); 425 } 426 427 void free_sftp_dirents(SFTP_DIRENT **s) 428 { 429 int i; 430 431 for (i = 0; s[i]; i++) { 432 xfree(s[i]->filename); 433 xfree(s[i]->longname); 434 xfree(s[i]); 435 } 436 xfree(s); 437 } 438 439 int 440 do_rm(struct sftp_conn *conn, char *path) 441 { 442 u_int status, id; 443 444 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 445 446 id = conn->msg_id++; 447 send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path, 448 strlen(path)); 449 status = get_status(conn->fd_in, id); 450 if (status != SSH2_FX_OK) 451 error("Couldn't delete file: %s", fx2txt(status)); 452 return(status); 453 } 454 455 int 456 do_mkdir(struct sftp_conn *conn, char *path, Attrib *a) 457 { 458 u_int status, id; 459 460 id = conn->msg_id++; 461 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path, 462 strlen(path), a); 463 464 status = get_status(conn->fd_in, id); 465 if (status != SSH2_FX_OK) 466 error("Couldn't create directory: %s", fx2txt(status)); 467 468 return(status); 469 } 470 471 int 472 do_rmdir(struct sftp_conn *conn, char *path) 473 { 474 u_int status, id; 475 476 id = conn->msg_id++; 477 send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path, 478 strlen(path)); 479 480 status = get_status(conn->fd_in, id); 481 if (status != SSH2_FX_OK) 482 error("Couldn't remove directory: %s", fx2txt(status)); 483 484 return(status); 485 } 486 487 Attrib * 488 do_stat(struct sftp_conn *conn, char *path, int quiet) 489 { 490 u_int id; 491 492 id = conn->msg_id++; 493 494 send_string_request(conn->fd_out, id, 495 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 496 path, strlen(path)); 497 498 return(get_decode_stat(conn->fd_in, id, quiet)); 499 } 500 501 Attrib * 502 do_lstat(struct sftp_conn *conn, char *path, int quiet) 503 { 504 u_int id; 505 506 if (conn->version == 0) { 507 if (quiet) 508 debug("Server version does not support lstat operation"); 509 else 510 logit("Server version does not support lstat operation"); 511 return(do_stat(conn, path, quiet)); 512 } 513 514 id = conn->msg_id++; 515 send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path, 516 strlen(path)); 517 518 return(get_decode_stat(conn->fd_in, id, quiet)); 519 } 520 521 Attrib * 522 do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) 523 { 524 u_int id; 525 526 id = conn->msg_id++; 527 send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle, 528 handle_len); 529 530 return(get_decode_stat(conn->fd_in, id, quiet)); 531 } 532 533 int 534 do_setstat(struct sftp_conn *conn, char *path, Attrib *a) 535 { 536 u_int status, id; 537 538 id = conn->msg_id++; 539 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path, 540 strlen(path), a); 541 542 status = get_status(conn->fd_in, id); 543 if (status != SSH2_FX_OK) 544 error("Couldn't setstat on \"%s\": %s", path, 545 fx2txt(status)); 546 547 return(status); 548 } 549 550 int 551 do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, 552 Attrib *a) 553 { 554 u_int status, id; 555 556 id = conn->msg_id++; 557 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle, 558 handle_len, a); 559 560 status = get_status(conn->fd_in, id); 561 if (status != SSH2_FX_OK) 562 error("Couldn't fsetstat: %s", fx2txt(status)); 563 564 return(status); 565 } 566 567 char * 568 do_realpath(struct sftp_conn *conn, char *path) 569 { 570 Buffer msg; 571 u_int type, expected_id, count, id; 572 char *filename, *longname; 573 Attrib *a; 574 575 expected_id = id = conn->msg_id++; 576 send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path, 577 strlen(path)); 578 579 buffer_init(&msg); 580 581 get_msg(conn->fd_in, &msg); 582 type = buffer_get_char(&msg); 583 id = buffer_get_int(&msg); 584 585 if (id != expected_id) 586 fatal("ID mismatch (%u != %u)", id, expected_id); 587 588 if (type == SSH2_FXP_STATUS) { 589 u_int status = buffer_get_int(&msg); 590 591 error("Couldn't canonicalise: %s", fx2txt(status)); 592 return(NULL); 593 } else if (type != SSH2_FXP_NAME) 594 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 595 SSH2_FXP_NAME, type); 596 597 count = buffer_get_int(&msg); 598 if (count != 1) 599 fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); 600 601 filename = buffer_get_string(&msg, NULL); 602 longname = buffer_get_string(&msg, NULL); 603 a = decode_attrib(&msg); 604 605 debug3("SSH_FXP_REALPATH %s -> %s", path, filename); 606 607 xfree(longname); 608 609 buffer_free(&msg); 610 611 return(filename); 612 } 613 614 int 615 do_rename(struct sftp_conn *conn, char *oldpath, char *newpath) 616 { 617 Buffer msg; 618 u_int status, id; 619 620 buffer_init(&msg); 621 622 /* Send rename request */ 623 id = conn->msg_id++; 624 buffer_put_char(&msg, SSH2_FXP_RENAME); 625 buffer_put_int(&msg, id); 626 buffer_put_cstring(&msg, oldpath); 627 buffer_put_cstring(&msg, newpath); 628 send_msg(conn->fd_out, &msg); 629 debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath, 630 newpath); 631 buffer_free(&msg); 632 633 status = get_status(conn->fd_in, id); 634 if (status != SSH2_FX_OK) 635 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 636 newpath, fx2txt(status)); 637 638 return(status); 639 } 640 641 int 642 do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) 643 { 644 Buffer msg; 645 u_int status, id; 646 647 if (conn->version < 3) { 648 error("This server does not support the symlink operation"); 649 return(SSH2_FX_OP_UNSUPPORTED); 650 } 651 652 buffer_init(&msg); 653 654 /* Send symlink request */ 655 id = conn->msg_id++; 656 buffer_put_char(&msg, SSH2_FXP_SYMLINK); 657 buffer_put_int(&msg, id); 658 buffer_put_cstring(&msg, oldpath); 659 buffer_put_cstring(&msg, newpath); 660 send_msg(conn->fd_out, &msg); 661 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 662 newpath); 663 buffer_free(&msg); 664 665 status = get_status(conn->fd_in, id); 666 if (status != SSH2_FX_OK) 667 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 668 newpath, fx2txt(status)); 669 670 return(status); 671 } 672 673 char * 674 do_readlink(struct sftp_conn *conn, char *path) 675 { 676 Buffer msg; 677 u_int type, expected_id, count, id; 678 char *filename, *longname; 679 Attrib *a; 680 681 expected_id = id = conn->msg_id++; 682 send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path, 683 strlen(path)); 684 685 buffer_init(&msg); 686 687 get_msg(conn->fd_in, &msg); 688 type = buffer_get_char(&msg); 689 id = buffer_get_int(&msg); 690 691 if (id != expected_id) 692 fatal("ID mismatch (%u != %u)", id, expected_id); 693 694 if (type == SSH2_FXP_STATUS) { 695 u_int status = buffer_get_int(&msg); 696 697 error("Couldn't readlink: %s", fx2txt(status)); 698 return(NULL); 699 } else if (type != SSH2_FXP_NAME) 700 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 701 SSH2_FXP_NAME, type); 702 703 count = buffer_get_int(&msg); 704 if (count != 1) 705 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); 706 707 filename = buffer_get_string(&msg, NULL); 708 longname = buffer_get_string(&msg, NULL); 709 a = decode_attrib(&msg); 710 711 debug3("SSH_FXP_READLINK %s -> %s", path, filename); 712 713 xfree(longname); 714 715 buffer_free(&msg); 716 717 return(filename); 718 } 719 720 static void 721 send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, 722 char *handle, u_int handle_len) 723 { 724 Buffer msg; 725 726 buffer_init(&msg); 727 buffer_clear(&msg); 728 buffer_put_char(&msg, SSH2_FXP_READ); 729 buffer_put_int(&msg, id); 730 buffer_put_string(&msg, handle, handle_len); 731 buffer_put_int64(&msg, offset); 732 buffer_put_int(&msg, len); 733 send_msg(fd_out, &msg); 734 buffer_free(&msg); 735 } 736 737 int 738 do_download(struct sftp_conn *conn, char *remote_path, char *local_path, 739 int pflag) 740 { 741 Attrib junk, *a; 742 Buffer msg; 743 char *handle; 744 int local_fd, status, num_req, max_req, write_error; 745 int read_error, write_errno; 746 u_int64_t offset, size; 747 u_int handle_len, mode, type, id, buflen; 748 off_t progress_counter; 749 struct request { 750 u_int id; 751 u_int len; 752 u_int64_t offset; 753 TAILQ_ENTRY(request) tq; 754 }; 755 TAILQ_HEAD(reqhead, request) requests; 756 struct request *req; 757 758 TAILQ_INIT(&requests); 759 760 a = do_stat(conn, remote_path, 0); 761 if (a == NULL) 762 return(-1); 763 764 /* XXX: should we preserve set[ug]id? */ 765 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 766 mode = a->perm & 0777; 767 else 768 mode = 0666; 769 770 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 771 (!S_ISREG(a->perm))) { 772 error("Cannot download non-regular file: %s", remote_path); 773 return(-1); 774 } 775 776 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 777 size = a->size; 778 else 779 size = 0; 780 781 buflen = conn->transfer_buflen; 782 buffer_init(&msg); 783 784 /* Send open request */ 785 id = conn->msg_id++; 786 buffer_put_char(&msg, SSH2_FXP_OPEN); 787 buffer_put_int(&msg, id); 788 buffer_put_cstring(&msg, remote_path); 789 buffer_put_int(&msg, SSH2_FXF_READ); 790 attrib_clear(&junk); /* Send empty attributes */ 791 encode_attrib(&msg, &junk); 792 send_msg(conn->fd_out, &msg); 793 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 794 795 handle = get_handle(conn->fd_in, id, &handle_len); 796 if (handle == NULL) { 797 buffer_free(&msg); 798 return(-1); 799 } 800 801 local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, 802 mode | S_IWRITE); 803 if (local_fd == -1) { 804 error("Couldn't open local file \"%s\" for writing: %s", 805 local_path, strerror(errno)); 806 buffer_free(&msg); 807 xfree(handle); 808 return(-1); 809 } 810 811 /* Read from remote and write to local */ 812 write_error = read_error = write_errno = num_req = offset = 0; 813 max_req = 1; 814 progress_counter = 0; 815 816 if (showprogress && size != 0) 817 start_progress_meter(remote_path, size, &progress_counter); 818 819 while (num_req > 0 || max_req > 0) { 820 char *data; 821 u_int len; 822 823 /* 824 * Simulate EOF on interrupt: stop sending new requests and 825 * allow outstanding requests to drain gracefully 826 */ 827 if (interrupted) { 828 if (num_req == 0) /* If we haven't started yet... */ 829 break; 830 max_req = 0; 831 } 832 833 /* Send some more requests */ 834 while (num_req < max_req) { 835 debug3("Request range %llu -> %llu (%d/%d)", 836 (unsigned long long)offset, 837 (unsigned long long)offset + buflen - 1, 838 num_req, max_req); 839 req = xmalloc(sizeof(*req)); 840 req->id = conn->msg_id++; 841 req->len = buflen; 842 req->offset = offset; 843 offset += buflen; 844 num_req++; 845 TAILQ_INSERT_TAIL(&requests, req, tq); 846 send_read_request(conn->fd_out, req->id, req->offset, 847 req->len, handle, handle_len); 848 } 849 850 buffer_clear(&msg); 851 get_msg(conn->fd_in, &msg); 852 type = buffer_get_char(&msg); 853 id = buffer_get_int(&msg); 854 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 855 856 /* Find the request in our queue */ 857 for(req = TAILQ_FIRST(&requests); 858 req != NULL && req->id != id; 859 req = TAILQ_NEXT(req, tq)) 860 ; 861 if (req == NULL) 862 fatal("Unexpected reply %u", id); 863 864 switch (type) { 865 case SSH2_FXP_STATUS: 866 status = buffer_get_int(&msg); 867 if (status != SSH2_FX_EOF) 868 read_error = 1; 869 max_req = 0; 870 TAILQ_REMOVE(&requests, req, tq); 871 xfree(req); 872 num_req--; 873 break; 874 case SSH2_FXP_DATA: 875 data = buffer_get_string(&msg, &len); 876 debug3("Received data %llu -> %llu", 877 (unsigned long long)req->offset, 878 (unsigned long long)req->offset + len - 1); 879 if (len > req->len) 880 fatal("Received more data than asked for " 881 "%u > %u", len, req->len); 882 if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || 883 atomicio(vwrite, local_fd, data, len) != len) && 884 !write_error) { 885 write_errno = errno; 886 write_error = 1; 887 max_req = 0; 888 } 889 progress_counter += len; 890 xfree(data); 891 892 if (len == req->len) { 893 TAILQ_REMOVE(&requests, req, tq); 894 xfree(req); 895 num_req--; 896 } else { 897 /* Resend the request for the missing data */ 898 debug3("Short data block, re-requesting " 899 "%llu -> %llu (%2d)", 900 (unsigned long long)req->offset + len, 901 (unsigned long long)req->offset + 902 req->len - 1, num_req); 903 req->id = conn->msg_id++; 904 req->len -= len; 905 req->offset += len; 906 send_read_request(conn->fd_out, req->id, 907 req->offset, req->len, handle, handle_len); 908 /* Reduce the request size */ 909 if (len < buflen) 910 buflen = MAX(MIN_READ_SIZE, len); 911 } 912 if (max_req > 0) { /* max_req = 0 iff EOF received */ 913 if (size > 0 && offset > size) { 914 /* Only one request at a time 915 * after the expected EOF */ 916 debug3("Finish at %llu (%2d)", 917 (unsigned long long)offset, 918 num_req); 919 max_req = 1; 920 } else if (max_req <= conn->num_requests) { 921 ++max_req; 922 } 923 } 924 break; 925 default: 926 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 927 SSH2_FXP_DATA, type); 928 } 929 } 930 931 if (showprogress && size) 932 stop_progress_meter(); 933 934 /* Sanity check */ 935 if (TAILQ_FIRST(&requests) != NULL) 936 fatal("Transfer complete, but requests still in queue"); 937 938 if (read_error) { 939 error("Couldn't read from remote file \"%s\" : %s", 940 remote_path, fx2txt(status)); 941 do_close(conn, handle, handle_len); 942 } else if (write_error) { 943 error("Couldn't write to \"%s\": %s", local_path, 944 strerror(write_errno)); 945 status = -1; 946 do_close(conn, handle, handle_len); 947 } else { 948 status = do_close(conn, handle, handle_len); 949 950 /* Override umask and utimes if asked */ 951 #ifdef HAVE_FCHMOD 952 if (pflag && fchmod(local_fd, mode) == -1) 953 #else 954 if (pflag && chmod(local_path, mode) == -1) 955 #endif /* HAVE_FCHMOD */ 956 error("Couldn't set mode on \"%s\": %s", local_path, 957 strerror(errno)); 958 if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { 959 struct timeval tv[2]; 960 tv[0].tv_sec = a->atime; 961 tv[1].tv_sec = a->mtime; 962 tv[0].tv_usec = tv[1].tv_usec = 0; 963 if (utimes(local_path, tv) == -1) 964 error("Can't set times on \"%s\": %s", 965 local_path, strerror(errno)); 966 } 967 } 968 close(local_fd); 969 buffer_free(&msg); 970 xfree(handle); 971 972 return(status); 973 } 974 975 int 976 do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, 977 int pflag) 978 { 979 int local_fd, status; 980 u_int handle_len, id, type; 981 u_int64_t offset; 982 char *handle, *data; 983 Buffer msg; 984 struct stat sb; 985 Attrib a; 986 u_int32_t startid; 987 u_int32_t ackid; 988 struct outstanding_ack { 989 u_int id; 990 u_int len; 991 u_int64_t offset; 992 TAILQ_ENTRY(outstanding_ack) tq; 993 }; 994 TAILQ_HEAD(ackhead, outstanding_ack) acks; 995 struct outstanding_ack *ack = NULL; 996 997 TAILQ_INIT(&acks); 998 999 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { 1000 error("Couldn't open local file \"%s\" for reading: %s", 1001 local_path, strerror(errno)); 1002 return(-1); 1003 } 1004 if (fstat(local_fd, &sb) == -1) { 1005 error("Couldn't fstat local file \"%s\": %s", 1006 local_path, strerror(errno)); 1007 close(local_fd); 1008 return(-1); 1009 } 1010 if (!S_ISREG(sb.st_mode)) { 1011 error("%s is not a regular file", local_path); 1012 close(local_fd); 1013 return(-1); 1014 } 1015 stat_to_attrib(&sb, &a); 1016 1017 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1018 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1019 a.perm &= 0777; 1020 if (!pflag) 1021 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1022 1023 buffer_init(&msg); 1024 1025 /* Send open request */ 1026 id = conn->msg_id++; 1027 buffer_put_char(&msg, SSH2_FXP_OPEN); 1028 buffer_put_int(&msg, id); 1029 buffer_put_cstring(&msg, remote_path); 1030 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1031 encode_attrib(&msg, &a); 1032 send_msg(conn->fd_out, &msg); 1033 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1034 1035 buffer_clear(&msg); 1036 1037 handle = get_handle(conn->fd_in, id, &handle_len); 1038 if (handle == NULL) { 1039 close(local_fd); 1040 buffer_free(&msg); 1041 return(-1); 1042 } 1043 1044 startid = ackid = id + 1; 1045 data = xmalloc(conn->transfer_buflen); 1046 1047 /* Read from local and write to remote */ 1048 offset = 0; 1049 if (showprogress) 1050 start_progress_meter(local_path, sb.st_size, &offset); 1051 1052 for (;;) { 1053 int len; 1054 1055 /* 1056 * Can't use atomicio here because it returns 0 on EOF, 1057 * thus losing the last block of the file. 1058 * Simulate an EOF on interrupt, allowing ACKs from the 1059 * server to drain. 1060 */ 1061 if (interrupted) 1062 len = 0; 1063 else do 1064 len = read(local_fd, data, conn->transfer_buflen); 1065 while ((len == -1) && (errno == EINTR || errno == EAGAIN)); 1066 1067 if (len == -1) 1068 fatal("Couldn't read from \"%s\": %s", local_path, 1069 strerror(errno)); 1070 1071 if (len != 0) { 1072 ack = xmalloc(sizeof(*ack)); 1073 ack->id = ++id; 1074 ack->offset = offset; 1075 ack->len = len; 1076 TAILQ_INSERT_TAIL(&acks, ack, tq); 1077 1078 buffer_clear(&msg); 1079 buffer_put_char(&msg, SSH2_FXP_WRITE); 1080 buffer_put_int(&msg, ack->id); 1081 buffer_put_string(&msg, handle, handle_len); 1082 buffer_put_int64(&msg, offset); 1083 buffer_put_string(&msg, data, len); 1084 send_msg(conn->fd_out, &msg); 1085 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1086 id, (unsigned long long)offset, len); 1087 } else if (TAILQ_FIRST(&acks) == NULL) 1088 break; 1089 1090 if (ack == NULL) 1091 fatal("Unexpected ACK %u", id); 1092 1093 if (id == startid || len == 0 || 1094 id - ackid >= conn->num_requests) { 1095 u_int r_id; 1096 1097 buffer_clear(&msg); 1098 get_msg(conn->fd_in, &msg); 1099 type = buffer_get_char(&msg); 1100 r_id = buffer_get_int(&msg); 1101 1102 if (type != SSH2_FXP_STATUS) 1103 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 1104 "got %d", SSH2_FXP_STATUS, type); 1105 1106 status = buffer_get_int(&msg); 1107 debug3("SSH2_FXP_STATUS %d", status); 1108 1109 /* Find the request in our queue */ 1110 for(ack = TAILQ_FIRST(&acks); 1111 ack != NULL && ack->id != r_id; 1112 ack = TAILQ_NEXT(ack, tq)) 1113 ; 1114 if (ack == NULL) 1115 fatal("Can't find request for ID %u", r_id); 1116 TAILQ_REMOVE(&acks, ack, tq); 1117 1118 if (status != SSH2_FX_OK) { 1119 error("Couldn't write to remote file \"%s\": %s", 1120 remote_path, fx2txt(status)); 1121 do_close(conn, handle, handle_len); 1122 close(local_fd); 1123 xfree(data); 1124 xfree(ack); 1125 goto done; 1126 } 1127 debug3("In write loop, ack for %u %u bytes at %llu", 1128 ack->id, ack->len, (unsigned long long)ack->offset); 1129 ++ackid; 1130 xfree(ack); 1131 } 1132 offset += len; 1133 } 1134 if (showprogress) 1135 stop_progress_meter(); 1136 xfree(data); 1137 1138 if (close(local_fd) == -1) { 1139 error("Couldn't close local file \"%s\": %s", local_path, 1140 strerror(errno)); 1141 do_close(conn, handle, handle_len); 1142 status = -1; 1143 goto done; 1144 } 1145 1146 /* Override umask and utimes if asked */ 1147 if (pflag) 1148 do_fsetstat(conn, handle, handle_len, &a); 1149 1150 status = do_close(conn, handle, handle_len); 1151 1152 done: 1153 xfree(handle); 1154 buffer_free(&msg); 1155 return(status); 1156 } 1157