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