1 /* $NetBSD: sftp-client.c,v 1.40 2026/09/21 21:31:00 christos Exp $ */ 2 /* $OpenBSD: sftp-client.c,v 1.186 2026/06/29 01:53:21 djm 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.40 2026/09/21 21:31:00 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, seen_zerolen = 0; 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 if (len == 0) { 1734 if (seen_zerolen) 1735 fatal_f("server sent zero data length"); 1736 seen_zerolen = 1; 1737 } 1738 lmodified = 1; 1739 if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || 1740 atomicio(vwrite, local_fd, data, len) != len) && 1741 !write_error) { 1742 write_errno = errno; 1743 write_error = 1; 1744 max_req = 0; 1745 } else { 1746 /* 1747 * Track both the highest offset acknowledged 1748 * and the highest *contiguous* offset 1749 * acknowledged. 1750 * We'll need the latter for ftruncate()ing 1751 * interrupted transfers. 1752 */ 1753 if (maxack < req->offset + len) 1754 maxack = req->offset + len; 1755 if (!reordered && req->offset <= highwater) 1756 highwater = maxack; 1757 else if (!reordered && req->offset > highwater) 1758 reordered = 1; 1759 } 1760 progress_counter += len; 1761 free(data); 1762 1763 if (len == req->len) { 1764 TAILQ_REMOVE(&requests, req, tq); 1765 free(req); 1766 num_req--; 1767 } else { 1768 /* Resend the request for the missing data */ 1769 debug3("Short data block, re-requesting " 1770 "%llu -> %llu (%2d)", 1771 (unsigned long long)req->offset + len, 1772 (unsigned long long)req->offset + 1773 req->len - 1, num_req); 1774 req->id = conn->msg_id++; 1775 req->len -= len; 1776 req->offset += len; 1777 send_read_request(conn, req->id, 1778 req->offset, req->len, handle, handle_len); 1779 /* Reduce the request size */ 1780 if (len < buflen) 1781 buflen = MAXIMUM(MIN_READ_SIZE, len); 1782 } 1783 if (max_req > 0) { /* max_req = 0 iff EOF received */ 1784 if (size > 0 && offset > size) { 1785 /* Only one request at a time 1786 * after the expected EOF */ 1787 debug3("Finish at %llu (%2d)", 1788 (unsigned long long)offset, 1789 num_req); 1790 max_req = 1; 1791 } else if (max_req < conn->num_requests) { 1792 ++max_req; 1793 } 1794 } 1795 break; 1796 default: 1797 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 1798 SSH2_FXP_DATA, type); 1799 } 1800 } 1801 1802 if (showprogress && size) 1803 stop_progress_meter(); 1804 1805 /* Sanity check */ 1806 if (TAILQ_FIRST(&requests) != NULL) 1807 fatal("Transfer complete, but requests still in queue"); 1808 1809 if (!read_error && !write_error && !interrupted) { 1810 /* we got everything */ 1811 highwater = maxack; 1812 } 1813 1814 /* 1815 * Truncate at highest contiguous point to avoid holes on interrupt, 1816 * or unconditionally if writing in place. 1817 */ 1818 if (inplace_flag || read_error || write_error || interrupted) { 1819 if (reordered && resume_flag && 1820 (read_error || write_error || interrupted)) { 1821 error("Unable to resume download of \"%s\": " 1822 "server reordered requests", local_path); 1823 } 1824 debug("truncating at %llu", (unsigned long long)highwater); 1825 if (ftruncate(local_fd, highwater) == -1) 1826 error("local ftruncate \"%s\": %s", local_path, 1827 strerror(errno)); 1828 } 1829 if (read_error) { 1830 error("read remote \"%s\" : %s", remote_path, fx2txt(status)); 1831 status = -1; 1832 sftp_close(conn, handle, handle_len); 1833 } else if (write_error) { 1834 error("write local \"%s\": %s", local_path, 1835 strerror(write_errno)); 1836 status = SSH2_FX_FAILURE; 1837 sftp_close(conn, handle, handle_len); 1838 } else { 1839 if (sftp_close(conn, handle, handle_len) != 0 || interrupted) 1840 status = SSH2_FX_FAILURE; 1841 else 1842 status = SSH2_FX_OK; 1843 /* Override umask and utimes if asked */ 1844 if (preserve_flag && fchmod(local_fd, mode) == -1) 1845 error("local chmod \"%s\": %s", local_path, 1846 strerror(errno)); 1847 if (preserve_flag && 1848 (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { 1849 struct timeval tv[2]; 1850 tv[0].tv_sec = a->atime; 1851 tv[1].tv_sec = a->mtime; 1852 tv[0].tv_usec = tv[1].tv_usec = 0; 1853 if (utimes(local_path, tv) == -1) 1854 error("local set times \"%s\": %s", 1855 local_path, strerror(errno)); 1856 } 1857 if (resume_flag && !lmodified) 1858 logit("File \"%s\" was not modified", local_path); 1859 else if (fsync_flag) { 1860 debug("syncing \"%s\"", local_path); 1861 if (fsync(local_fd) == -1) 1862 error("local sync \"%s\": %s", 1863 local_path, strerror(errno)); 1864 } 1865 } 1866 close(local_fd); 1867 sshbuf_free(msg); 1868 free(handle); 1869 1870 return status == SSH2_FX_OK ? 0 : -1; 1871 } 1872 1873 static int 1874 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1875 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 1876 int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) 1877 { 1878 int i, ret = 0; 1879 SFTP_DIRENT **dir_entries; 1880 char *filename, *new_src = NULL, *new_dst = NULL; 1881 mode_t mode = 0777, tmpmode = mode; 1882 Attrib *a, ldirattrib, lsym; 1883 1884 if (depth >= MAX_DIR_DEPTH) { 1885 error("Maximum directory depth exceeded: %d levels", depth); 1886 return -1; 1887 } 1888 1889 debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst); 1890 1891 if (dirattrib == NULL) { 1892 if (sftp_stat(conn, src, 1, &ldirattrib) != 0) { 1893 error("stat remote \"%s\" directory failed", src); 1894 return -1; 1895 } 1896 dirattrib = &ldirattrib; 1897 } 1898 if (!S_ISDIR(dirattrib->perm)) { 1899 error("\"%s\" is not a directory", src); 1900 return -1; 1901 } 1902 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 1903 mprintf("Retrieving %s\n", src); 1904 1905 if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 1906 mode = dirattrib->perm & 01777; 1907 tmpmode = mode | (S_IWUSR|S_IXUSR); 1908 } else { 1909 debug("download remote \"%s\": server " 1910 "did not send permissions", dst); 1911 } 1912 1913 if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { 1914 error("mkdir %s: %s", dst, strerror(errno)); 1915 return -1; 1916 } 1917 1918 if (sftp_readdir(conn, src, &dir_entries) == -1) { 1919 error("remote readdir \"%s\" failed", src); 1920 return -1; 1921 } 1922 1923 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 1924 free(new_dst); 1925 free(new_src); 1926 1927 filename = dir_entries[i]->filename; 1928 new_dst = sftp_path_append(dst, filename); 1929 new_src = sftp_path_append(src, filename); 1930 1931 a = &dir_entries[i]->a; 1932 if (S_ISLNK(a->perm)) { 1933 if (!follow_link_flag) { 1934 logit("download \"%s\": not a regular file", 1935 new_src); 1936 continue; 1937 } 1938 /* Replace the stat contents with the symlink target */ 1939 if (sftp_stat(conn, new_src, 1, &lsym) != 0) { 1940 logit("remote stat \"%s\" failed", new_src); 1941 ret = -1; 1942 continue; 1943 } 1944 a = &lsym; 1945 } 1946 1947 if (S_ISDIR(a->perm)) { 1948 if (strcmp(filename, ".") == 0 || 1949 strcmp(filename, "..") == 0) 1950 continue; 1951 if (download_dir_internal(conn, new_src, new_dst, 1952 depth + 1, a, preserve_flag, 1953 print_flag, resume_flag, 1954 fsync_flag, follow_link_flag, inplace_flag) == -1) 1955 ret = -1; 1956 } else if (S_ISREG(a->perm)) { 1957 if (sftp_download(conn, new_src, new_dst, a, 1958 preserve_flag, resume_flag, fsync_flag, 1959 inplace_flag) == -1) { 1960 error("Download of file %s to %s failed", 1961 new_src, new_dst); 1962 ret = -1; 1963 } 1964 } else 1965 logit("download \"%s\": not a regular file", new_src); 1966 1967 } 1968 free(new_dst); 1969 free(new_src); 1970 1971 if (preserve_flag) { 1972 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1973 struct timeval tv[2]; 1974 tv[0].tv_sec = dirattrib->atime; 1975 tv[1].tv_sec = dirattrib->mtime; 1976 tv[0].tv_usec = tv[1].tv_usec = 0; 1977 if (utimes(dst, tv) == -1) 1978 error("local set times on \"%s\": %s", 1979 dst, strerror(errno)); 1980 } else 1981 debug("Server did not send times for directory " 1982 "\"%s\"", dst); 1983 } 1984 1985 if (mode != tmpmode && chmod(dst, mode) == -1) 1986 error("local chmod directory \"%s\": %s", dst, 1987 strerror(errno)); 1988 1989 sftp_free_dirents(dir_entries); 1990 1991 return ret; 1992 } 1993 1994 int 1995 sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst, 1996 Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, 1997 int fsync_flag, int follow_link_flag, int inplace_flag) 1998 { 1999 char *src_canon; 2000 int ret; 2001 2002 if ((src_canon = sftp_realpath(conn, src)) == NULL) { 2003 error("download \"%s\": path canonicalization failed", src); 2004 return -1; 2005 } 2006 2007 ret = download_dir_internal(conn, src_canon, dst, 0, 2008 dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, 2009 follow_link_flag, inplace_flag); 2010 free(src_canon); 2011 return ret; 2012 } 2013 2014 int 2015 sftp_upload(struct sftp_conn *conn, const char *local_path, 2016 const char *remote_path, int preserve_flag, int resume, 2017 int fsync_flag, int inplace_flag) 2018 { 2019 int r, local_fd; 2020 u_int openmode, id, status = SSH2_FX_OK, status2, reordered = 0; 2021 off_t offset, progress_counter; 2022 u_char type, *handle, *data; 2023 struct sshbuf *msg; 2024 struct stat sb; 2025 Attrib a, t, c; 2026 uint32_t startid, ackid; 2027 uint64_t highwater = 0, maxack = 0; 2028 struct request *ack = NULL; 2029 struct requests acks; 2030 size_t handle_len; 2031 2032 debug2_f("upload local \"%s\" to remote \"%s\"", 2033 local_path, remote_path); 2034 2035 TAILQ_INIT(&acks); 2036 2037 if ((local_fd = open(local_path, O_RDONLY)) == -1) { 2038 error("open local \"%s\": %s", local_path, strerror(errno)); 2039 return(-1); 2040 } 2041 if (fstat(local_fd, &sb) == -1) { 2042 error("fstat local \"%s\": %s", local_path, strerror(errno)); 2043 close(local_fd); 2044 return(-1); 2045 } 2046 if (!S_ISREG(sb.st_mode)) { 2047 error("local \"%s\" is not a regular file", local_path); 2048 close(local_fd); 2049 return(-1); 2050 } 2051 stat_to_attrib(&sb, &a); 2052 2053 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2054 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2055 a.perm &= 0777; 2056 if (!preserve_flag) 2057 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2058 2059 if (resume) { 2060 /* Get remote file size if it exists */ 2061 if (sftp_stat(conn, remote_path, 0, &c) != 0) { 2062 close(local_fd); 2063 return -1; 2064 } 2065 2066 if ((off_t)c.size >= sb.st_size) { 2067 error("resume \"%s\": destination file " 2068 "same size or larger", local_path); 2069 close(local_fd); 2070 return -1; 2071 } 2072 2073 if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) { 2074 close(local_fd); 2075 return -1; 2076 } 2077 highwater = c.size; 2078 } 2079 2080 openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT; 2081 if (resume) 2082 openmode |= SSH2_FXF_APPEND; 2083 else if (!inplace_flag) 2084 openmode |= SSH2_FXF_TRUNC; 2085 2086 /* Send open request */ 2087 if (send_open(conn, remote_path, "dest", openmode, &a, 2088 &handle, &handle_len) != 0) { 2089 close(local_fd); 2090 return -1; 2091 } 2092 2093 id = conn->msg_id; 2094 startid = ackid = id + 1; 2095 data = xmalloc(conn->upload_buflen); 2096 2097 /* Read from local and write to remote */ 2098 offset = progress_counter = (resume ? c.size : 0); 2099 if (showprogress) { 2100 start_progress_meter(progress_meter_path(local_path), 2101 sb.st_size, &progress_counter); 2102 } 2103 2104 if ((msg = sshbuf_new()) == NULL) 2105 fatal_f("sshbuf_new failed"); 2106 for (;;) { 2107 int len; 2108 2109 /* 2110 * Can't use atomicio here because it returns 0 on EOF, 2111 * thus losing the last block of the file. 2112 * Simulate an EOF on interrupt, allowing ACKs from the 2113 * server to drain. 2114 */ 2115 if (interrupted || status != SSH2_FX_OK) 2116 len = 0; 2117 else do 2118 len = read(local_fd, data, conn->upload_buflen); 2119 while ((len == -1) && (errno == EINTR || errno == EAGAIN)); 2120 2121 if (len == -1) { 2122 fatal("read local \"%s\": %s", 2123 local_path, strerror(errno)); 2124 } else if (len != 0) { 2125 ack = request_enqueue(&acks, ++id, len, offset); 2126 sshbuf_reset(msg); 2127 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 2128 (r = sshbuf_put_u32(msg, ack->id)) != 0 || 2129 (r = sshbuf_put_string(msg, handle, 2130 handle_len)) != 0 || 2131 (r = sshbuf_put_u64(msg, offset)) != 0 || 2132 (r = sshbuf_put_string(msg, data, len)) != 0) 2133 fatal_fr(r, "compose"); 2134 send_msg(conn, msg); 2135 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 2136 id, (unsigned long long)offset, len); 2137 } else if (TAILQ_FIRST(&acks) == NULL) 2138 break; 2139 2140 if (ack == NULL) 2141 fatal("Unexpected ACK %u", id); 2142 2143 if (id == startid || len == 0 || 2144 id - ackid >= conn->num_requests) { 2145 u_int rid; 2146 2147 sshbuf_reset(msg); 2148 get_msg(conn, msg); 2149 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2150 (r = sshbuf_get_u32(msg, &rid)) != 0) 2151 fatal_fr(r, "parse"); 2152 2153 if (type != SSH2_FXP_STATUS) 2154 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 2155 "got %d", SSH2_FXP_STATUS, type); 2156 2157 if ((r = sshbuf_get_u32(msg, &status2)) != 0) 2158 fatal_fr(r, "parse status"); 2159 debug3("SSH2_FXP_STATUS %u", status2); 2160 if (status2 != SSH2_FX_OK) 2161 status = status2; /* remember errors */ 2162 2163 /* Find the request in our queue */ 2164 if ((ack = request_find(&acks, rid)) == NULL) 2165 fatal("Can't find request for ID %u", rid); 2166 TAILQ_REMOVE(&acks, ack, tq); 2167 debug3("In write loop, ack for %u %zu bytes at %lld", 2168 ack->id, ack->len, (unsigned long long)ack->offset); 2169 ++ackid; 2170 progress_counter += ack->len; 2171 /* 2172 * Track both the highest offset acknowledged and the 2173 * highest *contiguous* offset acknowledged. 2174 * We'll need the latter for ftruncate()ing 2175 * interrupted transfers. 2176 */ 2177 if (maxack < ack->offset + ack->len) 2178 maxack = ack->offset + ack->len; 2179 if (!reordered && ack->offset <= highwater) 2180 highwater = maxack; 2181 else if (!reordered && ack->offset > highwater) { 2182 debug3_f("server reordered ACKs"); 2183 reordered = 1; 2184 } 2185 free(ack); 2186 } 2187 offset += len; 2188 if (offset < 0) 2189 fatal_f("offset < 0"); 2190 } 2191 sshbuf_free(msg); 2192 2193 if (showprogress) 2194 stop_progress_meter(); 2195 free(data); 2196 2197 if (status == SSH2_FX_OK && !interrupted) { 2198 /* we got everything */ 2199 highwater = maxack; 2200 } 2201 if (status != SSH2_FX_OK) { 2202 error("write remote \"%s\": %s", remote_path, fx2txt(status)); 2203 status = SSH2_FX_FAILURE; 2204 } 2205 2206 if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { 2207 debug("truncating at %llu", (unsigned long long)highwater); 2208 attrib_clear(&t); 2209 t.flags = SSH2_FILEXFER_ATTR_SIZE; 2210 t.size = highwater; 2211 sftp_fsetstat(conn, handle, handle_len, &t); 2212 } 2213 2214 if (close(local_fd) == -1) { 2215 error("close local \"%s\": %s", local_path, strerror(errno)); 2216 status = SSH2_FX_FAILURE; 2217 } 2218 2219 /* Override umask and utimes if asked */ 2220 if (preserve_flag) 2221 sftp_fsetstat(conn, handle, handle_len, &a); 2222 2223 if (fsync_flag) 2224 (void)sftp_fsync(conn, handle, handle_len); 2225 2226 if (sftp_close(conn, handle, handle_len) != 0) 2227 status = SSH2_FX_FAILURE; 2228 2229 free(handle); 2230 2231 return status == SSH2_FX_OK ? 0 : -1; 2232 } 2233 2234 static int 2235 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 2236 int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, 2237 int follow_link_flag, int inplace_flag) 2238 { 2239 int created = 0, ret = 0; 2240 DIR *dirp; 2241 struct dirent *dp; 2242 char *filename, *new_src = NULL, *new_dst = NULL; 2243 struct stat sb; 2244 Attrib a, dirattrib; 2245 uint32_t saved_perm; 2246 2247 debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst); 2248 2249 if (depth >= MAX_DIR_DEPTH) { 2250 error("Maximum directory depth exceeded: %d levels", depth); 2251 return -1; 2252 } 2253 2254 if (stat(src, &sb) == -1) { 2255 error("stat local \"%s\": %s", src, strerror(errno)); 2256 return -1; 2257 } 2258 if (!S_ISDIR(sb.st_mode)) { 2259 error("\"%s\" is not a directory", src); 2260 return -1; 2261 } 2262 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 2263 mprintf("Entering %s\n", src); 2264 2265 stat_to_attrib(&sb, &a); 2266 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2267 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2268 a.perm &= 01777; 2269 if (!preserve_flag) 2270 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2271 2272 /* 2273 * sftp lacks a portable status value to match errno EEXIST, 2274 * so if we get a failure back then we must check whether 2275 * the path already existed and is a directory. Ensure we can 2276 * write to the directory we create for the duration of the transfer. 2277 */ 2278 saved_perm = a.perm; 2279 a.perm |= (S_IWUSR|S_IXUSR); 2280 if (sftp_mkdir(conn, dst, &a, 0) == 0) 2281 created = 1; 2282 else { 2283 if (sftp_stat(conn, dst, 0, &dirattrib) != 0) 2284 return -1; 2285 if (!S_ISDIR(dirattrib.perm)) { 2286 error("\"%s\" exists but is not a directory", dst); 2287 return -1; 2288 } 2289 } 2290 a.perm = saved_perm; 2291 2292 if ((dirp = opendir(src)) == NULL) { 2293 error("local opendir \"%s\": %s", src, strerror(errno)); 2294 return -1; 2295 } 2296 2297 while (((dp = readdir(dirp)) != NULL) && !interrupted) { 2298 if (dp->d_ino == 0) 2299 continue; 2300 free(new_dst); 2301 free(new_src); 2302 filename = dp->d_name; 2303 new_dst = sftp_path_append(dst, filename); 2304 new_src = sftp_path_append(src, filename); 2305 2306 if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) 2307 continue; 2308 if (lstat(new_src, &sb) == -1) { 2309 logit("local lstat \"%s\": %s", filename, 2310 strerror(errno)); 2311 ret = -1; 2312 continue; 2313 } 2314 if (S_ISLNK(sb.st_mode)) { 2315 if (!follow_link_flag) { 2316 logit("%s: not a regular file", filename); 2317 continue; 2318 } 2319 /* Replace the stat contents with the symlink target */ 2320 if (stat(new_src, &sb) == -1) { 2321 logit("local stat \"%s\": %s", filename, 2322 strerror(errno)); 2323 ret = -1; 2324 continue; 2325 } 2326 } 2327 if (S_ISDIR(sb.st_mode)) { 2328 if (upload_dir_internal(conn, new_src, new_dst, 2329 depth + 1, preserve_flag, print_flag, resume, 2330 fsync_flag, follow_link_flag, inplace_flag) == -1) 2331 ret = -1; 2332 } else if (S_ISREG(sb.st_mode)) { 2333 if (sftp_upload(conn, new_src, new_dst, 2334 preserve_flag, resume, fsync_flag, 2335 inplace_flag) == -1) { 2336 error("upload \"%s\" to \"%s\" failed", 2337 new_src, new_dst); 2338 ret = -1; 2339 } 2340 } else 2341 logit("%s: not a regular file", filename); 2342 } 2343 free(new_dst); 2344 free(new_src); 2345 2346 if (created || preserve_flag) 2347 sftp_setstat(conn, dst, &a); 2348 2349 (void) closedir(dirp); 2350 return ret; 2351 } 2352 2353 int 2354 sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst, 2355 int preserve_flag, int print_flag, int resume, int fsync_flag, 2356 int follow_link_flag, int inplace_flag) 2357 { 2358 char *dst_canon; 2359 int ret; 2360 2361 if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { 2362 error("upload \"%s\": path canonicalization failed", dst); 2363 return -1; 2364 } 2365 2366 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 2367 print_flag, resume, fsync_flag, follow_link_flag, inplace_flag); 2368 2369 free(dst_canon); 2370 return ret; 2371 } 2372 2373 static void 2374 handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, 2375 u_int *nreqsp, int *write_errorp) 2376 { 2377 struct sshbuf *msg; 2378 u_char type; 2379 u_int id, status; 2380 int r; 2381 struct pollfd pfd; 2382 2383 if ((msg = sshbuf_new()) == NULL) 2384 fatal_f("sshbuf_new failed"); 2385 2386 /* Try to eat replies from the upload side */ 2387 while (*nreqsp > 0) { 2388 debug3_f("%u outstanding replies", *nreqsp); 2389 if (!synchronous) { 2390 /* Bail out if no data is ready to be read */ 2391 pfd.fd = to->fd_in; 2392 pfd.events = POLLIN; 2393 if ((r = poll(&pfd, 1, 0)) == -1) { 2394 if (errno == EINTR) 2395 break; 2396 fatal_f("poll: %s", strerror(errno)); 2397 } else if (r == 0) 2398 break; /* fd not ready */ 2399 } 2400 sshbuf_reset(msg); 2401 get_msg(to, msg); 2402 2403 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2404 (r = sshbuf_get_u32(msg, &id)) != 0) 2405 fatal_fr(r, "dest parse"); 2406 debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp); 2407 if (type != SSH2_FXP_STATUS) { 2408 fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d", 2409 SSH2_FXP_STATUS, type); 2410 } 2411 if ((r = sshbuf_get_u32(msg, &status)) != 0) 2412 fatal_fr(r, "parse dest status"); 2413 debug3("dest SSH2_FXP_STATUS %u", status); 2414 if (status != SSH2_FX_OK) { 2415 /* record first error */ 2416 if (*write_errorp == 0) 2417 *write_errorp = status; 2418 } 2419 /* 2420 * XXX this doesn't do full reply matching like sftp_upload and 2421 * so cannot gracefully truncate terminated uploads at a 2422 * high-water mark. ATM the only caller of this function (scp) 2423 * doesn't support transfer resumption, so this doesn't matter 2424 * a whole lot. 2425 * 2426 * To be safe, sftp_crossload truncates the destination file to 2427 * zero length on upload failure, since we can't trust the 2428 * server not to have reordered replies that could have 2429 * inserted holes where none existed in the source file. 2430 * 2431 * XXX we could get a more accurate progress bar if we updated 2432 * the counter based on the reply from the destination... 2433 */ 2434 (*nreqsp)--; 2435 } 2436 debug3_f("done: %u outstanding replies", *nreqsp); 2437 sshbuf_free(msg); 2438 } 2439 2440 int 2441 sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, 2442 const char *from_path, const char *to_path, 2443 Attrib *a, int preserve_flag) 2444 { 2445 struct sshbuf *msg; 2446 int write_error, read_error, r, seen_zerolen = 0; 2447 uint64_t offset = 0, size; 2448 u_int id, buflen, num_req, max_req, status = SSH2_FX_OK; 2449 u_int num_upload_req; 2450 off_t progress_counter; 2451 u_char *from_handle, *to_handle; 2452 size_t from_handle_len, to_handle_len; 2453 struct requests requests; 2454 struct request *req; 2455 u_char type; 2456 Attrib attr; 2457 2458 debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path); 2459 2460 TAILQ_INIT(&requests); 2461 2462 if (a == NULL) { 2463 if (sftp_stat(from, from_path, 0, &attr) != 0) 2464 return -1; 2465 a = &attr; 2466 } 2467 2468 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 2469 (!S_ISREG(a->perm))) { 2470 error("download \"%s\": not a regular file", from_path); 2471 return(-1); 2472 } 2473 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 2474 size = a->size; 2475 else 2476 size = 0; 2477 2478 buflen = from->download_buflen; 2479 if (buflen > to->upload_buflen) 2480 buflen = to->upload_buflen; 2481 2482 /* Send open request to read side */ 2483 if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL, 2484 &from_handle, &from_handle_len) != 0) 2485 return -1; 2486 2487 /* Send open request to write side */ 2488 a->flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2489 a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2490 a->perm &= 0777; 2491 if (!preserve_flag) 2492 a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2493 if (send_open(to, to_path, "dest", 2494 SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, 2495 &to_handle, &to_handle_len) != 0) { 2496 sftp_close(from, from_handle, from_handle_len); 2497 return -1; 2498 } 2499 2500 /* Read from remote "from" and write to remote "to" */ 2501 offset = 0; 2502 write_error = read_error = num_req = num_upload_req = 0; 2503 max_req = 1; 2504 progress_counter = 0; 2505 2506 if (showprogress && size != 0) { 2507 start_progress_meter(progress_meter_path(from_path), 2508 size, &progress_counter); 2509 } 2510 if ((msg = sshbuf_new()) == NULL) 2511 fatal_f("sshbuf_new failed"); 2512 while (num_req > 0 || max_req > 0) { 2513 u_char *data; 2514 size_t len; 2515 2516 /* 2517 * Simulate EOF on interrupt: stop sending new requests and 2518 * allow outstanding requests to drain gracefully 2519 */ 2520 if (interrupted) { 2521 if (num_req == 0) /* If we haven't started yet... */ 2522 break; 2523 max_req = 0; 2524 } 2525 2526 /* Send some more requests */ 2527 while (num_req < max_req) { 2528 debug3("Request range %llu -> %llu (%d/%d)", 2529 (unsigned long long)offset, 2530 (unsigned long long)offset + buflen - 1, 2531 num_req, max_req); 2532 req = request_enqueue(&requests, from->msg_id++, 2533 buflen, offset); 2534 offset += buflen; 2535 num_req++; 2536 send_read_request(from, req->id, req->offset, 2537 req->len, from_handle, from_handle_len); 2538 } 2539 2540 /* Try to eat replies from the upload side (nonblocking) */ 2541 handle_dest_replies(to, to_path, 0, 2542 &num_upload_req, &write_error); 2543 2544 sshbuf_reset(msg); 2545 get_msg(from, msg); 2546 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2547 (r = sshbuf_get_u32(msg, &id)) != 0) 2548 fatal_fr(r, "parse"); 2549 debug3("Received origin reply T:%u I:%u R:%d", 2550 type, id, max_req); 2551 2552 /* Find the request in our queue */ 2553 if ((req = request_find(&requests, id)) == NULL) 2554 fatal("Unexpected reply %u", id); 2555 2556 switch (type) { 2557 case SSH2_FXP_STATUS: 2558 if ((r = sshbuf_get_u32(msg, &status)) != 0) 2559 fatal_fr(r, "parse status"); 2560 if (status != SSH2_FX_EOF) 2561 read_error = 1; 2562 max_req = 0; 2563 TAILQ_REMOVE(&requests, req, tq); 2564 free(req); 2565 num_req--; 2566 break; 2567 case SSH2_FXP_DATA: 2568 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 2569 fatal_fr(r, "parse data"); 2570 debug3("Received data %llu -> %llu", 2571 (unsigned long long)req->offset, 2572 (unsigned long long)req->offset + len - 1); 2573 if (len > req->len) 2574 fatal("Received more data than asked for " 2575 "%zu > %zu", len, req->len); 2576 if (len == 0) { 2577 if (seen_zerolen) 2578 fatal_f("server sent zero data length"); 2579 seen_zerolen = 1; 2580 } 2581 2582 /* Write this chunk out to the destination */ 2583 sshbuf_reset(msg); 2584 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 2585 (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 || 2586 (r = sshbuf_put_string(msg, to_handle, 2587 to_handle_len)) != 0 || 2588 (r = sshbuf_put_u64(msg, req->offset)) != 0 || 2589 (r = sshbuf_put_string(msg, data, len)) != 0) 2590 fatal_fr(r, "compose write"); 2591 send_msg(to, msg); 2592 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu", 2593 id, (unsigned long long)offset, len); 2594 num_upload_req++; 2595 progress_counter += len; 2596 free(data); 2597 2598 if (len == req->len) { 2599 TAILQ_REMOVE(&requests, req, tq); 2600 free(req); 2601 num_req--; 2602 } else { 2603 /* Resend the request for the missing data */ 2604 debug3("Short data block, re-requesting " 2605 "%llu -> %llu (%2d)", 2606 (unsigned long long)req->offset + len, 2607 (unsigned long long)req->offset + 2608 req->len - 1, num_req); 2609 req->id = from->msg_id++; 2610 req->len -= len; 2611 req->offset += len; 2612 send_read_request(from, req->id, 2613 req->offset, req->len, 2614 from_handle, from_handle_len); 2615 /* Reduce the request size */ 2616 if (len < buflen) 2617 buflen = MAXIMUM(MIN_READ_SIZE, len); 2618 } 2619 if (max_req > 0) { /* max_req = 0 iff EOF received */ 2620 if (size > 0 && offset > size) { 2621 /* Only one request at a time 2622 * after the expected EOF */ 2623 debug3("Finish at %llu (%2d)", 2624 (unsigned long long)offset, 2625 num_req); 2626 max_req = 1; 2627 } else if (max_req < from->num_requests) { 2628 ++max_req; 2629 } 2630 } 2631 break; 2632 default: 2633 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 2634 SSH2_FXP_DATA, type); 2635 } 2636 } 2637 2638 if (showprogress && size) 2639 stop_progress_meter(); 2640 2641 /* Drain replies from the server (blocking) */ 2642 debug3_f("waiting for %u replies from destination", num_upload_req); 2643 handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error); 2644 2645 /* Sanity check */ 2646 if (TAILQ_FIRST(&requests) != NULL) 2647 fatal("Transfer complete, but requests still in queue"); 2648 /* Truncate at 0 length on interrupt or error to avoid holes at dest */ 2649 if (read_error || write_error || interrupted) { 2650 debug("truncating \"%s\" at 0", to_path); 2651 sftp_close(to, to_handle, to_handle_len); 2652 free(to_handle); 2653 if (send_open(to, to_path, "dest", 2654 SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, 2655 &to_handle, &to_handle_len) != 0) { 2656 error("dest truncate \"%s\" failed", to_path); 2657 to_handle = NULL; 2658 } 2659 } 2660 if (read_error) { 2661 error("read origin \"%s\": %s", from_path, fx2txt(status)); 2662 status = -1; 2663 sftp_close(from, from_handle, from_handle_len); 2664 if (to_handle != NULL) 2665 sftp_close(to, to_handle, to_handle_len); 2666 } else if (write_error) { 2667 error("write dest \"%s\": %s", to_path, fx2txt(write_error)); 2668 status = SSH2_FX_FAILURE; 2669 sftp_close(from, from_handle, from_handle_len); 2670 if (to_handle != NULL) 2671 sftp_close(to, to_handle, to_handle_len); 2672 } else { 2673 if (sftp_close(from, from_handle, from_handle_len) != 0 || 2674 interrupted) 2675 status = -1; 2676 else 2677 status = SSH2_FX_OK; 2678 if (to_handle != NULL) { 2679 /* Need to resend utimes after write */ 2680 if (preserve_flag) 2681 sftp_fsetstat(to, to_handle, to_handle_len, a); 2682 sftp_close(to, to_handle, to_handle_len); 2683 } 2684 } 2685 sshbuf_free(msg); 2686 free(from_handle); 2687 free(to_handle); 2688 2689 return status == SSH2_FX_OK ? 0 : -1; 2690 } 2691 2692 static int 2693 crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, 2694 const char *from_path, const char *to_path, 2695 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 2696 int follow_link_flag) 2697 { 2698 int i, ret = 0, created = 0; 2699 SFTP_DIRENT **dir_entries; 2700 char *filename, *new_from_path = NULL, *new_to_path = NULL; 2701 mode_t mode = 0777; 2702 Attrib *a, curdir, ldirattrib, newdir, lsym; 2703 2704 debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path); 2705 2706 if (depth >= MAX_DIR_DEPTH) { 2707 error("Maximum directory depth exceeded: %d levels", depth); 2708 return -1; 2709 } 2710 2711 if (dirattrib == NULL) { 2712 if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) { 2713 error("stat remote \"%s\" failed", from_path); 2714 return -1; 2715 } 2716 dirattrib = &ldirattrib; 2717 } 2718 if (!S_ISDIR(dirattrib->perm)) { 2719 error("\"%s\" is not a directory", from_path); 2720 return -1; 2721 } 2722 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 2723 mprintf("Retrieving %s\n", from_path); 2724 2725 curdir = *dirattrib; /* dirattrib will be clobbered */ 2726 curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2727 curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2728 if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) { 2729 debug("Origin did not send permissions for " 2730 "directory \"%s\"", to_path); 2731 curdir.perm = S_IWUSR|S_IXUSR; 2732 curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 2733 } 2734 /* We need to be able to write to the directory while we transfer it */ 2735 mode = curdir.perm & 01777; 2736 curdir.perm = mode | (S_IWUSR|S_IXUSR); 2737 2738 /* 2739 * sftp lacks a portable status value to match errno EEXIST, 2740 * so if we get a failure back then we must check whether 2741 * the path already existed and is a directory. Ensure we can 2742 * write to the directory we create for the duration of the transfer. 2743 */ 2744 if (sftp_mkdir(to, to_path, &curdir, 0) == 0) 2745 created = 1; 2746 else { 2747 if (sftp_stat(to, to_path, 0, &newdir) != 0) 2748 return -1; 2749 if (!S_ISDIR(newdir.perm)) { 2750 error("\"%s\" exists but is not a directory", to_path); 2751 return -1; 2752 } 2753 } 2754 curdir.perm = mode; 2755 2756 if (sftp_readdir(from, from_path, &dir_entries) == -1) { 2757 error("origin readdir \"%s\" failed", from_path); 2758 return -1; 2759 } 2760 2761 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 2762 free(new_from_path); 2763 free(new_to_path); 2764 2765 filename = dir_entries[i]->filename; 2766 new_from_path = sftp_path_append(from_path, filename); 2767 new_to_path = sftp_path_append(to_path, filename); 2768 2769 a = &dir_entries[i]->a; 2770 if (S_ISLNK(a->perm)) { 2771 if (!follow_link_flag) { 2772 logit("%s: not a regular file", filename); 2773 continue; 2774 } 2775 /* Replace the stat contents with the symlink target */ 2776 if (sftp_stat(from, new_from_path, 1, &lsym) != 0) { 2777 logit("remote stat \"%s\" failed", 2778 new_from_path); 2779 ret = -1; 2780 continue; 2781 } 2782 a = &lsym; 2783 } 2784 if (S_ISDIR(a->perm)) { 2785 if (strcmp(filename, ".") == 0 || 2786 strcmp(filename, "..") == 0) 2787 continue; 2788 if (crossload_dir_internal(from, to, 2789 new_from_path, new_to_path, 2790 depth + 1, a, preserve_flag, 2791 print_flag, follow_link_flag) == -1) 2792 ret = -1; 2793 } else if (S_ISREG(a->perm)) { 2794 if (sftp_crossload(from, to, new_from_path, 2795 new_to_path, a, preserve_flag) == -1) { 2796 error("crossload \"%s\" to \"%s\" failed", 2797 new_from_path, new_to_path); 2798 ret = -1; 2799 } 2800 } else { 2801 logit("origin \"%s\": not a regular file", 2802 new_from_path); 2803 } 2804 } 2805 free(new_to_path); 2806 free(new_from_path); 2807 2808 if (created || preserve_flag) 2809 sftp_setstat(to, to_path, &curdir); 2810 2811 sftp_free_dirents(dir_entries); 2812 2813 return ret; 2814 } 2815 2816 int 2817 sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to, 2818 const char *from_path, const char *to_path, 2819 Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) 2820 { 2821 char *from_path_canon; 2822 int ret; 2823 2824 if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { 2825 error("crossload \"%s\": path canonicalization failed", 2826 from_path); 2827 return -1; 2828 } 2829 2830 ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0, 2831 dirattrib, preserve_flag, print_flag, follow_link_flag); 2832 free(from_path_canon); 2833 return ret; 2834 } 2835 2836 int 2837 sftp_can_get_users_groups_by_id(struct sftp_conn *conn) 2838 { 2839 return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0; 2840 } 2841 2842 int 2843 sftp_get_users_groups_by_id(struct sftp_conn *conn, 2844 const u_int *uids, u_int nuids, 2845 const u_int *gids, u_int ngids, 2846 char ***usernamesp, char ***groupnamesp) 2847 { 2848 struct sshbuf *msg, *uidbuf, *gidbuf; 2849 u_int i, expected_id, id; 2850 char *name, **usernames = NULL, **groupnames = NULL; 2851 u_char type; 2852 int r; 2853 2854 *usernamesp = *groupnamesp = NULL; 2855 if (!sftp_can_get_users_groups_by_id(conn)) 2856 return SSH_ERR_FEATURE_UNSUPPORTED; 2857 2858 if ((msg = sshbuf_new()) == NULL || 2859 (uidbuf = sshbuf_new()) == NULL || 2860 (gidbuf = sshbuf_new()) == NULL) 2861 fatal_f("sshbuf_new failed"); 2862 expected_id = id = conn->msg_id++; 2863 debug2("Sending SSH2_FXP_EXTENDED(users-groups-by-id (at) openssh.com)"); 2864 for (i = 0; i < nuids; i++) { 2865 if ((r = sshbuf_put_u32(uidbuf, uids[i])) != 0) 2866 fatal_fr(r, "compose uids"); 2867 } 2868 for (i = 0; i < ngids; i++) { 2869 if ((r = sshbuf_put_u32(gidbuf, gids[i])) != 0) 2870 fatal_fr(r, "compose gids"); 2871 } 2872 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 2873 (r = sshbuf_put_u32(msg, id)) != 0 || 2874 (r = sshbuf_put_cstring(msg, 2875 "users-groups-by-id (at) openssh.com")) != 0 || 2876 (r = sshbuf_put_stringb(msg, uidbuf)) != 0 || 2877 (r = sshbuf_put_stringb(msg, gidbuf)) != 0) 2878 fatal_fr(r, "compose"); 2879 send_msg(conn, msg); 2880 get_msg(conn, msg); 2881 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2882 (r = sshbuf_get_u32(msg, &id)) != 0) 2883 fatal_fr(r, "parse"); 2884 if (id != expected_id) 2885 fatal("ID mismatch (%u != %u)", id, expected_id); 2886 if (type == SSH2_FXP_STATUS) { 2887 u_int status; 2888 char *errmsg; 2889 2890 if ((r = sshbuf_get_u32(msg, &status)) != 0 || 2891 (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) 2892 fatal_fr(r, "parse status"); 2893 error("users-groups-by-id %s", 2894 *errmsg == '\0' ? fx2txt(status) : errmsg); 2895 free(errmsg); 2896 sshbuf_free(msg); 2897 sshbuf_free(uidbuf); 2898 sshbuf_free(gidbuf); 2899 return -1; 2900 } else if (type != SSH2_FXP_EXTENDED_REPLY) 2901 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 2902 SSH2_FXP_EXTENDED_REPLY, type); 2903 2904 /* reuse */ 2905 sshbuf_free(uidbuf); 2906 sshbuf_free(gidbuf); 2907 uidbuf = gidbuf = NULL; 2908 if ((r = sshbuf_froms(msg, &uidbuf)) != 0 || 2909 (r = sshbuf_froms(msg, &gidbuf)) != 0) 2910 fatal_fr(r, "parse response"); 2911 if (nuids > 0) { 2912 usernames = xcalloc(nuids, sizeof(*usernames)); 2913 for (i = 0; i < nuids; i++) { 2914 if ((r = sshbuf_get_cstring(uidbuf, &name, NULL)) != 0) 2915 fatal_fr(r, "parse user name"); 2916 /* Handle unresolved names */ 2917 if (*name == '\0') { 2918 free(name); 2919 name = NULL; 2920 } 2921 usernames[i] = name; 2922 } 2923 } 2924 if (ngids > 0) { 2925 groupnames = xcalloc(ngids, sizeof(*groupnames)); 2926 for (i = 0; i < ngids; i++) { 2927 if ((r = sshbuf_get_cstring(gidbuf, &name, NULL)) != 0) 2928 fatal_fr(r, "parse user name"); 2929 /* Handle unresolved names */ 2930 if (*name == '\0') { 2931 free(name); 2932 name = NULL; 2933 } 2934 groupnames[i] = name; 2935 } 2936 } 2937 if (sshbuf_len(uidbuf) != 0) 2938 fatal_f("unexpected extra username data"); 2939 if (sshbuf_len(gidbuf) != 0) 2940 fatal_f("unexpected extra groupname data"); 2941 sshbuf_free(uidbuf); 2942 sshbuf_free(gidbuf); 2943 sshbuf_free(msg); 2944 /* success */ 2945 *usernamesp = usernames; 2946 *groupnamesp = groupnames; 2947 return 0; 2948 } 2949 2950 char * 2951 sftp_path_append(const char *p1, const char *p2) 2952 { 2953 char *ret; 2954 size_t len = strlen(p1) + strlen(p2) + 2; 2955 2956 ret = xmalloc(len); 2957 strlcpy(ret, p1, len); 2958 if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') 2959 strlcat(ret, "/", len); 2960 strlcat(ret, p2, len); 2961 2962 return(ret); 2963 } 2964 2965 /* 2966 * Arg p must be dynamically allocated. It will either be returned or 2967 * freed and a replacement allocated. Caller must free returned string. 2968 */ 2969 char * 2970 sftp_make_absolute(char *p, const char *pwd) 2971 { 2972 char *abs_str; 2973 2974 /* Derelativise */ 2975 if (p && !path_absolute(p)) { 2976 abs_str = sftp_path_append(pwd, p); 2977 free(p); 2978 return(abs_str); 2979 } else 2980 return(p); 2981 } 2982 2983 int 2984 sftp_remote_is_dir(struct sftp_conn *conn, const char *path) 2985 { 2986 Attrib a; 2987 2988 /* XXX: report errors? */ 2989 if (sftp_stat(conn, path, 1, &a) != 0) 2990 return(0); 2991 if (!(a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) 2992 return(0); 2993 return S_ISDIR(a.perm); 2994 } 2995 2996 2997 /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ 2998 int 2999 sftp_globpath_is_dir(const char *pathname) 3000 { 3001 size_t l = strlen(pathname); 3002 3003 return l > 0 && pathname[l - 1] == '/'; 3004 } 3005 3006