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