1 /* $OpenBSD: sftp-client.c,v 1.164 2022/05/15 23:47:21 djm 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 <sys/types.h> 24 #include <sys/poll.h> 25 #include <sys/queue.h> 26 #include <sys/stat.h> 27 #include <sys/time.h> 28 #include <sys/statvfs.h> 29 #include <sys/uio.h> 30 31 #include <dirent.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <poll.h> 35 #include <signal.h> 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 42 #include "xmalloc.h" 43 #include "ssherr.h" 44 #include "sshbuf.h" 45 #include "log.h" 46 #include "atomicio.h" 47 #include "progressmeter.h" 48 #include "misc.h" 49 #include "utf8.h" 50 51 #include "sftp.h" 52 #include "sftp-common.h" 53 #include "sftp-client.h" 54 55 extern volatile sig_atomic_t interrupted; 56 extern int showprogress; 57 58 /* Default size of buffer for up/download */ 59 #define DEFAULT_COPY_BUFLEN 32768 60 61 /* Default number of concurrent outstanding requests */ 62 #define DEFAULT_NUM_REQUESTS 64 63 64 /* Minimum amount of data to read at a time */ 65 #define MIN_READ_SIZE 512 66 67 /* Maximum depth to descend in directory trees */ 68 #define MAX_DIR_DEPTH 64 69 70 struct sftp_conn { 71 int fd_in; 72 int fd_out; 73 u_int download_buflen; 74 u_int upload_buflen; 75 u_int num_requests; 76 u_int version; 77 u_int msg_id; 78 #define SFTP_EXT_POSIX_RENAME 0x00000001 79 #define SFTP_EXT_STATVFS 0x00000002 80 #define SFTP_EXT_FSTATVFS 0x00000004 81 #define SFTP_EXT_HARDLINK 0x00000008 82 #define SFTP_EXT_FSYNC 0x00000010 83 #define SFTP_EXT_LSETSTAT 0x00000020 84 #define SFTP_EXT_LIMITS 0x00000040 85 #define SFTP_EXT_PATH_EXPAND 0x00000080 86 #define SFTP_EXT_COPY_DATA 0x00000100 87 u_int exts; 88 u_int64_t limit_kbps; 89 struct bwlimit bwlimit_in, bwlimit_out; 90 }; 91 92 /* Tracks in-progress requests during file transfers */ 93 struct request { 94 u_int id; 95 size_t len; 96 u_int64_t offset; 97 TAILQ_ENTRY(request) tq; 98 }; 99 TAILQ_HEAD(requests, request); 100 101 static u_char * 102 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 103 const char *errfmt, ...) __attribute__((format(printf, 4, 5))); 104 105 static struct request * 106 request_enqueue(struct requests *requests, u_int id, size_t len, 107 uint64_t offset) 108 { 109 struct request *req; 110 111 req = xcalloc(1, sizeof(*req)); 112 req->id = id; 113 req->len = len; 114 req->offset = offset; 115 TAILQ_INSERT_TAIL(requests, req, tq); 116 return req; 117 } 118 119 static struct request * 120 request_find(struct requests *requests, u_int id) 121 { 122 struct request *req; 123 124 for (req = TAILQ_FIRST(requests); 125 req != NULL && req->id != id; 126 req = TAILQ_NEXT(req, tq)) 127 ; 128 return req; 129 } 130 131 /* ARGSUSED */ 132 static int 133 sftpio(void *_bwlimit, size_t amount) 134 { 135 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; 136 137 refresh_progress_meter(0); 138 if (bwlimit != NULL) 139 bandwidth_limit(bwlimit, amount); 140 return 0; 141 } 142 143 static void 144 send_msg(struct sftp_conn *conn, struct sshbuf *m) 145 { 146 u_char mlen[4]; 147 struct iovec iov[2]; 148 149 if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) 150 fatal("Outbound message too long %zu", sshbuf_len(m)); 151 152 /* Send length first */ 153 put_u32(mlen, sshbuf_len(m)); 154 iov[0].iov_base = mlen; 155 iov[0].iov_len = sizeof(mlen); 156 iov[1].iov_base = (u_char *)sshbuf_ptr(m); 157 iov[1].iov_len = sshbuf_len(m); 158 159 if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, 160 conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) != 161 sshbuf_len(m) + sizeof(mlen)) 162 fatal("Couldn't send packet: %s", strerror(errno)); 163 164 sshbuf_reset(m); 165 } 166 167 static void 168 get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) 169 { 170 u_int msg_len; 171 u_char *p; 172 int r; 173 174 sshbuf_reset(m); 175 if ((r = sshbuf_reserve(m, 4, &p)) != 0) 176 fatal_fr(r, "reserve"); 177 if (atomicio6(read, conn->fd_in, p, 4, sftpio, 178 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) { 179 if (errno == EPIPE || errno == ECONNRESET) 180 fatal("Connection closed"); 181 else 182 fatal("Couldn't read packet: %s", strerror(errno)); 183 } 184 185 if ((r = sshbuf_get_u32(m, &msg_len)) != 0) 186 fatal_fr(r, "sshbuf_get_u32"); 187 if (msg_len > SFTP_MAX_MSG_LENGTH) { 188 do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL, 189 "Received message too long %u", msg_len); 190 fatal("Ensure the remote shell produces no output " 191 "for non-interactive sessions."); 192 } 193 194 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) 195 fatal_fr(r, "reserve"); 196 if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, 197 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) 198 != msg_len) { 199 if (errno == EPIPE) 200 fatal("Connection closed"); 201 else 202 fatal("Read packet: %s", strerror(errno)); 203 } 204 } 205 206 static void 207 get_msg(struct sftp_conn *conn, struct sshbuf *m) 208 { 209 get_msg_extended(conn, m, 0); 210 } 211 212 static void 213 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, 214 u_int len) 215 { 216 struct sshbuf *msg; 217 int r; 218 219 if ((msg = sshbuf_new()) == NULL) 220 fatal_f("sshbuf_new failed"); 221 if ((r = sshbuf_put_u8(msg, code)) != 0 || 222 (r = sshbuf_put_u32(msg, id)) != 0 || 223 (r = sshbuf_put_string(msg, s, len)) != 0) 224 fatal_fr(r, "compose"); 225 send_msg(conn, msg); 226 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 227 sshbuf_free(msg); 228 } 229 230 static void 231 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, 232 const void *s, u_int len, Attrib *a) 233 { 234 struct sshbuf *msg; 235 int r; 236 237 if ((msg = sshbuf_new()) == NULL) 238 fatal_f("sshbuf_new failed"); 239 if ((r = sshbuf_put_u8(msg, code)) != 0 || 240 (r = sshbuf_put_u32(msg, id)) != 0 || 241 (r = sshbuf_put_string(msg, s, len)) != 0 || 242 (r = encode_attrib(msg, a)) != 0) 243 fatal_fr(r, "compose"); 244 send_msg(conn, msg); 245 debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o", 246 conn->fd_out, code, id, a->flags, a->perm); 247 sshbuf_free(msg); 248 } 249 250 static u_int 251 get_status(struct sftp_conn *conn, u_int expected_id) 252 { 253 struct sshbuf *msg; 254 u_char type; 255 u_int id, status; 256 int r; 257 258 if ((msg = sshbuf_new()) == NULL) 259 fatal_f("sshbuf_new failed"); 260 get_msg(conn, msg); 261 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 262 (r = sshbuf_get_u32(msg, &id)) != 0) 263 fatal_fr(r, "compose"); 264 265 if (id != expected_id) 266 fatal("ID mismatch (%u != %u)", id, expected_id); 267 if (type != SSH2_FXP_STATUS) 268 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", 269 SSH2_FXP_STATUS, type); 270 271 if ((r = sshbuf_get_u32(msg, &status)) != 0) 272 fatal_fr(r, "parse"); 273 sshbuf_free(msg); 274 275 debug3("SSH2_FXP_STATUS %u", status); 276 277 return status; 278 } 279 280 static u_char * 281 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 282 const char *errfmt, ...) 283 { 284 struct sshbuf *msg; 285 u_int id, status; 286 u_char type; 287 u_char *handle; 288 char errmsg[256]; 289 va_list args; 290 int r; 291 292 va_start(args, errfmt); 293 if (errfmt != NULL) 294 vsnprintf(errmsg, sizeof(errmsg), errfmt, args); 295 va_end(args); 296 297 if ((msg = sshbuf_new()) == NULL) 298 fatal_f("sshbuf_new failed"); 299 get_msg(conn, msg); 300 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 301 (r = sshbuf_get_u32(msg, &id)) != 0) 302 fatal_fr(r, "parse"); 303 304 if (id != expected_id) 305 fatal("%s: ID mismatch (%u != %u)", 306 errfmt == NULL ? __func__ : errmsg, id, expected_id); 307 if (type == SSH2_FXP_STATUS) { 308 if ((r = sshbuf_get_u32(msg, &status)) != 0) 309 fatal_fr(r, "parse status"); 310 if (errfmt != NULL) 311 error("%s: %s", errmsg, fx2txt(status)); 312 sshbuf_free(msg); 313 return(NULL); 314 } else if (type != SSH2_FXP_HANDLE) 315 fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", 316 errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); 317 318 if ((r = sshbuf_get_string(msg, &handle, len)) != 0) 319 fatal_fr(r, "parse handle"); 320 sshbuf_free(msg); 321 322 return handle; 323 } 324 325 /* XXX returning &static is error-prone. Refactor to fill *Attrib argument */ 326 static Attrib * 327 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) 328 { 329 struct sshbuf *msg; 330 u_int id; 331 u_char type; 332 int r; 333 static Attrib a; 334 335 if ((msg = sshbuf_new()) == NULL) 336 fatal_f("sshbuf_new failed"); 337 get_msg(conn, msg); 338 339 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 340 (r = sshbuf_get_u32(msg, &id)) != 0) 341 fatal_fr(r, "parse"); 342 343 if (id != expected_id) 344 fatal("ID mismatch (%u != %u)", id, expected_id); 345 if (type == SSH2_FXP_STATUS) { 346 u_int status; 347 348 if ((r = sshbuf_get_u32(msg, &status)) != 0) 349 fatal_fr(r, "parse status"); 350 if (quiet) 351 debug("stat remote: %s", fx2txt(status)); 352 else 353 error("stat remote: %s", fx2txt(status)); 354 sshbuf_free(msg); 355 return(NULL); 356 } else if (type != SSH2_FXP_ATTRS) { 357 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", 358 SSH2_FXP_ATTRS, type); 359 } 360 if ((r = decode_attrib(msg, &a)) != 0) { 361 error_fr(r, "decode_attrib"); 362 sshbuf_free(msg); 363 return NULL; 364 } 365 debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o", 366 type, id, a.flags, a.perm); 367 sshbuf_free(msg); 368 369 return &a; 370 } 371 372 static int 373 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, 374 u_int expected_id, int quiet) 375 { 376 struct sshbuf *msg; 377 u_char type; 378 u_int id; 379 u_int64_t flag; 380 int r; 381 382 if ((msg = sshbuf_new()) == NULL) 383 fatal_f("sshbuf_new failed"); 384 get_msg(conn, msg); 385 386 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 387 (r = sshbuf_get_u32(msg, &id)) != 0) 388 fatal_fr(r, "parse"); 389 390 debug3("Received statvfs reply T:%u I:%u", type, id); 391 if (id != expected_id) 392 fatal("ID mismatch (%u != %u)", id, expected_id); 393 if (type == SSH2_FXP_STATUS) { 394 u_int status; 395 396 if ((r = sshbuf_get_u32(msg, &status)) != 0) 397 fatal_fr(r, "parse status"); 398 if (quiet) 399 debug("remote statvfs: %s", fx2txt(status)); 400 else 401 error("remote statvfs: %s", fx2txt(status)); 402 sshbuf_free(msg); 403 return -1; 404 } else if (type != SSH2_FXP_EXTENDED_REPLY) { 405 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 406 SSH2_FXP_EXTENDED_REPLY, type); 407 } 408 409 memset(st, 0, sizeof(*st)); 410 if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || 411 (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || 412 (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || 413 (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || 414 (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || 415 (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || 416 (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || 417 (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || 418 (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || 419 (r = sshbuf_get_u64(msg, &flag)) != 0 || 420 (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) 421 fatal_fr(r, "parse statvfs"); 422 423 st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; 424 st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; 425 426 sshbuf_free(msg); 427 428 return 0; 429 } 430 431 struct sftp_conn * 432 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, 433 u_int64_t limit_kbps) 434 { 435 u_char type; 436 struct sshbuf *msg; 437 struct sftp_conn *ret; 438 int r; 439 440 ret = xcalloc(1, sizeof(*ret)); 441 ret->msg_id = 1; 442 ret->fd_in = fd_in; 443 ret->fd_out = fd_out; 444 ret->download_buflen = ret->upload_buflen = 445 transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN; 446 ret->num_requests = 447 num_requests ? num_requests : DEFAULT_NUM_REQUESTS; 448 ret->exts = 0; 449 ret->limit_kbps = 0; 450 451 if ((msg = sshbuf_new()) == NULL) 452 fatal_f("sshbuf_new failed"); 453 if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || 454 (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) 455 fatal_fr(r, "parse"); 456 457 send_msg(ret, msg); 458 459 get_msg_extended(ret, msg, 1); 460 461 /* Expecting a VERSION reply */ 462 if ((r = sshbuf_get_u8(msg, &type)) != 0) 463 fatal_fr(r, "parse type"); 464 if (type != SSH2_FXP_VERSION) { 465 error("Invalid packet back from SSH2_FXP_INIT (type %u)", 466 type); 467 sshbuf_free(msg); 468 free(ret); 469 return(NULL); 470 } 471 if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) 472 fatal_fr(r, "parse version"); 473 474 debug2("Remote version: %u", ret->version); 475 476 /* Check for extensions */ 477 while (sshbuf_len(msg) > 0) { 478 char *name; 479 u_char *value; 480 size_t vlen; 481 int known = 0; 482 483 if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || 484 (r = sshbuf_get_string(msg, &value, &vlen)) != 0) 485 fatal_fr(r, "parse extension"); 486 if (strcmp(name, "posix-rename@openssh.com") == 0 && 487 strcmp((char *)value, "1") == 0) { 488 ret->exts |= SFTP_EXT_POSIX_RENAME; 489 known = 1; 490 } else if (strcmp(name, "statvfs@openssh.com") == 0 && 491 strcmp((char *)value, "2") == 0) { 492 ret->exts |= SFTP_EXT_STATVFS; 493 known = 1; 494 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && 495 strcmp((char *)value, "2") == 0) { 496 ret->exts |= SFTP_EXT_FSTATVFS; 497 known = 1; 498 } else if (strcmp(name, "hardlink@openssh.com") == 0 && 499 strcmp((char *)value, "1") == 0) { 500 ret->exts |= SFTP_EXT_HARDLINK; 501 known = 1; 502 } else if (strcmp(name, "fsync@openssh.com") == 0 && 503 strcmp((char *)value, "1") == 0) { 504 ret->exts |= SFTP_EXT_FSYNC; 505 known = 1; 506 } else if (strcmp(name, "lsetstat@openssh.com") == 0 && 507 strcmp((char *)value, "1") == 0) { 508 ret->exts |= SFTP_EXT_LSETSTAT; 509 known = 1; 510 } else if (strcmp(name, "limits@openssh.com") == 0 && 511 strcmp((char *)value, "1") == 0) { 512 ret->exts |= SFTP_EXT_LIMITS; 513 known = 1; 514 } else if (strcmp(name, "expand-path@openssh.com") == 0 && 515 strcmp((char *)value, "1") == 0) { 516 ret->exts |= SFTP_EXT_PATH_EXPAND; 517 known = 1; 518 } else if (strcmp(name, "copy-data") == 0 && 519 strcmp((char *)value, "1") == 0) { 520 ret->exts |= SFTP_EXT_COPY_DATA; 521 known = 1; 522 } 523 if (known) { 524 debug2("Server supports extension \"%s\" revision %s", 525 name, value); 526 } else { 527 debug2("Unrecognised server extension \"%s\"", name); 528 } 529 free(name); 530 free(value); 531 } 532 533 sshbuf_free(msg); 534 535 /* Query the server for its limits */ 536 if (ret->exts & SFTP_EXT_LIMITS) { 537 struct sftp_limits limits; 538 if (do_limits(ret, &limits) != 0) 539 fatal_f("limits failed"); 540 541 /* If the caller did not specify, find a good value */ 542 if (transfer_buflen == 0) { 543 ret->download_buflen = limits.read_length; 544 ret->upload_buflen = limits.write_length; 545 debug("Using server download size %u", ret->download_buflen); 546 debug("Using server upload size %u", ret->upload_buflen); 547 } 548 549 /* Use the server limit to scale down our value only */ 550 if (num_requests == 0 && limits.open_handles) { 551 ret->num_requests = 552 MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles); 553 debug("Server handle limit %llu; using %u", 554 (unsigned long long)limits.open_handles, 555 ret->num_requests); 556 } 557 } 558 559 /* Some filexfer v.0 servers don't support large packets */ 560 if (ret->version == 0) { 561 ret->download_buflen = MINIMUM(ret->download_buflen, 20480); 562 ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480); 563 } 564 565 ret->limit_kbps = limit_kbps; 566 if (ret->limit_kbps > 0) { 567 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps, 568 ret->download_buflen); 569 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps, 570 ret->upload_buflen); 571 } 572 573 return ret; 574 } 575 576 u_int 577 sftp_proto_version(struct sftp_conn *conn) 578 { 579 return conn->version; 580 } 581 582 int 583 do_limits(struct sftp_conn *conn, struct sftp_limits *limits) 584 { 585 u_int id, msg_id; 586 u_char type; 587 struct sshbuf *msg; 588 int r; 589 590 if ((conn->exts & SFTP_EXT_LIMITS) == 0) { 591 error("Server does not support limits@openssh.com extension"); 592 return -1; 593 } 594 595 if ((msg = sshbuf_new()) == NULL) 596 fatal_f("sshbuf_new failed"); 597 598 id = conn->msg_id++; 599 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 600 (r = sshbuf_put_u32(msg, id)) != 0 || 601 (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0) 602 fatal_fr(r, "compose"); 603 send_msg(conn, msg); 604 debug3("Sent message limits@openssh.com I:%u", id); 605 606 get_msg(conn, msg); 607 608 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 609 (r = sshbuf_get_u32(msg, &msg_id)) != 0) 610 fatal_fr(r, "parse"); 611 612 debug3("Received limits reply T:%u I:%u", type, msg_id); 613 if (id != msg_id) 614 fatal("ID mismatch (%u != %u)", msg_id, id); 615 if (type != SSH2_FXP_EXTENDED_REPLY) { 616 debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 617 SSH2_FXP_EXTENDED_REPLY, type); 618 /* Disable the limits extension */ 619 conn->exts &= ~SFTP_EXT_LIMITS; 620 sshbuf_free(msg); 621 return 0; 622 } 623 624 memset(limits, 0, sizeof(*limits)); 625 if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 || 626 (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 || 627 (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 || 628 (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0) 629 fatal_fr(r, "parse limits"); 630 631 sshbuf_free(msg); 632 633 return 0; 634 } 635 636 int 637 do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) 638 { 639 u_int id, status; 640 struct sshbuf *msg; 641 int r; 642 643 if ((msg = sshbuf_new()) == NULL) 644 fatal_f("sshbuf_new failed"); 645 646 id = conn->msg_id++; 647 if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || 648 (r = sshbuf_put_u32(msg, id)) != 0 || 649 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 650 fatal_fr(r, "parse"); 651 send_msg(conn, msg); 652 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 653 654 status = get_status(conn, id); 655 if (status != SSH2_FX_OK) 656 error("close remote: %s", fx2txt(status)); 657 658 sshbuf_free(msg); 659 660 return status == SSH2_FX_OK ? 0 : -1; 661 } 662 663 664 static int 665 do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, 666 SFTP_DIRENT ***dir) 667 { 668 struct sshbuf *msg; 669 u_int count, id, i, expected_id, ents = 0; 670 size_t handle_len; 671 u_char type, *handle; 672 int status = SSH2_FX_FAILURE; 673 int r; 674 675 if (dir) 676 *dir = NULL; 677 678 id = conn->msg_id++; 679 680 if ((msg = sshbuf_new()) == NULL) 681 fatal_f("sshbuf_new failed"); 682 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || 683 (r = sshbuf_put_u32(msg, id)) != 0 || 684 (r = sshbuf_put_cstring(msg, path)) != 0) 685 fatal_fr(r, "compose OPENDIR"); 686 send_msg(conn, msg); 687 688 handle = get_handle(conn, id, &handle_len, 689 "remote readdir(\"%s\")", path); 690 if (handle == NULL) { 691 sshbuf_free(msg); 692 return -1; 693 } 694 695 if (dir) { 696 ents = 0; 697 *dir = xcalloc(1, sizeof(**dir)); 698 (*dir)[0] = NULL; 699 } 700 701 for (; !interrupted;) { 702 id = expected_id = conn->msg_id++; 703 704 debug3("Sending SSH2_FXP_READDIR I:%u", id); 705 706 sshbuf_reset(msg); 707 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || 708 (r = sshbuf_put_u32(msg, id)) != 0 || 709 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 710 fatal_fr(r, "compose READDIR"); 711 send_msg(conn, msg); 712 713 sshbuf_reset(msg); 714 715 get_msg(conn, msg); 716 717 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 718 (r = sshbuf_get_u32(msg, &id)) != 0) 719 fatal_fr(r, "parse"); 720 721 debug3("Received reply T:%u I:%u", type, id); 722 723 if (id != expected_id) 724 fatal("ID mismatch (%u != %u)", id, expected_id); 725 726 if (type == SSH2_FXP_STATUS) { 727 u_int rstatus; 728 729 if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) 730 fatal_fr(r, "parse status"); 731 debug3("Received SSH2_FXP_STATUS %d", rstatus); 732 if (rstatus == SSH2_FX_EOF) 733 break; 734 error("Couldn't read directory: %s", fx2txt(rstatus)); 735 goto out; 736 } else if (type != SSH2_FXP_NAME) 737 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 738 SSH2_FXP_NAME, type); 739 740 if ((r = sshbuf_get_u32(msg, &count)) != 0) 741 fatal_fr(r, "parse count"); 742 if (count > SSHBUF_SIZE_MAX) 743 fatal_f("nonsensical number of entries"); 744 if (count == 0) 745 break; 746 debug3("Received %d SSH2_FXP_NAME responses", count); 747 for (i = 0; i < count; i++) { 748 char *filename, *longname; 749 Attrib a; 750 751 if ((r = sshbuf_get_cstring(msg, &filename, 752 NULL)) != 0 || 753 (r = sshbuf_get_cstring(msg, &longname, 754 NULL)) != 0) 755 fatal_fr(r, "parse filenames"); 756 if ((r = decode_attrib(msg, &a)) != 0) { 757 error_fr(r, "couldn't decode attrib"); 758 free(filename); 759 free(longname); 760 goto out; 761 } 762 763 if (print_flag) 764 mprintf("%s\n", longname); 765 766 /* 767 * Directory entries should never contain '/' 768 * These can be used to attack recursive ops 769 * (e.g. send '../../../../etc/passwd') 770 */ 771 if (strchr(filename, '/') != NULL) { 772 error("Server sent suspect path \"%s\" " 773 "during readdir of \"%s\"", filename, path); 774 } else if (dir) { 775 *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); 776 (*dir)[ents] = xcalloc(1, sizeof(***dir)); 777 (*dir)[ents]->filename = xstrdup(filename); 778 (*dir)[ents]->longname = xstrdup(longname); 779 memcpy(&(*dir)[ents]->a, &a, sizeof(a)); 780 (*dir)[++ents] = NULL; 781 } 782 free(filename); 783 free(longname); 784 } 785 } 786 status = 0; 787 788 out: 789 sshbuf_free(msg); 790 do_close(conn, handle, handle_len); 791 free(handle); 792 793 if (status != 0 && dir != NULL) { 794 /* Don't return results on error */ 795 free_sftp_dirents(*dir); 796 *dir = NULL; 797 } else if (interrupted && dir != NULL && *dir != NULL) { 798 /* Don't return partial matches on interrupt */ 799 free_sftp_dirents(*dir); 800 *dir = xcalloc(1, sizeof(**dir)); 801 **dir = NULL; 802 } 803 804 return status == SSH2_FX_OK ? 0 : -1; 805 } 806 807 int 808 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) 809 { 810 return(do_lsreaddir(conn, path, 0, dir)); 811 } 812 813 void free_sftp_dirents(SFTP_DIRENT **s) 814 { 815 int i; 816 817 if (s == NULL) 818 return; 819 for (i = 0; s[i]; i++) { 820 free(s[i]->filename); 821 free(s[i]->longname); 822 free(s[i]); 823 } 824 free(s); 825 } 826 827 int 828 do_rm(struct sftp_conn *conn, const char *path) 829 { 830 u_int status, id; 831 832 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 833 834 id = conn->msg_id++; 835 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); 836 status = get_status(conn, id); 837 if (status != SSH2_FX_OK) 838 error("remote delete %s: %s", path, fx2txt(status)); 839 return status == SSH2_FX_OK ? 0 : -1; 840 } 841 842 int 843 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) 844 { 845 u_int status, id; 846 847 debug2("Sending SSH2_FXP_MKDIR \"%s\"", path); 848 849 id = conn->msg_id++; 850 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, 851 strlen(path), a); 852 853 status = get_status(conn, id); 854 if (status != SSH2_FX_OK && print_flag) 855 error("remote mkdir \"%s\": %s", path, fx2txt(status)); 856 857 return status == SSH2_FX_OK ? 0 : -1; 858 } 859 860 int 861 do_rmdir(struct sftp_conn *conn, const char *path) 862 { 863 u_int status, id; 864 865 debug2("Sending SSH2_FXP_RMDIR \"%s\"", path); 866 867 id = conn->msg_id++; 868 send_string_request(conn, id, SSH2_FXP_RMDIR, path, 869 strlen(path)); 870 871 status = get_status(conn, id); 872 if (status != SSH2_FX_OK) 873 error("remote rmdir \"%s\": %s", path, fx2txt(status)); 874 875 return status == SSH2_FX_OK ? 0 : -1; 876 } 877 878 Attrib * 879 do_stat(struct sftp_conn *conn, const char *path, int quiet) 880 { 881 u_int id; 882 883 debug2("Sending SSH2_FXP_STAT \"%s\"", path); 884 885 id = conn->msg_id++; 886 887 send_string_request(conn, id, 888 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 889 path, strlen(path)); 890 891 return(get_decode_stat(conn, id, quiet)); 892 } 893 894 Attrib * 895 do_lstat(struct sftp_conn *conn, const char *path, int quiet) 896 { 897 u_int id; 898 899 if (conn->version == 0) { 900 if (quiet) 901 debug("Server version does not support lstat operation"); 902 else 903 logit("Server version does not support lstat operation"); 904 return(do_stat(conn, path, quiet)); 905 } 906 907 id = conn->msg_id++; 908 send_string_request(conn, id, SSH2_FXP_LSTAT, path, 909 strlen(path)); 910 911 return(get_decode_stat(conn, id, quiet)); 912 } 913 914 #ifdef notyet 915 Attrib * 916 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 917 int quiet) 918 { 919 u_int id; 920 921 debug2("Sending SSH2_FXP_FSTAT \"%s\""); 922 923 id = conn->msg_id++; 924 send_string_request(conn, id, SSH2_FXP_FSTAT, handle, 925 handle_len); 926 927 return(get_decode_stat(conn, id, quiet)); 928 } 929 #endif 930 931 int 932 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) 933 { 934 u_int status, id; 935 936 debug2("Sending SSH2_FXP_SETSTAT \"%s\"", path); 937 938 id = conn->msg_id++; 939 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, 940 strlen(path), a); 941 942 status = get_status(conn, id); 943 if (status != SSH2_FX_OK) 944 error("remote setstat \"%s\": %s", path, fx2txt(status)); 945 946 return status == SSH2_FX_OK ? 0 : -1; 947 } 948 949 int 950 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 951 Attrib *a) 952 { 953 u_int status, id; 954 955 debug2("Sending SSH2_FXP_FSETSTAT"); 956 957 id = conn->msg_id++; 958 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, 959 handle_len, a); 960 961 status = get_status(conn, id); 962 if (status != SSH2_FX_OK) 963 error("remote fsetstat: %s", fx2txt(status)); 964 965 return status == SSH2_FX_OK ? 0 : -1; 966 } 967 968 /* Implements both the realpath and expand-path operations */ 969 static char * 970 do_realpath_expand(struct sftp_conn *conn, const char *path, int expand) 971 { 972 struct sshbuf *msg; 973 u_int expected_id, count, id; 974 char *filename, *longname; 975 Attrib a; 976 u_char type; 977 int r; 978 const char *what = "SSH2_FXP_REALPATH"; 979 980 if (expand) 981 what = "expand-path@openssh.com"; 982 if ((msg = sshbuf_new()) == NULL) 983 fatal_f("sshbuf_new failed"); 984 985 expected_id = id = conn->msg_id++; 986 if (expand) { 987 debug2("Sending SSH2_FXP_EXTENDED(expand-path@openssh.com) " 988 "\"%s\"", path); 989 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 990 (r = sshbuf_put_u32(msg, id)) != 0 || 991 (r = sshbuf_put_cstring(msg, 992 "expand-path@openssh.com")) != 0 || 993 (r = sshbuf_put_cstring(msg, path)) != 0) 994 fatal_fr(r, "compose %s", what); 995 send_msg(conn, msg); 996 } else { 997 debug2("Sending SSH2_FXP_REALPATH \"%s\"", path); 998 send_string_request(conn, id, SSH2_FXP_REALPATH, 999 path, strlen(path)); 1000 } 1001 get_msg(conn, msg); 1002 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1003 (r = sshbuf_get_u32(msg, &id)) != 0) 1004 fatal_fr(r, "parse"); 1005 1006 if (id != expected_id) 1007 fatal("ID mismatch (%u != %u)", id, expected_id); 1008 1009 if (type == SSH2_FXP_STATUS) { 1010 u_int status; 1011 char *errmsg; 1012 1013 if ((r = sshbuf_get_u32(msg, &status)) != 0 || 1014 (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) 1015 fatal_fr(r, "parse status"); 1016 error("%s %s: %s", expand ? "expand" : "realpath", 1017 path, *errmsg == '\0' ? fx2txt(status) : errmsg); 1018 free(errmsg); 1019 sshbuf_free(msg); 1020 return NULL; 1021 } else if (type != SSH2_FXP_NAME) 1022 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 1023 SSH2_FXP_NAME, type); 1024 1025 if ((r = sshbuf_get_u32(msg, &count)) != 0) 1026 fatal_fr(r, "parse count"); 1027 if (count != 1) 1028 fatal("Got multiple names (%d) from %s", count, what); 1029 1030 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 1031 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 1032 (r = decode_attrib(msg, &a)) != 0) 1033 fatal_fr(r, "parse filename/attrib"); 1034 1035 debug3("%s %s -> %s", what, path, filename); 1036 1037 free(longname); 1038 1039 sshbuf_free(msg); 1040 1041 return(filename); 1042 } 1043 1044 char * 1045 do_realpath(struct sftp_conn *conn, const char *path) 1046 { 1047 return do_realpath_expand(conn, path, 0); 1048 } 1049 1050 int 1051 can_expand_path(struct sftp_conn *conn) 1052 { 1053 return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0; 1054 } 1055 1056 char * 1057 do_expand_path(struct sftp_conn *conn, const char *path) 1058 { 1059 if (!can_expand_path(conn)) { 1060 debug3_f("no server support, fallback to realpath"); 1061 return do_realpath_expand(conn, path, 0); 1062 } 1063 return do_realpath_expand(conn, path, 1); 1064 } 1065 1066 int 1067 do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) 1068 { 1069 Attrib junk, *a; 1070 struct sshbuf *msg; 1071 u_char *old_handle, *new_handle; 1072 u_int mode, status, id; 1073 size_t old_handle_len, new_handle_len; 1074 int r; 1075 1076 /* Return if the extension is not supported */ 1077 if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) { 1078 error("Server does not support copy-data extension"); 1079 return -1; 1080 } 1081 1082 /* Make sure the file exists, and we can copy its perms */ 1083 if ((a = do_stat(conn, oldpath, 0)) == NULL) 1084 return -1; 1085 1086 /* Do not preserve set[ug]id here, as we do not preserve ownership */ 1087 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 1088 mode = a->perm & 0777; 1089 1090 if (!S_ISREG(a->perm)) { 1091 error("Cannot copy non-regular file: %s", oldpath); 1092 return -1; 1093 } 1094 } else { 1095 /* NB: The user's umask will apply to this */ 1096 mode = 0666; 1097 } 1098 1099 /* Set up the new perms for the new file */ 1100 attrib_clear(a); 1101 a->perm = mode; 1102 a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 1103 1104 if ((msg = sshbuf_new()) == NULL) 1105 fatal("%s: sshbuf_new failed", __func__); 1106 1107 attrib_clear(&junk); /* Send empty attributes */ 1108 1109 /* Open the old file for reading */ 1110 id = conn->msg_id++; 1111 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1112 (r = sshbuf_put_u32(msg, id)) != 0 || 1113 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 1114 (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || 1115 (r = encode_attrib(msg, &junk)) != 0) 1116 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1117 send_msg(conn, msg); 1118 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath); 1119 1120 sshbuf_reset(msg); 1121 1122 old_handle = get_handle(conn, id, &old_handle_len, 1123 "remote open(\"%s\")", oldpath); 1124 if (old_handle == NULL) { 1125 sshbuf_free(msg); 1126 return -1; 1127 } 1128 1129 /* Open the new file for writing */ 1130 id = conn->msg_id++; 1131 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1132 (r = sshbuf_put_u32(msg, id)) != 0 || 1133 (r = sshbuf_put_cstring(msg, newpath)) != 0 || 1134 (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| 1135 SSH2_FXF_TRUNC)) != 0 || 1136 (r = encode_attrib(msg, a)) != 0) 1137 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1138 send_msg(conn, msg); 1139 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath); 1140 1141 sshbuf_reset(msg); 1142 1143 new_handle = get_handle(conn, id, &new_handle_len, 1144 "remote open(\"%s\")", newpath); 1145 if (new_handle == NULL) { 1146 sshbuf_free(msg); 1147 free(old_handle); 1148 return -1; 1149 } 1150 1151 /* Copy the file data */ 1152 id = conn->msg_id++; 1153 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1154 (r = sshbuf_put_u32(msg, id)) != 0 || 1155 (r = sshbuf_put_cstring(msg, "copy-data")) != 0 || 1156 (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 || 1157 (r = sshbuf_put_u64(msg, 0)) != 0 || 1158 (r = sshbuf_put_u64(msg, 0)) != 0 || 1159 (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 || 1160 (r = sshbuf_put_u64(msg, 0)) != 0) 1161 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1162 send_msg(conn, msg); 1163 debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0", 1164 oldpath, newpath); 1165 1166 status = get_status(conn, id); 1167 if (status != SSH2_FX_OK) 1168 error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath, 1169 newpath, fx2txt(status)); 1170 1171 /* Clean up everything */ 1172 sshbuf_free(msg); 1173 do_close(conn, old_handle, old_handle_len); 1174 do_close(conn, new_handle, new_handle_len); 1175 free(old_handle); 1176 free(new_handle); 1177 1178 return status == SSH2_FX_OK ? 0 : -1; 1179 } 1180 1181 int 1182 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, 1183 int force_legacy) 1184 { 1185 struct sshbuf *msg; 1186 u_int status, id; 1187 int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; 1188 1189 if ((msg = sshbuf_new()) == NULL) 1190 fatal_f("sshbuf_new failed"); 1191 1192 /* Send rename request */ 1193 id = conn->msg_id++; 1194 if (use_ext) { 1195 debug2("Sending SSH2_FXP_EXTENDED(posix-rename@openssh.com) " 1196 "\"%s\" to \"%s\"", oldpath, newpath); 1197 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1198 (r = sshbuf_put_u32(msg, id)) != 0 || 1199 (r = sshbuf_put_cstring(msg, 1200 "posix-rename@openssh.com")) != 0) 1201 fatal_fr(r, "compose posix-rename"); 1202 } else { 1203 debug2("Sending SSH2_FXP_RENAME \"%s\" to \"%s\"", 1204 oldpath, newpath); 1205 if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || 1206 (r = sshbuf_put_u32(msg, id)) != 0) 1207 fatal_fr(r, "compose rename"); 1208 } 1209 if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || 1210 (r = sshbuf_put_cstring(msg, newpath)) != 0) 1211 fatal_fr(r, "compose paths"); 1212 send_msg(conn, msg); 1213 debug3("Sent message %s \"%s\" -> \"%s\"", 1214 use_ext ? "posix-rename@openssh.com" : 1215 "SSH2_FXP_RENAME", oldpath, newpath); 1216 sshbuf_free(msg); 1217 1218 status = get_status(conn, id); 1219 if (status != SSH2_FX_OK) 1220 error("remote rename \"%s\" to \"%s\": %s", oldpath, 1221 newpath, fx2txt(status)); 1222 1223 return status == SSH2_FX_OK ? 0 : -1; 1224 } 1225 1226 int 1227 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 1228 { 1229 struct sshbuf *msg; 1230 u_int status, id; 1231 int r; 1232 1233 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { 1234 error("Server does not support hardlink@openssh.com extension"); 1235 return -1; 1236 } 1237 debug2("Sending SSH2_FXP_EXTENDED(hardlink@openssh.com) " 1238 "\"%s\" to \"%s\"", oldpath, newpath); 1239 1240 if ((msg = sshbuf_new()) == NULL) 1241 fatal_f("sshbuf_new failed"); 1242 1243 /* Send link request */ 1244 id = conn->msg_id++; 1245 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1246 (r = sshbuf_put_u32(msg, id)) != 0 || 1247 (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || 1248 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 1249 (r = sshbuf_put_cstring(msg, newpath)) != 0) 1250 fatal_fr(r, "compose"); 1251 send_msg(conn, msg); 1252 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", 1253 oldpath, newpath); 1254 sshbuf_free(msg); 1255 1256 status = get_status(conn, id); 1257 if (status != SSH2_FX_OK) 1258 error("remote link \"%s\" to \"%s\": %s", oldpath, 1259 newpath, fx2txt(status)); 1260 1261 return status == SSH2_FX_OK ? 0 : -1; 1262 } 1263 1264 int 1265 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 1266 { 1267 struct sshbuf *msg; 1268 u_int status, id; 1269 int r; 1270 1271 if (conn->version < 3) { 1272 error("This server does not support the symlink operation"); 1273 return(SSH2_FX_OP_UNSUPPORTED); 1274 } 1275 debug2("Sending SSH2_FXP_SYMLINK \"%s\" to \"%s\"", oldpath, newpath); 1276 1277 if ((msg = sshbuf_new()) == NULL) 1278 fatal_f("sshbuf_new failed"); 1279 1280 /* Send symlink request */ 1281 id = conn->msg_id++; 1282 if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || 1283 (r = sshbuf_put_u32(msg, id)) != 0 || 1284 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 1285 (r = sshbuf_put_cstring(msg, newpath)) != 0) 1286 fatal_fr(r, "compose"); 1287 send_msg(conn, msg); 1288 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 1289 newpath); 1290 sshbuf_free(msg); 1291 1292 status = get_status(conn, id); 1293 if (status != SSH2_FX_OK) 1294 error("remote symlink file \"%s\" to \"%s\": %s", oldpath, 1295 newpath, fx2txt(status)); 1296 1297 return status == SSH2_FX_OK ? 0 : -1; 1298 } 1299 1300 int 1301 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) 1302 { 1303 struct sshbuf *msg; 1304 u_int status, id; 1305 int r; 1306 1307 /* Silently return if the extension is not supported */ 1308 if ((conn->exts & SFTP_EXT_FSYNC) == 0) 1309 return -1; 1310 debug2("Sending SSH2_FXP_EXTENDED(fsync@openssh.com)"); 1311 1312 /* Send fsync request */ 1313 if ((msg = sshbuf_new()) == NULL) 1314 fatal_f("sshbuf_new failed"); 1315 id = conn->msg_id++; 1316 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1317 (r = sshbuf_put_u32(msg, id)) != 0 || 1318 (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || 1319 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1320 fatal_fr(r, "compose"); 1321 send_msg(conn, msg); 1322 debug3("Sent message fsync@openssh.com I:%u", id); 1323 sshbuf_free(msg); 1324 1325 status = get_status(conn, id); 1326 if (status != SSH2_FX_OK) 1327 error("remote fsync: %s", fx2txt(status)); 1328 1329 return status == SSH2_FX_OK ? 0 : -1; 1330 } 1331 1332 #ifdef notyet 1333 char * 1334 do_readlink(struct sftp_conn *conn, const char *path) 1335 { 1336 struct sshbuf *msg; 1337 u_int expected_id, count, id; 1338 char *filename, *longname; 1339 Attrib a; 1340 u_char type; 1341 int r; 1342 1343 debug2("Sending SSH2_FXP_READLINK \"%s\"", path); 1344 1345 expected_id = id = conn->msg_id++; 1346 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); 1347 1348 if ((msg = sshbuf_new()) == NULL) 1349 fatal_f("sshbuf_new failed"); 1350 1351 get_msg(conn, msg); 1352 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1353 (r = sshbuf_get_u32(msg, &id)) != 0) 1354 fatal_fr(r, "parse"); 1355 1356 if (id != expected_id) 1357 fatal("ID mismatch (%u != %u)", id, expected_id); 1358 1359 if (type == SSH2_FXP_STATUS) { 1360 u_int status; 1361 1362 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1363 fatal_fr(r, "parse status"); 1364 error("Couldn't readlink: %s", fx2txt(status)); 1365 sshbuf_free(msg); 1366 return(NULL); 1367 } else if (type != SSH2_FXP_NAME) 1368 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 1369 SSH2_FXP_NAME, type); 1370 1371 if ((r = sshbuf_get_u32(msg, &count)) != 0) 1372 fatal_fr(r, "parse count"); 1373 if (count != 1) 1374 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); 1375 1376 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 1377 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 1378 (r = decode_attrib(msg, &a)) != 0) 1379 fatal_fr(r, "parse filenames/attrib"); 1380 1381 debug3("SSH_FXP_READLINK %s -> %s", path, filename); 1382 1383 free(longname); 1384 1385 sshbuf_free(msg); 1386 1387 return filename; 1388 } 1389 #endif 1390 1391 int 1392 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, 1393 int quiet) 1394 { 1395 struct sshbuf *msg; 1396 u_int id; 1397 int r; 1398 1399 if ((conn->exts & SFTP_EXT_STATVFS) == 0) { 1400 error("Server does not support statvfs@openssh.com extension"); 1401 return -1; 1402 } 1403 1404 debug2("Sending SSH2_FXP_EXTENDED(statvfs@openssh.com) \"%s\"", path); 1405 1406 id = conn->msg_id++; 1407 1408 if ((msg = sshbuf_new()) == NULL) 1409 fatal_f("sshbuf_new failed"); 1410 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1411 (r = sshbuf_put_u32(msg, id)) != 0 || 1412 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || 1413 (r = sshbuf_put_cstring(msg, path)) != 0) 1414 fatal_fr(r, "compose"); 1415 send_msg(conn, msg); 1416 sshbuf_free(msg); 1417 1418 return get_decode_statvfs(conn, st, id, quiet); 1419 } 1420 1421 #ifdef notyet 1422 int 1423 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 1424 struct sftp_statvfs *st, int quiet) 1425 { 1426 struct sshbuf *msg; 1427 u_int id; 1428 1429 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { 1430 error("Server does not support fstatvfs@openssh.com extension"); 1431 return -1; 1432 } 1433 1434 debug2("Sending SSH2_FXP_EXTENDED(fstatvfs@openssh.com)"); 1435 1436 id = conn->msg_id++; 1437 1438 if ((msg = sshbuf_new()) == NULL) 1439 fatal_f("sshbuf_new failed"); 1440 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1441 (r = sshbuf_put_u32(msg, id)) != 0 || 1442 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || 1443 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1444 fatal_fr(r, "compose"); 1445 send_msg(conn, msg); 1446 sshbuf_free(msg); 1447 1448 return get_decode_statvfs(conn, st, id, quiet); 1449 } 1450 #endif 1451 1452 int 1453 do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) 1454 { 1455 struct sshbuf *msg; 1456 u_int status, id; 1457 int r; 1458 1459 if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) { 1460 error("Server does not support lsetstat@openssh.com extension"); 1461 return -1; 1462 } 1463 1464 debug2("Sending SSH2_FXP_EXTENDED(lsetstat@openssh.com) \"%s\"", path); 1465 1466 id = conn->msg_id++; 1467 if ((msg = sshbuf_new()) == NULL) 1468 fatal_f("sshbuf_new failed"); 1469 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1470 (r = sshbuf_put_u32(msg, id)) != 0 || 1471 (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || 1472 (r = sshbuf_put_cstring(msg, path)) != 0 || 1473 (r = encode_attrib(msg, a)) != 0) 1474 fatal_fr(r, "compose"); 1475 send_msg(conn, msg); 1476 sshbuf_free(msg); 1477 1478 status = get_status(conn, id); 1479 if (status != SSH2_FX_OK) 1480 error("remote lsetstat \"%s\": %s", path, fx2txt(status)); 1481 1482 return status == SSH2_FX_OK ? 0 : -1; 1483 } 1484 1485 static void 1486 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1487 u_int len, const u_char *handle, u_int handle_len) 1488 { 1489 struct sshbuf *msg; 1490 int r; 1491 1492 if ((msg = sshbuf_new()) == NULL) 1493 fatal_f("sshbuf_new failed"); 1494 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || 1495 (r = sshbuf_put_u32(msg, id)) != 0 || 1496 (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || 1497 (r = sshbuf_put_u64(msg, offset)) != 0 || 1498 (r = sshbuf_put_u32(msg, len)) != 0) 1499 fatal_fr(r, "compose"); 1500 send_msg(conn, msg); 1501 sshbuf_free(msg); 1502 } 1503 1504 static int 1505 send_open(struct sftp_conn *conn, const char *path, const char *tag, 1506 u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp) 1507 { 1508 Attrib junk; 1509 u_char *handle; 1510 size_t handle_len; 1511 struct sshbuf *msg; 1512 int r; 1513 u_int id; 1514 1515 debug2("Sending SSH2_FXP_OPEN \"%s\"", path); 1516 1517 *handlep = NULL; 1518 *handle_lenp = 0; 1519 1520 if (a == NULL) { 1521 attrib_clear(&junk); /* Send empty attributes */ 1522 a = &junk; 1523 } 1524 /* Send open request */ 1525 if ((msg = sshbuf_new()) == NULL) 1526 fatal_f("sshbuf_new failed"); 1527 id = conn->msg_id++; 1528 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1529 (r = sshbuf_put_u32(msg, id)) != 0 || 1530 (r = sshbuf_put_cstring(msg, path)) != 0 || 1531 (r = sshbuf_put_u32(msg, openmode)) != 0 || 1532 (r = encode_attrib(msg, a)) != 0) 1533 fatal_fr(r, "compose %s open", tag); 1534 send_msg(conn, msg); 1535 sshbuf_free(msg); 1536 debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x", 1537 tag, id, path, openmode); 1538 if ((handle = get_handle(conn, id, &handle_len, 1539 "%s open \"%s\"", tag, path)) == NULL) 1540 return -1; 1541 /* success */ 1542 *handlep = handle; 1543 *handle_lenp = handle_len; 1544 return 0; 1545 } 1546 1547 static const char * 1548 progress_meter_path(const char *path) 1549 { 1550 const char *progresspath; 1551 1552 if ((progresspath = strrchr(path, '/')) == NULL) 1553 return path; 1554 progresspath++; 1555 if (*progresspath == '\0') 1556 return path; 1557 return progresspath; 1558 } 1559 1560 int 1561 do_download(struct sftp_conn *conn, const char *remote_path, 1562 const char *local_path, Attrib *a, int preserve_flag, int resume_flag, 1563 int fsync_flag, int inplace_flag) 1564 { 1565 struct sshbuf *msg; 1566 u_char *handle; 1567 int local_fd = -1, write_error; 1568 int read_error, write_errno, lmodified = 0, reordered = 0, r; 1569 u_int64_t offset = 0, size, highwater; 1570 u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; 1571 off_t progress_counter; 1572 size_t handle_len; 1573 struct stat st; 1574 struct requests requests; 1575 struct request *req; 1576 u_char type; 1577 1578 debug2_f("download remote \"%s\" to local \"%s\"", 1579 remote_path, local_path); 1580 1581 TAILQ_INIT(&requests); 1582 1583 if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) 1584 return -1; 1585 1586 /* Do not preserve set[ug]id here, as we do not preserve ownership */ 1587 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1588 mode = a->perm & 0777; 1589 else 1590 mode = 0666; 1591 1592 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 1593 (!S_ISREG(a->perm))) { 1594 error("download %s: not a regular file", remote_path); 1595 return(-1); 1596 } 1597 1598 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 1599 size = a->size; 1600 else 1601 size = 0; 1602 1603 buflen = conn->download_buflen; 1604 1605 /* Send open request */ 1606 if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL, 1607 &handle, &handle_len) != 0) 1608 return -1; 1609 1610 local_fd = open(local_path, O_WRONLY | O_CREAT | 1611 ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR); 1612 if (local_fd == -1) { 1613 error("open local \"%s\": %s", local_path, strerror(errno)); 1614 goto fail; 1615 } 1616 offset = highwater = 0; 1617 if (resume_flag) { 1618 if (fstat(local_fd, &st) == -1) { 1619 error("stat local \"%s\": %s", 1620 local_path, strerror(errno)); 1621 goto fail; 1622 } 1623 if (st.st_size < 0) { 1624 error("\"%s\" has negative size", local_path); 1625 goto fail; 1626 } 1627 if ((u_int64_t)st.st_size > size) { 1628 error("Unable to resume download of \"%s\": " 1629 "local file is larger than remote", local_path); 1630 fail: 1631 do_close(conn, handle, handle_len); 1632 free(handle); 1633 if (local_fd != -1) 1634 close(local_fd); 1635 return -1; 1636 } 1637 offset = highwater = st.st_size; 1638 } 1639 1640 /* Read from remote and write to local */ 1641 write_error = read_error = write_errno = num_req = 0; 1642 max_req = 1; 1643 progress_counter = offset; 1644 1645 if (showprogress && size != 0) { 1646 start_progress_meter(progress_meter_path(remote_path), 1647 size, &progress_counter); 1648 } 1649 1650 if ((msg = sshbuf_new()) == NULL) 1651 fatal_f("sshbuf_new failed"); 1652 1653 while (num_req > 0 || max_req > 0) { 1654 u_char *data; 1655 size_t len; 1656 1657 /* 1658 * Simulate EOF on interrupt: stop sending new requests and 1659 * allow outstanding requests to drain gracefully 1660 */ 1661 if (interrupted) { 1662 if (num_req == 0) /* If we haven't started yet... */ 1663 break; 1664 max_req = 0; 1665 } 1666 1667 /* Send some more requests */ 1668 while (num_req < max_req) { 1669 debug3("Request range %llu -> %llu (%d/%d)", 1670 (unsigned long long)offset, 1671 (unsigned long long)offset + buflen - 1, 1672 num_req, max_req); 1673 req = request_enqueue(&requests, conn->msg_id++, 1674 buflen, offset); 1675 offset += buflen; 1676 num_req++; 1677 send_read_request(conn, req->id, req->offset, 1678 req->len, handle, handle_len); 1679 } 1680 1681 sshbuf_reset(msg); 1682 get_msg(conn, msg); 1683 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1684 (r = sshbuf_get_u32(msg, &id)) != 0) 1685 fatal_fr(r, "parse"); 1686 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1687 1688 /* Find the request in our queue */ 1689 if ((req = request_find(&requests, id)) == NULL) 1690 fatal("Unexpected reply %u", id); 1691 1692 switch (type) { 1693 case SSH2_FXP_STATUS: 1694 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1695 fatal_fr(r, "parse status"); 1696 if (status != SSH2_FX_EOF) 1697 read_error = 1; 1698 max_req = 0; 1699 TAILQ_REMOVE(&requests, req, tq); 1700 free(req); 1701 num_req--; 1702 break; 1703 case SSH2_FXP_DATA: 1704 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 1705 fatal_fr(r, "parse data"); 1706 debug3("Received data %llu -> %llu", 1707 (unsigned long long)req->offset, 1708 (unsigned long long)req->offset + len - 1); 1709 if (len > req->len) 1710 fatal("Received more data than asked for " 1711 "%zu > %zu", len, req->len); 1712 lmodified = 1; 1713 if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || 1714 atomicio(vwrite, local_fd, data, len) != len) && 1715 !write_error) { 1716 write_errno = errno; 1717 write_error = 1; 1718 max_req = 0; 1719 } 1720 else if (!reordered && req->offset <= highwater) 1721 highwater = req->offset + len; 1722 else if (!reordered && req->offset > highwater) 1723 reordered = 1; 1724 progress_counter += len; 1725 free(data); 1726 1727 if (len == req->len) { 1728 TAILQ_REMOVE(&requests, req, tq); 1729 free(req); 1730 num_req--; 1731 } else { 1732 /* Resend the request for the missing data */ 1733 debug3("Short data block, re-requesting " 1734 "%llu -> %llu (%2d)", 1735 (unsigned long long)req->offset + len, 1736 (unsigned long long)req->offset + 1737 req->len - 1, num_req); 1738 req->id = conn->msg_id++; 1739 req->len -= len; 1740 req->offset += len; 1741 send_read_request(conn, req->id, 1742 req->offset, req->len, handle, handle_len); 1743 /* Reduce the request size */ 1744 if (len < buflen) 1745 buflen = MAXIMUM(MIN_READ_SIZE, len); 1746 } 1747 if (max_req > 0) { /* max_req = 0 iff EOF received */ 1748 if (size > 0 && offset > size) { 1749 /* Only one request at a time 1750 * after the expected EOF */ 1751 debug3("Finish at %llu (%2d)", 1752 (unsigned long long)offset, 1753 num_req); 1754 max_req = 1; 1755 } else if (max_req < conn->num_requests) { 1756 ++max_req; 1757 } 1758 } 1759 break; 1760 default: 1761 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 1762 SSH2_FXP_DATA, type); 1763 } 1764 } 1765 1766 if (showprogress && size) 1767 stop_progress_meter(); 1768 1769 /* Sanity check */ 1770 if (TAILQ_FIRST(&requests) != NULL) 1771 fatal("Transfer complete, but requests still in queue"); 1772 /* 1773 * Truncate at highest contiguous point to avoid holes on interrupt, 1774 * or unconditionally if writing in place. 1775 */ 1776 if (inplace_flag || read_error || write_error || interrupted) { 1777 if (reordered && resume_flag) { 1778 error("Unable to resume download of \"%s\": " 1779 "server reordered requests", local_path); 1780 } 1781 debug("truncating at %llu", (unsigned long long)highwater); 1782 if (ftruncate(local_fd, highwater) == -1) 1783 error("local ftruncate \"%s\": %s", local_path, 1784 strerror(errno)); 1785 } 1786 if (read_error) { 1787 error("read remote \"%s\" : %s", remote_path, fx2txt(status)); 1788 status = -1; 1789 do_close(conn, handle, handle_len); 1790 } else if (write_error) { 1791 error("write local \"%s\": %s", local_path, 1792 strerror(write_errno)); 1793 status = SSH2_FX_FAILURE; 1794 do_close(conn, handle, handle_len); 1795 } else { 1796 if (do_close(conn, handle, handle_len) != 0 || interrupted) 1797 status = SSH2_FX_FAILURE; 1798 else 1799 status = SSH2_FX_OK; 1800 /* Override umask and utimes if asked */ 1801 if (preserve_flag && fchmod(local_fd, mode) == -1) 1802 error("local chmod \"%s\": %s", local_path, 1803 strerror(errno)); 1804 if (preserve_flag && 1805 (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { 1806 struct timeval tv[2]; 1807 tv[0].tv_sec = a->atime; 1808 tv[1].tv_sec = a->mtime; 1809 tv[0].tv_usec = tv[1].tv_usec = 0; 1810 if (utimes(local_path, tv) == -1) 1811 error("local set times \"%s\": %s", 1812 local_path, strerror(errno)); 1813 } 1814 if (resume_flag && !lmodified) 1815 logit("File \"%s\" was not modified", local_path); 1816 else if (fsync_flag) { 1817 debug("syncing \"%s\"", local_path); 1818 if (fsync(local_fd) == -1) 1819 error("local sync \"%s\": %s", 1820 local_path, strerror(errno)); 1821 } 1822 } 1823 close(local_fd); 1824 sshbuf_free(msg); 1825 free(handle); 1826 1827 return status == SSH2_FX_OK ? 0 : -1; 1828 } 1829 1830 static int 1831 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1832 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 1833 int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) 1834 { 1835 int i, ret = 0; 1836 SFTP_DIRENT **dir_entries; 1837 char *filename, *new_src = NULL, *new_dst = NULL; 1838 mode_t mode = 0777, tmpmode = mode; 1839 1840 if (depth >= MAX_DIR_DEPTH) { 1841 error("Maximum directory depth exceeded: %d levels", depth); 1842 return -1; 1843 } 1844 1845 debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst); 1846 1847 if (dirattrib == NULL && 1848 (dirattrib = do_stat(conn, src, 1)) == NULL) { 1849 error("stat remote \"%s\" directory failed", src); 1850 return -1; 1851 } 1852 if (!S_ISDIR(dirattrib->perm)) { 1853 error("\"%s\" is not a directory", src); 1854 return -1; 1855 } 1856 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 1857 mprintf("Retrieving %s\n", src); 1858 1859 if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 1860 mode = dirattrib->perm & 01777; 1861 tmpmode = mode | (S_IWUSR|S_IXUSR); 1862 } else { 1863 debug("download remote \"%s\": server " 1864 "did not send permissions", dst); 1865 } 1866 1867 if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { 1868 error("mkdir %s: %s", dst, strerror(errno)); 1869 return -1; 1870 } 1871 1872 if (do_readdir(conn, src, &dir_entries) == -1) { 1873 error("remote readdir \"%s\" failed", src); 1874 return -1; 1875 } 1876 1877 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 1878 free(new_dst); 1879 free(new_src); 1880 1881 filename = dir_entries[i]->filename; 1882 new_dst = path_append(dst, filename); 1883 new_src = path_append(src, filename); 1884 1885 if (S_ISDIR(dir_entries[i]->a.perm)) { 1886 if (strcmp(filename, ".") == 0 || 1887 strcmp(filename, "..") == 0) 1888 continue; 1889 if (download_dir_internal(conn, new_src, new_dst, 1890 depth + 1, &(dir_entries[i]->a), preserve_flag, 1891 print_flag, resume_flag, 1892 fsync_flag, follow_link_flag, inplace_flag) == -1) 1893 ret = -1; 1894 } else if (S_ISREG(dir_entries[i]->a.perm) || 1895 (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { 1896 /* 1897 * If this is a symlink then don't send the link's 1898 * Attrib. do_download() will do a FXP_STAT operation 1899 * and get the link target's attributes. 1900 */ 1901 if (do_download(conn, new_src, new_dst, 1902 S_ISLNK(dir_entries[i]->a.perm) ? NULL : 1903 &(dir_entries[i]->a), 1904 preserve_flag, resume_flag, fsync_flag, 1905 inplace_flag) == -1) { 1906 error("Download of file %s to %s failed", 1907 new_src, new_dst); 1908 ret = -1; 1909 } 1910 } else 1911 logit("download \"%s\": not a regular file", new_src); 1912 1913 } 1914 free(new_dst); 1915 free(new_src); 1916 1917 if (preserve_flag) { 1918 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1919 struct timeval tv[2]; 1920 tv[0].tv_sec = dirattrib->atime; 1921 tv[1].tv_sec = dirattrib->mtime; 1922 tv[0].tv_usec = tv[1].tv_usec = 0; 1923 if (utimes(dst, tv) == -1) 1924 error("local set times on \"%s\": %s", 1925 dst, strerror(errno)); 1926 } else 1927 debug("Server did not send times for directory " 1928 "\"%s\"", dst); 1929 } 1930 1931 if (mode != tmpmode && chmod(dst, mode) == -1) 1932 error("local chmod directory \"%s\": %s", dst, 1933 strerror(errno)); 1934 1935 free_sftp_dirents(dir_entries); 1936 1937 return ret; 1938 } 1939 1940 int 1941 download_dir(struct sftp_conn *conn, const char *src, const char *dst, 1942 Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, 1943 int fsync_flag, int follow_link_flag, int inplace_flag) 1944 { 1945 char *src_canon; 1946 int ret; 1947 1948 if ((src_canon = do_realpath(conn, src)) == NULL) { 1949 error("download \"%s\": path canonicalization failed", src); 1950 return -1; 1951 } 1952 1953 ret = download_dir_internal(conn, src_canon, dst, 0, 1954 dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, 1955 follow_link_flag, inplace_flag); 1956 free(src_canon); 1957 return ret; 1958 } 1959 1960 int 1961 do_upload(struct sftp_conn *conn, const char *local_path, 1962 const char *remote_path, int preserve_flag, int resume, 1963 int fsync_flag, int inplace_flag) 1964 { 1965 int r, local_fd; 1966 u_int openmode, id, status = SSH2_FX_OK, reordered = 0; 1967 off_t offset, progress_counter; 1968 u_char type, *handle, *data; 1969 struct sshbuf *msg; 1970 struct stat sb; 1971 Attrib a, t, *c = NULL; 1972 u_int32_t startid, ackid; 1973 u_int64_t highwater = 0; 1974 struct request *ack = NULL; 1975 struct requests acks; 1976 size_t handle_len; 1977 1978 debug2_f("upload local \"%s\" to remote \"%s\"", 1979 local_path, remote_path); 1980 1981 TAILQ_INIT(&acks); 1982 1983 if ((local_fd = open(local_path, O_RDONLY)) == -1) { 1984 error("open local \"%s\": %s", local_path, strerror(errno)); 1985 return(-1); 1986 } 1987 if (fstat(local_fd, &sb) == -1) { 1988 error("fstat local \"%s\": %s", local_path, strerror(errno)); 1989 close(local_fd); 1990 return(-1); 1991 } 1992 if (!S_ISREG(sb.st_mode)) { 1993 error("local \"%s\" is not a regular file", local_path); 1994 close(local_fd); 1995 return(-1); 1996 } 1997 stat_to_attrib(&sb, &a); 1998 1999 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2000 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2001 a.perm &= 0777; 2002 if (!preserve_flag) 2003 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2004 2005 if (resume) { 2006 /* Get remote file size if it exists */ 2007 if ((c = do_stat(conn, remote_path, 0)) == NULL) { 2008 close(local_fd); 2009 return -1; 2010 } 2011 2012 if ((off_t)c->size >= sb.st_size) { 2013 error("resume \"%s\": destination file " 2014 "same size or larger", local_path); 2015 close(local_fd); 2016 return -1; 2017 } 2018 2019 if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { 2020 close(local_fd); 2021 return -1; 2022 } 2023 } 2024 2025 openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT; 2026 if (resume) 2027 openmode |= SSH2_FXF_APPEND; 2028 else if (!inplace_flag) 2029 openmode |= SSH2_FXF_TRUNC; 2030 2031 /* Send open request */ 2032 if (send_open(conn, remote_path, "dest", openmode, &a, 2033 &handle, &handle_len) != 0) { 2034 close(local_fd); 2035 return -1; 2036 } 2037 2038 id = conn->msg_id; 2039 startid = ackid = id + 1; 2040 data = xmalloc(conn->upload_buflen); 2041 2042 /* Read from local and write to remote */ 2043 offset = progress_counter = (resume ? c->size : 0); 2044 if (showprogress) { 2045 start_progress_meter(progress_meter_path(local_path), 2046 sb.st_size, &progress_counter); 2047 } 2048 2049 if ((msg = sshbuf_new()) == NULL) 2050 fatal_f("sshbuf_new failed"); 2051 for (;;) { 2052 int len; 2053 2054 /* 2055 * Can't use atomicio here because it returns 0 on EOF, 2056 * thus losing the last block of the file. 2057 * Simulate an EOF on interrupt, allowing ACKs from the 2058 * server to drain. 2059 */ 2060 if (interrupted || status != SSH2_FX_OK) 2061 len = 0; 2062 else do 2063 len = read(local_fd, data, conn->upload_buflen); 2064 while ((len == -1) && (errno == EINTR || errno == EAGAIN)); 2065 2066 if (len == -1) { 2067 fatal("read local \"%s\": %s", 2068 local_path, strerror(errno)); 2069 } else if (len != 0) { 2070 ack = request_enqueue(&acks, ++id, len, offset); 2071 sshbuf_reset(msg); 2072 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 2073 (r = sshbuf_put_u32(msg, ack->id)) != 0 || 2074 (r = sshbuf_put_string(msg, handle, 2075 handle_len)) != 0 || 2076 (r = sshbuf_put_u64(msg, offset)) != 0 || 2077 (r = sshbuf_put_string(msg, data, len)) != 0) 2078 fatal_fr(r, "compose"); 2079 send_msg(conn, msg); 2080 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 2081 id, (unsigned long long)offset, len); 2082 } else if (TAILQ_FIRST(&acks) == NULL) 2083 break; 2084 2085 if (ack == NULL) 2086 fatal("Unexpected ACK %u", id); 2087 2088 if (id == startid || len == 0 || 2089 id - ackid >= conn->num_requests) { 2090 u_int rid; 2091 2092 sshbuf_reset(msg); 2093 get_msg(conn, msg); 2094 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2095 (r = sshbuf_get_u32(msg, &rid)) != 0) 2096 fatal_fr(r, "parse"); 2097 2098 if (type != SSH2_FXP_STATUS) 2099 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 2100 "got %d", SSH2_FXP_STATUS, type); 2101 2102 if ((r = sshbuf_get_u32(msg, &status)) != 0) 2103 fatal_fr(r, "parse status"); 2104 debug3("SSH2_FXP_STATUS %u", status); 2105 2106 /* Find the request in our queue */ 2107 if ((ack = request_find(&acks, rid)) == NULL) 2108 fatal("Can't find request for ID %u", rid); 2109 TAILQ_REMOVE(&acks, ack, tq); 2110 debug3("In write loop, ack for %u %zu bytes at %lld", 2111 ack->id, ack->len, (unsigned long long)ack->offset); 2112 ++ackid; 2113 progress_counter += ack->len; 2114 if (!reordered && ack->offset <= highwater) 2115 highwater = ack->offset + ack->len; 2116 else if (!reordered && ack->offset > highwater) { 2117 debug3_f("server reordered ACKs"); 2118 reordered = 1; 2119 } 2120 free(ack); 2121 } 2122 offset += len; 2123 if (offset < 0) 2124 fatal_f("offset < 0"); 2125 } 2126 sshbuf_free(msg); 2127 2128 if (showprogress) 2129 stop_progress_meter(); 2130 free(data); 2131 2132 if (status != SSH2_FX_OK) { 2133 error("write remote \"%s\": %s", remote_path, fx2txt(status)); 2134 status = SSH2_FX_FAILURE; 2135 } 2136 2137 if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { 2138 debug("truncating at %llu", (unsigned long long)highwater); 2139 attrib_clear(&t); 2140 t.flags = SSH2_FILEXFER_ATTR_SIZE; 2141 t.size = highwater; 2142 do_fsetstat(conn, handle, handle_len, &t); 2143 } 2144 2145 if (close(local_fd) == -1) { 2146 error("close local \"%s\": %s", local_path, strerror(errno)); 2147 status = SSH2_FX_FAILURE; 2148 } 2149 2150 /* Override umask and utimes if asked */ 2151 if (preserve_flag) 2152 do_fsetstat(conn, handle, handle_len, &a); 2153 2154 if (fsync_flag) 2155 (void)do_fsync(conn, handle, handle_len); 2156 2157 if (do_close(conn, handle, handle_len) != 0) 2158 status = SSH2_FX_FAILURE; 2159 2160 free(handle); 2161 2162 return status == SSH2_FX_OK ? 0 : -1; 2163 } 2164 2165 static int 2166 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 2167 int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, 2168 int follow_link_flag, int inplace_flag) 2169 { 2170 int ret = 0; 2171 DIR *dirp; 2172 struct dirent *dp; 2173 char *filename, *new_src = NULL, *new_dst = NULL; 2174 struct stat sb; 2175 Attrib a, *dirattrib; 2176 u_int32_t saved_perm; 2177 2178 debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst); 2179 2180 if (depth >= MAX_DIR_DEPTH) { 2181 error("Maximum directory depth exceeded: %d levels", depth); 2182 return -1; 2183 } 2184 2185 if (stat(src, &sb) == -1) { 2186 error("stat local \"%s\": %s", src, strerror(errno)); 2187 return -1; 2188 } 2189 if (!S_ISDIR(sb.st_mode)) { 2190 error("\"%s\" is not a directory", src); 2191 return -1; 2192 } 2193 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 2194 mprintf("Entering %s\n", src); 2195 2196 stat_to_attrib(&sb, &a); 2197 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2198 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2199 a.perm &= 01777; 2200 if (!preserve_flag) 2201 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2202 2203 /* 2204 * sftp lacks a portable status value to match errno EEXIST, 2205 * so if we get a failure back then we must check whether 2206 * the path already existed and is a directory. Ensure we can 2207 * write to the directory we create for the duration of the transfer. 2208 */ 2209 saved_perm = a.perm; 2210 a.perm |= (S_IWUSR|S_IXUSR); 2211 if (do_mkdir(conn, dst, &a, 0) != 0) { 2212 if ((dirattrib = do_stat(conn, dst, 0)) == NULL) 2213 return -1; 2214 if (!S_ISDIR(dirattrib->perm)) { 2215 error("\"%s\" exists but is not a directory", dst); 2216 return -1; 2217 } 2218 } 2219 a.perm = saved_perm; 2220 2221 if ((dirp = opendir(src)) == NULL) { 2222 error("local opendir \"%s\": %s", src, strerror(errno)); 2223 return -1; 2224 } 2225 2226 while (((dp = readdir(dirp)) != NULL) && !interrupted) { 2227 if (dp->d_ino == 0) 2228 continue; 2229 free(new_dst); 2230 free(new_src); 2231 filename = dp->d_name; 2232 new_dst = path_append(dst, filename); 2233 new_src = path_append(src, filename); 2234 2235 if (lstat(new_src, &sb) == -1) { 2236 logit("local lstat \"%s\": %s", filename, 2237 strerror(errno)); 2238 ret = -1; 2239 } else if (S_ISDIR(sb.st_mode)) { 2240 if (strcmp(filename, ".") == 0 || 2241 strcmp(filename, "..") == 0) 2242 continue; 2243 2244 if (upload_dir_internal(conn, new_src, new_dst, 2245 depth + 1, preserve_flag, print_flag, resume, 2246 fsync_flag, follow_link_flag, inplace_flag) == -1) 2247 ret = -1; 2248 } else if (S_ISREG(sb.st_mode) || 2249 (follow_link_flag && S_ISLNK(sb.st_mode))) { 2250 if (do_upload(conn, new_src, new_dst, 2251 preserve_flag, resume, fsync_flag, 2252 inplace_flag) == -1) { 2253 error("upload \"%s\" to \"%s\" failed", 2254 new_src, new_dst); 2255 ret = -1; 2256 } 2257 } else 2258 logit("%s: not a regular file", filename); 2259 } 2260 free(new_dst); 2261 free(new_src); 2262 2263 do_setstat(conn, dst, &a); 2264 2265 (void) closedir(dirp); 2266 return ret; 2267 } 2268 2269 int 2270 upload_dir(struct sftp_conn *conn, const char *src, const char *dst, 2271 int preserve_flag, int print_flag, int resume, int fsync_flag, 2272 int follow_link_flag, int inplace_flag) 2273 { 2274 char *dst_canon; 2275 int ret; 2276 2277 if ((dst_canon = do_realpath(conn, dst)) == NULL) { 2278 error("upload \"%s\": path canonicalization failed", dst); 2279 return -1; 2280 } 2281 2282 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 2283 print_flag, resume, fsync_flag, follow_link_flag, inplace_flag); 2284 2285 free(dst_canon); 2286 return ret; 2287 } 2288 2289 static void 2290 handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, 2291 u_int *nreqsp, u_int *write_errorp) 2292 { 2293 struct sshbuf *msg; 2294 u_char type; 2295 u_int id, status; 2296 int r; 2297 struct pollfd pfd; 2298 2299 if ((msg = sshbuf_new()) == NULL) 2300 fatal_f("sshbuf_new failed"); 2301 2302 /* Try to eat replies from the upload side */ 2303 while (*nreqsp > 0) { 2304 debug3_f("%u outstanding replies", *nreqsp); 2305 if (!synchronous) { 2306 /* Bail out if no data is ready to be read */ 2307 pfd.fd = to->fd_in; 2308 pfd.events = POLLIN; 2309 if ((r = poll(&pfd, 1, 0)) == -1) { 2310 if (errno == EINTR) 2311 break; 2312 fatal_f("poll: %s", strerror(errno)); 2313 } else if (r == 0) 2314 break; /* fd not ready */ 2315 } 2316 sshbuf_reset(msg); 2317 get_msg(to, msg); 2318 2319 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2320 (r = sshbuf_get_u32(msg, &id)) != 0) 2321 fatal_fr(r, "dest parse"); 2322 debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp); 2323 if (type != SSH2_FXP_STATUS) { 2324 fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d", 2325 SSH2_FXP_STATUS, type); 2326 } 2327 if ((r = sshbuf_get_u32(msg, &status)) != 0) 2328 fatal_fr(r, "parse dest status"); 2329 debug3("dest SSH2_FXP_STATUS %u", status); 2330 if (status != SSH2_FX_OK) { 2331 /* record first error */ 2332 if (*write_errorp == 0) 2333 *write_errorp = status; 2334 } 2335 /* 2336 * XXX this doesn't do full reply matching like do_upload and 2337 * so cannot gracefully truncate terminated uploads at a 2338 * high-water mark. ATM the only caller of this function (scp) 2339 * doesn't support transfer resumption, so this doesn't matter 2340 * a whole lot. 2341 * 2342 * To be safe, do_crossload truncates the destination file to 2343 * zero length on upload failure, since we can't trust the 2344 * server not to have reordered replies that could have 2345 * inserted holes where none existed in the source file. 2346 * 2347 * XXX we could get a more accutate progress bar if we updated 2348 * the counter based on the reply from the destination... 2349 */ 2350 (*nreqsp)--; 2351 } 2352 debug3_f("done: %u outstanding replies", *nreqsp); 2353 sshbuf_free(msg); 2354 } 2355 2356 int 2357 do_crossload(struct sftp_conn *from, struct sftp_conn *to, 2358 const char *from_path, const char *to_path, 2359 Attrib *a, int preserve_flag) 2360 { 2361 struct sshbuf *msg; 2362 int write_error, read_error, r; 2363 u_int64_t offset = 0, size; 2364 u_int id, buflen, num_req, max_req, status = SSH2_FX_OK; 2365 u_int num_upload_req; 2366 off_t progress_counter; 2367 u_char *from_handle, *to_handle; 2368 size_t from_handle_len, to_handle_len; 2369 struct requests requests; 2370 struct request *req; 2371 u_char type; 2372 2373 debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path); 2374 2375 TAILQ_INIT(&requests); 2376 2377 if (a == NULL && (a = do_stat(from, from_path, 0)) == NULL) 2378 return -1; 2379 2380 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 2381 (!S_ISREG(a->perm))) { 2382 error("download \"%s\": not a regular file", from_path); 2383 return(-1); 2384 } 2385 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 2386 size = a->size; 2387 else 2388 size = 0; 2389 2390 buflen = from->download_buflen; 2391 if (buflen > to->upload_buflen) 2392 buflen = to->upload_buflen; 2393 2394 /* Send open request to read side */ 2395 if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL, 2396 &from_handle, &from_handle_len) != 0) 2397 return -1; 2398 2399 /* Send open request to write side */ 2400 a->flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2401 a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2402 a->perm &= 0777; 2403 if (!preserve_flag) 2404 a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2405 if (send_open(to, to_path, "dest", 2406 SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, 2407 &to_handle, &to_handle_len) != 0) { 2408 do_close(from, from_handle, from_handle_len); 2409 return -1; 2410 } 2411 2412 /* Read from remote "from" and write to remote "to" */ 2413 offset = 0; 2414 write_error = read_error = num_req = num_upload_req = 0; 2415 max_req = 1; 2416 progress_counter = 0; 2417 2418 if (showprogress && size != 0) { 2419 start_progress_meter(progress_meter_path(from_path), 2420 size, &progress_counter); 2421 } 2422 if ((msg = sshbuf_new()) == NULL) 2423 fatal_f("sshbuf_new failed"); 2424 while (num_req > 0 || max_req > 0) { 2425 u_char *data; 2426 size_t len; 2427 2428 /* 2429 * Simulate EOF on interrupt: stop sending new requests and 2430 * allow outstanding requests to drain gracefully 2431 */ 2432 if (interrupted) { 2433 if (num_req == 0) /* If we haven't started yet... */ 2434 break; 2435 max_req = 0; 2436 } 2437 2438 /* Send some more requests */ 2439 while (num_req < max_req) { 2440 debug3("Request range %llu -> %llu (%d/%d)", 2441 (unsigned long long)offset, 2442 (unsigned long long)offset + buflen - 1, 2443 num_req, max_req); 2444 req = request_enqueue(&requests, from->msg_id++, 2445 buflen, offset); 2446 offset += buflen; 2447 num_req++; 2448 send_read_request(from, req->id, req->offset, 2449 req->len, from_handle, from_handle_len); 2450 } 2451 2452 /* Try to eat replies from the upload side (nonblocking) */ 2453 handle_dest_replies(to, to_path, 0, 2454 &num_upload_req, &write_error); 2455 2456 sshbuf_reset(msg); 2457 get_msg(from, msg); 2458 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2459 (r = sshbuf_get_u32(msg, &id)) != 0) 2460 fatal_fr(r, "parse"); 2461 debug3("Received origin reply T:%u I:%u R:%d", 2462 type, id, max_req); 2463 2464 /* Find the request in our queue */ 2465 if ((req = request_find(&requests, id)) == NULL) 2466 fatal("Unexpected reply %u", id); 2467 2468 switch (type) { 2469 case SSH2_FXP_STATUS: 2470 if ((r = sshbuf_get_u32(msg, &status)) != 0) 2471 fatal_fr(r, "parse status"); 2472 if (status != SSH2_FX_EOF) 2473 read_error = 1; 2474 max_req = 0; 2475 TAILQ_REMOVE(&requests, req, tq); 2476 free(req); 2477 num_req--; 2478 break; 2479 case SSH2_FXP_DATA: 2480 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 2481 fatal_fr(r, "parse data"); 2482 debug3("Received data %llu -> %llu", 2483 (unsigned long long)req->offset, 2484 (unsigned long long)req->offset + len - 1); 2485 if (len > req->len) 2486 fatal("Received more data than asked for " 2487 "%zu > %zu", len, req->len); 2488 2489 /* Write this chunk out to the destination */ 2490 sshbuf_reset(msg); 2491 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 2492 (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 || 2493 (r = sshbuf_put_string(msg, to_handle, 2494 to_handle_len)) != 0 || 2495 (r = sshbuf_put_u64(msg, req->offset)) != 0 || 2496 (r = sshbuf_put_string(msg, data, len)) != 0) 2497 fatal_fr(r, "compose write"); 2498 send_msg(to, msg); 2499 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu", 2500 id, (unsigned long long)offset, len); 2501 num_upload_req++; 2502 progress_counter += len; 2503 free(data); 2504 2505 if (len == req->len) { 2506 TAILQ_REMOVE(&requests, req, tq); 2507 free(req); 2508 num_req--; 2509 } else { 2510 /* Resend the request for the missing data */ 2511 debug3("Short data block, re-requesting " 2512 "%llu -> %llu (%2d)", 2513 (unsigned long long)req->offset + len, 2514 (unsigned long long)req->offset + 2515 req->len - 1, num_req); 2516 req->id = from->msg_id++; 2517 req->len -= len; 2518 req->offset += len; 2519 send_read_request(from, req->id, 2520 req->offset, req->len, 2521 from_handle, from_handle_len); 2522 /* Reduce the request size */ 2523 if (len < buflen) 2524 buflen = MAXIMUM(MIN_READ_SIZE, len); 2525 } 2526 if (max_req > 0) { /* max_req = 0 iff EOF received */ 2527 if (size > 0 && offset > size) { 2528 /* Only one request at a time 2529 * after the expected EOF */ 2530 debug3("Finish at %llu (%2d)", 2531 (unsigned long long)offset, 2532 num_req); 2533 max_req = 1; 2534 } else if (max_req < from->num_requests) { 2535 ++max_req; 2536 } 2537 } 2538 break; 2539 default: 2540 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 2541 SSH2_FXP_DATA, type); 2542 } 2543 } 2544 2545 if (showprogress && size) 2546 stop_progress_meter(); 2547 2548 /* Drain replies from the server (blocking) */ 2549 debug3_f("waiting for %u replies from destination", num_upload_req); 2550 handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error); 2551 2552 /* Sanity check */ 2553 if (TAILQ_FIRST(&requests) != NULL) 2554 fatal("Transfer complete, but requests still in queue"); 2555 /* Truncate at 0 length on interrupt or error to avoid holes at dest */ 2556 if (read_error || write_error || interrupted) { 2557 debug("truncating \"%s\" at 0", to_path); 2558 do_close(to, to_handle, to_handle_len); 2559 free(to_handle); 2560 if (send_open(to, to_path, "dest", 2561 SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, 2562 &to_handle, &to_handle_len) != 0) { 2563 error("dest truncate \"%s\" failed", to_path); 2564 to_handle = NULL; 2565 } 2566 } 2567 if (read_error) { 2568 error("read origin \"%s\": %s", from_path, fx2txt(status)); 2569 status = -1; 2570 do_close(from, from_handle, from_handle_len); 2571 if (to_handle != NULL) 2572 do_close(to, to_handle, to_handle_len); 2573 } else if (write_error) { 2574 error("write dest \"%s\": %s", to_path, fx2txt(write_error)); 2575 status = SSH2_FX_FAILURE; 2576 do_close(from, from_handle, from_handle_len); 2577 if (to_handle != NULL) 2578 do_close(to, to_handle, to_handle_len); 2579 } else { 2580 if (do_close(from, from_handle, from_handle_len) != 0 || 2581 interrupted) 2582 status = -1; 2583 else 2584 status = SSH2_FX_OK; 2585 if (to_handle != NULL) { 2586 /* Need to resend utimes after write */ 2587 if (preserve_flag) 2588 do_fsetstat(to, to_handle, to_handle_len, a); 2589 do_close(to, to_handle, to_handle_len); 2590 } 2591 } 2592 sshbuf_free(msg); 2593 free(from_handle); 2594 free(to_handle); 2595 2596 return status == SSH2_FX_OK ? 0 : -1; 2597 } 2598 2599 static int 2600 crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, 2601 const char *from_path, const char *to_path, 2602 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 2603 int follow_link_flag) 2604 { 2605 int i, ret = 0; 2606 SFTP_DIRENT **dir_entries; 2607 char *filename, *new_from_path = NULL, *new_to_path = NULL; 2608 mode_t mode = 0777; 2609 Attrib curdir; 2610 2611 debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path); 2612 2613 if (depth >= MAX_DIR_DEPTH) { 2614 error("Maximum directory depth exceeded: %d levels", depth); 2615 return -1; 2616 } 2617 2618 if (dirattrib == NULL && 2619 (dirattrib = do_stat(from, from_path, 1)) == NULL) { 2620 error("stat remote \"%s\" failed", from_path); 2621 return -1; 2622 } 2623 if (!S_ISDIR(dirattrib->perm)) { 2624 error("\"%s\" is not a directory", from_path); 2625 return -1; 2626 } 2627 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 2628 mprintf("Retrieving %s\n", from_path); 2629 2630 curdir = *dirattrib; /* dirattrib will be clobbered */ 2631 curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2632 curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2633 if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) { 2634 debug("Origin did not send permissions for " 2635 "directory \"%s\"", to_path); 2636 curdir.perm = S_IWUSR|S_IXUSR; 2637 curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 2638 } 2639 /* We need to be able to write to the directory while we transfer it */ 2640 mode = curdir.perm & 01777; 2641 curdir.perm = mode | (S_IWUSR|S_IXUSR); 2642 2643 /* 2644 * sftp lacks a portable status value to match errno EEXIST, 2645 * so if we get a failure back then we must check whether 2646 * the path already existed and is a directory. Ensure we can 2647 * write to the directory we create for the duration of the transfer. 2648 */ 2649 if (do_mkdir(to, to_path, &curdir, 0) != 0) { 2650 if ((dirattrib = do_stat(to, to_path, 0)) == NULL) 2651 return -1; 2652 if (!S_ISDIR(dirattrib->perm)) { 2653 error("\"%s\" exists but is not a directory", to_path); 2654 return -1; 2655 } 2656 } 2657 curdir.perm = mode; 2658 2659 if (do_readdir(from, from_path, &dir_entries) == -1) { 2660 error("origin readdir \"%s\" failed", from_path); 2661 return -1; 2662 } 2663 2664 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 2665 free(new_from_path); 2666 free(new_to_path); 2667 2668 filename = dir_entries[i]->filename; 2669 new_from_path = path_append(from_path, filename); 2670 new_to_path = path_append(to_path, filename); 2671 2672 if (S_ISDIR(dir_entries[i]->a.perm)) { 2673 if (strcmp(filename, ".") == 0 || 2674 strcmp(filename, "..") == 0) 2675 continue; 2676 if (crossload_dir_internal(from, to, 2677 new_from_path, new_to_path, 2678 depth + 1, &(dir_entries[i]->a), preserve_flag, 2679 print_flag, follow_link_flag) == -1) 2680 ret = -1; 2681 } else if (S_ISREG(dir_entries[i]->a.perm) || 2682 (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { 2683 /* 2684 * If this is a symlink then don't send the link's 2685 * Attrib. do_download() will do a FXP_STAT operation 2686 * and get the link target's attributes. 2687 */ 2688 if (do_crossload(from, to, new_from_path, new_to_path, 2689 S_ISLNK(dir_entries[i]->a.perm) ? NULL : 2690 &(dir_entries[i]->a), preserve_flag) == -1) { 2691 error("crossload \"%s\" to \"%s\" failed", 2692 new_from_path, new_to_path); 2693 ret = -1; 2694 } 2695 } else { 2696 logit("origin \"%s\": not a regular file", 2697 new_from_path); 2698 } 2699 } 2700 free(new_to_path); 2701 free(new_from_path); 2702 2703 do_setstat(to, to_path, &curdir); 2704 2705 free_sftp_dirents(dir_entries); 2706 2707 return ret; 2708 } 2709 2710 int 2711 crossload_dir(struct sftp_conn *from, struct sftp_conn *to, 2712 const char *from_path, const char *to_path, 2713 Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) 2714 { 2715 char *from_path_canon; 2716 int ret; 2717 2718 if ((from_path_canon = do_realpath(from, from_path)) == NULL) { 2719 error("crossload \"%s\": path canonicalization failed", 2720 from_path); 2721 return -1; 2722 } 2723 2724 ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0, 2725 dirattrib, preserve_flag, print_flag, follow_link_flag); 2726 free(from_path_canon); 2727 return ret; 2728 } 2729 2730 char * 2731 path_append(const char *p1, const char *p2) 2732 { 2733 char *ret; 2734 size_t len = strlen(p1) + strlen(p2) + 2; 2735 2736 ret = xmalloc(len); 2737 strlcpy(ret, p1, len); 2738 if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') 2739 strlcat(ret, "/", len); 2740 strlcat(ret, p2, len); 2741 2742 return(ret); 2743 } 2744 2745 char * 2746 make_absolute(char *p, const char *pwd) 2747 { 2748 char *abs_str; 2749 2750 /* Derelativise */ 2751 if (p && !path_absolute(p)) { 2752 abs_str = path_append(pwd, p); 2753 free(p); 2754 return(abs_str); 2755 } else 2756 return(p); 2757 } 2758 2759 int 2760 remote_is_dir(struct sftp_conn *conn, const char *path) 2761 { 2762 Attrib *a; 2763 2764 /* XXX: report errors? */ 2765 if ((a = do_stat(conn, path, 1)) == NULL) 2766 return(0); 2767 if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) 2768 return(0); 2769 return(S_ISDIR(a->perm)); 2770 } 2771 2772 2773 int 2774 local_is_dir(const char *path) 2775 { 2776 struct stat sb; 2777 2778 /* XXX: report errors? */ 2779 if (stat(path, &sb) == -1) 2780 return(0); 2781 2782 return(S_ISDIR(sb.st_mode)); 2783 } 2784 2785 /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ 2786 int 2787 globpath_is_dir(const char *pathname) 2788 { 2789 size_t l = strlen(pathname); 2790 2791 return l > 0 && pathname[l - 1] == '/'; 2792 } 2793 2794