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