1 /* $OpenBSD: sftp-client.c,v 1.127 2017/08/11 04:41:08 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 <signal.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include "xmalloc.h" 42 #include "ssherr.h" 43 #include "sshbuf.h" 44 #include "log.h" 45 #include "atomicio.h" 46 #include "progressmeter.h" 47 #include "misc.h" 48 #include "utf8.h" 49 50 #include "sftp.h" 51 #include "sftp-common.h" 52 #include "sftp-client.h" 53 54 extern volatile sig_atomic_t interrupted; 55 extern int showprogress; 56 57 /* Minimum amount of data to read at a time */ 58 #define MIN_READ_SIZE 512 59 60 /* Maximum depth to descend in directory trees */ 61 #define MAX_DIR_DEPTH 64 62 63 struct sftp_conn { 64 int fd_in; 65 int fd_out; 66 u_int transfer_buflen; 67 u_int num_requests; 68 u_int version; 69 u_int msg_id; 70 #define SFTP_EXT_POSIX_RENAME 0x00000001 71 #define SFTP_EXT_STATVFS 0x00000002 72 #define SFTP_EXT_FSTATVFS 0x00000004 73 #define SFTP_EXT_HARDLINK 0x00000008 74 #define SFTP_EXT_FSYNC 0x00000010 75 u_int exts; 76 u_int64_t limit_kbps; 77 struct bwlimit bwlimit_in, bwlimit_out; 78 }; 79 80 static u_char * 81 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 82 const char *errfmt, ...) __attribute__((format(printf, 4, 5))); 83 84 /* ARGSUSED */ 85 static int 86 sftpio(void *_bwlimit, size_t amount) 87 { 88 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; 89 90 bandwidth_limit(bwlimit, amount); 91 return 0; 92 } 93 94 static void 95 send_msg(struct sftp_conn *conn, struct sshbuf *m) 96 { 97 u_char mlen[4]; 98 struct iovec iov[2]; 99 100 if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) 101 fatal("Outbound message too long %zu", sshbuf_len(m)); 102 103 /* Send length first */ 104 put_u32(mlen, sshbuf_len(m)); 105 iov[0].iov_base = mlen; 106 iov[0].iov_len = sizeof(mlen); 107 iov[1].iov_base = (u_char *)sshbuf_ptr(m); 108 iov[1].iov_len = sshbuf_len(m); 109 110 if (atomiciov6(writev, conn->fd_out, iov, 2, 111 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != 112 sshbuf_len(m) + sizeof(mlen)) 113 fatal("Couldn't send packet: %s", strerror(errno)); 114 115 sshbuf_reset(m); 116 } 117 118 static void 119 get_msg(struct sftp_conn *conn, struct sshbuf *m) 120 { 121 u_int msg_len; 122 u_char *p; 123 int r; 124 125 if ((r = sshbuf_reserve(m, 4, &p)) != 0) 126 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 127 if (atomicio6(read, conn->fd_in, p, 4, 128 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { 129 if (errno == EPIPE || errno == ECONNRESET) 130 fatal("Connection closed"); 131 else 132 fatal("Couldn't read packet: %s", strerror(errno)); 133 } 134 135 if ((r = sshbuf_get_u32(m, &msg_len)) != 0) 136 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 137 if (msg_len > SFTP_MAX_MSG_LENGTH) 138 fatal("Received message too long %u", msg_len); 139 140 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) 141 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 142 if (atomicio6(read, conn->fd_in, p, msg_len, 143 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) 144 != msg_len) { 145 if (errno == EPIPE) 146 fatal("Connection closed"); 147 else 148 fatal("Read packet: %s", strerror(errno)); 149 } 150 } 151 152 static void 153 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, 154 u_int len) 155 { 156 struct sshbuf *msg; 157 int r; 158 159 if ((msg = sshbuf_new()) == NULL) 160 fatal("%s: sshbuf_new failed", __func__); 161 if ((r = sshbuf_put_u8(msg, code)) != 0 || 162 (r = sshbuf_put_u32(msg, id)) != 0 || 163 (r = sshbuf_put_string(msg, s, len)) != 0) 164 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 165 send_msg(conn, msg); 166 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 167 sshbuf_free(msg); 168 } 169 170 static void 171 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, 172 const void *s, u_int len, Attrib *a) 173 { 174 struct sshbuf *msg; 175 int r; 176 177 if ((msg = sshbuf_new()) == NULL) 178 fatal("%s: sshbuf_new failed", __func__); 179 if ((r = sshbuf_put_u8(msg, code)) != 0 || 180 (r = sshbuf_put_u32(msg, id)) != 0 || 181 (r = sshbuf_put_string(msg, s, len)) != 0 || 182 (r = encode_attrib(msg, a)) != 0) 183 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 184 send_msg(conn, msg); 185 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 186 sshbuf_free(msg); 187 } 188 189 static u_int 190 get_status(struct sftp_conn *conn, u_int expected_id) 191 { 192 struct sshbuf *msg; 193 u_char type; 194 u_int id, status; 195 int r; 196 197 if ((msg = sshbuf_new()) == NULL) 198 fatal("%s: sshbuf_new failed", __func__); 199 get_msg(conn, msg); 200 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 201 (r = sshbuf_get_u32(msg, &id)) != 0) 202 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 203 204 if (id != expected_id) 205 fatal("ID mismatch (%u != %u)", id, expected_id); 206 if (type != SSH2_FXP_STATUS) 207 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", 208 SSH2_FXP_STATUS, type); 209 210 if ((r = sshbuf_get_u32(msg, &status)) != 0) 211 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 212 sshbuf_free(msg); 213 214 debug3("SSH2_FXP_STATUS %u", status); 215 216 return status; 217 } 218 219 static u_char * 220 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 221 const char *errfmt, ...) 222 { 223 struct sshbuf *msg; 224 u_int id, status; 225 u_char type; 226 u_char *handle; 227 char errmsg[256]; 228 va_list args; 229 int r; 230 231 va_start(args, errfmt); 232 if (errfmt != NULL) 233 vsnprintf(errmsg, sizeof(errmsg), errfmt, args); 234 va_end(args); 235 236 if ((msg = sshbuf_new()) == NULL) 237 fatal("%s: sshbuf_new failed", __func__); 238 get_msg(conn, msg); 239 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 240 (r = sshbuf_get_u32(msg, &id)) != 0) 241 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 242 243 if (id != expected_id) 244 fatal("%s: ID mismatch (%u != %u)", 245 errfmt == NULL ? __func__ : errmsg, id, expected_id); 246 if (type == SSH2_FXP_STATUS) { 247 if ((r = sshbuf_get_u32(msg, &status)) != 0) 248 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 249 if (errfmt != NULL) 250 error("%s: %s", errmsg, fx2txt(status)); 251 sshbuf_free(msg); 252 return(NULL); 253 } else if (type != SSH2_FXP_HANDLE) 254 fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", 255 errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); 256 257 if ((r = sshbuf_get_string(msg, &handle, len)) != 0) 258 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 259 sshbuf_free(msg); 260 261 return handle; 262 } 263 264 static Attrib * 265 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) 266 { 267 struct sshbuf *msg; 268 u_int id; 269 u_char type; 270 int r; 271 static Attrib a; 272 273 if ((msg = sshbuf_new()) == NULL) 274 fatal("%s: sshbuf_new failed", __func__); 275 get_msg(conn, msg); 276 277 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 278 (r = sshbuf_get_u32(msg, &id)) != 0) 279 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 280 281 debug3("Received stat reply T:%u I:%u", type, id); 282 if (id != expected_id) 283 fatal("ID mismatch (%u != %u)", id, expected_id); 284 if (type == SSH2_FXP_STATUS) { 285 u_int status; 286 287 if ((r = sshbuf_get_u32(msg, &status)) != 0) 288 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 289 if (quiet) 290 debug("Couldn't stat remote file: %s", fx2txt(status)); 291 else 292 error("Couldn't stat remote file: %s", fx2txt(status)); 293 sshbuf_free(msg); 294 return(NULL); 295 } else if (type != SSH2_FXP_ATTRS) { 296 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", 297 SSH2_FXP_ATTRS, type); 298 } 299 if ((r = decode_attrib(msg, &a)) != 0) { 300 error("%s: couldn't decode attrib: %s", __func__, ssh_err(r)); 301 sshbuf_free(msg); 302 return NULL; 303 } 304 sshbuf_free(msg); 305 306 return &a; 307 } 308 309 static int 310 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, 311 u_int expected_id, int quiet) 312 { 313 struct sshbuf *msg; 314 u_char type; 315 u_int id; 316 u_int64_t flag; 317 int r; 318 319 if ((msg = sshbuf_new()) == NULL) 320 fatal("%s: sshbuf_new failed", __func__); 321 get_msg(conn, msg); 322 323 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 324 (r = sshbuf_get_u32(msg, &id)) != 0) 325 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 326 327 debug3("Received statvfs reply T:%u I:%u", type, id); 328 if (id != expected_id) 329 fatal("ID mismatch (%u != %u)", id, expected_id); 330 if (type == SSH2_FXP_STATUS) { 331 u_int status; 332 333 if ((r = sshbuf_get_u32(msg, &status)) != 0) 334 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 335 if (quiet) 336 debug("Couldn't statvfs: %s", fx2txt(status)); 337 else 338 error("Couldn't statvfs: %s", fx2txt(status)); 339 sshbuf_free(msg); 340 return -1; 341 } else if (type != SSH2_FXP_EXTENDED_REPLY) { 342 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 343 SSH2_FXP_EXTENDED_REPLY, type); 344 } 345 346 memset(st, 0, sizeof(*st)); 347 if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || 348 (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || 349 (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || 350 (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || 351 (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || 352 (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || 353 (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || 354 (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || 355 (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || 356 (r = sshbuf_get_u64(msg, &flag)) != 0 || 357 (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) 358 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 359 360 st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; 361 st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; 362 363 sshbuf_free(msg); 364 365 return 0; 366 } 367 368 struct sftp_conn * 369 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, 370 u_int64_t limit_kbps) 371 { 372 u_char type; 373 struct sshbuf *msg; 374 struct sftp_conn *ret; 375 int r; 376 377 ret = xcalloc(1, sizeof(*ret)); 378 ret->msg_id = 1; 379 ret->fd_in = fd_in; 380 ret->fd_out = fd_out; 381 ret->transfer_buflen = transfer_buflen; 382 ret->num_requests = num_requests; 383 ret->exts = 0; 384 ret->limit_kbps = 0; 385 386 if ((msg = sshbuf_new()) == NULL) 387 fatal("%s: sshbuf_new failed", __func__); 388 if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || 389 (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) 390 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 391 send_msg(ret, msg); 392 393 sshbuf_reset(msg); 394 395 get_msg(ret, msg); 396 397 /* Expecting a VERSION reply */ 398 if ((r = sshbuf_get_u8(msg, &type)) != 0) 399 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 400 if (type != SSH2_FXP_VERSION) { 401 error("Invalid packet back from SSH2_FXP_INIT (type %u)", 402 type); 403 sshbuf_free(msg); 404 free(ret); 405 return(NULL); 406 } 407 if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) 408 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 409 410 debug2("Remote version: %u", ret->version); 411 412 /* Check for extensions */ 413 while (sshbuf_len(msg) > 0) { 414 char *name; 415 u_char *value; 416 size_t vlen; 417 int known = 0; 418 419 if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || 420 (r = sshbuf_get_string(msg, &value, &vlen)) != 0) 421 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 422 if (strcmp(name, "posix-rename@openssh.com") == 0 && 423 strcmp((char *)value, "1") == 0) { 424 ret->exts |= SFTP_EXT_POSIX_RENAME; 425 known = 1; 426 } else if (strcmp(name, "statvfs@openssh.com") == 0 && 427 strcmp((char *)value, "2") == 0) { 428 ret->exts |= SFTP_EXT_STATVFS; 429 known = 1; 430 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && 431 strcmp((char *)value, "2") == 0) { 432 ret->exts |= SFTP_EXT_FSTATVFS; 433 known = 1; 434 } else if (strcmp(name, "hardlink@openssh.com") == 0 && 435 strcmp((char *)value, "1") == 0) { 436 ret->exts |= SFTP_EXT_HARDLINK; 437 known = 1; 438 } else if (strcmp(name, "fsync@openssh.com") == 0 && 439 strcmp((char *)value, "1") == 0) { 440 ret->exts |= SFTP_EXT_FSYNC; 441 known = 1; 442 } 443 if (known) { 444 debug2("Server supports extension \"%s\" revision %s", 445 name, value); 446 } else { 447 debug2("Unrecognised server extension \"%s\"", name); 448 } 449 free(name); 450 free(value); 451 } 452 453 sshbuf_free(msg); 454 455 /* Some filexfer v.0 servers don't support large packets */ 456 if (ret->version == 0) 457 ret->transfer_buflen = MINIMUM(ret->transfer_buflen, 20480); 458 459 ret->limit_kbps = limit_kbps; 460 if (ret->limit_kbps > 0) { 461 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps, 462 ret->transfer_buflen); 463 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps, 464 ret->transfer_buflen); 465 } 466 467 return ret; 468 } 469 470 u_int 471 sftp_proto_version(struct sftp_conn *conn) 472 { 473 return conn->version; 474 } 475 476 int 477 do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) 478 { 479 u_int id, status; 480 struct sshbuf *msg; 481 int r; 482 483 if ((msg = sshbuf_new()) == NULL) 484 fatal("%s: sshbuf_new failed", __func__); 485 486 id = conn->msg_id++; 487 if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || 488 (r = sshbuf_put_u32(msg, id)) != 0 || 489 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 490 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 491 send_msg(conn, msg); 492 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 493 494 status = get_status(conn, id); 495 if (status != SSH2_FX_OK) 496 error("Couldn't close file: %s", fx2txt(status)); 497 498 sshbuf_free(msg); 499 500 return status == SSH2_FX_OK ? 0 : -1; 501 } 502 503 504 static int 505 do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, 506 SFTP_DIRENT ***dir) 507 { 508 struct sshbuf *msg; 509 u_int count, id, i, expected_id, ents = 0; 510 size_t handle_len; 511 u_char type, *handle; 512 int status = SSH2_FX_FAILURE; 513 int r; 514 515 if (dir) 516 *dir = NULL; 517 518 id = conn->msg_id++; 519 520 if ((msg = sshbuf_new()) == NULL) 521 fatal("%s: sshbuf_new failed", __func__); 522 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || 523 (r = sshbuf_put_u32(msg, id)) != 0 || 524 (r = sshbuf_put_cstring(msg, path)) != 0) 525 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 526 send_msg(conn, msg); 527 528 handle = get_handle(conn, id, &handle_len, 529 "remote readdir(\"%s\")", path); 530 if (handle == NULL) { 531 sshbuf_free(msg); 532 return -1; 533 } 534 535 if (dir) { 536 ents = 0; 537 *dir = xcalloc(1, sizeof(**dir)); 538 (*dir)[0] = NULL; 539 } 540 541 for (; !interrupted;) { 542 id = expected_id = conn->msg_id++; 543 544 debug3("Sending SSH2_FXP_READDIR I:%u", id); 545 546 sshbuf_reset(msg); 547 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || 548 (r = sshbuf_put_u32(msg, id)) != 0 || 549 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 550 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 551 send_msg(conn, msg); 552 553 sshbuf_reset(msg); 554 555 get_msg(conn, msg); 556 557 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 558 (r = sshbuf_get_u32(msg, &id)) != 0) 559 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 560 561 debug3("Received reply T:%u I:%u", type, id); 562 563 if (id != expected_id) 564 fatal("ID mismatch (%u != %u)", id, expected_id); 565 566 if (type == SSH2_FXP_STATUS) { 567 u_int rstatus; 568 569 if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) 570 fatal("%s: buffer error: %s", 571 __func__, ssh_err(r)); 572 debug3("Received SSH2_FXP_STATUS %d", rstatus); 573 if (rstatus == SSH2_FX_EOF) 574 break; 575 error("Couldn't read directory: %s", fx2txt(rstatus)); 576 goto out; 577 } else if (type != SSH2_FXP_NAME) 578 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 579 SSH2_FXP_NAME, type); 580 581 if ((r = sshbuf_get_u32(msg, &count)) != 0) 582 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 583 if (count > SSHBUF_SIZE_MAX) 584 fatal("%s: nonsensical number of entries", __func__); 585 if (count == 0) 586 break; 587 debug3("Received %d SSH2_FXP_NAME responses", count); 588 for (i = 0; i < count; i++) { 589 char *filename, *longname; 590 Attrib a; 591 592 if ((r = sshbuf_get_cstring(msg, &filename, 593 NULL)) != 0 || 594 (r = sshbuf_get_cstring(msg, &longname, 595 NULL)) != 0) 596 fatal("%s: buffer error: %s", 597 __func__, ssh_err(r)); 598 if ((r = decode_attrib(msg, &a)) != 0) { 599 error("%s: couldn't decode attrib: %s", 600 __func__, ssh_err(r)); 601 free(filename); 602 free(longname); 603 sshbuf_free(msg); 604 return -1; 605 } 606 607 if (print_flag) 608 mprintf("%s\n", longname); 609 610 /* 611 * Directory entries should never contain '/' 612 * These can be used to attack recursive ops 613 * (e.g. send '../../../../etc/passwd') 614 */ 615 if (strchr(filename, '/') != NULL) { 616 error("Server sent suspect path \"%s\" " 617 "during readdir of \"%s\"", filename, path); 618 } else if (dir) { 619 *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); 620 (*dir)[ents] = xcalloc(1, sizeof(***dir)); 621 (*dir)[ents]->filename = xstrdup(filename); 622 (*dir)[ents]->longname = xstrdup(longname); 623 memcpy(&(*dir)[ents]->a, &a, sizeof(a)); 624 (*dir)[++ents] = NULL; 625 } 626 free(filename); 627 free(longname); 628 } 629 } 630 status = 0; 631 632 out: 633 sshbuf_free(msg); 634 do_close(conn, handle, handle_len); 635 free(handle); 636 637 if (status != 0 && dir != NULL) { 638 /* Don't return results on error */ 639 free_sftp_dirents(*dir); 640 *dir = NULL; 641 } else if (interrupted && dir != NULL && *dir != NULL) { 642 /* Don't return partial matches on interrupt */ 643 free_sftp_dirents(*dir); 644 *dir = xcalloc(1, sizeof(**dir)); 645 **dir = NULL; 646 } 647 648 return status; 649 } 650 651 int 652 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) 653 { 654 return(do_lsreaddir(conn, path, 0, dir)); 655 } 656 657 void free_sftp_dirents(SFTP_DIRENT **s) 658 { 659 int i; 660 661 if (s == NULL) 662 return; 663 for (i = 0; s[i]; i++) { 664 free(s[i]->filename); 665 free(s[i]->longname); 666 free(s[i]); 667 } 668 free(s); 669 } 670 671 int 672 do_rm(struct sftp_conn *conn, const char *path) 673 { 674 u_int status, id; 675 676 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 677 678 id = conn->msg_id++; 679 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); 680 status = get_status(conn, id); 681 if (status != SSH2_FX_OK) 682 error("Couldn't delete file: %s", fx2txt(status)); 683 return status == SSH2_FX_OK ? 0 : -1; 684 } 685 686 int 687 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) 688 { 689 u_int status, id; 690 691 id = conn->msg_id++; 692 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, 693 strlen(path), a); 694 695 status = get_status(conn, id); 696 if (status != SSH2_FX_OK && print_flag) 697 error("Couldn't create directory: %s", fx2txt(status)); 698 699 return status == SSH2_FX_OK ? 0 : -1; 700 } 701 702 int 703 do_rmdir(struct sftp_conn *conn, const char *path) 704 { 705 u_int status, id; 706 707 id = conn->msg_id++; 708 send_string_request(conn, id, SSH2_FXP_RMDIR, path, 709 strlen(path)); 710 711 status = get_status(conn, id); 712 if (status != SSH2_FX_OK) 713 error("Couldn't remove directory: %s", fx2txt(status)); 714 715 return status == SSH2_FX_OK ? 0 : -1; 716 } 717 718 Attrib * 719 do_stat(struct sftp_conn *conn, const char *path, int quiet) 720 { 721 u_int id; 722 723 id = conn->msg_id++; 724 725 send_string_request(conn, id, 726 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 727 path, strlen(path)); 728 729 return(get_decode_stat(conn, id, quiet)); 730 } 731 732 Attrib * 733 do_lstat(struct sftp_conn *conn, const char *path, int quiet) 734 { 735 u_int id; 736 737 if (conn->version == 0) { 738 if (quiet) 739 debug("Server version does not support lstat operation"); 740 else 741 logit("Server version does not support lstat operation"); 742 return(do_stat(conn, path, quiet)); 743 } 744 745 id = conn->msg_id++; 746 send_string_request(conn, id, SSH2_FXP_LSTAT, path, 747 strlen(path)); 748 749 return(get_decode_stat(conn, id, quiet)); 750 } 751 752 #ifdef notyet 753 Attrib * 754 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 755 int quiet) 756 { 757 u_int id; 758 759 id = conn->msg_id++; 760 send_string_request(conn, id, SSH2_FXP_FSTAT, handle, 761 handle_len); 762 763 return(get_decode_stat(conn, id, quiet)); 764 } 765 #endif 766 767 int 768 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) 769 { 770 u_int status, id; 771 772 id = conn->msg_id++; 773 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, 774 strlen(path), a); 775 776 status = get_status(conn, id); 777 if (status != SSH2_FX_OK) 778 error("Couldn't setstat on \"%s\": %s", path, 779 fx2txt(status)); 780 781 return status == SSH2_FX_OK ? 0 : -1; 782 } 783 784 int 785 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 786 Attrib *a) 787 { 788 u_int status, id; 789 790 id = conn->msg_id++; 791 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, 792 handle_len, a); 793 794 status = get_status(conn, id); 795 if (status != SSH2_FX_OK) 796 error("Couldn't fsetstat: %s", fx2txt(status)); 797 798 return status == SSH2_FX_OK ? 0 : -1; 799 } 800 801 char * 802 do_realpath(struct sftp_conn *conn, const char *path) 803 { 804 struct sshbuf *msg; 805 u_int expected_id, count, id; 806 char *filename, *longname; 807 Attrib a; 808 u_char type; 809 int r; 810 811 expected_id = id = conn->msg_id++; 812 send_string_request(conn, id, SSH2_FXP_REALPATH, path, 813 strlen(path)); 814 815 if ((msg = sshbuf_new()) == NULL) 816 fatal("%s: sshbuf_new failed", __func__); 817 818 get_msg(conn, msg); 819 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 820 (r = sshbuf_get_u32(msg, &id)) != 0) 821 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 822 823 if (id != expected_id) 824 fatal("ID mismatch (%u != %u)", id, expected_id); 825 826 if (type == SSH2_FXP_STATUS) { 827 u_int status; 828 829 if ((r = sshbuf_get_u32(msg, &status)) != 0) 830 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 831 error("Couldn't canonicalize: %s", fx2txt(status)); 832 sshbuf_free(msg); 833 return NULL; 834 } else if (type != SSH2_FXP_NAME) 835 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 836 SSH2_FXP_NAME, type); 837 838 if ((r = sshbuf_get_u32(msg, &count)) != 0) 839 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 840 if (count != 1) 841 fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); 842 843 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 844 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 845 (r = decode_attrib(msg, &a)) != 0) 846 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 847 848 debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, 849 (unsigned long)a.size); 850 851 free(longname); 852 853 sshbuf_free(msg); 854 855 return(filename); 856 } 857 858 int 859 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, 860 int force_legacy) 861 { 862 struct sshbuf *msg; 863 u_int status, id; 864 int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; 865 866 if ((msg = sshbuf_new()) == NULL) 867 fatal("%s: sshbuf_new failed", __func__); 868 869 /* Send rename request */ 870 id = conn->msg_id++; 871 if (use_ext) { 872 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 873 (r = sshbuf_put_u32(msg, id)) != 0 || 874 (r = sshbuf_put_cstring(msg, 875 "posix-rename@openssh.com")) != 0) 876 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 877 } else { 878 if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || 879 (r = sshbuf_put_u32(msg, id)) != 0) 880 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 881 } 882 if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || 883 (r = sshbuf_put_cstring(msg, newpath)) != 0) 884 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 885 send_msg(conn, msg); 886 debug3("Sent message %s \"%s\" -> \"%s\"", 887 use_ext ? "posix-rename@openssh.com" : 888 "SSH2_FXP_RENAME", oldpath, newpath); 889 sshbuf_free(msg); 890 891 status = get_status(conn, id); 892 if (status != SSH2_FX_OK) 893 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 894 newpath, fx2txt(status)); 895 896 return status == SSH2_FX_OK ? 0 : -1; 897 } 898 899 int 900 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 901 { 902 struct sshbuf *msg; 903 u_int status, id; 904 int r; 905 906 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { 907 error("Server does not support hardlink@openssh.com extension"); 908 return -1; 909 } 910 911 if ((msg = sshbuf_new()) == NULL) 912 fatal("%s: sshbuf_new failed", __func__); 913 914 /* Send link request */ 915 id = conn->msg_id++; 916 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 917 (r = sshbuf_put_u32(msg, id)) != 0 || 918 (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || 919 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 920 (r = sshbuf_put_cstring(msg, newpath)) != 0) 921 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 922 send_msg(conn, msg); 923 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", 924 oldpath, newpath); 925 sshbuf_free(msg); 926 927 status = get_status(conn, id); 928 if (status != SSH2_FX_OK) 929 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, 930 newpath, fx2txt(status)); 931 932 return status == SSH2_FX_OK ? 0 : -1; 933 } 934 935 int 936 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 937 { 938 struct sshbuf *msg; 939 u_int status, id; 940 int r; 941 942 if (conn->version < 3) { 943 error("This server does not support the symlink operation"); 944 return(SSH2_FX_OP_UNSUPPORTED); 945 } 946 947 if ((msg = sshbuf_new()) == NULL) 948 fatal("%s: sshbuf_new failed", __func__); 949 950 /* Send symlink request */ 951 id = conn->msg_id++; 952 if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || 953 (r = sshbuf_put_u32(msg, id)) != 0 || 954 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 955 (r = sshbuf_put_cstring(msg, newpath)) != 0) 956 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 957 send_msg(conn, msg); 958 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 959 newpath); 960 sshbuf_free(msg); 961 962 status = get_status(conn, id); 963 if (status != SSH2_FX_OK) 964 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 965 newpath, fx2txt(status)); 966 967 return status == SSH2_FX_OK ? 0 : -1; 968 } 969 970 int 971 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) 972 { 973 struct sshbuf *msg; 974 u_int status, id; 975 int r; 976 977 /* Silently return if the extension is not supported */ 978 if ((conn->exts & SFTP_EXT_FSYNC) == 0) 979 return -1; 980 981 /* Send fsync request */ 982 if ((msg = sshbuf_new()) == NULL) 983 fatal("%s: sshbuf_new failed", __func__); 984 id = conn->msg_id++; 985 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 986 (r = sshbuf_put_u32(msg, id)) != 0 || 987 (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || 988 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 989 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 990 send_msg(conn, msg); 991 debug3("Sent message fsync@openssh.com I:%u", id); 992 sshbuf_free(msg); 993 994 status = get_status(conn, id); 995 if (status != SSH2_FX_OK) 996 error("Couldn't sync file: %s", fx2txt(status)); 997 998 return status; 999 } 1000 1001 #ifdef notyet 1002 char * 1003 do_readlink(struct sftp_conn *conn, const char *path) 1004 { 1005 struct sshbuf *msg; 1006 u_int expected_id, count, id; 1007 char *filename, *longname; 1008 Attrib a; 1009 u_char type; 1010 int r; 1011 1012 expected_id = id = conn->msg_id++; 1013 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); 1014 1015 if ((msg = sshbuf_new()) == NULL) 1016 fatal("%s: sshbuf_new failed", __func__); 1017 1018 get_msg(conn, msg); 1019 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1020 (r = sshbuf_get_u32(msg, &id)) != 0) 1021 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1022 1023 if (id != expected_id) 1024 fatal("ID mismatch (%u != %u)", id, expected_id); 1025 1026 if (type == SSH2_FXP_STATUS) { 1027 u_int status; 1028 1029 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1030 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1031 error("Couldn't readlink: %s", fx2txt(status)); 1032 sshbuf_free(msg); 1033 return(NULL); 1034 } else if (type != SSH2_FXP_NAME) 1035 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 1036 SSH2_FXP_NAME, type); 1037 1038 if ((r = sshbuf_get_u32(msg, &count)) != 0) 1039 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1040 if (count != 1) 1041 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); 1042 1043 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 1044 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 1045 (r = decode_attrib(msg, &a)) != 0) 1046 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1047 1048 debug3("SSH_FXP_READLINK %s -> %s", path, filename); 1049 1050 free(longname); 1051 1052 sshbuf_free(msg); 1053 1054 return filename; 1055 } 1056 #endif 1057 1058 int 1059 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, 1060 int quiet) 1061 { 1062 struct sshbuf *msg; 1063 u_int id; 1064 int r; 1065 1066 if ((conn->exts & SFTP_EXT_STATVFS) == 0) { 1067 error("Server does not support statvfs@openssh.com extension"); 1068 return -1; 1069 } 1070 1071 id = conn->msg_id++; 1072 1073 if ((msg = sshbuf_new()) == NULL) 1074 fatal("%s: sshbuf_new failed", __func__); 1075 sshbuf_reset(msg); 1076 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1077 (r = sshbuf_put_u32(msg, id)) != 0 || 1078 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || 1079 (r = sshbuf_put_cstring(msg, path)) != 0) 1080 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1081 send_msg(conn, msg); 1082 sshbuf_free(msg); 1083 1084 return get_decode_statvfs(conn, st, id, quiet); 1085 } 1086 1087 #ifdef notyet 1088 int 1089 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 1090 struct sftp_statvfs *st, int quiet) 1091 { 1092 struct sshbuf *msg; 1093 u_int id; 1094 1095 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { 1096 error("Server does not support fstatvfs@openssh.com extension"); 1097 return -1; 1098 } 1099 1100 id = conn->msg_id++; 1101 1102 if ((msg = sshbuf_new()) == NULL) 1103 fatal("%s: sshbuf_new failed", __func__); 1104 sshbuf_reset(msg); 1105 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1106 (r = sshbuf_put_u32(msg, id)) != 0 || 1107 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || 1108 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1109 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1110 send_msg(conn, msg); 1111 sshbuf_free(msg); 1112 1113 return get_decode_statvfs(conn, st, id, quiet); 1114 } 1115 #endif 1116 1117 static void 1118 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1119 u_int len, const u_char *handle, u_int handle_len) 1120 { 1121 struct sshbuf *msg; 1122 int r; 1123 1124 if ((msg = sshbuf_new()) == NULL) 1125 fatal("%s: sshbuf_new failed", __func__); 1126 sshbuf_reset(msg); 1127 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || 1128 (r = sshbuf_put_u32(msg, id)) != 0 || 1129 (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || 1130 (r = sshbuf_put_u64(msg, offset)) != 0 || 1131 (r = sshbuf_put_u32(msg, len)) != 0) 1132 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1133 send_msg(conn, msg); 1134 sshbuf_free(msg); 1135 } 1136 1137 int 1138 do_download(struct sftp_conn *conn, const char *remote_path, 1139 const char *local_path, Attrib *a, int preserve_flag, int resume_flag, 1140 int fsync_flag) 1141 { 1142 Attrib junk; 1143 struct sshbuf *msg; 1144 u_char *handle; 1145 int local_fd = -1, write_error; 1146 int read_error, write_errno, reordered = 0, r; 1147 u_int64_t offset = 0, size, highwater; 1148 u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; 1149 off_t progress_counter; 1150 size_t handle_len; 1151 struct stat st; 1152 struct request { 1153 u_int id; 1154 size_t len; 1155 u_int64_t offset; 1156 TAILQ_ENTRY(request) tq; 1157 }; 1158 TAILQ_HEAD(reqhead, request) requests; 1159 struct request *req; 1160 u_char type; 1161 1162 TAILQ_INIT(&requests); 1163 1164 if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) 1165 return -1; 1166 1167 /* Do not preserve set[ug]id here, as we do not preserve ownership */ 1168 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1169 mode = a->perm & 0777; 1170 else 1171 mode = 0666; 1172 1173 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 1174 (!S_ISREG(a->perm))) { 1175 error("Cannot download non-regular file: %s", remote_path); 1176 return(-1); 1177 } 1178 1179 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 1180 size = a->size; 1181 else 1182 size = 0; 1183 1184 buflen = conn->transfer_buflen; 1185 if ((msg = sshbuf_new()) == NULL) 1186 fatal("%s: sshbuf_new failed", __func__); 1187 1188 attrib_clear(&junk); /* Send empty attributes */ 1189 1190 /* Send open request */ 1191 id = conn->msg_id++; 1192 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1193 (r = sshbuf_put_u32(msg, id)) != 0 || 1194 (r = sshbuf_put_cstring(msg, remote_path)) != 0 || 1195 (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || 1196 (r = encode_attrib(msg, &junk)) != 0) 1197 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1198 send_msg(conn, msg); 1199 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1200 1201 handle = get_handle(conn, id, &handle_len, 1202 "remote open(\"%s\")", remote_path); 1203 if (handle == NULL) { 1204 sshbuf_free(msg); 1205 return(-1); 1206 } 1207 1208 local_fd = open(local_path, 1209 O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); 1210 if (local_fd == -1) { 1211 error("Couldn't open local file \"%s\" for writing: %s", 1212 local_path, strerror(errno)); 1213 goto fail; 1214 } 1215 offset = highwater = 0; 1216 if (resume_flag) { 1217 if (fstat(local_fd, &st) == -1) { 1218 error("Unable to stat local file \"%s\": %s", 1219 local_path, strerror(errno)); 1220 goto fail; 1221 } 1222 if (st.st_size < 0) { 1223 error("\"%s\" has negative size", local_path); 1224 goto fail; 1225 } 1226 if ((u_int64_t)st.st_size > size) { 1227 error("Unable to resume download of \"%s\": " 1228 "local file is larger than remote", local_path); 1229 fail: 1230 do_close(conn, handle, handle_len); 1231 sshbuf_free(msg); 1232 free(handle); 1233 if (local_fd != -1) 1234 close(local_fd); 1235 return -1; 1236 } 1237 offset = highwater = st.st_size; 1238 } 1239 1240 /* Read from remote and write to local */ 1241 write_error = read_error = write_errno = num_req = 0; 1242 max_req = 1; 1243 progress_counter = offset; 1244 1245 if (showprogress && size != 0) 1246 start_progress_meter(remote_path, size, &progress_counter); 1247 1248 while (num_req > 0 || max_req > 0) { 1249 u_char *data; 1250 size_t len; 1251 1252 /* 1253 * Simulate EOF on interrupt: stop sending new requests and 1254 * allow outstanding requests to drain gracefully 1255 */ 1256 if (interrupted) { 1257 if (num_req == 0) /* If we haven't started yet... */ 1258 break; 1259 max_req = 0; 1260 } 1261 1262 /* Send some more requests */ 1263 while (num_req < max_req) { 1264 debug3("Request range %llu -> %llu (%d/%d)", 1265 (unsigned long long)offset, 1266 (unsigned long long)offset + buflen - 1, 1267 num_req, max_req); 1268 req = xcalloc(1, sizeof(*req)); 1269 req->id = conn->msg_id++; 1270 req->len = buflen; 1271 req->offset = offset; 1272 offset += buflen; 1273 num_req++; 1274 TAILQ_INSERT_TAIL(&requests, req, tq); 1275 send_read_request(conn, req->id, req->offset, 1276 req->len, handle, handle_len); 1277 } 1278 1279 sshbuf_reset(msg); 1280 get_msg(conn, msg); 1281 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1282 (r = sshbuf_get_u32(msg, &id)) != 0) 1283 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1284 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1285 1286 /* Find the request in our queue */ 1287 for (req = TAILQ_FIRST(&requests); 1288 req != NULL && req->id != id; 1289 req = TAILQ_NEXT(req, tq)) 1290 ; 1291 if (req == NULL) 1292 fatal("Unexpected reply %u", id); 1293 1294 switch (type) { 1295 case SSH2_FXP_STATUS: 1296 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1297 fatal("%s: buffer error: %s", 1298 __func__, ssh_err(r)); 1299 if (status != SSH2_FX_EOF) 1300 read_error = 1; 1301 max_req = 0; 1302 TAILQ_REMOVE(&requests, req, tq); 1303 free(req); 1304 num_req--; 1305 break; 1306 case SSH2_FXP_DATA: 1307 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 1308 fatal("%s: buffer error: %s", 1309 __func__, ssh_err(r)); 1310 debug3("Received data %llu -> %llu", 1311 (unsigned long long)req->offset, 1312 (unsigned long long)req->offset + len - 1); 1313 if (len > req->len) 1314 fatal("Received more data than asked for " 1315 "%zu > %zu", len, req->len); 1316 if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || 1317 atomicio(vwrite, local_fd, data, len) != len) && 1318 !write_error) { 1319 write_errno = errno; 1320 write_error = 1; 1321 max_req = 0; 1322 } 1323 else if (!reordered && req->offset <= highwater) 1324 highwater = req->offset + len; 1325 else if (!reordered && req->offset > highwater) 1326 reordered = 1; 1327 progress_counter += len; 1328 free(data); 1329 1330 if (len == req->len) { 1331 TAILQ_REMOVE(&requests, req, tq); 1332 free(req); 1333 num_req--; 1334 } else { 1335 /* Resend the request for the missing data */ 1336 debug3("Short data block, re-requesting " 1337 "%llu -> %llu (%2d)", 1338 (unsigned long long)req->offset + len, 1339 (unsigned long long)req->offset + 1340 req->len - 1, num_req); 1341 req->id = conn->msg_id++; 1342 req->len -= len; 1343 req->offset += len; 1344 send_read_request(conn, req->id, 1345 req->offset, req->len, handle, handle_len); 1346 /* Reduce the request size */ 1347 if (len < buflen) 1348 buflen = MAXIMUM(MIN_READ_SIZE, len); 1349 } 1350 if (max_req > 0) { /* max_req = 0 iff EOF received */ 1351 if (size > 0 && offset > size) { 1352 /* Only one request at a time 1353 * after the expected EOF */ 1354 debug3("Finish at %llu (%2d)", 1355 (unsigned long long)offset, 1356 num_req); 1357 max_req = 1; 1358 } else if (max_req <= conn->num_requests) { 1359 ++max_req; 1360 } 1361 } 1362 break; 1363 default: 1364 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 1365 SSH2_FXP_DATA, type); 1366 } 1367 } 1368 1369 if (showprogress && size) 1370 stop_progress_meter(); 1371 1372 /* Sanity check */ 1373 if (TAILQ_FIRST(&requests) != NULL) 1374 fatal("Transfer complete, but requests still in queue"); 1375 /* Truncate at highest contiguous point to avoid holes on interrupt */ 1376 if (read_error || write_error || interrupted) { 1377 if (reordered && resume_flag) { 1378 error("Unable to resume download of \"%s\": " 1379 "server reordered requests", local_path); 1380 } 1381 debug("truncating at %llu", (unsigned long long)highwater); 1382 if (ftruncate(local_fd, highwater) == -1) 1383 error("ftruncate \"%s\": %s", local_path, 1384 strerror(errno)); 1385 } 1386 if (read_error) { 1387 error("Couldn't read from remote file \"%s\" : %s", 1388 remote_path, fx2txt(status)); 1389 status = -1; 1390 do_close(conn, handle, handle_len); 1391 } else if (write_error) { 1392 error("Couldn't write to \"%s\": %s", local_path, 1393 strerror(write_errno)); 1394 status = SSH2_FX_FAILURE; 1395 do_close(conn, handle, handle_len); 1396 } else { 1397 if (do_close(conn, handle, handle_len) != 0 || interrupted) 1398 status = SSH2_FX_FAILURE; 1399 else 1400 status = SSH2_FX_OK; 1401 /* Override umask and utimes if asked */ 1402 if (preserve_flag && fchmod(local_fd, mode) == -1) 1403 error("Couldn't set mode on \"%s\": %s", local_path, 1404 strerror(errno)); 1405 if (preserve_flag && 1406 (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { 1407 struct timeval tv[2]; 1408 tv[0].tv_sec = a->atime; 1409 tv[1].tv_sec = a->mtime; 1410 tv[0].tv_usec = tv[1].tv_usec = 0; 1411 if (utimes(local_path, tv) == -1) 1412 error("Can't set times on \"%s\": %s", 1413 local_path, strerror(errno)); 1414 } 1415 if (fsync_flag) { 1416 debug("syncing \"%s\"", local_path); 1417 if (fsync(local_fd) == -1) 1418 error("Couldn't sync file \"%s\": %s", 1419 local_path, strerror(errno)); 1420 } 1421 } 1422 close(local_fd); 1423 sshbuf_free(msg); 1424 free(handle); 1425 1426 return(status); 1427 } 1428 1429 static int 1430 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1431 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 1432 int resume_flag, int fsync_flag) 1433 { 1434 int i, ret = 0; 1435 SFTP_DIRENT **dir_entries; 1436 char *filename, *new_src, *new_dst; 1437 mode_t mode = 0777; 1438 1439 if (depth >= MAX_DIR_DEPTH) { 1440 error("Maximum directory depth exceeded: %d levels", depth); 1441 return -1; 1442 } 1443 1444 if (dirattrib == NULL && 1445 (dirattrib = do_stat(conn, src, 1)) == NULL) { 1446 error("Unable to stat remote directory \"%s\"", src); 1447 return -1; 1448 } 1449 if (!S_ISDIR(dirattrib->perm)) { 1450 error("\"%s\" is not a directory", src); 1451 return -1; 1452 } 1453 if (print_flag) 1454 mprintf("Retrieving %s\n", src); 1455 1456 if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1457 mode = dirattrib->perm & 01777; 1458 else { 1459 debug("Server did not send permissions for " 1460 "directory \"%s\"", dst); 1461 } 1462 1463 if (mkdir(dst, mode) == -1 && errno != EEXIST) { 1464 error("mkdir %s: %s", dst, strerror(errno)); 1465 return -1; 1466 } 1467 1468 if (do_readdir(conn, src, &dir_entries) == -1) { 1469 error("%s: Failed to get directory contents", src); 1470 return -1; 1471 } 1472 1473 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 1474 filename = dir_entries[i]->filename; 1475 1476 new_dst = path_append(dst, filename); 1477 new_src = path_append(src, filename); 1478 1479 if (S_ISDIR(dir_entries[i]->a.perm)) { 1480 if (strcmp(filename, ".") == 0 || 1481 strcmp(filename, "..") == 0) 1482 continue; 1483 if (download_dir_internal(conn, new_src, new_dst, 1484 depth + 1, &(dir_entries[i]->a), preserve_flag, 1485 print_flag, resume_flag, fsync_flag) == -1) 1486 ret = -1; 1487 } else if (S_ISREG(dir_entries[i]->a.perm) ) { 1488 if (do_download(conn, new_src, new_dst, 1489 &(dir_entries[i]->a), preserve_flag, 1490 resume_flag, fsync_flag) == -1) { 1491 error("Download of file %s to %s failed", 1492 new_src, new_dst); 1493 ret = -1; 1494 } 1495 } else 1496 logit("%s: not a regular file\n", new_src); 1497 1498 free(new_dst); 1499 free(new_src); 1500 } 1501 1502 if (preserve_flag) { 1503 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1504 struct timeval tv[2]; 1505 tv[0].tv_sec = dirattrib->atime; 1506 tv[1].tv_sec = dirattrib->mtime; 1507 tv[0].tv_usec = tv[1].tv_usec = 0; 1508 if (utimes(dst, tv) == -1) 1509 error("Can't set times on \"%s\": %s", 1510 dst, strerror(errno)); 1511 } else 1512 debug("Server did not send times for directory " 1513 "\"%s\"", dst); 1514 } 1515 1516 free_sftp_dirents(dir_entries); 1517 1518 return ret; 1519 } 1520 1521 int 1522 download_dir(struct sftp_conn *conn, const char *src, const char *dst, 1523 Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, 1524 int fsync_flag) 1525 { 1526 char *src_canon; 1527 int ret; 1528 1529 if ((src_canon = do_realpath(conn, src)) == NULL) { 1530 error("Unable to canonicalize path \"%s\"", src); 1531 return -1; 1532 } 1533 1534 ret = download_dir_internal(conn, src_canon, dst, 0, 1535 dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag); 1536 free(src_canon); 1537 return ret; 1538 } 1539 1540 int 1541 do_upload(struct sftp_conn *conn, const char *local_path, 1542 const char *remote_path, int preserve_flag, int resume, int fsync_flag) 1543 { 1544 int r, local_fd; 1545 u_int status = SSH2_FX_OK; 1546 u_int id; 1547 u_char type; 1548 off_t offset, progress_counter; 1549 u_char *handle, *data; 1550 struct sshbuf *msg; 1551 struct stat sb; 1552 Attrib a, *c = NULL; 1553 u_int32_t startid; 1554 u_int32_t ackid; 1555 struct outstanding_ack { 1556 u_int id; 1557 u_int len; 1558 off_t offset; 1559 TAILQ_ENTRY(outstanding_ack) tq; 1560 }; 1561 TAILQ_HEAD(ackhead, outstanding_ack) acks; 1562 struct outstanding_ack *ack = NULL; 1563 size_t handle_len; 1564 1565 TAILQ_INIT(&acks); 1566 1567 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { 1568 error("Couldn't open local file \"%s\" for reading: %s", 1569 local_path, strerror(errno)); 1570 return(-1); 1571 } 1572 if (fstat(local_fd, &sb) == -1) { 1573 error("Couldn't fstat local file \"%s\": %s", 1574 local_path, strerror(errno)); 1575 close(local_fd); 1576 return(-1); 1577 } 1578 if (!S_ISREG(sb.st_mode)) { 1579 error("%s is not a regular file", local_path); 1580 close(local_fd); 1581 return(-1); 1582 } 1583 stat_to_attrib(&sb, &a); 1584 1585 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1586 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1587 a.perm &= 0777; 1588 if (!preserve_flag) 1589 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1590 1591 if (resume) { 1592 /* Get remote file size if it exists */ 1593 if ((c = do_stat(conn, remote_path, 0)) == NULL) { 1594 close(local_fd); 1595 return -1; 1596 } 1597 1598 if ((off_t)c->size >= sb.st_size) { 1599 error("destination file bigger or same size as " 1600 "source file"); 1601 close(local_fd); 1602 return -1; 1603 } 1604 1605 if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { 1606 close(local_fd); 1607 return -1; 1608 } 1609 } 1610 1611 if ((msg = sshbuf_new()) == NULL) 1612 fatal("%s: sshbuf_new failed", __func__); 1613 1614 /* Send open request */ 1615 id = conn->msg_id++; 1616 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1617 (r = sshbuf_put_u32(msg, id)) != 0 || 1618 (r = sshbuf_put_cstring(msg, remote_path)) != 0 || 1619 (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| 1620 (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 || 1621 (r = encode_attrib(msg, &a)) != 0) 1622 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1623 send_msg(conn, msg); 1624 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1625 1626 sshbuf_reset(msg); 1627 1628 handle = get_handle(conn, id, &handle_len, 1629 "remote open(\"%s\")", remote_path); 1630 if (handle == NULL) { 1631 close(local_fd); 1632 sshbuf_free(msg); 1633 return -1; 1634 } 1635 1636 startid = ackid = id + 1; 1637 data = xmalloc(conn->transfer_buflen); 1638 1639 /* Read from local and write to remote */ 1640 offset = progress_counter = (resume ? c->size : 0); 1641 if (showprogress) 1642 start_progress_meter(local_path, sb.st_size, 1643 &progress_counter); 1644 1645 for (;;) { 1646 int len; 1647 1648 /* 1649 * Can't use atomicio here because it returns 0 on EOF, 1650 * thus losing the last block of the file. 1651 * Simulate an EOF on interrupt, allowing ACKs from the 1652 * server to drain. 1653 */ 1654 if (interrupted || status != SSH2_FX_OK) 1655 len = 0; 1656 else do 1657 len = read(local_fd, data, conn->transfer_buflen); 1658 while ((len == -1) && (errno == EINTR || errno == EAGAIN)); 1659 1660 if (len == -1) 1661 fatal("Couldn't read from \"%s\": %s", local_path, 1662 strerror(errno)); 1663 1664 if (len != 0) { 1665 ack = xcalloc(1, sizeof(*ack)); 1666 ack->id = ++id; 1667 ack->offset = offset; 1668 ack->len = len; 1669 TAILQ_INSERT_TAIL(&acks, ack, tq); 1670 1671 sshbuf_reset(msg); 1672 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 1673 (r = sshbuf_put_u32(msg, ack->id)) != 0 || 1674 (r = sshbuf_put_string(msg, handle, 1675 handle_len)) != 0 || 1676 (r = sshbuf_put_u64(msg, offset)) != 0 || 1677 (r = sshbuf_put_string(msg, data, len)) != 0) 1678 fatal("%s: buffer error: %s", 1679 __func__, ssh_err(r)); 1680 send_msg(conn, msg); 1681 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1682 id, (unsigned long long)offset, len); 1683 } else if (TAILQ_FIRST(&acks) == NULL) 1684 break; 1685 1686 if (ack == NULL) 1687 fatal("Unexpected ACK %u", id); 1688 1689 if (id == startid || len == 0 || 1690 id - ackid >= conn->num_requests) { 1691 u_int rid; 1692 1693 sshbuf_reset(msg); 1694 get_msg(conn, msg); 1695 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1696 (r = sshbuf_get_u32(msg, &rid)) != 0) 1697 fatal("%s: buffer error: %s", 1698 __func__, ssh_err(r)); 1699 1700 if (type != SSH2_FXP_STATUS) 1701 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 1702 "got %d", SSH2_FXP_STATUS, type); 1703 1704 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1705 fatal("%s: buffer error: %s", 1706 __func__, ssh_err(r)); 1707 debug3("SSH2_FXP_STATUS %u", status); 1708 1709 /* Find the request in our queue */ 1710 for (ack = TAILQ_FIRST(&acks); 1711 ack != NULL && ack->id != rid; 1712 ack = TAILQ_NEXT(ack, tq)) 1713 ; 1714 if (ack == NULL) 1715 fatal("Can't find request for ID %u", rid); 1716 TAILQ_REMOVE(&acks, ack, tq); 1717 debug3("In write loop, ack for %u %u bytes at %lld", 1718 ack->id, ack->len, (long long)ack->offset); 1719 ++ackid; 1720 progress_counter += ack->len; 1721 free(ack); 1722 } 1723 offset += len; 1724 if (offset < 0) 1725 fatal("%s: offset < 0", __func__); 1726 } 1727 sshbuf_free(msg); 1728 1729 if (showprogress) 1730 stop_progress_meter(); 1731 free(data); 1732 1733 if (status != SSH2_FX_OK) { 1734 error("Couldn't write to remote file \"%s\": %s", 1735 remote_path, fx2txt(status)); 1736 status = SSH2_FX_FAILURE; 1737 } 1738 1739 if (close(local_fd) == -1) { 1740 error("Couldn't close local file \"%s\": %s", local_path, 1741 strerror(errno)); 1742 status = SSH2_FX_FAILURE; 1743 } 1744 1745 /* Override umask and utimes if asked */ 1746 if (preserve_flag) 1747 do_fsetstat(conn, handle, handle_len, &a); 1748 1749 if (fsync_flag) 1750 (void)do_fsync(conn, handle, handle_len); 1751 1752 if (do_close(conn, handle, handle_len) != 0) 1753 status = SSH2_FX_FAILURE; 1754 1755 free(handle); 1756 1757 return status == SSH2_FX_OK ? 0 : -1; 1758 } 1759 1760 static int 1761 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1762 int depth, int preserve_flag, int print_flag, int resume, int fsync_flag) 1763 { 1764 int ret = 0; 1765 DIR *dirp; 1766 struct dirent *dp; 1767 char *filename, *new_src, *new_dst; 1768 struct stat sb; 1769 Attrib a, *dirattrib; 1770 1771 if (depth >= MAX_DIR_DEPTH) { 1772 error("Maximum directory depth exceeded: %d levels", depth); 1773 return -1; 1774 } 1775 1776 if (stat(src, &sb) == -1) { 1777 error("Couldn't stat directory \"%s\": %s", 1778 src, strerror(errno)); 1779 return -1; 1780 } 1781 if (!S_ISDIR(sb.st_mode)) { 1782 error("\"%s\" is not a directory", src); 1783 return -1; 1784 } 1785 if (print_flag) 1786 mprintf("Entering %s\n", src); 1787 1788 attrib_clear(&a); 1789 stat_to_attrib(&sb, &a); 1790 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1791 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1792 a.perm &= 01777; 1793 if (!preserve_flag) 1794 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1795 1796 /* 1797 * sftp lacks a portable status value to match errno EEXIST, 1798 * so if we get a failure back then we must check whether 1799 * the path already existed and is a directory. 1800 */ 1801 if (do_mkdir(conn, dst, &a, 0) != 0) { 1802 if ((dirattrib = do_stat(conn, dst, 0)) == NULL) 1803 return -1; 1804 if (!S_ISDIR(dirattrib->perm)) { 1805 error("\"%s\" exists but is not a directory", dst); 1806 return -1; 1807 } 1808 } 1809 1810 if ((dirp = opendir(src)) == NULL) { 1811 error("Failed to open dir \"%s\": %s", src, strerror(errno)); 1812 return -1; 1813 } 1814 1815 while (((dp = readdir(dirp)) != NULL) && !interrupted) { 1816 if (dp->d_ino == 0) 1817 continue; 1818 filename = dp->d_name; 1819 new_dst = path_append(dst, filename); 1820 new_src = path_append(src, filename); 1821 1822 if (lstat(new_src, &sb) == -1) { 1823 logit("%s: lstat failed: %s", filename, 1824 strerror(errno)); 1825 ret = -1; 1826 } else if (S_ISDIR(sb.st_mode)) { 1827 if (strcmp(filename, ".") == 0 || 1828 strcmp(filename, "..") == 0) 1829 continue; 1830 1831 if (upload_dir_internal(conn, new_src, new_dst, 1832 depth + 1, preserve_flag, print_flag, resume, 1833 fsync_flag) == -1) 1834 ret = -1; 1835 } else if (S_ISREG(sb.st_mode)) { 1836 if (do_upload(conn, new_src, new_dst, 1837 preserve_flag, resume, fsync_flag) == -1) { 1838 error("Uploading of file %s to %s failed!", 1839 new_src, new_dst); 1840 ret = -1; 1841 } 1842 } else 1843 logit("%s: not a regular file\n", filename); 1844 free(new_dst); 1845 free(new_src); 1846 } 1847 1848 do_setstat(conn, dst, &a); 1849 1850 (void) closedir(dirp); 1851 return ret; 1852 } 1853 1854 int 1855 upload_dir(struct sftp_conn *conn, const char *src, const char *dst, 1856 int preserve_flag, int print_flag, int resume, int fsync_flag) 1857 { 1858 char *dst_canon; 1859 int ret; 1860 1861 if ((dst_canon = do_realpath(conn, dst)) == NULL) { 1862 error("Unable to canonicalize path \"%s\"", dst); 1863 return -1; 1864 } 1865 1866 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 1867 print_flag, resume, fsync_flag); 1868 1869 free(dst_canon); 1870 return ret; 1871 } 1872 1873 char * 1874 path_append(const char *p1, const char *p2) 1875 { 1876 char *ret; 1877 size_t len = strlen(p1) + strlen(p2) + 2; 1878 1879 ret = xmalloc(len); 1880 strlcpy(ret, p1, len); 1881 if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') 1882 strlcat(ret, "/", len); 1883 strlcat(ret, p2, len); 1884 1885 return(ret); 1886 } 1887 1888