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