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