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