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