1 /* $OpenBSD: sftp-client.c,v 1.114 2014/01/31 16:39:19 tedu Exp $ */ 2 /* 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* XXX: memleaks */ 19 /* XXX: signed vs unsigned */ 20 /* XXX: remove all logging, only return status codes */ 21 /* XXX: copy between two remote sites */ 22 23 #include "includes.h" 24 25 #include <sys/types.h> 26 #include <sys/param.h> 27 #ifdef HAVE_SYS_STATVFS_H 28 #include <sys/statvfs.h> 29 #endif 30 #include "openbsd-compat/sys-queue.h" 31 #ifdef HAVE_SYS_STAT_H 32 # include <sys/stat.h> 33 #endif 34 #ifdef HAVE_SYS_TIME_H 35 # include <sys/time.h> 36 #endif 37 #include <sys/uio.h> 38 39 #include <dirent.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <signal.h> 43 #include <stdarg.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include "xmalloc.h" 50 #include "buffer.h" 51 #include "log.h" 52 #include "atomicio.h" 53 #include "progressmeter.h" 54 #include "misc.h" 55 56 #include "sftp.h" 57 #include "sftp-common.h" 58 #include "sftp-client.h" 59 60 extern volatile sig_atomic_t interrupted; 61 extern int showprogress; 62 63 /* Minimum amount of data to read at a time */ 64 #define MIN_READ_SIZE 512 65 66 /* Maximum depth to descend in directory trees */ 67 #define MAX_DIR_DEPTH 64 68 69 struct sftp_conn { 70 int fd_in; 71 int fd_out; 72 u_int transfer_buflen; 73 u_int num_requests; 74 u_int version; 75 u_int msg_id; 76 #define SFTP_EXT_POSIX_RENAME 0x00000001 77 #define SFTP_EXT_STATVFS 0x00000002 78 #define SFTP_EXT_FSTATVFS 0x00000004 79 #define SFTP_EXT_HARDLINK 0x00000008 80 #define SFTP_EXT_FSYNC 0x00000010 81 u_int exts; 82 u_int64_t limit_kbps; 83 struct bwlimit bwlimit_in, bwlimit_out; 84 }; 85 86 static char * 87 get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, 88 const char *errfmt, ...) __attribute__((format(printf, 4, 5))); 89 90 /* ARGSUSED */ 91 static int 92 sftpio(void *_bwlimit, size_t amount) 93 { 94 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; 95 96 bandwidth_limit(bwlimit, amount); 97 return 0; 98 } 99 100 static void 101 send_msg(struct sftp_conn *conn, Buffer *m) 102 { 103 u_char mlen[4]; 104 struct iovec iov[2]; 105 106 if (buffer_len(m) > SFTP_MAX_MSG_LENGTH) 107 fatal("Outbound message too long %u", buffer_len(m)); 108 109 /* Send length first */ 110 put_u32(mlen, buffer_len(m)); 111 iov[0].iov_base = mlen; 112 iov[0].iov_len = sizeof(mlen); 113 iov[1].iov_base = buffer_ptr(m); 114 iov[1].iov_len = buffer_len(m); 115 116 if (atomiciov6(writev, conn->fd_out, iov, 2, 117 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != 118 buffer_len(m) + sizeof(mlen)) 119 fatal("Couldn't send packet: %s", strerror(errno)); 120 121 buffer_clear(m); 122 } 123 124 static void 125 get_msg(struct sftp_conn *conn, Buffer *m) 126 { 127 u_int msg_len; 128 129 buffer_append_space(m, 4); 130 if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4, 131 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { 132 if (errno == EPIPE) 133 fatal("Connection closed"); 134 else 135 fatal("Couldn't read packet: %s", strerror(errno)); 136 } 137 138 msg_len = buffer_get_int(m); 139 if (msg_len > SFTP_MAX_MSG_LENGTH) 140 fatal("Received message too long %u", msg_len); 141 142 buffer_append_space(m, msg_len); 143 if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len, 144 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) 145 != msg_len) { 146 if (errno == EPIPE) 147 fatal("Connection closed"); 148 else 149 fatal("Read packet: %s", strerror(errno)); 150 } 151 } 152 153 static void 154 send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, 155 u_int len) 156 { 157 Buffer msg; 158 159 buffer_init(&msg); 160 buffer_put_char(&msg, code); 161 buffer_put_int(&msg, id); 162 buffer_put_string(&msg, s, len); 163 send_msg(conn, &msg); 164 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 165 buffer_free(&msg); 166 } 167 168 static void 169 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, 170 char *s, u_int len, Attrib *a) 171 { 172 Buffer msg; 173 174 buffer_init(&msg); 175 buffer_put_char(&msg, code); 176 buffer_put_int(&msg, id); 177 buffer_put_string(&msg, s, len); 178 encode_attrib(&msg, a); 179 send_msg(conn, &msg); 180 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 181 buffer_free(&msg); 182 } 183 184 static u_int 185 get_status(struct sftp_conn *conn, u_int expected_id) 186 { 187 Buffer msg; 188 u_int type, id, status; 189 190 buffer_init(&msg); 191 get_msg(conn, &msg); 192 type = buffer_get_char(&msg); 193 id = buffer_get_int(&msg); 194 195 if (id != expected_id) 196 fatal("ID mismatch (%u != %u)", id, expected_id); 197 if (type != SSH2_FXP_STATUS) 198 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", 199 SSH2_FXP_STATUS, type); 200 201 status = buffer_get_int(&msg); 202 buffer_free(&msg); 203 204 debug3("SSH2_FXP_STATUS %u", status); 205 206 return status; 207 } 208 209 static char * 210 get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, 211 const char *errfmt, ...) 212 { 213 Buffer msg; 214 u_int type, id; 215 char *handle, errmsg[256]; 216 va_list args; 217 int status; 218 219 va_start(args, errfmt); 220 if (errfmt != NULL) 221 vsnprintf(errmsg, sizeof(errmsg), errfmt, args); 222 va_end(args); 223 224 buffer_init(&msg); 225 get_msg(conn, &msg); 226 type = buffer_get_char(&msg); 227 id = buffer_get_int(&msg); 228 229 if (id != expected_id) 230 fatal("%s: ID mismatch (%u != %u)", 231 errfmt == NULL ? __func__ : errmsg, id, expected_id); 232 if (type == SSH2_FXP_STATUS) { 233 status = buffer_get_int(&msg); 234 if (errfmt != NULL) 235 error("%s: %s", errmsg, fx2txt(status)); 236 buffer_free(&msg); 237 return(NULL); 238 } else if (type != SSH2_FXP_HANDLE) 239 fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", 240 errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); 241 242 handle = buffer_get_string(&msg, len); 243 buffer_free(&msg); 244 245 return(handle); 246 } 247 248 static Attrib * 249 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) 250 { 251 Buffer msg; 252 u_int type, id; 253 Attrib *a; 254 255 buffer_init(&msg); 256 get_msg(conn, &msg); 257 258 type = buffer_get_char(&msg); 259 id = buffer_get_int(&msg); 260 261 debug3("Received stat reply T:%u I:%u", type, id); 262 if (id != expected_id) 263 fatal("ID mismatch (%u != %u)", id, expected_id); 264 if (type == SSH2_FXP_STATUS) { 265 int status = buffer_get_int(&msg); 266 267 if (quiet) 268 debug("Couldn't stat remote file: %s", fx2txt(status)); 269 else 270 error("Couldn't stat remote file: %s", fx2txt(status)); 271 buffer_free(&msg); 272 return(NULL); 273 } else if (type != SSH2_FXP_ATTRS) { 274 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", 275 SSH2_FXP_ATTRS, type); 276 } 277 a = decode_attrib(&msg); 278 buffer_free(&msg); 279 280 return(a); 281 } 282 283 static int 284 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, 285 u_int expected_id, int quiet) 286 { 287 Buffer msg; 288 u_int type, id, flag; 289 290 buffer_init(&msg); 291 get_msg(conn, &msg); 292 293 type = buffer_get_char(&msg); 294 id = buffer_get_int(&msg); 295 296 debug3("Received statvfs reply T:%u I:%u", type, id); 297 if (id != expected_id) 298 fatal("ID mismatch (%u != %u)", id, expected_id); 299 if (type == SSH2_FXP_STATUS) { 300 int status = buffer_get_int(&msg); 301 302 if (quiet) 303 debug("Couldn't statvfs: %s", fx2txt(status)); 304 else 305 error("Couldn't statvfs: %s", fx2txt(status)); 306 buffer_free(&msg); 307 return -1; 308 } else if (type != SSH2_FXP_EXTENDED_REPLY) { 309 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 310 SSH2_FXP_EXTENDED_REPLY, type); 311 } 312 313 memset(st, 0, sizeof(*st)); 314 st->f_bsize = buffer_get_int64(&msg); 315 st->f_frsize = buffer_get_int64(&msg); 316 st->f_blocks = buffer_get_int64(&msg); 317 st->f_bfree = buffer_get_int64(&msg); 318 st->f_bavail = buffer_get_int64(&msg); 319 st->f_files = buffer_get_int64(&msg); 320 st->f_ffree = buffer_get_int64(&msg); 321 st->f_favail = buffer_get_int64(&msg); 322 st->f_fsid = buffer_get_int64(&msg); 323 flag = buffer_get_int64(&msg); 324 st->f_namemax = buffer_get_int64(&msg); 325 326 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; 328 329 buffer_free(&msg); 330 331 return 0; 332 } 333 334 struct sftp_conn * 335 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, 336 u_int64_t limit_kbps) 337 { 338 u_int type; 339 Buffer msg; 340 struct sftp_conn *ret; 341 342 ret = xcalloc(1, sizeof(*ret)); 343 ret->msg_id = 1; 344 ret->fd_in = fd_in; 345 ret->fd_out = fd_out; 346 ret->transfer_buflen = transfer_buflen; 347 ret->num_requests = num_requests; 348 ret->exts = 0; 349 ret->limit_kbps = 0; 350 351 buffer_init(&msg); 352 buffer_put_char(&msg, SSH2_FXP_INIT); 353 buffer_put_int(&msg, SSH2_FILEXFER_VERSION); 354 send_msg(ret, &msg); 355 356 buffer_clear(&msg); 357 358 get_msg(ret, &msg); 359 360 /* Expecting a VERSION reply */ 361 if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { 362 error("Invalid packet back from SSH2_FXP_INIT (type %u)", 363 type); 364 buffer_free(&msg); 365 return(NULL); 366 } 367 ret->version = buffer_get_int(&msg); 368 369 debug2("Remote version: %u", ret->version); 370 371 /* Check for extensions */ 372 while (buffer_len(&msg) > 0) { 373 char *name = buffer_get_string(&msg, NULL); 374 char *value = buffer_get_string(&msg, NULL); 375 int known = 0; 376 377 if (strcmp(name, "posix-rename@openssh.com") == 0 && 378 strcmp(value, "1") == 0) { 379 ret->exts |= SFTP_EXT_POSIX_RENAME; 380 known = 1; 381 } else if (strcmp(name, "statvfs@openssh.com") == 0 && 382 strcmp(value, "2") == 0) { 383 ret->exts |= SFTP_EXT_STATVFS; 384 known = 1; 385 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && 386 strcmp(value, "2") == 0) { 387 ret->exts |= SFTP_EXT_FSTATVFS; 388 known = 1; 389 } else if (strcmp(name, "hardlink@openssh.com") == 0 && 390 strcmp(value, "1") == 0) { 391 ret->exts |= SFTP_EXT_HARDLINK; 392 known = 1; 393 } else if (strcmp(name, "fsync@openssh.com") == 0 && 394 strcmp(value, "1") == 0) { 395 ret->exts |= SFTP_EXT_FSYNC; 396 known = 1; 397 } 398 if (known) { 399 debug2("Server supports extension \"%s\" revision %s", 400 name, value); 401 } else { 402 debug2("Unrecognised server extension \"%s\"", name); 403 } 404 free(name); 405 free(value); 406 } 407 408 buffer_free(&msg); 409 410 /* Some filexfer v.0 servers don't support large packets */ 411 if (ret->version == 0) 412 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480); 413 414 ret->limit_kbps = limit_kbps; 415 if (ret->limit_kbps > 0) { 416 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps, 417 ret->transfer_buflen); 418 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps, 419 ret->transfer_buflen); 420 } 421 422 return ret; 423 } 424 425 u_int 426 sftp_proto_version(struct sftp_conn *conn) 427 { 428 return conn->version; 429 } 430 431 int 432 do_close(struct sftp_conn *conn, char *handle, u_int handle_len) 433 { 434 u_int id, status; 435 Buffer msg; 436 437 buffer_init(&msg); 438 439 id = conn->msg_id++; 440 buffer_put_char(&msg, SSH2_FXP_CLOSE); 441 buffer_put_int(&msg, id); 442 buffer_put_string(&msg, handle, handle_len); 443 send_msg(conn, &msg); 444 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 445 446 status = get_status(conn, id); 447 if (status != SSH2_FX_OK) 448 error("Couldn't close file: %s", fx2txt(status)); 449 450 buffer_free(&msg); 451 452 return status; 453 } 454 455 456 static int 457 do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, 458 SFTP_DIRENT ***dir) 459 { 460 Buffer msg; 461 u_int count, type, id, handle_len, i, expected_id, ents = 0; 462 char *handle; 463 int status = SSH2_FX_FAILURE; 464 465 if (dir) 466 *dir = NULL; 467 468 id = conn->msg_id++; 469 470 buffer_init(&msg); 471 buffer_put_char(&msg, SSH2_FXP_OPENDIR); 472 buffer_put_int(&msg, id); 473 buffer_put_cstring(&msg, path); 474 send_msg(conn, &msg); 475 476 handle = get_handle(conn, id, &handle_len, 477 "remote readdir(\"%s\")", path); 478 if (handle == NULL) { 479 buffer_free(&msg); 480 return -1; 481 } 482 483 if (dir) { 484 ents = 0; 485 *dir = xcalloc(1, sizeof(**dir)); 486 (*dir)[0] = NULL; 487 } 488 489 for (; !interrupted;) { 490 id = expected_id = conn->msg_id++; 491 492 debug3("Sending SSH2_FXP_READDIR I:%u", id); 493 494 buffer_clear(&msg); 495 buffer_put_char(&msg, SSH2_FXP_READDIR); 496 buffer_put_int(&msg, id); 497 buffer_put_string(&msg, handle, handle_len); 498 send_msg(conn, &msg); 499 500 buffer_clear(&msg); 501 502 get_msg(conn, &msg); 503 504 type = buffer_get_char(&msg); 505 id = buffer_get_int(&msg); 506 507 debug3("Received reply T:%u I:%u", type, id); 508 509 if (id != expected_id) 510 fatal("ID mismatch (%u != %u)", id, expected_id); 511 512 if (type == SSH2_FXP_STATUS) { 513 status = buffer_get_int(&msg); 514 debug3("Received SSH2_FXP_STATUS %d", status); 515 if (status == SSH2_FX_EOF) 516 break; 517 error("Couldn't read directory: %s", fx2txt(status)); 518 goto out; 519 } else if (type != SSH2_FXP_NAME) 520 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 521 SSH2_FXP_NAME, type); 522 523 count = buffer_get_int(&msg); 524 if (count == 0) 525 break; 526 debug3("Received %d SSH2_FXP_NAME responses", count); 527 for (i = 0; i < count; i++) { 528 char *filename, *longname; 529 Attrib *a; 530 531 filename = buffer_get_string(&msg, NULL); 532 longname = buffer_get_string(&msg, NULL); 533 a = decode_attrib(&msg); 534 535 if (print_flag) 536 printf("%s\n", longname); 537 538 /* 539 * Directory entries should never contain '/' 540 * These can be used to attack recursive ops 541 * (e.g. send '../../../../etc/passwd') 542 */ 543 if (strchr(filename, '/') != NULL) { 544 error("Server sent suspect path \"%s\" " 545 "during readdir of \"%s\"", filename, path); 546 } else if (dir) { 547 *dir = xrealloc(*dir, ents + 2, sizeof(**dir)); 548 (*dir)[ents] = xcalloc(1, sizeof(***dir)); 549 (*dir)[ents]->filename = xstrdup(filename); 550 (*dir)[ents]->longname = xstrdup(longname); 551 memcpy(&(*dir)[ents]->a, a, sizeof(*a)); 552 (*dir)[++ents] = NULL; 553 } 554 free(filename); 555 free(longname); 556 } 557 } 558 status = 0; 559 560 out: 561 buffer_free(&msg); 562 do_close(conn, handle, handle_len); 563 free(handle); 564 565 if (status != 0 && dir != NULL) { 566 /* Don't return results on error */ 567 free_sftp_dirents(*dir); 568 *dir = NULL; 569 } else if (interrupted && dir != NULL && *dir != NULL) { 570 /* Don't return partial matches on interrupt */ 571 free_sftp_dirents(*dir); 572 *dir = xcalloc(1, sizeof(**dir)); 573 **dir = NULL; 574 } 575 576 return status; 577 } 578 579 int 580 do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) 581 { 582 return(do_lsreaddir(conn, path, 0, dir)); 583 } 584 585 void free_sftp_dirents(SFTP_DIRENT **s) 586 { 587 int i; 588 589 if (s == NULL) 590 return; 591 for (i = 0; s[i]; i++) { 592 free(s[i]->filename); 593 free(s[i]->longname); 594 free(s[i]); 595 } 596 free(s); 597 } 598 599 int 600 do_rm(struct sftp_conn *conn, char *path) 601 { 602 u_int status, id; 603 604 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 605 606 id = conn->msg_id++; 607 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); 608 status = get_status(conn, id); 609 if (status != SSH2_FX_OK) 610 error("Couldn't delete file: %s", fx2txt(status)); 611 return(status); 612 } 613 614 int 615 do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) 616 { 617 u_int status, id; 618 619 id = conn->msg_id++; 620 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, 621 strlen(path), a); 622 623 status = get_status(conn, id); 624 if (status != SSH2_FX_OK && print_flag) 625 error("Couldn't create directory: %s", fx2txt(status)); 626 627 return(status); 628 } 629 630 int 631 do_rmdir(struct sftp_conn *conn, char *path) 632 { 633 u_int status, id; 634 635 id = conn->msg_id++; 636 send_string_request(conn, id, SSH2_FXP_RMDIR, path, 637 strlen(path)); 638 639 status = get_status(conn, id); 640 if (status != SSH2_FX_OK) 641 error("Couldn't remove directory: %s", fx2txt(status)); 642 643 return(status); 644 } 645 646 Attrib * 647 do_stat(struct sftp_conn *conn, char *path, int quiet) 648 { 649 u_int id; 650 651 id = conn->msg_id++; 652 653 send_string_request(conn, id, 654 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 655 path, strlen(path)); 656 657 return(get_decode_stat(conn, id, quiet)); 658 } 659 660 Attrib * 661 do_lstat(struct sftp_conn *conn, char *path, int quiet) 662 { 663 u_int id; 664 665 if (conn->version == 0) { 666 if (quiet) 667 debug("Server version does not support lstat operation"); 668 else 669 logit("Server version does not support lstat operation"); 670 return(do_stat(conn, path, quiet)); 671 } 672 673 id = conn->msg_id++; 674 send_string_request(conn, id, SSH2_FXP_LSTAT, path, 675 strlen(path)); 676 677 return(get_decode_stat(conn, id, quiet)); 678 } 679 680 #ifdef notyet 681 Attrib * 682 do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) 683 { 684 u_int id; 685 686 id = conn->msg_id++; 687 send_string_request(conn, id, SSH2_FXP_FSTAT, handle, 688 handle_len); 689 690 return(get_decode_stat(conn, id, quiet)); 691 } 692 #endif 693 694 int 695 do_setstat(struct sftp_conn *conn, char *path, Attrib *a) 696 { 697 u_int status, id; 698 699 id = conn->msg_id++; 700 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, 701 strlen(path), a); 702 703 status = get_status(conn, id); 704 if (status != SSH2_FX_OK) 705 error("Couldn't setstat on \"%s\": %s", path, 706 fx2txt(status)); 707 708 return(status); 709 } 710 711 int 712 do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, 713 Attrib *a) 714 { 715 u_int status, id; 716 717 id = conn->msg_id++; 718 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, 719 handle_len, a); 720 721 status = get_status(conn, id); 722 if (status != SSH2_FX_OK) 723 error("Couldn't fsetstat: %s", fx2txt(status)); 724 725 return(status); 726 } 727 728 char * 729 do_realpath(struct sftp_conn *conn, char *path) 730 { 731 Buffer msg; 732 u_int type, expected_id, count, id; 733 char *filename, *longname; 734 Attrib *a; 735 736 expected_id = id = conn->msg_id++; 737 send_string_request(conn, id, SSH2_FXP_REALPATH, path, 738 strlen(path)); 739 740 buffer_init(&msg); 741 742 get_msg(conn, &msg); 743 type = buffer_get_char(&msg); 744 id = buffer_get_int(&msg); 745 746 if (id != expected_id) 747 fatal("ID mismatch (%u != %u)", id, expected_id); 748 749 if (type == SSH2_FXP_STATUS) { 750 u_int status = buffer_get_int(&msg); 751 752 error("Couldn't canonicalize: %s", fx2txt(status)); 753 buffer_free(&msg); 754 return NULL; 755 } else if (type != SSH2_FXP_NAME) 756 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 757 SSH2_FXP_NAME, type); 758 759 count = buffer_get_int(&msg); 760 if (count != 1) 761 fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); 762 763 filename = buffer_get_string(&msg, NULL); 764 longname = buffer_get_string(&msg, NULL); 765 a = decode_attrib(&msg); 766 767 debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, 768 (unsigned long)a->size); 769 770 free(longname); 771 772 buffer_free(&msg); 773 774 return(filename); 775 } 776 777 int 778 do_rename(struct sftp_conn *conn, char *oldpath, char *newpath, 779 int force_legacy) 780 { 781 Buffer msg; 782 u_int status, id; 783 int use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; 784 785 buffer_init(&msg); 786 787 /* Send rename request */ 788 id = conn->msg_id++; 789 if (use_ext) { 790 buffer_put_char(&msg, SSH2_FXP_EXTENDED); 791 buffer_put_int(&msg, id); 792 buffer_put_cstring(&msg, "posix-rename@openssh.com"); 793 } else { 794 buffer_put_char(&msg, SSH2_FXP_RENAME); 795 buffer_put_int(&msg, id); 796 } 797 buffer_put_cstring(&msg, oldpath); 798 buffer_put_cstring(&msg, newpath); 799 send_msg(conn, &msg); 800 debug3("Sent message %s \"%s\" -> \"%s\"", 801 use_ext ? "posix-rename@openssh.com" : "SSH2_FXP_RENAME", 802 oldpath, newpath); 803 buffer_free(&msg); 804 805 status = get_status(conn, id); 806 if (status != SSH2_FX_OK) 807 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 808 newpath, fx2txt(status)); 809 810 return(status); 811 } 812 813 int 814 do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) 815 { 816 Buffer msg; 817 u_int status, id; 818 819 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { 820 error("Server does not support hardlink@openssh.com extension"); 821 return -1; 822 } 823 824 buffer_init(&msg); 825 826 /* Send link request */ 827 id = conn->msg_id++; 828 buffer_put_char(&msg, SSH2_FXP_EXTENDED); 829 buffer_put_int(&msg, id); 830 buffer_put_cstring(&msg, "hardlink@openssh.com"); 831 buffer_put_cstring(&msg, oldpath); 832 buffer_put_cstring(&msg, newpath); 833 send_msg(conn, &msg); 834 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", 835 oldpath, newpath); 836 buffer_free(&msg); 837 838 status = get_status(conn, id); 839 if (status != SSH2_FX_OK) 840 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, 841 newpath, fx2txt(status)); 842 843 return(status); 844 } 845 846 int 847 do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) 848 { 849 Buffer msg; 850 u_int status, id; 851 852 if (conn->version < 3) { 853 error("This server does not support the symlink operation"); 854 return(SSH2_FX_OP_UNSUPPORTED); 855 } 856 857 buffer_init(&msg); 858 859 /* Send symlink request */ 860 id = conn->msg_id++; 861 buffer_put_char(&msg, SSH2_FXP_SYMLINK); 862 buffer_put_int(&msg, id); 863 buffer_put_cstring(&msg, oldpath); 864 buffer_put_cstring(&msg, newpath); 865 send_msg(conn, &msg); 866 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 867 newpath); 868 buffer_free(&msg); 869 870 status = get_status(conn, id); 871 if (status != SSH2_FX_OK) 872 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 873 newpath, fx2txt(status)); 874 875 return(status); 876 } 877 878 int 879 do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) 880 { 881 Buffer msg; 882 u_int status, id; 883 884 /* Silently return if the extension is not supported */ 885 if ((conn->exts & SFTP_EXT_FSYNC) == 0) 886 return -1; 887 888 buffer_init(&msg); 889 890 /* Send fsync request */ 891 id = conn->msg_id++; 892 893 buffer_put_char(&msg, SSH2_FXP_EXTENDED); 894 buffer_put_int(&msg, id); 895 buffer_put_cstring(&msg, "fsync@openssh.com"); 896 buffer_put_string(&msg, handle, handle_len); 897 send_msg(conn, &msg); 898 debug3("Sent message fsync@openssh.com I:%u", id); 899 buffer_free(&msg); 900 901 status = get_status(conn, id); 902 if (status != SSH2_FX_OK) 903 error("Couldn't sync file: %s", fx2txt(status)); 904 905 return status; 906 } 907 908 #ifdef notyet 909 char * 910 do_readlink(struct sftp_conn *conn, char *path) 911 { 912 Buffer msg; 913 u_int type, expected_id, count, id; 914 char *filename, *longname; 915 Attrib *a; 916 917 expected_id = id = conn->msg_id++; 918 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); 919 920 buffer_init(&msg); 921 922 get_msg(conn, &msg); 923 type = buffer_get_char(&msg); 924 id = buffer_get_int(&msg); 925 926 if (id != expected_id) 927 fatal("ID mismatch (%u != %u)", id, expected_id); 928 929 if (type == SSH2_FXP_STATUS) { 930 u_int status = buffer_get_int(&msg); 931 932 error("Couldn't readlink: %s", fx2txt(status)); 933 buffer_free(&msg); 934 return(NULL); 935 } else if (type != SSH2_FXP_NAME) 936 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 937 SSH2_FXP_NAME, type); 938 939 count = buffer_get_int(&msg); 940 if (count != 1) 941 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); 942 943 filename = buffer_get_string(&msg, NULL); 944 longname = buffer_get_string(&msg, NULL); 945 a = decode_attrib(&msg); 946 947 debug3("SSH_FXP_READLINK %s -> %s", path, filename); 948 949 free(longname); 950 951 buffer_free(&msg); 952 953 return(filename); 954 } 955 #endif 956 957 int 958 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, 959 int quiet) 960 { 961 Buffer msg; 962 u_int id; 963 964 if ((conn->exts & SFTP_EXT_STATVFS) == 0) { 965 error("Server does not support statvfs@openssh.com extension"); 966 return -1; 967 } 968 969 id = conn->msg_id++; 970 971 buffer_init(&msg); 972 buffer_clear(&msg); 973 buffer_put_char(&msg, SSH2_FXP_EXTENDED); 974 buffer_put_int(&msg, id); 975 buffer_put_cstring(&msg, "statvfs@openssh.com"); 976 buffer_put_cstring(&msg, path); 977 send_msg(conn, &msg); 978 buffer_free(&msg); 979 980 return get_decode_statvfs(conn, st, id, quiet); 981 } 982 983 #ifdef notyet 984 int 985 do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, 986 struct sftp_statvfs *st, int quiet) 987 { 988 Buffer msg; 989 u_int id; 990 991 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { 992 error("Server does not support fstatvfs@openssh.com extension"); 993 return -1; 994 } 995 996 id = conn->msg_id++; 997 998 buffer_init(&msg); 999 buffer_clear(&msg); 1000 buffer_put_char(&msg, SSH2_FXP_EXTENDED); 1001 buffer_put_int(&msg, id); 1002 buffer_put_cstring(&msg, "fstatvfs@openssh.com"); 1003 buffer_put_string(&msg, handle, handle_len); 1004 send_msg(conn, &msg); 1005 buffer_free(&msg); 1006 1007 return get_decode_statvfs(conn, st, id, quiet); 1008 } 1009 #endif 1010 1011 static void 1012 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1013 u_int len, char *handle, u_int handle_len) 1014 { 1015 Buffer msg; 1016 1017 buffer_init(&msg); 1018 buffer_clear(&msg); 1019 buffer_put_char(&msg, SSH2_FXP_READ); 1020 buffer_put_int(&msg, id); 1021 buffer_put_string(&msg, handle, handle_len); 1022 buffer_put_int64(&msg, offset); 1023 buffer_put_int(&msg, len); 1024 send_msg(conn, &msg); 1025 buffer_free(&msg); 1026 } 1027 1028 int 1029 do_download(struct sftp_conn *conn, char *remote_path, char *local_path, 1030 Attrib *a, int preserve_flag, int resume_flag, int fsync_flag) 1031 { 1032 Attrib junk; 1033 Buffer msg; 1034 char *handle; 1035 int local_fd = -1, status = 0, write_error; 1036 int read_error, write_errno, reordered = 0; 1037 u_int64_t offset = 0, size, highwater; 1038 u_int handle_len, mode, type, id, buflen, num_req, max_req; 1039 off_t progress_counter; 1040 struct stat st; 1041 struct request { 1042 u_int id; 1043 u_int len; 1044 u_int64_t offset; 1045 TAILQ_ENTRY(request) tq; 1046 }; 1047 TAILQ_HEAD(reqhead, request) requests; 1048 struct request *req; 1049 1050 TAILQ_INIT(&requests); 1051 1052 if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) 1053 return -1; 1054 1055 /* Do not preserve set[ug]id here, as we do not preserve ownership */ 1056 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1057 mode = a->perm & 0777; 1058 else 1059 mode = 0666; 1060 1061 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 1062 (!S_ISREG(a->perm))) { 1063 error("Cannot download non-regular file: %s", remote_path); 1064 return(-1); 1065 } 1066 1067 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 1068 size = a->size; 1069 else 1070 size = 0; 1071 1072 buflen = conn->transfer_buflen; 1073 buffer_init(&msg); 1074 1075 /* Send open request */ 1076 id = conn->msg_id++; 1077 buffer_put_char(&msg, SSH2_FXP_OPEN); 1078 buffer_put_int(&msg, id); 1079 buffer_put_cstring(&msg, remote_path); 1080 buffer_put_int(&msg, SSH2_FXF_READ); 1081 attrib_clear(&junk); /* Send empty attributes */ 1082 encode_attrib(&msg, &junk); 1083 send_msg(conn, &msg); 1084 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1085 1086 handle = get_handle(conn, id, &handle_len, 1087 "remote open(\"%s\")", remote_path); 1088 if (handle == NULL) { 1089 buffer_free(&msg); 1090 return(-1); 1091 } 1092 1093 local_fd = open(local_path, 1094 O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); 1095 if (local_fd == -1) { 1096 error("Couldn't open local file \"%s\" for writing: %s", 1097 local_path, strerror(errno)); 1098 goto fail; 1099 } 1100 offset = highwater = 0; 1101 if (resume_flag) { 1102 if (fstat(local_fd, &st) == -1) { 1103 error("Unable to stat local file \"%s\": %s", 1104 local_path, strerror(errno)); 1105 goto fail; 1106 } 1107 if (st.st_size < 0) { 1108 error("\"%s\" has negative size", local_path); 1109 goto fail; 1110 } 1111 if ((u_int64_t)st.st_size > size) { 1112 error("Unable to resume download of \"%s\": " 1113 "local file is larger than remote", local_path); 1114 fail: 1115 do_close(conn, handle, handle_len); 1116 buffer_free(&msg); 1117 free(handle); 1118 if (local_fd != -1) 1119 close(local_fd); 1120 return -1; 1121 } 1122 offset = highwater = st.st_size; 1123 } 1124 1125 /* Read from remote and write to local */ 1126 write_error = read_error = write_errno = num_req = 0; 1127 max_req = 1; 1128 progress_counter = offset; 1129 1130 if (showprogress && size != 0) 1131 start_progress_meter(remote_path, size, &progress_counter); 1132 1133 while (num_req > 0 || max_req > 0) { 1134 char *data; 1135 u_int len; 1136 1137 /* 1138 * Simulate EOF on interrupt: stop sending new requests and 1139 * allow outstanding requests to drain gracefully 1140 */ 1141 if (interrupted) { 1142 if (num_req == 0) /* If we haven't started yet... */ 1143 break; 1144 max_req = 0; 1145 } 1146 1147 /* Send some more requests */ 1148 while (num_req < max_req) { 1149 debug3("Request range %llu -> %llu (%d/%d)", 1150 (unsigned long long)offset, 1151 (unsigned long long)offset + buflen - 1, 1152 num_req, max_req); 1153 req = xcalloc(1, sizeof(*req)); 1154 req->id = conn->msg_id++; 1155 req->len = buflen; 1156 req->offset = offset; 1157 offset += buflen; 1158 num_req++; 1159 TAILQ_INSERT_TAIL(&requests, req, tq); 1160 send_read_request(conn, req->id, req->offset, 1161 req->len, handle, handle_len); 1162 } 1163 1164 buffer_clear(&msg); 1165 get_msg(conn, &msg); 1166 type = buffer_get_char(&msg); 1167 id = buffer_get_int(&msg); 1168 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1169 1170 /* Find the request in our queue */ 1171 for (req = TAILQ_FIRST(&requests); 1172 req != NULL && req->id != id; 1173 req = TAILQ_NEXT(req, tq)) 1174 ; 1175 if (req == NULL) 1176 fatal("Unexpected reply %u", id); 1177 1178 switch (type) { 1179 case SSH2_FXP_STATUS: 1180 status = buffer_get_int(&msg); 1181 if (status != SSH2_FX_EOF) 1182 read_error = 1; 1183 max_req = 0; 1184 TAILQ_REMOVE(&requests, req, tq); 1185 free(req); 1186 num_req--; 1187 break; 1188 case SSH2_FXP_DATA: 1189 data = buffer_get_string(&msg, &len); 1190 debug3("Received data %llu -> %llu", 1191 (unsigned long long)req->offset, 1192 (unsigned long long)req->offset + len - 1); 1193 if (len > req->len) 1194 fatal("Received more data than asked for " 1195 "%u > %u", len, req->len); 1196 if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || 1197 atomicio(vwrite, local_fd, data, len) != len) && 1198 !write_error) { 1199 write_errno = errno; 1200 write_error = 1; 1201 max_req = 0; 1202 } 1203 else if (!reordered && req->offset <= highwater) 1204 highwater = req->offset + len; 1205 else if (!reordered && req->offset > highwater) 1206 reordered = 1; 1207 progress_counter += len; 1208 free(data); 1209 1210 if (len == req->len) { 1211 TAILQ_REMOVE(&requests, req, tq); 1212 free(req); 1213 num_req--; 1214 } else { 1215 /* Resend the request for the missing data */ 1216 debug3("Short data block, re-requesting " 1217 "%llu -> %llu (%2d)", 1218 (unsigned long long)req->offset + len, 1219 (unsigned long long)req->offset + 1220 req->len - 1, num_req); 1221 req->id = conn->msg_id++; 1222 req->len -= len; 1223 req->offset += len; 1224 send_read_request(conn, req->id, 1225 req->offset, req->len, handle, handle_len); 1226 /* Reduce the request size */ 1227 if (len < buflen) 1228 buflen = MAX(MIN_READ_SIZE, len); 1229 } 1230 if (max_req > 0) { /* max_req = 0 iff EOF received */ 1231 if (size > 0 && offset > size) { 1232 /* Only one request at a time 1233 * after the expected EOF */ 1234 debug3("Finish at %llu (%2d)", 1235 (unsigned long long)offset, 1236 num_req); 1237 max_req = 1; 1238 } else if (max_req <= conn->num_requests) { 1239 ++max_req; 1240 } 1241 } 1242 break; 1243 default: 1244 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 1245 SSH2_FXP_DATA, type); 1246 } 1247 } 1248 1249 if (showprogress && size) 1250 stop_progress_meter(); 1251 1252 /* Sanity check */ 1253 if (TAILQ_FIRST(&requests) != NULL) 1254 fatal("Transfer complete, but requests still in queue"); 1255 /* Truncate at highest contiguous point to avoid holes on interrupt */ 1256 if (read_error || write_error || interrupted) { 1257 if (reordered && resume_flag) { 1258 error("Unable to resume download of \"%s\": " 1259 "server reordered requests", local_path); 1260 } 1261 debug("truncating at %llu", (unsigned long long)highwater); 1262 ftruncate(local_fd, highwater); 1263 } 1264 if (read_error) { 1265 error("Couldn't read from remote file \"%s\" : %s", 1266 remote_path, fx2txt(status)); 1267 status = -1; 1268 do_close(conn, handle, handle_len); 1269 } else if (write_error) { 1270 error("Couldn't write to \"%s\": %s", local_path, 1271 strerror(write_errno)); 1272 status = -1; 1273 do_close(conn, handle, handle_len); 1274 } else { 1275 status = do_close(conn, handle, handle_len); 1276 if (interrupted || status != SSH2_FX_OK) 1277 status = -1; 1278 /* Override umask and utimes if asked */ 1279 #ifdef HAVE_FCHMOD 1280 if (preserve_flag && fchmod(local_fd, mode) == -1) 1281 #else 1282 if (preserve_flag && chmod(local_path, mode) == -1) 1283 #endif /* HAVE_FCHMOD */ 1284 error("Couldn't set mode on \"%s\": %s", local_path, 1285 strerror(errno)); 1286 if (preserve_flag && 1287 (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { 1288 struct timeval tv[2]; 1289 tv[0].tv_sec = a->atime; 1290 tv[1].tv_sec = a->mtime; 1291 tv[0].tv_usec = tv[1].tv_usec = 0; 1292 if (utimes(local_path, tv) == -1) 1293 error("Can't set times on \"%s\": %s", 1294 local_path, strerror(errno)); 1295 } 1296 if (fsync_flag) { 1297 debug("syncing \"%s\"", local_path); 1298 if (fsync(local_fd) == -1) 1299 error("Couldn't sync file \"%s\": %s", 1300 local_path, strerror(errno)); 1301 } 1302 } 1303 close(local_fd); 1304 buffer_free(&msg); 1305 free(handle); 1306 1307 return(status); 1308 } 1309 1310 static int 1311 download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, 1312 Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, 1313 int fsync_flag) 1314 { 1315 int i, ret = 0; 1316 SFTP_DIRENT **dir_entries; 1317 char *filename, *new_src, *new_dst; 1318 mode_t mode = 0777; 1319 1320 if (depth >= MAX_DIR_DEPTH) { 1321 error("Maximum directory depth exceeded: %d levels", depth); 1322 return -1; 1323 } 1324 1325 if (dirattrib == NULL && 1326 (dirattrib = do_stat(conn, src, 1)) == NULL) { 1327 error("Unable to stat remote directory \"%s\"", src); 1328 return -1; 1329 } 1330 if (!S_ISDIR(dirattrib->perm)) { 1331 error("\"%s\" is not a directory", src); 1332 return -1; 1333 } 1334 if (print_flag) 1335 printf("Retrieving %s\n", src); 1336 1337 if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1338 mode = dirattrib->perm & 01777; 1339 else { 1340 debug("Server did not send permissions for " 1341 "directory \"%s\"", dst); 1342 } 1343 1344 if (mkdir(dst, mode) == -1 && errno != EEXIST) { 1345 error("mkdir %s: %s", dst, strerror(errno)); 1346 return -1; 1347 } 1348 1349 if (do_readdir(conn, src, &dir_entries) == -1) { 1350 error("%s: Failed to get directory contents", src); 1351 return -1; 1352 } 1353 1354 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 1355 filename = dir_entries[i]->filename; 1356 1357 new_dst = path_append(dst, filename); 1358 new_src = path_append(src, filename); 1359 1360 if (S_ISDIR(dir_entries[i]->a.perm)) { 1361 if (strcmp(filename, ".") == 0 || 1362 strcmp(filename, "..") == 0) 1363 continue; 1364 if (download_dir_internal(conn, new_src, new_dst, 1365 depth + 1, &(dir_entries[i]->a), preserve_flag, 1366 print_flag, resume_flag, fsync_flag) == -1) 1367 ret = -1; 1368 } else if (S_ISREG(dir_entries[i]->a.perm) ) { 1369 if (do_download(conn, new_src, new_dst, 1370 &(dir_entries[i]->a), preserve_flag, 1371 resume_flag, fsync_flag) == -1) { 1372 error("Download of file %s to %s failed", 1373 new_src, new_dst); 1374 ret = -1; 1375 } 1376 } else 1377 logit("%s: not a regular file\n", new_src); 1378 1379 free(new_dst); 1380 free(new_src); 1381 } 1382 1383 if (preserve_flag) { 1384 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1385 struct timeval tv[2]; 1386 tv[0].tv_sec = dirattrib->atime; 1387 tv[1].tv_sec = dirattrib->mtime; 1388 tv[0].tv_usec = tv[1].tv_usec = 0; 1389 if (utimes(dst, tv) == -1) 1390 error("Can't set times on \"%s\": %s", 1391 dst, strerror(errno)); 1392 } else 1393 debug("Server did not send times for directory " 1394 "\"%s\"", dst); 1395 } 1396 1397 free_sftp_dirents(dir_entries); 1398 1399 return ret; 1400 } 1401 1402 int 1403 download_dir(struct sftp_conn *conn, char *src, char *dst, 1404 Attrib *dirattrib, int preserve_flag, int print_flag, 1405 int resume_flag, int fsync_flag) 1406 { 1407 char *src_canon; 1408 int ret; 1409 1410 if ((src_canon = do_realpath(conn, src)) == NULL) { 1411 error("Unable to canonicalize path \"%s\"", src); 1412 return -1; 1413 } 1414 1415 ret = download_dir_internal(conn, src_canon, dst, 0, 1416 dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag); 1417 free(src_canon); 1418 return ret; 1419 } 1420 1421 int 1422 do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, 1423 int preserve_flag, int fsync_flag) 1424 { 1425 int local_fd; 1426 int status = SSH2_FX_OK; 1427 u_int handle_len, id, type; 1428 off_t offset, progress_counter; 1429 char *handle, *data; 1430 Buffer msg; 1431 struct stat sb; 1432 Attrib a; 1433 u_int32_t startid; 1434 u_int32_t ackid; 1435 struct outstanding_ack { 1436 u_int id; 1437 u_int len; 1438 off_t offset; 1439 TAILQ_ENTRY(outstanding_ack) tq; 1440 }; 1441 TAILQ_HEAD(ackhead, outstanding_ack) acks; 1442 struct outstanding_ack *ack = NULL; 1443 1444 TAILQ_INIT(&acks); 1445 1446 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { 1447 error("Couldn't open local file \"%s\" for reading: %s", 1448 local_path, strerror(errno)); 1449 return(-1); 1450 } 1451 if (fstat(local_fd, &sb) == -1) { 1452 error("Couldn't fstat local file \"%s\": %s", 1453 local_path, strerror(errno)); 1454 close(local_fd); 1455 return(-1); 1456 } 1457 if (!S_ISREG(sb.st_mode)) { 1458 error("%s is not a regular file", local_path); 1459 close(local_fd); 1460 return(-1); 1461 } 1462 stat_to_attrib(&sb, &a); 1463 1464 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1465 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1466 a.perm &= 0777; 1467 if (!preserve_flag) 1468 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1469 1470 buffer_init(&msg); 1471 1472 /* Send open request */ 1473 id = conn->msg_id++; 1474 buffer_put_char(&msg, SSH2_FXP_OPEN); 1475 buffer_put_int(&msg, id); 1476 buffer_put_cstring(&msg, remote_path); 1477 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1478 encode_attrib(&msg, &a); 1479 send_msg(conn, &msg); 1480 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1481 1482 buffer_clear(&msg); 1483 1484 handle = get_handle(conn, id, &handle_len, 1485 "remote open(\"%s\")", remote_path); 1486 if (handle == NULL) { 1487 close(local_fd); 1488 buffer_free(&msg); 1489 return -1; 1490 } 1491 1492 startid = ackid = id + 1; 1493 data = xmalloc(conn->transfer_buflen); 1494 1495 /* Read from local and write to remote */ 1496 offset = progress_counter = 0; 1497 if (showprogress) 1498 start_progress_meter(local_path, sb.st_size, 1499 &progress_counter); 1500 1501 for (;;) { 1502 int len; 1503 1504 /* 1505 * Can't use atomicio here because it returns 0 on EOF, 1506 * thus losing the last block of the file. 1507 * Simulate an EOF on interrupt, allowing ACKs from the 1508 * server to drain. 1509 */ 1510 if (interrupted || status != SSH2_FX_OK) 1511 len = 0; 1512 else do 1513 len = read(local_fd, data, conn->transfer_buflen); 1514 while ((len == -1) && 1515 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); 1516 1517 if (len == -1) 1518 fatal("Couldn't read from \"%s\": %s", local_path, 1519 strerror(errno)); 1520 1521 if (len != 0) { 1522 ack = xcalloc(1, sizeof(*ack)); 1523 ack->id = ++id; 1524 ack->offset = offset; 1525 ack->len = len; 1526 TAILQ_INSERT_TAIL(&acks, ack, tq); 1527 1528 buffer_clear(&msg); 1529 buffer_put_char(&msg, SSH2_FXP_WRITE); 1530 buffer_put_int(&msg, ack->id); 1531 buffer_put_string(&msg, handle, handle_len); 1532 buffer_put_int64(&msg, offset); 1533 buffer_put_string(&msg, data, len); 1534 send_msg(conn, &msg); 1535 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1536 id, (unsigned long long)offset, len); 1537 } else if (TAILQ_FIRST(&acks) == NULL) 1538 break; 1539 1540 if (ack == NULL) 1541 fatal("Unexpected ACK %u", id); 1542 1543 if (id == startid || len == 0 || 1544 id - ackid >= conn->num_requests) { 1545 u_int r_id; 1546 1547 buffer_clear(&msg); 1548 get_msg(conn, &msg); 1549 type = buffer_get_char(&msg); 1550 r_id = buffer_get_int(&msg); 1551 1552 if (type != SSH2_FXP_STATUS) 1553 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 1554 "got %d", SSH2_FXP_STATUS, type); 1555 1556 status = buffer_get_int(&msg); 1557 debug3("SSH2_FXP_STATUS %d", status); 1558 1559 /* Find the request in our queue */ 1560 for (ack = TAILQ_FIRST(&acks); 1561 ack != NULL && ack->id != r_id; 1562 ack = TAILQ_NEXT(ack, tq)) 1563 ; 1564 if (ack == NULL) 1565 fatal("Can't find request for ID %u", r_id); 1566 TAILQ_REMOVE(&acks, ack, tq); 1567 debug3("In write loop, ack for %u %u bytes at %lld", 1568 ack->id, ack->len, (long long)ack->offset); 1569 ++ackid; 1570 progress_counter += ack->len; 1571 free(ack); 1572 } 1573 offset += len; 1574 if (offset < 0) 1575 fatal("%s: offset < 0", __func__); 1576 } 1577 buffer_free(&msg); 1578 1579 if (showprogress) 1580 stop_progress_meter(); 1581 free(data); 1582 1583 if (status != SSH2_FX_OK) { 1584 error("Couldn't write to remote file \"%s\": %s", 1585 remote_path, fx2txt(status)); 1586 status = -1; 1587 } 1588 1589 if (close(local_fd) == -1) { 1590 error("Couldn't close local file \"%s\": %s", local_path, 1591 strerror(errno)); 1592 status = -1; 1593 } 1594 1595 /* Override umask and utimes if asked */ 1596 if (preserve_flag) 1597 do_fsetstat(conn, handle, handle_len, &a); 1598 1599 if (fsync_flag) 1600 (void)do_fsync(conn, handle, handle_len); 1601 1602 if (do_close(conn, handle, handle_len) != SSH2_FX_OK) 1603 status = -1; 1604 free(handle); 1605 1606 return status; 1607 } 1608 1609 static int 1610 upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, 1611 int preserve_flag, int print_flag, int fsync_flag) 1612 { 1613 int ret = 0, status; 1614 DIR *dirp; 1615 struct dirent *dp; 1616 char *filename, *new_src, *new_dst; 1617 struct stat sb; 1618 Attrib a; 1619 1620 if (depth >= MAX_DIR_DEPTH) { 1621 error("Maximum directory depth exceeded: %d levels", depth); 1622 return -1; 1623 } 1624 1625 if (stat(src, &sb) == -1) { 1626 error("Couldn't stat directory \"%s\": %s", 1627 src, strerror(errno)); 1628 return -1; 1629 } 1630 if (!S_ISDIR(sb.st_mode)) { 1631 error("\"%s\" is not a directory", src); 1632 return -1; 1633 } 1634 if (print_flag) 1635 printf("Entering %s\n", src); 1636 1637 attrib_clear(&a); 1638 stat_to_attrib(&sb, &a); 1639 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1640 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1641 a.perm &= 01777; 1642 if (!preserve_flag) 1643 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1644 1645 status = do_mkdir(conn, dst, &a, 0); 1646 /* 1647 * we lack a portable status for errno EEXIST, 1648 * so if we get a SSH2_FX_FAILURE back we must check 1649 * if it was created successfully. 1650 */ 1651 if (status != SSH2_FX_OK) { 1652 if (status != SSH2_FX_FAILURE) 1653 return -1; 1654 if (do_stat(conn, dst, 0) == NULL) 1655 return -1; 1656 } 1657 1658 if ((dirp = opendir(src)) == NULL) { 1659 error("Failed to open dir \"%s\": %s", src, strerror(errno)); 1660 return -1; 1661 } 1662 1663 while (((dp = readdir(dirp)) != NULL) && !interrupted) { 1664 if (dp->d_ino == 0) 1665 continue; 1666 filename = dp->d_name; 1667 new_dst = path_append(dst, filename); 1668 new_src = path_append(src, filename); 1669 1670 if (lstat(new_src, &sb) == -1) { 1671 logit("%s: lstat failed: %s", filename, 1672 strerror(errno)); 1673 ret = -1; 1674 } else if (S_ISDIR(sb.st_mode)) { 1675 if (strcmp(filename, ".") == 0 || 1676 strcmp(filename, "..") == 0) 1677 continue; 1678 1679 if (upload_dir_internal(conn, new_src, new_dst, 1680 depth + 1, preserve_flag, print_flag, 1681 fsync_flag) == -1) 1682 ret = -1; 1683 } else if (S_ISREG(sb.st_mode)) { 1684 if (do_upload(conn, new_src, new_dst, 1685 preserve_flag, fsync_flag) == -1) { 1686 error("Uploading of file %s to %s failed!", 1687 new_src, new_dst); 1688 ret = -1; 1689 } 1690 } else 1691 logit("%s: not a regular file\n", filename); 1692 free(new_dst); 1693 free(new_src); 1694 } 1695 1696 do_setstat(conn, dst, &a); 1697 1698 (void) closedir(dirp); 1699 return ret; 1700 } 1701 1702 int 1703 upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, 1704 int print_flag, int fsync_flag) 1705 { 1706 char *dst_canon; 1707 int ret; 1708 1709 if ((dst_canon = do_realpath(conn, dst)) == NULL) { 1710 error("Unable to canonicalize path \"%s\"", dst); 1711 return -1; 1712 } 1713 1714 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 1715 print_flag, fsync_flag); 1716 1717 free(dst_canon); 1718 return ret; 1719 } 1720 1721 char * 1722 path_append(char *p1, char *p2) 1723 { 1724 char *ret; 1725 size_t len = strlen(p1) + strlen(p2) + 2; 1726 1727 ret = xmalloc(len); 1728 strlcpy(ret, p1, len); 1729 if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') 1730 strlcat(ret, "/", len); 1731 strlcat(ret, p2, len); 1732 1733 return(ret); 1734 } 1735 1736