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