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