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