1 /* $OpenBSD: scp.c,v 1.275 2026/06/28 23:47:16 djm Exp $ */ 2 /* 3 * scp - secure remote copy. This is basically patched BSD rcp which 4 * uses ssh to do the data transfer (instead of using rcmd). 5 * 6 * NOTE: This version should NOT be suid root. (This uses ssh to 7 * do the transfer and ssh has the necessary privileges.) 8 * 9 * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi> 10 * 11 * As far as I am concerned, the code I have written for this software 12 * can be used freely for any purpose. Any derived versions of this 13 * software must be clearly marked as such, and if the derived work is 14 * incompatible with the protocol description in the RFC file, it must be 15 * called by a name other than "ssh" or "Secure Shell". 16 */ 17 /* 18 * Copyright (c) 1999 Theo de Raadt. All rights reserved. 19 * Copyright (c) 1999 Aaron Campbell. All rights reserved. 20 * 21 * Redistribution and use in source and binary forms, with or without 22 * modification, are permitted provided that the following conditions 23 * are met: 24 * 1. Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * 2. Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in the 28 * documentation and/or other materials provided with the distribution. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 */ 41 42 /* 43 * Parts from: 44 * 45 * Copyright (c) 1983, 1990, 1992, 1993, 1995 46 * The Regents of the University of California. All rights reserved. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 3. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 * 72 */ 73 74 #include "includes.h" 75 76 #include <sys/types.h> 77 #include <sys/stat.h> 78 #include <sys/time.h> 79 #include <sys/wait.h> 80 #include <sys/uio.h> 81 82 #include <ctype.h> 83 #include <dirent.h> 84 #include <errno.h> 85 #include <fcntl.h> 86 #ifdef HAVE_FNMATCH_H 87 #include <fnmatch.h> 88 #endif 89 #include <glob.h> 90 #include <libgen.h> 91 #include <locale.h> 92 #include <poll.h> 93 #include <pwd.h> 94 #include <signal.h> 95 #include <stdarg.h> 96 #include <stdint.h> 97 #include <stdio.h> 98 #include <stdlib.h> 99 #include <string.h> 100 #include <time.h> 101 #include <unistd.h> 102 #include <limits.h> 103 #include <util.h> 104 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 105 #include <vis.h> 106 #endif 107 108 #include "xmalloc.h" 109 #include "ssh.h" 110 #include "atomicio.h" 111 #include "pathnames.h" 112 #include "log.h" 113 #include "misc.h" 114 #include "progressmeter.h" 115 #include "utf8.h" 116 #include "sftp.h" 117 118 #include "sftp-common.h" 119 #include "sftp-client.h" 120 121 extern char *__progname; 122 123 #define COPY_BUFLEN 16384 124 125 int do_cmd(char *, char *, char *, int, int, char *, int *, int *, pid_t *); 126 int do_cmd2(char *, char *, int, char *, int, int); 127 128 /* Struct for addargs */ 129 arglist args; 130 arglist remote_remote_args; 131 132 /* Bandwidth limit */ 133 long long limit_kbps = 0; 134 struct bwlimit bwlimit; 135 136 /* Name of current file being transferred. */ 137 char *curfile; 138 139 /* This is set to non-zero to enable verbose mode. */ 140 int verbose_mode = 0; 141 LogLevel log_level = SYSLOG_LEVEL_INFO; 142 143 /* This is set to zero if the progressmeter is not desired. */ 144 int showprogress = 1; 145 146 /* 147 * This is set to non-zero if remote-remote copy should be piped 148 * through this process. 149 */ 150 int throughlocal = 1; 151 152 /* Non-standard port to use for the ssh connection or -1. */ 153 int sshport = -1; 154 155 /* This is the program to execute for the secure connection. ("ssh" or -S) */ 156 char *ssh_program = _PATH_SSH_PROGRAM; 157 158 /* This is used to store the pid of ssh_program */ 159 pid_t do_cmd_pid = -1; 160 pid_t do_cmd_pid2 = -1; 161 162 /* SFTP copy parameters */ 163 size_t sftp_copy_buflen; 164 size_t sftp_nrequests; 165 166 /* Needed for sftp */ 167 volatile sig_atomic_t interrupted = 0; 168 169 int sftp_glob(struct sftp_conn *, const char *, int, 170 int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ 171 172 static void 173 killchild(int signo) 174 { 175 if (do_cmd_pid > 1) { 176 kill(do_cmd_pid, signo ? signo : SIGTERM); 177 (void)waitpid(do_cmd_pid, NULL, 0); 178 } 179 if (do_cmd_pid2 > 1) { 180 kill(do_cmd_pid2, signo ? signo : SIGTERM); 181 (void)waitpid(do_cmd_pid2, NULL, 0); 182 } 183 184 if (signo) 185 _exit(1); 186 exit(1); 187 } 188 189 static void 190 suspone(int pid, int signo) 191 { 192 int status; 193 194 if (pid > 1) { 195 kill(pid, signo); 196 while (waitpid(pid, &status, WUNTRACED) == -1 && 197 errno == EINTR) 198 ; 199 } 200 } 201 202 static void 203 suspchild(int signo) 204 { 205 int save_errno = errno; 206 suspone(do_cmd_pid, signo); 207 suspone(do_cmd_pid2, signo); 208 kill(getpid(), SIGSTOP); 209 errno = save_errno; 210 } 211 212 static int 213 do_local_cmd(arglist *a) 214 { 215 char *cp; 216 int status; 217 pid_t pid; 218 219 if (a->num == 0) 220 fatal("do_local_cmd: no arguments"); 221 222 if (verbose_mode) { 223 cp = argv_assemble(a->num, a->list); 224 fmprintf(stderr, "Executing: %s\n", cp); 225 free(cp); 226 } 227 if ((pid = fork()) == -1) 228 fatal("do_local_cmd: fork: %s", strerror(errno)); 229 230 if (pid == 0) { 231 execvp(a->list[0], a->list); 232 perror(a->list[0]); 233 exit(1); 234 } 235 236 do_cmd_pid = pid; 237 ssh_signal(SIGTERM, killchild); 238 ssh_signal(SIGINT, killchild); 239 ssh_signal(SIGHUP, killchild); 240 241 while (waitpid(pid, &status, 0) == -1) 242 if (errno != EINTR) 243 fatal("do_local_cmd: waitpid: %s", strerror(errno)); 244 245 do_cmd_pid = -1; 246 247 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 248 return (-1); 249 250 return (0); 251 } 252 253 /* 254 * This function executes the given command as the specified user on the 255 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 256 * assigns the input and output file descriptors on success. 257 */ 258 259 int 260 do_cmd(char *program, char *host, char *remuser, int port, int subsystem, 261 char *cmd, int *fdin, int *fdout, pid_t *pid) 262 { 263 #ifdef USE_PIPES 264 int pin[2], pout[2]; 265 #else 266 int sv[2]; 267 #endif 268 269 if (verbose_mode) 270 fmprintf(stderr, 271 "Executing: program %s host %s, user %s, command %s\n", 272 program, host, 273 remuser ? remuser : "(unspecified)", cmd); 274 275 if (port == -1) 276 port = sshport; 277 278 #ifdef USE_PIPES 279 if (pipe(pin) == -1 || pipe(pout) == -1) 280 fatal("pipe: %s", strerror(errno)); 281 #else 282 /* Create a socket pair for communicating with ssh. */ 283 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) 284 fatal("socketpair: %s", strerror(errno)); 285 #endif 286 287 ssh_signal(SIGTSTP, suspchild); 288 ssh_signal(SIGTTIN, suspchild); 289 ssh_signal(SIGTTOU, suspchild); 290 291 /* Fork a child to execute the command on the remote host using ssh. */ 292 *pid = fork(); 293 switch (*pid) { 294 case -1: 295 fatal("fork: %s", strerror(errno)); 296 case 0: 297 /* Child. */ 298 #ifdef USE_PIPES 299 if (dup2(pin[0], STDIN_FILENO) == -1 || 300 dup2(pout[1], STDOUT_FILENO) == -1) { 301 error("dup2: %s", strerror(errno)); 302 _exit(1); 303 } 304 close(pin[0]); 305 close(pin[1]); 306 close(pout[0]); 307 close(pout[1]); 308 #else 309 if (dup2(sv[0], STDIN_FILENO) == -1 || 310 dup2(sv[0], STDOUT_FILENO) == -1) { 311 error("dup2: %s", strerror(errno)); 312 _exit(1); 313 } 314 close(sv[0]); 315 close(sv[1]); 316 #endif 317 replacearg(&args, 0, "%s", program); 318 if (port != -1) { 319 addargs(&args, "-p"); 320 addargs(&args, "%d", port); 321 } 322 if (remuser != NULL) { 323 addargs(&args, "-l"); 324 addargs(&args, "%s", remuser); 325 } 326 if (subsystem) 327 addargs(&args, "-s"); 328 addargs(&args, "--"); 329 addargs(&args, "%s", host); 330 addargs(&args, "%s", cmd); 331 332 execvp(program, args.list); 333 perror(program); 334 _exit(1); 335 default: 336 /* Parent. Close the other side, and return the local side. */ 337 #ifdef USE_PIPES 338 close(pin[0]); 339 close(pout[1]); 340 *fdout = pin[1]; 341 *fdin = pout[0]; 342 #else 343 close(sv[0]); 344 *fdin = sv[1]; 345 *fdout = sv[1]; 346 #endif 347 ssh_signal(SIGTERM, killchild); 348 ssh_signal(SIGINT, killchild); 349 ssh_signal(SIGHUP, killchild); 350 return 0; 351 } 352 } 353 354 /* 355 * This function executes a command similar to do_cmd(), but expects the 356 * input and output descriptors to be setup by a previous call to do_cmd(). 357 * This way the input and output of two commands can be connected. 358 */ 359 int 360 do_cmd2(char *host, char *remuser, int port, char *cmd, 361 int fdin, int fdout) 362 { 363 int status; 364 pid_t pid; 365 366 if (verbose_mode) 367 fmprintf(stderr, 368 "Executing: 2nd program %s host %s, user %s, command %s\n", 369 ssh_program, host, 370 remuser ? remuser : "(unspecified)", cmd); 371 372 if (port == -1) 373 port = sshport; 374 375 /* Fork a child to execute the command on the remote host using ssh. */ 376 pid = fork(); 377 if (pid == 0) { 378 if (dup2(fdin, 0) == -1) 379 perror("dup2"); 380 if (dup2(fdout, 1) == -1) 381 perror("dup2"); 382 383 replacearg(&args, 0, "%s", ssh_program); 384 if (port != -1) { 385 addargs(&args, "-p"); 386 addargs(&args, "%d", port); 387 } 388 if (remuser != NULL) { 389 addargs(&args, "-l"); 390 addargs(&args, "%s", remuser); 391 } 392 addargs(&args, "-oBatchMode=yes"); 393 addargs(&args, "--"); 394 addargs(&args, "%s", host); 395 addargs(&args, "%s", cmd); 396 397 execvp(ssh_program, args.list); 398 perror(ssh_program); 399 exit(1); 400 } else if (pid == -1) { 401 fatal("fork: %s", strerror(errno)); 402 } 403 while (waitpid(pid, &status, 0) == -1) 404 if (errno != EINTR) 405 fatal("do_cmd2: waitpid: %s", strerror(errno)); 406 return 0; 407 } 408 409 typedef struct { 410 size_t cnt; 411 char *buf; 412 } BUF; 413 414 BUF *allocbuf(BUF *, int, int); 415 void lostconn(int); 416 int okname(char *); 417 void run_err(const char *,...) 418 __attribute__((__format__ (printf, 1, 2))) 419 __attribute__((__nonnull__ (1))); 420 int note_err(const char *,...) 421 __attribute__((__format__ (printf, 1, 2))); 422 void verifydir(char *); 423 424 struct passwd *pwd; 425 uid_t userid; 426 int errs, remin, remout, remin2, remout2; 427 int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory; 428 429 #define CMDNEEDS 64 430 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ 431 432 enum scp_mode_e { 433 MODE_SCP, 434 MODE_SFTP 435 }; 436 437 int response(void); 438 void rsource(char *, struct stat *); 439 void sink(int, char *[], const char *); 440 void source(int, char *[]); 441 void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct); 442 void toremote(int, char *[], enum scp_mode_e, char *sftp_direct); 443 void usage(void); 444 445 void source_sftp(int, char *, char *, struct sftp_conn *); 446 void sink_sftp(int, char *, const char *, struct sftp_conn *); 447 void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *, 448 char *, char *); 449 450 int 451 main(int argc, char **argv) 452 { 453 int ch, fflag, tflag, status, r, n; 454 char **newargv, *argv0; 455 const char *errstr; 456 extern char *optarg; 457 extern int optind; 458 enum scp_mode_e mode = MODE_SFTP; 459 char *sftp_direct = NULL; 460 long long llv; 461 462 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 463 sanitise_stdfd(); 464 465 msetlocale(); 466 467 /* Copy argv, because we modify it */ 468 argv0 = argv[0]; 469 newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); 470 for (n = 0; n < argc; n++) 471 newargv[n] = xstrdup(argv[n]); 472 argv = newargv; 473 474 __progname = ssh_get_progname(argv[0]); 475 476 log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); 477 478 memset(&args, '\0', sizeof(args)); 479 memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); 480 args.list = remote_remote_args.list = NULL; 481 addargs(&args, "%s", ssh_program); 482 addargs(&args, "-x"); 483 addargs(&args, "-oPermitLocalCommand=no"); 484 addargs(&args, "-oClearAllForwardings=yes"); 485 addargs(&args, "-oRemoteCommand=none"); 486 addargs(&args, "-oRequestTTY=no"); 487 addargs(&args, "-oControlMaster=no"); 488 489 fflag = Tflag = tflag = 0; 490 while ((ch = getopt(argc, argv, 491 "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:X:")) != -1) { 492 switch (ch) { 493 /* User-visible flags. */ 494 case '1': 495 fatal("SSH protocol v.1 is no longer supported"); 496 break; 497 case '2': 498 /* Ignored */ 499 break; 500 case 'A': 501 case '4': 502 case '6': 503 case 'C': 504 addargs(&args, "-%c", ch); 505 addargs(&remote_remote_args, "-%c", ch); 506 break; 507 case 'D': 508 sftp_direct = optarg; 509 break; 510 case '3': 511 throughlocal = 1; 512 break; 513 case 'R': 514 throughlocal = 0; 515 break; 516 case 'o': 517 case 'c': 518 case 'i': 519 case 'F': 520 case 'J': 521 addargs(&remote_remote_args, "-%c", ch); 522 addargs(&remote_remote_args, "%s", optarg); 523 addargs(&args, "-%c", ch); 524 addargs(&args, "%s", optarg); 525 break; 526 case 'O': 527 mode = MODE_SCP; 528 break; 529 case 's': 530 mode = MODE_SFTP; 531 break; 532 case 'P': 533 sshport = a2port(optarg); 534 if (sshport <= 0) 535 fatal("bad port \"%s\"\n", optarg); 536 break; 537 case 'B': 538 addargs(&remote_remote_args, "-oBatchmode=yes"); 539 addargs(&args, "-oBatchmode=yes"); 540 break; 541 case 'l': 542 limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, 543 &errstr); 544 if (errstr != NULL) 545 usage(); 546 limit_kbps *= 1024; /* kbps */ 547 bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); 548 break; 549 case 'p': 550 pflag = 1; 551 break; 552 case 'r': 553 iamrecursive = 1; 554 break; 555 case 'S': 556 ssh_program = xstrdup(optarg); 557 break; 558 case 'v': 559 addargs(&args, "-v"); 560 addargs(&remote_remote_args, "-v"); 561 if (verbose_mode == 0) 562 log_level = SYSLOG_LEVEL_DEBUG1; 563 else if (log_level < SYSLOG_LEVEL_DEBUG3) 564 log_level++; 565 verbose_mode = 1; 566 break; 567 case 'q': 568 addargs(&args, "-q"); 569 addargs(&remote_remote_args, "-q"); 570 showprogress = 0; 571 break; 572 case 'X': 573 /* Please keep in sync with sftp.c -X */ 574 if (strncmp(optarg, "buffer=", 7) == 0) { 575 r = scan_scaled(optarg + 7, &llv); 576 if (r == 0 && (llv <= 0 || llv > 256 * 1024)) { 577 r = -1; 578 errno = EINVAL; 579 } 580 if (r == -1) { 581 fatal("Invalid buffer size \"%s\": %s", 582 optarg + 7, strerror(errno)); 583 } 584 sftp_copy_buflen = (size_t)llv; 585 } else if (strncmp(optarg, "nrequests=", 10) == 0) { 586 llv = strtonum(optarg + 10, 1, 256 * 1024, 587 &errstr); 588 if (errstr != NULL) { 589 fatal("Invalid number of requests " 590 "\"%s\": %s", optarg + 10, errstr); 591 } 592 sftp_nrequests = (size_t)llv; 593 } else { 594 fatal("Invalid -X option"); 595 } 596 break; 597 598 /* Server options. */ 599 case 'd': 600 targetshouldbedirectory = 1; 601 break; 602 case 'f': /* "from" */ 603 iamremote = 1; 604 fflag = 1; 605 break; 606 case 't': /* "to" */ 607 iamremote = 1; 608 tflag = 1; 609 #ifdef HAVE_CYGWIN 610 setmode(0, O_BINARY); 611 #endif 612 break; 613 case 'T': 614 Tflag = 1; 615 break; 616 default: 617 usage(); 618 } 619 } 620 argc -= optind; 621 argv += optind; 622 623 log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); 624 625 /* Do this last because we want the user to be able to override it */ 626 addargs(&args, "-oForwardAgent=no"); 627 628 if (iamremote) 629 mode = MODE_SCP; 630 631 if ((pwd = getpwuid(userid = getuid())) == NULL) 632 fatal("unknown user %u", (u_int) userid); 633 634 if (!isatty(STDOUT_FILENO)) 635 showprogress = 0; 636 637 if (pflag) { 638 /* Cannot pledge: -p allows setuid/setgid files... */ 639 } else { 640 if (pledge("stdio rpath wpath cpath fattr tty proc exec", 641 NULL) == -1) { 642 perror("pledge"); 643 exit(1); 644 } 645 } 646 647 remin = STDIN_FILENO; 648 remout = STDOUT_FILENO; 649 650 if (fflag) { 651 /* Follow "protocol", send data. */ 652 (void) response(); 653 source(argc, argv); 654 exit(errs != 0); 655 } 656 if (tflag) { 657 /* Receive data. */ 658 sink(argc, argv, NULL); 659 exit(errs != 0); 660 } 661 if (argc < 2) 662 usage(); 663 if (argc > 2) 664 targetshouldbedirectory = 1; 665 666 remin = remout = -1; 667 do_cmd_pid = -1; 668 /* Command to be executed on remote system using "ssh". */ 669 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", 670 verbose_mode ? " -v" : "", 671 iamrecursive ? " -r" : "", pflag ? " -p" : "", 672 targetshouldbedirectory ? " -d" : ""); 673 674 (void) ssh_signal(SIGPIPE, lostconn); 675 676 if (colon(argv[argc - 1])) /* Dest is remote host. */ 677 toremote(argc, argv, mode, sftp_direct); 678 else { 679 if (targetshouldbedirectory) 680 verifydir(argv[argc - 1]); 681 tolocal(argc, argv, mode, sftp_direct); /* Dest is local host. */ 682 } 683 /* 684 * Finally check the exit status of the ssh process, if one was forked 685 * and no error has occurred yet 686 */ 687 if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) { 688 if (remin != -1) 689 (void) close(remin); 690 if (remout != -1) 691 (void) close(remout); 692 if (waitpid(do_cmd_pid, &status, 0) == -1) 693 errs = 1; 694 else { 695 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 696 errs = 1; 697 } 698 } 699 exit(errs != 0); 700 } 701 702 /* Callback from atomicio6 to update progress meter and limit bandwidth */ 703 static int 704 scpio(void *_cnt, size_t s) 705 { 706 off_t *cnt = (off_t *)_cnt; 707 708 *cnt += s; 709 refresh_progress_meter(0); 710 if (limit_kbps > 0) 711 bandwidth_limit(&bwlimit, s); 712 return 0; 713 } 714 715 static int 716 do_times(int fd, int verb, const struct stat *sb) 717 { 718 /* strlen(2^64) == 20; strlen(10^6) == 7 */ 719 char buf[(20 + 7 + 2) * 2 + 2]; 720 721 (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n", 722 (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime), 723 (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime)); 724 if (verb) { 725 fprintf(stderr, "File mtime %lld atime %lld\n", 726 (long long)sb->st_mtime, (long long)sb->st_atime); 727 fprintf(stderr, "Sending file timestamps: %s", buf); 728 } 729 (void) atomicio(vwrite, fd, buf, strlen(buf)); 730 return (response()); 731 } 732 733 static int 734 parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp, 735 char **pathp) 736 { 737 int r; 738 739 r = parse_uri("scp", uri, userp, hostp, portp, pathp); 740 if (r == 0 && *pathp == NULL) 741 *pathp = xstrdup("."); 742 return r; 743 } 744 745 /* Appends a string to an array; returns 0 on success, -1 on alloc failure */ 746 static int 747 append(char *cp, char ***ap, size_t *np) 748 { 749 char **tmp; 750 751 if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL) 752 return -1; 753 tmp[(*np)] = cp; 754 (*np)++; 755 *ap = tmp; 756 return 0; 757 } 758 759 /* 760 * Finds the start and end of the first brace pair in the pattern. 761 * returns 0 on success or -1 for invalid patterns. 762 */ 763 static int 764 find_brace(const char *pattern, int *startp, int *endp) 765 { 766 int i; 767 int in_bracket, brace_level; 768 769 *startp = *endp = -1; 770 in_bracket = brace_level = 0; 771 for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) { 772 switch (pattern[i]) { 773 case '\\': 774 /* skip next character */ 775 if (pattern[i + 1] != '\0') 776 i++; 777 break; 778 case '[': 779 in_bracket = 1; 780 break; 781 case ']': 782 in_bracket = 0; 783 break; 784 case '{': 785 if (in_bracket) 786 break; 787 if (pattern[i + 1] == '}') { 788 /* Protect a single {}, for find(1), like csh */ 789 i++; /* skip */ 790 break; 791 } 792 if (*startp == -1) 793 *startp = i; 794 brace_level++; 795 break; 796 case '}': 797 if (in_bracket) 798 break; 799 if (*startp < 0) { 800 /* Unbalanced brace */ 801 return -1; 802 } 803 if (--brace_level <= 0) 804 *endp = i; 805 break; 806 } 807 } 808 /* unbalanced brackets/braces */ 809 if (*endp < 0 && (*startp >= 0 || in_bracket)) 810 return -1; 811 return 0; 812 } 813 814 /* 815 * Assembles and records a successfully-expanded pattern, returns -1 on 816 * alloc failure. 817 */ 818 static int 819 emit_expansion(const char *pattern, int brace_start, int brace_end, 820 int sel_start, int sel_end, char ***patternsp, size_t *npatternsp) 821 { 822 char *cp; 823 size_t pattern_len; 824 int o = 0, tail_len; 825 826 if ((pattern_len = strlen(pattern)) == 0 || pattern_len >= INT_MAX) 827 return -1; 828 829 tail_len = strlen(pattern + brace_end + 1); 830 if ((cp = malloc(brace_start + (sel_end - sel_start) + 831 tail_len + 1)) == NULL) 832 return -1; 833 834 /* Pattern before initial brace */ 835 if (brace_start > 0) { 836 memcpy(cp, pattern, brace_start); 837 o = brace_start; 838 } 839 /* Current braced selection */ 840 if (sel_end - sel_start > 0) { 841 memcpy(cp + o, pattern + sel_start, 842 sel_end - sel_start); 843 o += sel_end - sel_start; 844 } 845 /* Remainder of pattern after closing brace */ 846 if (tail_len > 0) { 847 memcpy(cp + o, pattern + brace_end + 1, tail_len); 848 o += tail_len; 849 } 850 cp[o] = '\0'; 851 if (append(cp, patternsp, npatternsp) != 0) { 852 free(cp); 853 return -1; 854 } 855 return 0; 856 } 857 858 /* 859 * Expand the first encountered brace in pattern, appending the expanded 860 * patterns it yielded to the *patternsp array. 861 * 862 * Returns 0 on success or -1 on allocation failure. 863 * 864 * Signals whether expansion was performed via *expanded and whether 865 * pattern was invalid via *invalid. 866 */ 867 static int 868 brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp, 869 int *expanded, int *invalid) 870 { 871 int i; 872 int in_bracket, brace_start, brace_end, brace_level; 873 int sel_start, sel_end; 874 875 *invalid = *expanded = 0; 876 877 if (find_brace(pattern, &brace_start, &brace_end) != 0) { 878 *invalid = 1; 879 return 0; 880 } else if (brace_start == -1) 881 return 0; 882 883 in_bracket = brace_level = 0; 884 for (i = sel_start = brace_start + 1; i < brace_end; i++) { 885 switch (pattern[i]) { 886 case '{': 887 if (in_bracket) 888 break; 889 brace_level++; 890 break; 891 case '}': 892 if (in_bracket) 893 break; 894 brace_level--; 895 break; 896 case '[': 897 in_bracket = 1; 898 break; 899 case ']': 900 in_bracket = 0; 901 break; 902 case '\\': 903 if (i < brace_end - 1) 904 i++; /* skip */ 905 break; 906 } 907 if (pattern[i] == ',' || i == brace_end - 1) { 908 if (in_bracket || brace_level > 0) 909 continue; 910 /* End of a selection, emit an expanded pattern */ 911 912 /* Adjust end index for last selection */ 913 sel_end = (i == brace_end - 1) ? brace_end : i; 914 if (emit_expansion(pattern, brace_start, brace_end, 915 sel_start, sel_end, patternsp, npatternsp) != 0) 916 return -1; 917 /* move on to the next selection */ 918 sel_start = i + 1; 919 continue; 920 } 921 } 922 if (in_bracket || brace_level > 0) { 923 *invalid = 1; 924 return 0; 925 } 926 /* success */ 927 *expanded = 1; 928 return 0; 929 } 930 931 /* Expand braces from pattern. Returns 0 on success, -1 on failure */ 932 static int 933 brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp) 934 { 935 char *cp, *cp2, **active = NULL, **done = NULL; 936 size_t i, nactive = 0, ndone = 0; 937 int ret = -1, invalid = 0, expanded = 0; 938 939 *patternsp = NULL; 940 *npatternsp = 0; 941 942 /* Start the worklist with the original pattern */ 943 if ((cp = strdup(pattern)) == NULL) 944 return -1; 945 if (append(cp, &active, &nactive) != 0) { 946 free(cp); 947 return -1; 948 } 949 while (nactive > 0) { 950 cp = active[nactive - 1]; 951 nactive--; 952 if (brace_expand_one(cp, &active, &nactive, 953 &expanded, &invalid) == -1) { 954 free(cp); 955 goto fail; 956 } 957 if (invalid) 958 fatal_f("invalid brace pattern \"%s\"", cp); 959 if (expanded) { 960 /* 961 * Current entry expanded to new entries on the 962 * active list; discard the progenitor pattern. 963 */ 964 free(cp); 965 continue; 966 } 967 /* 968 * Pattern did not expand; append the filename component to 969 * the completed list 970 */ 971 if ((cp2 = strrchr(cp, '/')) != NULL) 972 *cp2++ = '\0'; 973 else 974 cp2 = cp; 975 if (append(xstrdup(cp2), &done, &ndone) != 0) { 976 free(cp); 977 goto fail; 978 } 979 free(cp); 980 } 981 /* success */ 982 *patternsp = done; 983 *npatternsp = ndone; 984 done = NULL; 985 ndone = 0; 986 ret = 0; 987 fail: 988 for (i = 0; i < nactive; i++) 989 free(active[i]); 990 free(active); 991 for (i = 0; i < ndone; i++) 992 free(done[i]); 993 free(done); 994 return ret; 995 } 996 997 static struct sftp_conn * 998 do_sftp_connect(char *host, char *user, int port, char *sftp_direct, 999 int *reminp, int *remoutp, int *pidp) 1000 { 1001 if (sftp_direct == NULL) { 1002 if (do_cmd(ssh_program, host, user, port, 1, "sftp", 1003 reminp, remoutp, pidp) < 0) 1004 return NULL; 1005 1006 } else { 1007 freeargs(&args); 1008 addargs(&args, "sftp-server"); 1009 if (do_cmd(sftp_direct, host, NULL, -1, 0, "sftp", 1010 reminp, remoutp, pidp) < 0) 1011 return NULL; 1012 } 1013 return sftp_init(*reminp, *remoutp, 1014 sftp_copy_buflen, sftp_nrequests, limit_kbps); 1015 } 1016 1017 void 1018 toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) 1019 { 1020 char *suser = NULL, *host = NULL, *src = NULL; 1021 char *bp, *tuser, *thost, *targ; 1022 int sport = -1, tport = -1; 1023 struct sftp_conn *conn = NULL, *conn2 = NULL; 1024 arglist alist; 1025 int i, r, status; 1026 struct stat sb; 1027 u_int j; 1028 1029 memset(&alist, '\0', sizeof(alist)); 1030 alist.list = NULL; 1031 1032 /* Parse target */ 1033 r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ); 1034 if (r == -1) { 1035 fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]); 1036 ++errs; 1037 goto out; 1038 } 1039 if (r != 0) { 1040 if (parse_user_host_path(argv[argc - 1], &tuser, &thost, 1041 &targ) == -1) { 1042 fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]); 1043 ++errs; 1044 goto out; 1045 } 1046 } 1047 1048 /* Parse source files */ 1049 for (i = 0; i < argc - 1; i++) { 1050 free(suser); 1051 free(host); 1052 free(src); 1053 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); 1054 if (r == -1) { 1055 fmprintf(stderr, "%s: invalid uri\n", argv[i]); 1056 ++errs; 1057 continue; 1058 } 1059 if (r != 0) { 1060 parse_user_host_path(argv[i], &suser, &host, &src); 1061 } 1062 if (suser != NULL && !okname(suser)) { 1063 ++errs; 1064 continue; 1065 } 1066 if (host && throughlocal) { /* extended remote to remote */ 1067 if (mode == MODE_SFTP) { 1068 if (remin == -1 || conn == NULL) { 1069 /* Connect to dest now */ 1070 sftp_free(conn); 1071 conn = do_sftp_connect(thost, tuser, 1072 tport, sftp_direct, 1073 &remin, &remout, &do_cmd_pid); 1074 if (conn == NULL) { 1075 fatal("Unable to open " 1076 "destination connection"); 1077 } 1078 debug3_f("origin in %d out %d pid %ld", 1079 remin, remout, (long)do_cmd_pid); 1080 } 1081 /* 1082 * XXX remember suser/host/sport and only 1083 * reconnect if they change between arguments. 1084 * would save reconnections for cases like 1085 * scp -3 hosta:/foo hosta:/bar hostb: 1086 */ 1087 /* Connect to origin now */ 1088 sftp_free(conn2); 1089 conn2 = do_sftp_connect(host, suser, 1090 sport, sftp_direct, 1091 &remin2, &remout2, &do_cmd_pid2); 1092 if (conn2 == NULL) { 1093 fatal("Unable to open " 1094 "source connection"); 1095 } 1096 debug3_f("destination in %d out %d pid %ld", 1097 remin2, remout2, (long)do_cmd_pid2); 1098 throughlocal_sftp(conn2, conn, src, targ); 1099 (void) close(remin2); 1100 (void) close(remout2); 1101 remin2 = remout2 = -1; 1102 if (waitpid(do_cmd_pid2, &status, 0) == -1) 1103 ++errs; 1104 else if (!WIFEXITED(status) || 1105 WEXITSTATUS(status) != 0) 1106 ++errs; 1107 do_cmd_pid2 = -1; 1108 continue; 1109 } else { 1110 xasprintf(&bp, "%s -f %s%s", cmd, 1111 *src == '-' ? "-- " : "", src); 1112 if (do_cmd(ssh_program, host, suser, sport, 0, 1113 bp, &remin, &remout, &do_cmd_pid) < 0) 1114 exit(1); 1115 free(bp); 1116 xasprintf(&bp, "%s -t %s%s", cmd, 1117 *targ == '-' ? "-- " : "", targ); 1118 if (do_cmd2(thost, tuser, tport, bp, 1119 remin, remout) < 0) 1120 exit(1); 1121 free(bp); 1122 (void) close(remin); 1123 (void) close(remout); 1124 remin = remout = -1; 1125 } 1126 } else if (host) { /* standard remote to remote */ 1127 /* 1128 * Second remote user is passed to first remote side 1129 * via scp command-line. Ensure it contains no obvious 1130 * shell characters. 1131 */ 1132 if (tuser != NULL && !okname(tuser)) { 1133 ++errs; 1134 continue; 1135 } 1136 if (tport != -1 && tport != SSH_DEFAULT_PORT) { 1137 /* This would require the remote support URIs */ 1138 fatal("target port not supported with two " 1139 "remote hosts and the -R option"); 1140 } 1141 1142 freeargs(&alist); 1143 addargs(&alist, "%s", ssh_program); 1144 addargs(&alist, "-x"); 1145 addargs(&alist, "-oClearAllForwardings=yes"); 1146 addargs(&alist, "-n"); 1147 for (j = 0; j < remote_remote_args.num; j++) { 1148 addargs(&alist, "%s", 1149 remote_remote_args.list[j]); 1150 } 1151 1152 if (sport != -1) { 1153 addargs(&alist, "-p"); 1154 addargs(&alist, "%d", sport); 1155 } 1156 if (suser) { 1157 addargs(&alist, "-l"); 1158 addargs(&alist, "%s", suser); 1159 } 1160 addargs(&alist, "--"); 1161 addargs(&alist, "%s", host); 1162 addargs(&alist, "%s", cmd); 1163 addargs(&alist, "%s", src); 1164 addargs(&alist, "%s%s%s:%s", 1165 tuser ? tuser : "", tuser ? "@" : "", 1166 thost, targ); 1167 if (do_local_cmd(&alist) != 0) 1168 errs = 1; 1169 } else { /* local to remote */ 1170 if (mode == MODE_SFTP) { 1171 /* no need to glob: already done by shell */ 1172 if (stat(argv[i], &sb) != 0) { 1173 fatal("stat local \"%s\": %s", argv[i], 1174 strerror(errno)); 1175 } 1176 if (remin == -1) { 1177 /* Connect to remote now */ 1178 sftp_free(conn); 1179 conn = do_sftp_connect(thost, tuser, 1180 tport, sftp_direct, 1181 &remin, &remout, &do_cmd_pid); 1182 if (conn == NULL) { 1183 fatal("Unable to open sftp " 1184 "connection"); 1185 } 1186 } 1187 1188 /* The protocol */ 1189 source_sftp(1, argv[i], targ, conn); 1190 continue; 1191 } 1192 /* SCP */ 1193 if (remin == -1) { 1194 xasprintf(&bp, "%s -t %s%s", cmd, 1195 *targ == '-' ? "-- " : "", targ); 1196 if (do_cmd(ssh_program, thost, tuser, tport, 0, 1197 bp, &remin, &remout, &do_cmd_pid) < 0) 1198 exit(1); 1199 if (response() < 0) 1200 exit(1); 1201 free(bp); 1202 } 1203 source(1, argv + i); 1204 } 1205 } 1206 out: 1207 freeargs(&alist); 1208 free(tuser); 1209 free(thost); 1210 free(targ); 1211 free(suser); 1212 free(host); 1213 free(src); 1214 sftp_free(conn); 1215 sftp_free(conn2); 1216 } 1217 1218 void 1219 tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) 1220 { 1221 char *bp, *host = NULL, *src = NULL, *suser = NULL; 1222 arglist alist; 1223 struct sftp_conn *conn = NULL; 1224 int i, r, sport = -1; 1225 1226 memset(&alist, '\0', sizeof(alist)); 1227 alist.list = NULL; 1228 1229 for (i = 0; i < argc - 1; i++) { 1230 free(suser); 1231 free(host); 1232 free(src); 1233 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); 1234 if (r == -1) { 1235 fmprintf(stderr, "%s: invalid uri\n", argv[i]); 1236 ++errs; 1237 continue; 1238 } 1239 if (r != 0) 1240 parse_user_host_path(argv[i], &suser, &host, &src); 1241 if (suser != NULL && !okname(suser)) { 1242 ++errs; 1243 continue; 1244 } 1245 if (!host) { /* Local to local. */ 1246 freeargs(&alist); 1247 addargs(&alist, "%s", _PATH_CP); 1248 if (iamrecursive) 1249 addargs(&alist, "-r"); 1250 if (pflag) 1251 addargs(&alist, "-p"); 1252 addargs(&alist, "--"); 1253 addargs(&alist, "%s", argv[i]); 1254 addargs(&alist, "%s", argv[argc-1]); 1255 if (do_local_cmd(&alist)) 1256 ++errs; 1257 continue; 1258 } 1259 /* Remote to local. */ 1260 if (mode == MODE_SFTP) { 1261 sftp_free(conn); 1262 conn = do_sftp_connect(host, suser, sport, 1263 sftp_direct, &remin, &remout, &do_cmd_pid); 1264 if (conn == NULL) { 1265 error("sftp connection failed"); 1266 ++errs; 1267 continue; 1268 } 1269 1270 /* The protocol */ 1271 sink_sftp(1, argv[argc - 1], src, conn); 1272 1273 (void) close(remin); 1274 (void) close(remout); 1275 remin = remout = -1; 1276 continue; 1277 } 1278 /* SCP */ 1279 xasprintf(&bp, "%s -f %s%s", 1280 cmd, *src == '-' ? "-- " : "", src); 1281 if (do_cmd(ssh_program, host, suser, sport, 0, bp, 1282 &remin, &remout, &do_cmd_pid) < 0) { 1283 free(bp); 1284 ++errs; 1285 continue; 1286 } 1287 free(bp); 1288 sink(1, argv + argc - 1, src); 1289 (void) close(remin); 1290 remin = remout = -1; 1291 } 1292 freeargs(&alist); 1293 free(suser); 1294 free(host); 1295 free(src); 1296 sftp_free(conn); 1297 } 1298 1299 /* Prepare remote path, handling ~ by assuming cwd is the homedir */ 1300 static char * 1301 prepare_remote_path(struct sftp_conn *conn, const char *path) 1302 { 1303 size_t nslash; 1304 1305 /* Handle ~ prefixed paths */ 1306 if (*path == '\0' || strcmp(path, "~") == 0) 1307 return xstrdup("."); 1308 if (*path != '~') 1309 return xstrdup(path); 1310 if (strncmp(path, "~/", 2) == 0) { 1311 if ((nslash = strspn(path + 2, "/")) == strlen(path + 2)) 1312 return xstrdup("."); 1313 return xstrdup(path + 2 + nslash); 1314 } 1315 if (sftp_can_expand_path(conn)) 1316 return sftp_expand_path(conn, path); 1317 /* No protocol extension */ 1318 error("server expand-path extension is required " 1319 "for ~user paths in SFTP mode"); 1320 return NULL; 1321 } 1322 1323 void 1324 source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) 1325 { 1326 char *target = NULL, *filename = NULL, *abs_dst = NULL; 1327 int src_is_dir, target_is_dir; 1328 Attrib a; 1329 struct stat st; 1330 1331 memset(&a, '\0', sizeof(a)); 1332 if (stat(src, &st) != 0) 1333 fatal("stat local \"%s\": %s", src, strerror(errno)); 1334 src_is_dir = S_ISDIR(st.st_mode); 1335 if ((filename = basename(src)) == NULL) 1336 fatal("basename \"%s\": %s", src, strerror(errno)); 1337 1338 /* Special handling for source of '..' */ 1339 if (strcmp(filename, "..") == 0) 1340 filename = "."; /* Upload to dest, not dest/.. */ 1341 1342 /* 1343 * No need to glob here - the local shell already took care of 1344 * the expansions 1345 */ 1346 if ((target = prepare_remote_path(conn, targ)) == NULL) 1347 cleanup_exit(255); 1348 target_is_dir = sftp_remote_is_dir(conn, target); 1349 if (targetshouldbedirectory && !target_is_dir) { 1350 debug("target directory \"%s\" does not exist", target); 1351 a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; 1352 a.perm = st.st_mode | 0700; /* ensure writable */ 1353 if (sftp_mkdir(conn, target, &a, 1) != 0) 1354 cleanup_exit(255); /* error already logged */ 1355 target_is_dir = 1; 1356 } 1357 if (target_is_dir) 1358 abs_dst = sftp_path_append(target, filename); 1359 else { 1360 abs_dst = target; 1361 target = NULL; 1362 } 1363 debug3_f("copying local %s to remote %s", src, abs_dst); 1364 1365 if (src_is_dir && iamrecursive) { 1366 if (sftp_upload_dir(conn, src, abs_dst, pflag, 1367 SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { 1368 error("failed to upload directory %s to %s", src, targ); 1369 errs = 1; 1370 } 1371 } else if (sftp_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { 1372 error("failed to upload file %s to %s", src, targ); 1373 errs = 1; 1374 } 1375 1376 free(abs_dst); 1377 free(target); 1378 } 1379 1380 void 1381 source(int argc, char **argv) 1382 { 1383 struct stat stb; 1384 static BUF buffer; 1385 BUF *bp; 1386 off_t i, statbytes; 1387 size_t amt, nr; 1388 int fd = -1, haderr, indx; 1389 char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX]; 1390 int len; 1391 1392 for (indx = 0; indx < argc; ++indx) { 1393 name = argv[indx]; 1394 statbytes = 0; 1395 len = strlen(name); 1396 while (len > 1 && name[len-1] == '/') 1397 name[--len] = '\0'; 1398 if ((fd = open(name, O_RDONLY|O_NONBLOCK)) == -1) 1399 goto syserr; 1400 if (strchr(name, '\n') != NULL) { 1401 strnvis(encname, name, sizeof(encname), VIS_NL); 1402 name = encname; 1403 } 1404 if (fstat(fd, &stb) == -1) { 1405 syserr: run_err("%s: %s", name, strerror(errno)); 1406 goto next; 1407 } 1408 if (stb.st_size < 0) { 1409 run_err("%s: %s", name, "Negative file size"); 1410 goto next; 1411 } 1412 unset_nonblock(fd); 1413 switch (stb.st_mode & S_IFMT) { 1414 case S_IFREG: 1415 break; 1416 case S_IFDIR: 1417 if (iamrecursive) { 1418 rsource(name, &stb); 1419 goto next; 1420 } 1421 /* FALLTHROUGH */ 1422 default: 1423 run_err("%s: not a regular file", name); 1424 goto next; 1425 } 1426 if ((last = strrchr(name, '/')) == NULL) 1427 last = name; 1428 else 1429 ++last; 1430 curfile = last; 1431 if (pflag) { 1432 if (do_times(remout, verbose_mode, &stb) < 0) 1433 goto next; 1434 } 1435 #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 1436 snprintf(buf, sizeof buf, "C%04o %lld %s\n", 1437 (u_int) (stb.st_mode & FILEMODEMASK), 1438 (long long)stb.st_size, last); 1439 if (verbose_mode) 1440 fmprintf(stderr, "Sending file modes: %s", buf); 1441 (void) atomicio(vwrite, remout, buf, strlen(buf)); 1442 if (response() < 0) 1443 goto next; 1444 if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) { 1445 next: if (fd != -1) { 1446 (void) close(fd); 1447 fd = -1; 1448 } 1449 continue; 1450 } 1451 if (showprogress) 1452 start_progress_meter(curfile, stb.st_size, &statbytes); 1453 set_nonblock(remout); 1454 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 1455 amt = bp->cnt; 1456 if (i + (off_t)amt > stb.st_size) 1457 amt = stb.st_size - i; 1458 if (!haderr) { 1459 if ((nr = atomicio(read, fd, 1460 bp->buf, amt)) != amt) { 1461 haderr = errno; 1462 memset(bp->buf + nr, 0, amt - nr); 1463 } 1464 } 1465 /* Keep writing after error to retain sync */ 1466 if (haderr) { 1467 (void)atomicio(vwrite, remout, bp->buf, amt); 1468 memset(bp->buf, 0, amt); 1469 continue; 1470 } 1471 if (atomicio6(vwrite, remout, bp->buf, amt, scpio, 1472 &statbytes) != amt) 1473 haderr = errno; 1474 } 1475 unset_nonblock(remout); 1476 1477 if (fd != -1) { 1478 if (close(fd) == -1 && !haderr) 1479 haderr = errno; 1480 fd = -1; 1481 } 1482 if (!haderr) 1483 (void) atomicio(vwrite, remout, "", 1); 1484 else 1485 run_err("%s: %s", name, strerror(haderr)); 1486 (void) response(); 1487 if (showprogress) 1488 stop_progress_meter(); 1489 } 1490 } 1491 1492 void 1493 rsource(char *name, struct stat *statp) 1494 { 1495 DIR *dirp; 1496 struct dirent *dp; 1497 char *last, *vect[1], path[PATH_MAX]; 1498 1499 if (!(dirp = opendir(name))) { 1500 run_err("%s: %s", name, strerror(errno)); 1501 return; 1502 } 1503 last = strrchr(name, '/'); 1504 if (last == NULL) 1505 last = name; 1506 else 1507 last++; 1508 if (pflag) { 1509 if (do_times(remout, verbose_mode, statp) < 0) { 1510 closedir(dirp); 1511 return; 1512 } 1513 } 1514 (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", 1515 (u_int) (statp->st_mode & FILEMODEMASK), 0, last); 1516 if (verbose_mode) 1517 fmprintf(stderr, "Entering directory: %s", path); 1518 (void) atomicio(vwrite, remout, path, strlen(path)); 1519 if (response() < 0) { 1520 closedir(dirp); 1521 return; 1522 } 1523 while ((dp = readdir(dirp)) != NULL) { 1524 if (dp->d_ino == 0) 1525 continue; 1526 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 1527 continue; 1528 if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) { 1529 run_err("%s/%s: name too long", name, dp->d_name); 1530 continue; 1531 } 1532 (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name); 1533 vect[0] = path; 1534 source(1, vect); 1535 } 1536 (void) closedir(dirp); 1537 (void) atomicio(vwrite, remout, "E\n", 2); 1538 (void) response(); 1539 } 1540 1541 void 1542 sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) 1543 { 1544 char *abs_src = NULL; 1545 char *abs_dst = NULL; 1546 glob_t g; 1547 char *filename, *tmp = NULL; 1548 int i, r, err = 0, dst_is_dir; 1549 struct stat st; 1550 1551 memset(&g, 0, sizeof(g)); 1552 1553 /* 1554 * Here, we need remote glob as SFTP can not depend on remote shell 1555 * expansions 1556 */ 1557 if ((abs_src = prepare_remote_path(conn, src)) == NULL) { 1558 err = -1; 1559 goto out; 1560 } 1561 1562 debug3_f("copying remote %s to local %s", abs_src, dst); 1563 if ((r = sftp_glob(conn, abs_src, GLOB_NOCHECK|GLOB_MARK, 1564 NULL, &g)) != 0) { 1565 if (r == GLOB_NOSPACE) 1566 error("%s: too many glob matches", src); 1567 else 1568 error("%s: %s", src, strerror(ENOENT)); 1569 err = -1; 1570 goto out; 1571 } 1572 1573 /* Did we actually get any matches back from the glob? */ 1574 if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != NULL) { 1575 /* 1576 * If nothing matched but a path returned, then it's probably 1577 * a GLOB_NOCHECK result. Check whether the unglobbed path 1578 * exists so we can give a nice error message early. 1579 */ 1580 if (sftp_stat(conn, g.gl_pathv[0], 1, NULL) != 0) { 1581 error("%s: %s", src, strerror(ENOENT)); 1582 err = -1; 1583 goto out; 1584 } 1585 } 1586 1587 if ((r = stat(dst, &st)) != 0) 1588 debug2_f("stat local \"%s\": %s", dst, strerror(errno)); 1589 dst_is_dir = r == 0 && S_ISDIR(st.st_mode); 1590 1591 if (g.gl_matchc > 1 && !dst_is_dir) { 1592 if (r == 0) { 1593 error("Multiple files match pattern, but destination " 1594 "\"%s\" is not a directory", dst); 1595 err = -1; 1596 goto out; 1597 } 1598 debug2_f("creating destination \"%s\"", dst); 1599 if (mkdir(dst, 0777) != 0) { 1600 error("local mkdir \"%s\": %s", dst, strerror(errno)); 1601 err = -1; 1602 goto out; 1603 } 1604 dst_is_dir = 1; 1605 } 1606 1607 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 1608 tmp = xstrdup(g.gl_pathv[i]); 1609 if ((filename = basename(tmp)) == NULL) { 1610 error("basename %s: %s", tmp, strerror(errno)); 1611 err = -1; 1612 goto out; 1613 } 1614 1615 /* Special handling for destination of '..' */ 1616 if (strcmp(filename, "..") == 0) 1617 filename = "."; /* Download to dest, not dest/.. */ 1618 1619 if (dst_is_dir) 1620 abs_dst = sftp_path_append(dst, filename); 1621 else 1622 abs_dst = xstrdup(dst); 1623 1624 debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 1625 if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { 1626 if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst, 1627 NULL, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) 1628 err = -1; 1629 } else { 1630 if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL, 1631 pflag, 0, 0, 1) == -1) 1632 err = -1; 1633 } 1634 free(abs_dst); 1635 abs_dst = NULL; 1636 free(tmp); 1637 tmp = NULL; 1638 } 1639 1640 out: 1641 free(abs_src); 1642 free(tmp); 1643 globfree(&g); 1644 if (err == -1) 1645 errs = 1; 1646 } 1647 1648 1649 #define TYPE_OVERFLOW(type, val) \ 1650 ((sizeof(type) == 4 && (val) > INT32_MAX) || \ 1651 (sizeof(type) == 8 && (val) > INT64_MAX) || \ 1652 (sizeof(type) != 4 && sizeof(type) != 8)) 1653 1654 void 1655 sink(int argc, char **argv, const char *src) 1656 { 1657 static BUF buffer; 1658 struct stat stb; 1659 BUF *bp; 1660 off_t i; 1661 size_t j, count; 1662 int amt, exists, first, ofd; 1663 mode_t mode, omode, mask; 1664 off_t size, statbytes; 1665 unsigned long long ull; 1666 int setimes, targisdir, wrerr; 1667 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; 1668 char **patterns = NULL; 1669 size_t n, npatterns = 0; 1670 struct timeval tv[2]; 1671 1672 #define atime tv[0] 1673 #define mtime tv[1] 1674 #define SCREWUP(str) { why = str; goto screwup; } 1675 1676 if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0)) 1677 SCREWUP("Unexpected off_t/time_t size"); 1678 1679 setimes = targisdir = 0; 1680 mask = umask(0); 1681 if (!pflag) { 1682 (void) umask(mask); 1683 mask |= 07000; 1684 } 1685 if (argc != 1) { 1686 run_err("ambiguous target"); 1687 exit(1); 1688 } 1689 targ = *argv; 1690 if (targetshouldbedirectory) 1691 verifydir(targ); 1692 1693 (void) atomicio(vwrite, remout, "", 1); 1694 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 1695 targisdir = 1; 1696 if (src != NULL && !iamrecursive && !Tflag) { 1697 /* 1698 * Prepare to try to restrict incoming filenames to match 1699 * the requested destination file glob. 1700 */ 1701 if (brace_expand(src, &patterns, &npatterns) != 0) 1702 fatal_f("could not expand pattern"); 1703 } 1704 for (first = 1;; first = 0) { 1705 cp = buf; 1706 if (atomicio(read, remin, cp, 1) != 1) 1707 goto done; 1708 if (*cp++ == '\n') 1709 SCREWUP("unexpected <newline>"); 1710 do { 1711 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 1712 SCREWUP("lost connection"); 1713 *cp++ = ch; 1714 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); 1715 *cp = 0; 1716 if (verbose_mode) 1717 fmprintf(stderr, "Sink: %s", buf); 1718 1719 if (buf[0] == '\01' || buf[0] == '\02') { 1720 if (iamremote == 0) { 1721 (void) snmprintf(visbuf, sizeof(visbuf), 1722 NULL, "%s", buf + 1); 1723 (void) atomicio(vwrite, STDERR_FILENO, 1724 visbuf, strlen(visbuf)); 1725 } 1726 if (buf[0] == '\02') 1727 exit(1); 1728 ++errs; 1729 continue; 1730 } 1731 if (buf[0] == 'E') { 1732 (void) atomicio(vwrite, remout, "", 1); 1733 goto done; 1734 } 1735 if (ch == '\n') 1736 *--cp = 0; 1737 1738 cp = buf; 1739 if (*cp == 'T') { 1740 setimes++; 1741 cp++; 1742 if (!isdigit((unsigned char)*cp)) 1743 SCREWUP("mtime.sec not present"); 1744 ull = strtoull(cp, &cp, 10); 1745 if (!cp || *cp++ != ' ') 1746 SCREWUP("mtime.sec not delimited"); 1747 if (TYPE_OVERFLOW(time_t, ull)) 1748 setimes = 0; /* out of range */ 1749 mtime.tv_sec = ull; 1750 mtime.tv_usec = strtol(cp, &cp, 10); 1751 if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 || 1752 mtime.tv_usec > 999999) 1753 SCREWUP("mtime.usec not delimited"); 1754 if (!isdigit((unsigned char)*cp)) 1755 SCREWUP("atime.sec not present"); 1756 ull = strtoull(cp, &cp, 10); 1757 if (!cp || *cp++ != ' ') 1758 SCREWUP("atime.sec not delimited"); 1759 if (TYPE_OVERFLOW(time_t, ull)) 1760 setimes = 0; /* out of range */ 1761 atime.tv_sec = ull; 1762 atime.tv_usec = strtol(cp, &cp, 10); 1763 if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || 1764 atime.tv_usec > 999999) 1765 SCREWUP("atime.usec not delimited"); 1766 (void) atomicio(vwrite, remout, "", 1); 1767 continue; 1768 } 1769 if (*cp != 'C' && *cp != 'D') { 1770 /* 1771 * Check for the case "rcp remote:foo\* local:bar". 1772 * In this case, the line "No match." can be returned 1773 * by the shell before the rcp command on the remote is 1774 * executed so the ^Aerror_message convention isn't 1775 * followed. 1776 */ 1777 if (first) { 1778 run_err("%s", cp); 1779 exit(1); 1780 } 1781 SCREWUP("expected control record"); 1782 } 1783 mode = 0; 1784 for (++cp; cp < buf + 5; cp++) { 1785 if (*cp < '0' || *cp > '7') 1786 SCREWUP("bad mode"); 1787 mode = (mode << 3) | (*cp - '0'); 1788 } 1789 if (!pflag) 1790 mode &= ~mask; 1791 if (*cp++ != ' ') 1792 SCREWUP("mode not delimited"); 1793 1794 if (!isdigit((unsigned char)*cp)) 1795 SCREWUP("size not present"); 1796 ull = strtoull(cp, &cp, 10); 1797 if (!cp || *cp++ != ' ') 1798 SCREWUP("size not delimited"); 1799 if (TYPE_OVERFLOW(off_t, ull)) 1800 SCREWUP("size out of range"); 1801 size = (off_t)ull; 1802 1803 if (*cp == '\0' || strchr(cp, '/') != NULL || 1804 strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) { 1805 run_err("error: unexpected filename: %s", cp); 1806 exit(1); 1807 } 1808 if (npatterns > 0) { 1809 for (n = 0; n < npatterns; n++) { 1810 if (strcmp(patterns[n], cp) == 0 || 1811 fnmatch(patterns[n], cp, 0) == 0) 1812 break; 1813 } 1814 if (n >= npatterns) { 1815 debug2_f("incoming filename \"%s\" does not " 1816 "match any of %zu expected patterns", cp, 1817 npatterns); 1818 for (n = 0; n < npatterns; n++) { 1819 debug3_f("expected pattern %zu: \"%s\"", 1820 n, patterns[n]); 1821 } 1822 SCREWUP("filename does not match request"); 1823 } 1824 } 1825 if (targisdir) { 1826 static char *namebuf; 1827 static size_t cursize; 1828 size_t need; 1829 1830 need = strlen(targ) + strlen(cp) + 250; 1831 if (need > cursize) { 1832 free(namebuf); 1833 namebuf = xmalloc(need); 1834 cursize = need; 1835 } 1836 (void) snprintf(namebuf, need, "%s%s%s", targ, 1837 strcmp(targ, "/") ? "/" : "", cp); 1838 np = namebuf; 1839 } else 1840 np = targ; 1841 curfile = cp; 1842 exists = stat(np, &stb) == 0; 1843 if (buf[0] == 'D') { 1844 int mod_flag = pflag; 1845 if (!iamrecursive) 1846 SCREWUP("received directory without -r"); 1847 if (exists) { 1848 if (!S_ISDIR(stb.st_mode)) { 1849 errno = ENOTDIR; 1850 goto bad; 1851 } 1852 if (pflag) 1853 (void) chmod(np, mode); 1854 } else { 1855 /* Handle copying from a read-only directory */ 1856 mod_flag = 1; 1857 if (mkdir(np, mode | S_IRWXU) == -1) 1858 goto bad; 1859 } 1860 vect[0] = xstrdup(np); 1861 sink(1, vect, src); 1862 if (setimes) { 1863 setimes = 0; 1864 (void) utimes(vect[0], tv); 1865 } 1866 if (mod_flag) 1867 (void) chmod(vect[0], mode); 1868 free(vect[0]); 1869 continue; 1870 } 1871 omode = mode; 1872 mode |= S_IWUSR; 1873 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { 1874 bad: run_err("%s: %s", np, strerror(errno)); 1875 continue; 1876 } 1877 (void) atomicio(vwrite, remout, "", 1); 1878 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { 1879 (void) close(ofd); 1880 continue; 1881 } 1882 cp = bp->buf; 1883 wrerr = 0; 1884 1885 /* 1886 * NB. do not use run_err() unless immediately followed by 1887 * exit() below as it may send a spurious reply that might 1888 * desynchronise us from the peer. Use note_err() instead. 1889 */ 1890 statbytes = 0; 1891 if (showprogress) 1892 start_progress_meter(curfile, size, &statbytes); 1893 set_nonblock(remin); 1894 for (count = i = 0; i < size; i += bp->cnt) { 1895 amt = bp->cnt; 1896 if (i + amt > size) 1897 amt = size - i; 1898 count += amt; 1899 do { 1900 j = atomicio6(read, remin, cp, amt, 1901 scpio, &statbytes); 1902 if (j == 0) { 1903 run_err("%s", j != EPIPE ? 1904 strerror(errno) : 1905 "dropped connection"); 1906 exit(1); 1907 } 1908 amt -= j; 1909 cp += j; 1910 } while (amt > 0); 1911 1912 if (count == bp->cnt) { 1913 /* Keep reading so we stay sync'd up. */ 1914 if (!wrerr) { 1915 if (atomicio(vwrite, ofd, bp->buf, 1916 count) != count) { 1917 note_err("%s: %s", np, 1918 strerror(errno)); 1919 wrerr = 1; 1920 } 1921 } 1922 count = 0; 1923 cp = bp->buf; 1924 } 1925 } 1926 unset_nonblock(remin); 1927 if (count != 0 && !wrerr && 1928 atomicio(vwrite, ofd, bp->buf, count) != count) { 1929 note_err("%s: %s", np, strerror(errno)); 1930 wrerr = 1; 1931 } 1932 if (!wrerr && (!exists || S_ISREG(stb.st_mode)) && 1933 ftruncate(ofd, size) != 0) 1934 note_err("%s: truncate: %s", np, strerror(errno)); 1935 if (pflag) { 1936 if (exists || omode != mode) 1937 #ifdef HAVE_FCHMOD 1938 if (fchmod(ofd, omode)) { 1939 #else /* HAVE_FCHMOD */ 1940 if (chmod(np, omode)) { 1941 #endif /* HAVE_FCHMOD */ 1942 note_err("%s: set mode: %s", 1943 np, strerror(errno)); 1944 } 1945 } else { 1946 if (!exists && omode != mode) 1947 #ifdef HAVE_FCHMOD 1948 if (fchmod(ofd, omode & ~mask)) { 1949 #else /* HAVE_FCHMOD */ 1950 if (chmod(np, omode & ~mask)) { 1951 #endif /* HAVE_FCHMOD */ 1952 note_err("%s: set mode: %s", 1953 np, strerror(errno)); 1954 } 1955 } 1956 if (close(ofd) == -1) 1957 note_err("%s: close: %s", np, strerror(errno)); 1958 (void) response(); 1959 if (showprogress) 1960 stop_progress_meter(); 1961 if (setimes && !wrerr) { 1962 setimes = 0; 1963 if (utimes(np, tv) == -1) { 1964 note_err("%s: set times: %s", 1965 np, strerror(errno)); 1966 } 1967 } 1968 /* If no error was noted then signal success for this file */ 1969 if (note_err(NULL) == 0) 1970 (void) atomicio(vwrite, remout, "", 1); 1971 } 1972 done: 1973 for (n = 0; n < npatterns; n++) 1974 free(patterns[n]); 1975 free(patterns); 1976 return; 1977 screwup: 1978 for (n = 0; n < npatterns; n++) 1979 free(patterns[n]); 1980 free(patterns); 1981 run_err("protocol error: %s", why); 1982 exit(1); 1983 } 1984 1985 void 1986 throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, 1987 char *src, char *targ) 1988 { 1989 char *target = NULL, *filename = NULL, *abs_dst = NULL; 1990 char *abs_src = NULL, *tmp = NULL; 1991 glob_t g; 1992 int i, r, targetisdir, err = 0; 1993 1994 if ((filename = basename(src)) == NULL) 1995 fatal("basename %s: %s", src, strerror(errno)); 1996 1997 if ((abs_src = prepare_remote_path(from, src)) == NULL || 1998 (target = prepare_remote_path(to, targ)) == NULL) 1999 cleanup_exit(255); 2000 memset(&g, 0, sizeof(g)); 2001 2002 targetisdir = sftp_remote_is_dir(to, target); 2003 if (!targetisdir && targetshouldbedirectory) { 2004 error("%s: destination is not a directory", targ); 2005 err = -1; 2006 goto out; 2007 } 2008 2009 debug3_f("copying remote %s to remote %s", abs_src, target); 2010 if ((r = sftp_glob(from, abs_src, GLOB_NOCHECK|GLOB_MARK, 2011 NULL, &g)) != 0) { 2012 if (r == GLOB_NOSPACE) 2013 error("%s: too many glob matches", src); 2014 else 2015 error("%s: %s", src, strerror(ENOENT)); 2016 err = -1; 2017 goto out; 2018 } 2019 2020 /* Did we actually get any matches back from the glob? */ 2021 if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != NULL) { 2022 /* 2023 * If nothing matched but a path returned, then it's probably 2024 * a GLOB_NOCHECK result. Check whether the unglobbed path 2025 * exists so we can give a nice error message early. 2026 */ 2027 if (sftp_stat(from, g.gl_pathv[0], 1, NULL) != 0) { 2028 error("%s: %s", src, strerror(ENOENT)); 2029 err = -1; 2030 goto out; 2031 } 2032 } 2033 2034 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 2035 tmp = xstrdup(g.gl_pathv[i]); 2036 if ((filename = basename(tmp)) == NULL) { 2037 error("basename %s: %s", tmp, strerror(errno)); 2038 err = -1; 2039 goto out; 2040 } 2041 2042 /* Special handling for source of '..' */ 2043 if (strcmp(filename, "..") == 0) 2044 filename = "."; /* Download to dest, not dest/.. */ 2045 2046 if (targetisdir) 2047 abs_dst = sftp_path_append(target, filename); 2048 else 2049 abs_dst = xstrdup(target); 2050 2051 debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 2052 if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { 2053 if (sftp_crossload_dir(from, to, g.gl_pathv[i], abs_dst, 2054 NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1) 2055 err = -1; 2056 } else { 2057 if (sftp_crossload(from, to, g.gl_pathv[i], abs_dst, 2058 NULL, pflag) == -1) 2059 err = -1; 2060 } 2061 free(abs_dst); 2062 abs_dst = NULL; 2063 free(tmp); 2064 tmp = NULL; 2065 } 2066 2067 out: 2068 free(abs_src); 2069 free(abs_dst); 2070 free(target); 2071 free(tmp); 2072 globfree(&g); 2073 if (err == -1) 2074 errs = 1; 2075 } 2076 2077 int 2078 response(void) 2079 { 2080 char ch, *cp, resp, rbuf[2048], visbuf[2048]; 2081 2082 if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) 2083 lostconn(0); 2084 2085 cp = rbuf; 2086 switch (resp) { 2087 case 0: /* ok */ 2088 return (0); 2089 default: 2090 *cp++ = resp; 2091 /* FALLTHROUGH */ 2092 case 1: /* error, followed by error msg */ 2093 case 2: /* fatal error, "" */ 2094 do { 2095 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 2096 lostconn(0); 2097 *cp++ = ch; 2098 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); 2099 2100 if (!iamremote) { 2101 cp[-1] = '\0'; 2102 (void) snmprintf(visbuf, sizeof(visbuf), 2103 NULL, "%s\n", rbuf); 2104 (void) atomicio(vwrite, STDERR_FILENO, 2105 visbuf, strlen(visbuf)); 2106 } 2107 ++errs; 2108 if (resp == 1) 2109 return (-1); 2110 exit(1); 2111 } 2112 /* NOTREACHED */ 2113 } 2114 2115 void 2116 usage(void) 2117 { 2118 (void) fprintf(stderr, 2119 "usage: scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" 2120 " [-i identity_file] [-J destination] [-l limit] [-o ssh_option]\n" 2121 " [-P port] [-S program] [-X sftp_option] source ... target\n"); 2122 exit(1); 2123 } 2124 2125 void 2126 run_err(const char *fmt,...) 2127 { 2128 static FILE *fp; 2129 va_list ap; 2130 2131 ++errs; 2132 if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) { 2133 (void) fprintf(fp, "%c", 0x01); 2134 (void) fprintf(fp, "scp: "); 2135 va_start(ap, fmt); 2136 (void) vfprintf(fp, fmt, ap); 2137 va_end(ap); 2138 (void) fprintf(fp, "\n"); 2139 (void) fflush(fp); 2140 } 2141 2142 if (!iamremote) { 2143 va_start(ap, fmt); 2144 vfmprintf(stderr, fmt, ap); 2145 va_end(ap); 2146 fprintf(stderr, "\n"); 2147 } 2148 } 2149 2150 /* 2151 * Notes a sink error for sending at the end of a file transfer. Returns 0 if 2152 * no error has been noted or -1 otherwise. Use note_err(NULL) to flush 2153 * any active error at the end of the transfer. 2154 */ 2155 int 2156 note_err(const char *fmt, ...) 2157 { 2158 static char *emsg; 2159 va_list ap; 2160 2161 /* Replay any previously-noted error */ 2162 if (fmt == NULL) { 2163 if (emsg == NULL) 2164 return 0; 2165 run_err("%s", emsg); 2166 free(emsg); 2167 emsg = NULL; 2168 return -1; 2169 } 2170 2171 errs++; 2172 /* Prefer first-noted error */ 2173 if (emsg != NULL) 2174 return -1; 2175 2176 va_start(ap, fmt); 2177 vasnmprintf(&emsg, INT_MAX, NULL, fmt, ap); 2178 va_end(ap); 2179 return -1; 2180 } 2181 2182 void 2183 verifydir(char *cp) 2184 { 2185 struct stat stb; 2186 2187 if (!stat(cp, &stb)) { 2188 if (S_ISDIR(stb.st_mode)) 2189 return; 2190 errno = ENOTDIR; 2191 } 2192 run_err("%s: %s", cp, strerror(errno)); 2193 killchild(0); 2194 } 2195 2196 int 2197 okname(char *cp0) 2198 { 2199 int c; 2200 char *cp; 2201 2202 cp = cp0; 2203 do { 2204 c = (int)*cp; 2205 if (c & 0200) 2206 goto bad; 2207 if (!isalpha(c) && !isdigit((unsigned char)c)) { 2208 switch (c) { 2209 case '\'': 2210 case '"': 2211 case '`': 2212 case ' ': 2213 case '#': 2214 goto bad; 2215 default: 2216 break; 2217 } 2218 } 2219 } while (*++cp); 2220 return (1); 2221 2222 bad: fmprintf(stderr, "%s: invalid user name\n", cp0); 2223 return (0); 2224 } 2225 2226 BUF * 2227 allocbuf(BUF *bp, int fd, int blksize) 2228 { 2229 size_t size; 2230 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 2231 struct stat stb; 2232 2233 if (fstat(fd, &stb) == -1) { 2234 run_err("fstat: %s", strerror(errno)); 2235 return (NULL); 2236 } 2237 size = ROUNDUP(stb.st_blksize, blksize); 2238 if (size == 0) 2239 size = blksize; 2240 #else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 2241 size = blksize; 2242 #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 2243 if (bp->cnt >= size) 2244 return (bp); 2245 bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1); 2246 bp->cnt = size; 2247 return (bp); 2248 } 2249 2250 void 2251 lostconn(int signo) 2252 { 2253 if (!iamremote) 2254 (void)write(STDERR_FILENO, "lost connection\n", 16); 2255 if (signo) 2256 _exit(1); 2257 else 2258 exit(1); 2259 } 2260 2261 void 2262 cleanup_exit(int i) 2263 { 2264 if (remin > 0) 2265 close(remin); 2266 if (remout > 0) 2267 close(remout); 2268 if (remin2 > 0) 2269 close(remin2); 2270 if (remout2 > 0) 2271 close(remout2); 2272 if (do_cmd_pid > 0) 2273 (void)waitpid(do_cmd_pid, NULL, 0); 2274 if (do_cmd_pid2 > 0) 2275 (void)waitpid(do_cmd_pid2, NULL, 0); 2276 exit(i); 2277 } 2278