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