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