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