1 /* $OpenBSD: scp.c,v 1.195 2018/02/10 06:15:12 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 #ifdef HAVE_SYS_STAT_H 78 # include <sys/stat.h> 79 #endif 80 #ifdef HAVE_POLL_H 81 #include <poll.h> 82 #else 83 # ifdef HAVE_SYS_POLL_H 84 # include <sys/poll.h> 85 # endif 86 #endif 87 #ifdef HAVE_SYS_TIME_H 88 # include <sys/time.h> 89 #endif 90 #include <sys/wait.h> 91 #include <sys/uio.h> 92 93 #include <ctype.h> 94 #include <dirent.h> 95 #include <errno.h> 96 #include <fcntl.h> 97 #include <limits.h> 98 #include <locale.h> 99 #include <pwd.h> 100 #include <signal.h> 101 #include <stdarg.h> 102 #ifdef HAVE_STDINT_H 103 #include <stdint.h> 104 #endif 105 #include <stdio.h> 106 #include <stdlib.h> 107 #include <string.h> 108 #include <time.h> 109 #include <unistd.h> 110 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 111 #include <vis.h> 112 #endif 113 114 #include "xmalloc.h" 115 #include "ssh.h" 116 #include "atomicio.h" 117 #include "pathnames.h" 118 #include "log.h" 119 #include "misc.h" 120 #include "progressmeter.h" 121 #include "utf8.h" 122 123 extern char *__progname; 124 125 #define COPY_BUFLEN 16384 126 127 int do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout); 128 int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout); 129 130 /* Struct for addargs */ 131 arglist args; 132 arglist remote_remote_args; 133 134 /* Bandwidth limit */ 135 long long limit_kbps = 0; 136 struct bwlimit bwlimit; 137 138 /* Name of current file being transferred. */ 139 char *curfile; 140 141 /* This is set to non-zero to enable verbose mode. */ 142 int verbose_mode = 0; 143 144 /* This is set to zero if the progressmeter is not desired. */ 145 int showprogress = 1; 146 147 /* 148 * This is set to non-zero if remote-remote copy should be piped 149 * through this process. 150 */ 151 int throughlocal = 0; 152 153 /* Non-standard port to use for the ssh connection or -1. */ 154 int sshport = -1; 155 156 /* This is the program to execute for the secured connection. ("ssh" or -S) */ 157 char *ssh_program = _PATH_SSH_PROGRAM; 158 159 /* This is used to store the pid of ssh_program */ 160 pid_t do_cmd_pid = -1; 161 162 static void 163 killchild(int signo) 164 { 165 if (do_cmd_pid > 1) { 166 kill(do_cmd_pid, signo ? signo : SIGTERM); 167 waitpid(do_cmd_pid, NULL, 0); 168 } 169 170 if (signo) 171 _exit(1); 172 exit(1); 173 } 174 175 static void 176 suspchild(int signo) 177 { 178 int status; 179 180 if (do_cmd_pid > 1) { 181 kill(do_cmd_pid, signo); 182 while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 && 183 errno == EINTR) 184 ; 185 kill(getpid(), SIGSTOP); 186 } 187 } 188 189 static int 190 do_local_cmd(arglist *a) 191 { 192 u_int i; 193 int status; 194 pid_t pid; 195 196 if (a->num == 0) 197 fatal("do_local_cmd: no arguments"); 198 199 if (verbose_mode) { 200 fprintf(stderr, "Executing:"); 201 for (i = 0; i < a->num; i++) 202 fmprintf(stderr, " %s", a->list[i]); 203 fprintf(stderr, "\n"); 204 } 205 if ((pid = fork()) == -1) 206 fatal("do_local_cmd: fork: %s", strerror(errno)); 207 208 if (pid == 0) { 209 execvp(a->list[0], a->list); 210 perror(a->list[0]); 211 exit(1); 212 } 213 214 do_cmd_pid = pid; 215 signal(SIGTERM, killchild); 216 signal(SIGINT, killchild); 217 signal(SIGHUP, killchild); 218 219 while (waitpid(pid, &status, 0) == -1) 220 if (errno != EINTR) 221 fatal("do_local_cmd: waitpid: %s", strerror(errno)); 222 223 do_cmd_pid = -1; 224 225 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 226 return (-1); 227 228 return (0); 229 } 230 231 /* 232 * This function executes the given command as the specified user on the 233 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 234 * assigns the input and output file descriptors on success. 235 */ 236 237 int 238 do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout) 239 { 240 int pin[2], pout[2], reserved[2]; 241 242 if (verbose_mode) 243 fmprintf(stderr, 244 "Executing: program %s host %s, user %s, command %s\n", 245 ssh_program, host, 246 remuser ? remuser : "(unspecified)", cmd); 247 248 if (port == -1) 249 port = sshport; 250 251 /* 252 * Reserve two descriptors so that the real pipes won't get 253 * descriptors 0 and 1 because that will screw up dup2 below. 254 */ 255 if (pipe(reserved) < 0) 256 fatal("pipe: %s", strerror(errno)); 257 258 /* Create a socket pair for communicating with ssh. */ 259 if (pipe(pin) < 0) 260 fatal("pipe: %s", strerror(errno)); 261 if (pipe(pout) < 0) 262 fatal("pipe: %s", strerror(errno)); 263 264 /* Free the reserved descriptors. */ 265 close(reserved[0]); 266 close(reserved[1]); 267 268 signal(SIGTSTP, suspchild); 269 signal(SIGTTIN, suspchild); 270 signal(SIGTTOU, suspchild); 271 272 /* Fork a child to execute the command on the remote host using ssh. */ 273 do_cmd_pid = fork(); 274 if (do_cmd_pid == 0) { 275 /* Child. */ 276 close(pin[1]); 277 close(pout[0]); 278 dup2(pin[0], 0); 279 dup2(pout[1], 1); 280 close(pin[0]); 281 close(pout[1]); 282 283 replacearg(&args, 0, "%s", ssh_program); 284 if (port != -1) { 285 addargs(&args, "-p"); 286 addargs(&args, "%d", port); 287 } 288 if (remuser != NULL) { 289 addargs(&args, "-l"); 290 addargs(&args, "%s", remuser); 291 } 292 addargs(&args, "--"); 293 addargs(&args, "%s", host); 294 addargs(&args, "%s", cmd); 295 296 execvp(ssh_program, args.list); 297 perror(ssh_program); 298 exit(1); 299 } else if (do_cmd_pid == -1) { 300 fatal("fork: %s", strerror(errno)); 301 } 302 /* Parent. Close the other side, and return the local side. */ 303 close(pin[0]); 304 *fdout = pin[1]; 305 close(pout[1]); 306 *fdin = pout[0]; 307 signal(SIGTERM, killchild); 308 signal(SIGINT, killchild); 309 signal(SIGHUP, killchild); 310 return 0; 311 } 312 313 /* 314 * This functions executes a command simlar to do_cmd(), but expects the 315 * input and output descriptors to be setup by a previous call to do_cmd(). 316 * This way the input and output of two commands can be connected. 317 */ 318 int 319 do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout) 320 { 321 pid_t pid; 322 int status; 323 324 if (verbose_mode) 325 fmprintf(stderr, 326 "Executing: 2nd program %s host %s, user %s, command %s\n", 327 ssh_program, host, 328 remuser ? remuser : "(unspecified)", cmd); 329 330 if (port == -1) 331 port = sshport; 332 333 /* Fork a child to execute the command on the remote host using ssh. */ 334 pid = fork(); 335 if (pid == 0) { 336 dup2(fdin, 0); 337 dup2(fdout, 1); 338 339 replacearg(&args, 0, "%s", ssh_program); 340 if (port != -1) { 341 addargs(&args, "-p"); 342 addargs(&args, "%d", port); 343 } 344 if (remuser != NULL) { 345 addargs(&args, "-l"); 346 addargs(&args, "%s", remuser); 347 } 348 addargs(&args, "--"); 349 addargs(&args, "%s", host); 350 addargs(&args, "%s", cmd); 351 352 execvp(ssh_program, args.list); 353 perror(ssh_program); 354 exit(1); 355 } else if (pid == -1) { 356 fatal("fork: %s", strerror(errno)); 357 } 358 while (waitpid(pid, &status, 0) == -1) 359 if (errno != EINTR) 360 fatal("do_cmd2: waitpid: %s", strerror(errno)); 361 return 0; 362 } 363 364 typedef struct { 365 size_t cnt; 366 char *buf; 367 } BUF; 368 369 BUF *allocbuf(BUF *, int, int); 370 void lostconn(int); 371 int okname(char *); 372 void run_err(const char *,...); 373 void verifydir(char *); 374 375 struct passwd *pwd; 376 uid_t userid; 377 int errs, remin, remout; 378 int pflag, iamremote, iamrecursive, targetshouldbedirectory; 379 380 #define CMDNEEDS 64 381 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ 382 383 int response(void); 384 void rsource(char *, struct stat *); 385 void sink(int, char *[]); 386 void source(int, char *[]); 387 void tolocal(int, char *[]); 388 void toremote(int, char *[]); 389 void usage(void); 390 391 int 392 main(int argc, char **argv) 393 { 394 int ch, fflag, tflag, status, n; 395 char **newargv; 396 const char *errstr; 397 extern char *optarg; 398 extern int optind; 399 400 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 401 sanitise_stdfd(); 402 403 msetlocale(); 404 405 /* Copy argv, because we modify it */ 406 newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); 407 for (n = 0; n < argc; n++) 408 newargv[n] = xstrdup(argv[n]); 409 argv = newargv; 410 411 __progname = ssh_get_progname(argv[0]); 412 413 memset(&args, '\0', sizeof(args)); 414 memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); 415 args.list = remote_remote_args.list = NULL; 416 addargs(&args, "%s", ssh_program); 417 addargs(&args, "-x"); 418 addargs(&args, "-oForwardAgent=no"); 419 addargs(&args, "-oPermitLocalCommand=no"); 420 addargs(&args, "-oClearAllForwardings=yes"); 421 addargs(&args, "-oRemoteCommand=none"); 422 addargs(&args, "-oRequestTTY=no"); 423 424 fflag = tflag = 0; 425 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) 426 switch (ch) { 427 /* User-visible flags. */ 428 case '1': 429 fatal("SSH protocol v.1 is no longer supported"); 430 break; 431 case '2': 432 /* Ignored */ 433 break; 434 case '4': 435 case '6': 436 case 'C': 437 addargs(&args, "-%c", ch); 438 addargs(&remote_remote_args, "-%c", ch); 439 break; 440 case '3': 441 throughlocal = 1; 442 break; 443 case 'o': 444 case 'c': 445 case 'i': 446 case 'F': 447 addargs(&remote_remote_args, "-%c", ch); 448 addargs(&remote_remote_args, "%s", optarg); 449 addargs(&args, "-%c", ch); 450 addargs(&args, "%s", optarg); 451 break; 452 case 'P': 453 sshport = a2port(optarg); 454 if (sshport <= 0) 455 fatal("bad port \"%s\"\n", optarg); 456 break; 457 case 'B': 458 addargs(&remote_remote_args, "-oBatchmode=yes"); 459 addargs(&args, "-oBatchmode=yes"); 460 break; 461 case 'l': 462 limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, 463 &errstr); 464 if (errstr != NULL) 465 usage(); 466 limit_kbps *= 1024; /* kbps */ 467 bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); 468 break; 469 case 'p': 470 pflag = 1; 471 break; 472 case 'r': 473 iamrecursive = 1; 474 break; 475 case 'S': 476 ssh_program = xstrdup(optarg); 477 break; 478 case 'v': 479 addargs(&args, "-v"); 480 addargs(&remote_remote_args, "-v"); 481 verbose_mode = 1; 482 break; 483 case 'q': 484 addargs(&args, "-q"); 485 addargs(&remote_remote_args, "-q"); 486 showprogress = 0; 487 break; 488 489 /* Server options. */ 490 case 'd': 491 targetshouldbedirectory = 1; 492 break; 493 case 'f': /* "from" */ 494 iamremote = 1; 495 fflag = 1; 496 break; 497 case 't': /* "to" */ 498 iamremote = 1; 499 tflag = 1; 500 #ifdef HAVE_CYGWIN 501 setmode(0, O_BINARY); 502 #endif 503 break; 504 default: 505 usage(); 506 } 507 argc -= optind; 508 argv += optind; 509 510 if ((pwd = getpwuid(userid = getuid())) == NULL) 511 fatal("unknown user %u", (u_int) userid); 512 513 if (!isatty(STDOUT_FILENO)) 514 showprogress = 0; 515 516 if (pflag) { 517 /* Cannot pledge: -p allows setuid/setgid files... */ 518 } else { 519 if (pledge("stdio rpath wpath cpath fattr tty proc exec", 520 NULL) == -1) { 521 perror("pledge"); 522 exit(1); 523 } 524 } 525 526 remin = STDIN_FILENO; 527 remout = STDOUT_FILENO; 528 529 if (fflag) { 530 /* Follow "protocol", send data. */ 531 (void) response(); 532 source(argc, argv); 533 exit(errs != 0); 534 } 535 if (tflag) { 536 /* Receive data. */ 537 sink(argc, argv); 538 exit(errs != 0); 539 } 540 if (argc < 2) 541 usage(); 542 if (argc > 2) 543 targetshouldbedirectory = 1; 544 545 remin = remout = -1; 546 do_cmd_pid = -1; 547 /* Command to be executed on remote system using "ssh". */ 548 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", 549 verbose_mode ? " -v" : "", 550 iamrecursive ? " -r" : "", pflag ? " -p" : "", 551 targetshouldbedirectory ? " -d" : ""); 552 553 (void) signal(SIGPIPE, lostconn); 554 555 if (colon(argv[argc - 1])) /* Dest is remote host. */ 556 toremote(argc, argv); 557 else { 558 if (targetshouldbedirectory) 559 verifydir(argv[argc - 1]); 560 tolocal(argc, argv); /* Dest is local host. */ 561 } 562 /* 563 * Finally check the exit status of the ssh process, if one was forked 564 * and no error has occurred yet 565 */ 566 if (do_cmd_pid != -1 && errs == 0) { 567 if (remin != -1) 568 (void) close(remin); 569 if (remout != -1) 570 (void) close(remout); 571 if (waitpid(do_cmd_pid, &status, 0) == -1) 572 errs = 1; 573 else { 574 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 575 errs = 1; 576 } 577 } 578 exit(errs != 0); 579 } 580 581 /* Callback from atomicio6 to update progress meter and limit bandwidth */ 582 static int 583 scpio(void *_cnt, size_t s) 584 { 585 off_t *cnt = (off_t *)_cnt; 586 587 *cnt += s; 588 if (limit_kbps > 0) 589 bandwidth_limit(&bwlimit, s); 590 return 0; 591 } 592 593 static int 594 do_times(int fd, int verb, const struct stat *sb) 595 { 596 /* strlen(2^64) == 20; strlen(10^6) == 7 */ 597 char buf[(20 + 7 + 2) * 2 + 2]; 598 599 (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n", 600 (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime), 601 (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime)); 602 if (verb) { 603 fprintf(stderr, "File mtime %lld atime %lld\n", 604 (long long)sb->st_mtime, (long long)sb->st_atime); 605 fprintf(stderr, "Sending file timestamps: %s", buf); 606 } 607 (void) atomicio(vwrite, fd, buf, strlen(buf)); 608 return (response()); 609 } 610 611 static int 612 parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp, 613 char **pathp) 614 { 615 int r; 616 617 r = parse_uri("scp", uri, userp, hostp, portp, pathp); 618 if (r == 0 && *pathp == NULL) 619 *pathp = xstrdup("."); 620 return r; 621 } 622 623 void 624 toremote(int argc, char **argv) 625 { 626 char *suser = NULL, *host = NULL, *src = NULL; 627 char *bp, *tuser, *thost, *targ; 628 int sport = -1, tport = -1; 629 arglist alist; 630 int i, r; 631 u_int j; 632 633 memset(&alist, '\0', sizeof(alist)); 634 alist.list = NULL; 635 636 /* Parse target */ 637 r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ); 638 if (r == -1) { 639 fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]); 640 ++errs; 641 goto out; 642 } 643 if (r != 0) { 644 if (parse_user_host_path(argv[argc - 1], &tuser, &thost, 645 &targ) == -1) { 646 fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]); 647 ++errs; 648 goto out; 649 } 650 } 651 if (tuser != NULL && !okname(tuser)) { 652 ++errs; 653 goto out; 654 } 655 656 /* Parse source files */ 657 for (i = 0; i < argc - 1; i++) { 658 free(suser); 659 free(host); 660 free(src); 661 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); 662 if (r == -1) { 663 fmprintf(stderr, "%s: invalid uri\n", argv[i]); 664 ++errs; 665 continue; 666 } 667 if (r != 0) { 668 parse_user_host_path(argv[i], &suser, &host, &src); 669 } 670 if (suser != NULL && !okname(suser)) { 671 ++errs; 672 continue; 673 } 674 if (host && throughlocal) { /* extended remote to remote */ 675 xasprintf(&bp, "%s -f %s%s", cmd, 676 *src == '-' ? "-- " : "", src); 677 if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) 678 exit(1); 679 free(bp); 680 xasprintf(&bp, "%s -t %s%s", cmd, 681 *targ == '-' ? "-- " : "", targ); 682 if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0) 683 exit(1); 684 free(bp); 685 (void) close(remin); 686 (void) close(remout); 687 remin = remout = -1; 688 } else if (host) { /* standard remote to remote */ 689 if (tport != -1 && tport != SSH_DEFAULT_PORT) { 690 /* This would require the remote support URIs */ 691 fatal("target port not supported with two " 692 "remote hosts without the -3 option"); 693 } 694 695 freeargs(&alist); 696 addargs(&alist, "%s", ssh_program); 697 addargs(&alist, "-x"); 698 addargs(&alist, "-oClearAllForwardings=yes"); 699 addargs(&alist, "-n"); 700 for (j = 0; j < remote_remote_args.num; j++) { 701 addargs(&alist, "%s", 702 remote_remote_args.list[j]); 703 } 704 705 if (sport != -1) { 706 addargs(&alist, "-p"); 707 addargs(&alist, "%d", sport); 708 } 709 if (suser) { 710 addargs(&alist, "-l"); 711 addargs(&alist, "%s", suser); 712 } 713 addargs(&alist, "--"); 714 addargs(&alist, "%s", host); 715 addargs(&alist, "%s", cmd); 716 addargs(&alist, "%s", src); 717 addargs(&alist, "%s%s%s:%s", 718 tuser ? tuser : "", tuser ? "@" : "", 719 thost, targ); 720 if (do_local_cmd(&alist) != 0) 721 errs = 1; 722 } else { /* local to remote */ 723 if (remin == -1) { 724 xasprintf(&bp, "%s -t %s%s", cmd, 725 *targ == '-' ? "-- " : "", targ); 726 if (do_cmd(thost, tuser, tport, bp, &remin, 727 &remout) < 0) 728 exit(1); 729 if (response() < 0) 730 exit(1); 731 free(bp); 732 } 733 source(1, argv + i); 734 } 735 } 736 out: 737 free(tuser); 738 free(thost); 739 free(targ); 740 free(suser); 741 free(host); 742 free(src); 743 } 744 745 void 746 tolocal(int argc, char **argv) 747 { 748 char *bp, *host = NULL, *src = NULL, *suser = NULL; 749 arglist alist; 750 int i, r, sport = -1; 751 752 memset(&alist, '\0', sizeof(alist)); 753 alist.list = NULL; 754 755 for (i = 0; i < argc - 1; i++) { 756 free(suser); 757 free(host); 758 free(src); 759 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); 760 if (r == -1) { 761 fmprintf(stderr, "%s: invalid uri\n", argv[i]); 762 ++errs; 763 continue; 764 } 765 if (r != 0) 766 parse_user_host_path(argv[i], &suser, &host, &src); 767 if (suser != NULL && !okname(suser)) { 768 ++errs; 769 continue; 770 } 771 if (!host) { /* Local to local. */ 772 freeargs(&alist); 773 addargs(&alist, "%s", _PATH_CP); 774 if (iamrecursive) 775 addargs(&alist, "-r"); 776 if (pflag) 777 addargs(&alist, "-p"); 778 addargs(&alist, "--"); 779 addargs(&alist, "%s", argv[i]); 780 addargs(&alist, "%s", argv[argc-1]); 781 if (do_local_cmd(&alist)) 782 ++errs; 783 continue; 784 } 785 /* Remote to local. */ 786 xasprintf(&bp, "%s -f %s%s", 787 cmd, *src == '-' ? "-- " : "", src); 788 if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) { 789 free(bp); 790 ++errs; 791 continue; 792 } 793 free(bp); 794 sink(1, argv + argc - 1); 795 (void) close(remin); 796 remin = remout = -1; 797 } 798 free(suser); 799 free(host); 800 free(src); 801 } 802 803 void 804 source(int argc, char **argv) 805 { 806 struct stat stb; 807 static BUF buffer; 808 BUF *bp; 809 off_t i, statbytes; 810 size_t amt, nr; 811 int fd = -1, haderr, indx; 812 char *last, *name, buf[2048], encname[PATH_MAX]; 813 int len; 814 815 for (indx = 0; indx < argc; ++indx) { 816 name = argv[indx]; 817 statbytes = 0; 818 len = strlen(name); 819 while (len > 1 && name[len-1] == '/') 820 name[--len] = '\0'; 821 if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0) 822 goto syserr; 823 if (strchr(name, '\n') != NULL) { 824 strnvis(encname, name, sizeof(encname), VIS_NL); 825 name = encname; 826 } 827 if (fstat(fd, &stb) < 0) { 828 syserr: run_err("%s: %s", name, strerror(errno)); 829 goto next; 830 } 831 if (stb.st_size < 0) { 832 run_err("%s: %s", name, "Negative file size"); 833 goto next; 834 } 835 unset_nonblock(fd); 836 switch (stb.st_mode & S_IFMT) { 837 case S_IFREG: 838 break; 839 case S_IFDIR: 840 if (iamrecursive) { 841 rsource(name, &stb); 842 goto next; 843 } 844 /* FALLTHROUGH */ 845 default: 846 run_err("%s: not a regular file", name); 847 goto next; 848 } 849 if ((last = strrchr(name, '/')) == NULL) 850 last = name; 851 else 852 ++last; 853 curfile = last; 854 if (pflag) { 855 if (do_times(remout, verbose_mode, &stb) < 0) 856 goto next; 857 } 858 #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 859 snprintf(buf, sizeof buf, "C%04o %lld %s\n", 860 (u_int) (stb.st_mode & FILEMODEMASK), 861 (long long)stb.st_size, last); 862 if (verbose_mode) 863 fmprintf(stderr, "Sending file modes: %s", buf); 864 (void) atomicio(vwrite, remout, buf, strlen(buf)); 865 if (response() < 0) 866 goto next; 867 if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) { 868 next: if (fd != -1) { 869 (void) close(fd); 870 fd = -1; 871 } 872 continue; 873 } 874 if (showprogress) 875 start_progress_meter(curfile, stb.st_size, &statbytes); 876 set_nonblock(remout); 877 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 878 amt = bp->cnt; 879 if (i + (off_t)amt > stb.st_size) 880 amt = stb.st_size - i; 881 if (!haderr) { 882 if ((nr = atomicio(read, fd, 883 bp->buf, amt)) != amt) { 884 haderr = errno; 885 memset(bp->buf + nr, 0, amt - nr); 886 } 887 } 888 /* Keep writing after error to retain sync */ 889 if (haderr) { 890 (void)atomicio(vwrite, remout, bp->buf, amt); 891 memset(bp->buf, 0, amt); 892 continue; 893 } 894 if (atomicio6(vwrite, remout, bp->buf, amt, scpio, 895 &statbytes) != amt) 896 haderr = errno; 897 } 898 unset_nonblock(remout); 899 900 if (fd != -1) { 901 if (close(fd) < 0 && !haderr) 902 haderr = errno; 903 fd = -1; 904 } 905 if (!haderr) 906 (void) atomicio(vwrite, remout, "", 1); 907 else 908 run_err("%s: %s", name, strerror(haderr)); 909 (void) response(); 910 if (showprogress) 911 stop_progress_meter(); 912 } 913 } 914 915 void 916 rsource(char *name, struct stat *statp) 917 { 918 DIR *dirp; 919 struct dirent *dp; 920 char *last, *vect[1], path[PATH_MAX]; 921 922 if (!(dirp = opendir(name))) { 923 run_err("%s: %s", name, strerror(errno)); 924 return; 925 } 926 last = strrchr(name, '/'); 927 if (last == NULL) 928 last = name; 929 else 930 last++; 931 if (pflag) { 932 if (do_times(remout, verbose_mode, statp) < 0) { 933 closedir(dirp); 934 return; 935 } 936 } 937 (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", 938 (u_int) (statp->st_mode & FILEMODEMASK), 0, last); 939 if (verbose_mode) 940 fmprintf(stderr, "Entering directory: %s", path); 941 (void) atomicio(vwrite, remout, path, strlen(path)); 942 if (response() < 0) { 943 closedir(dirp); 944 return; 945 } 946 while ((dp = readdir(dirp)) != NULL) { 947 if (dp->d_ino == 0) 948 continue; 949 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 950 continue; 951 if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) { 952 run_err("%s/%s: name too long", name, dp->d_name); 953 continue; 954 } 955 (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name); 956 vect[0] = path; 957 source(1, vect); 958 } 959 (void) closedir(dirp); 960 (void) atomicio(vwrite, remout, "E\n", 2); 961 (void) response(); 962 } 963 964 #define TYPE_OVERFLOW(type, val) \ 965 ((sizeof(type) == 4 && (val) > INT32_MAX) || \ 966 (sizeof(type) == 8 && (val) > INT64_MAX) || \ 967 (sizeof(type) != 4 && sizeof(type) != 8)) 968 969 void 970 sink(int argc, char **argv) 971 { 972 static BUF buffer; 973 struct stat stb; 974 enum { 975 YES, NO, DISPLAYED 976 } wrerr; 977 BUF *bp; 978 off_t i; 979 size_t j, count; 980 int amt, exists, first, ofd; 981 mode_t mode, omode, mask; 982 off_t size, statbytes; 983 unsigned long long ull; 984 int setimes, targisdir, wrerrno = 0; 985 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; 986 struct timeval tv[2]; 987 988 #define atime tv[0] 989 #define mtime tv[1] 990 #define SCREWUP(str) { why = str; goto screwup; } 991 992 if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0)) 993 SCREWUP("Unexpected off_t/time_t size"); 994 995 setimes = targisdir = 0; 996 mask = umask(0); 997 if (!pflag) 998 (void) umask(mask); 999 if (argc != 1) { 1000 run_err("ambiguous target"); 1001 exit(1); 1002 } 1003 targ = *argv; 1004 if (targetshouldbedirectory) 1005 verifydir(targ); 1006 1007 (void) atomicio(vwrite, remout, "", 1); 1008 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 1009 targisdir = 1; 1010 for (first = 1;; first = 0) { 1011 cp = buf; 1012 if (atomicio(read, remin, cp, 1) != 1) 1013 return; 1014 if (*cp++ == '\n') 1015 SCREWUP("unexpected <newline>"); 1016 do { 1017 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 1018 SCREWUP("lost connection"); 1019 *cp++ = ch; 1020 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); 1021 *cp = 0; 1022 if (verbose_mode) 1023 fmprintf(stderr, "Sink: %s", buf); 1024 1025 if (buf[0] == '\01' || buf[0] == '\02') { 1026 if (iamremote == 0) { 1027 (void) snmprintf(visbuf, sizeof(visbuf), 1028 NULL, "%s", buf + 1); 1029 (void) atomicio(vwrite, STDERR_FILENO, 1030 visbuf, strlen(visbuf)); 1031 } 1032 if (buf[0] == '\02') 1033 exit(1); 1034 ++errs; 1035 continue; 1036 } 1037 if (buf[0] == 'E') { 1038 (void) atomicio(vwrite, remout, "", 1); 1039 return; 1040 } 1041 if (ch == '\n') 1042 *--cp = 0; 1043 1044 cp = buf; 1045 if (*cp == 'T') { 1046 setimes++; 1047 cp++; 1048 if (!isdigit((unsigned char)*cp)) 1049 SCREWUP("mtime.sec not present"); 1050 ull = strtoull(cp, &cp, 10); 1051 if (!cp || *cp++ != ' ') 1052 SCREWUP("mtime.sec not delimited"); 1053 if (TYPE_OVERFLOW(time_t, ull)) 1054 setimes = 0; /* out of range */ 1055 mtime.tv_sec = ull; 1056 mtime.tv_usec = strtol(cp, &cp, 10); 1057 if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 || 1058 mtime.tv_usec > 999999) 1059 SCREWUP("mtime.usec not delimited"); 1060 if (!isdigit((unsigned char)*cp)) 1061 SCREWUP("atime.sec not present"); 1062 ull = strtoull(cp, &cp, 10); 1063 if (!cp || *cp++ != ' ') 1064 SCREWUP("atime.sec not delimited"); 1065 if (TYPE_OVERFLOW(time_t, ull)) 1066 setimes = 0; /* out of range */ 1067 atime.tv_sec = ull; 1068 atime.tv_usec = strtol(cp, &cp, 10); 1069 if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || 1070 atime.tv_usec > 999999) 1071 SCREWUP("atime.usec not delimited"); 1072 (void) atomicio(vwrite, remout, "", 1); 1073 continue; 1074 } 1075 if (*cp != 'C' && *cp != 'D') { 1076 /* 1077 * Check for the case "rcp remote:foo\* local:bar". 1078 * In this case, the line "No match." can be returned 1079 * by the shell before the rcp command on the remote is 1080 * executed so the ^Aerror_message convention isn't 1081 * followed. 1082 */ 1083 if (first) { 1084 run_err("%s", cp); 1085 exit(1); 1086 } 1087 SCREWUP("expected control record"); 1088 } 1089 mode = 0; 1090 for (++cp; cp < buf + 5; cp++) { 1091 if (*cp < '0' || *cp > '7') 1092 SCREWUP("bad mode"); 1093 mode = (mode << 3) | (*cp - '0'); 1094 } 1095 if (*cp++ != ' ') 1096 SCREWUP("mode not delimited"); 1097 1098 if (!isdigit((unsigned char)*cp)) 1099 SCREWUP("size not present"); 1100 ull = strtoull(cp, &cp, 10); 1101 if (!cp || *cp++ != ' ') 1102 SCREWUP("size not delimited"); 1103 if (TYPE_OVERFLOW(off_t, ull)) 1104 SCREWUP("size out of range"); 1105 size = (off_t)ull; 1106 1107 if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) { 1108 run_err("error: unexpected filename: %s", cp); 1109 exit(1); 1110 } 1111 if (targisdir) { 1112 static char *namebuf; 1113 static size_t cursize; 1114 size_t need; 1115 1116 need = strlen(targ) + strlen(cp) + 250; 1117 if (need > cursize) { 1118 free(namebuf); 1119 namebuf = xmalloc(need); 1120 cursize = need; 1121 } 1122 (void) snprintf(namebuf, need, "%s%s%s", targ, 1123 strcmp(targ, "/") ? "/" : "", cp); 1124 np = namebuf; 1125 } else 1126 np = targ; 1127 curfile = cp; 1128 exists = stat(np, &stb) == 0; 1129 if (buf[0] == 'D') { 1130 int mod_flag = pflag; 1131 if (!iamrecursive) 1132 SCREWUP("received directory without -r"); 1133 if (exists) { 1134 if (!S_ISDIR(stb.st_mode)) { 1135 errno = ENOTDIR; 1136 goto bad; 1137 } 1138 if (pflag) 1139 (void) chmod(np, mode); 1140 } else { 1141 /* Handle copying from a read-only 1142 directory */ 1143 mod_flag = 1; 1144 if (mkdir(np, mode | S_IRWXU) < 0) 1145 goto bad; 1146 } 1147 vect[0] = xstrdup(np); 1148 sink(1, vect); 1149 if (setimes) { 1150 setimes = 0; 1151 if (utimes(vect[0], tv) < 0) 1152 run_err("%s: set times: %s", 1153 vect[0], strerror(errno)); 1154 } 1155 if (mod_flag) 1156 (void) chmod(vect[0], mode); 1157 free(vect[0]); 1158 continue; 1159 } 1160 omode = mode; 1161 mode |= S_IWUSR; 1162 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { 1163 bad: run_err("%s: %s", np, strerror(errno)); 1164 continue; 1165 } 1166 (void) atomicio(vwrite, remout, "", 1); 1167 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { 1168 (void) close(ofd); 1169 continue; 1170 } 1171 cp = bp->buf; 1172 wrerr = NO; 1173 1174 statbytes = 0; 1175 if (showprogress) 1176 start_progress_meter(curfile, size, &statbytes); 1177 set_nonblock(remin); 1178 for (count = i = 0; i < size; i += bp->cnt) { 1179 amt = bp->cnt; 1180 if (i + amt > size) 1181 amt = size - i; 1182 count += amt; 1183 do { 1184 j = atomicio6(read, remin, cp, amt, 1185 scpio, &statbytes); 1186 if (j == 0) { 1187 run_err("%s", j != EPIPE ? 1188 strerror(errno) : 1189 "dropped connection"); 1190 exit(1); 1191 } 1192 amt -= j; 1193 cp += j; 1194 } while (amt > 0); 1195 1196 if (count == bp->cnt) { 1197 /* Keep reading so we stay sync'd up. */ 1198 if (wrerr == NO) { 1199 if (atomicio(vwrite, ofd, bp->buf, 1200 count) != count) { 1201 wrerr = YES; 1202 wrerrno = errno; 1203 } 1204 } 1205 count = 0; 1206 cp = bp->buf; 1207 } 1208 } 1209 unset_nonblock(remin); 1210 if (count != 0 && wrerr == NO && 1211 atomicio(vwrite, ofd, bp->buf, count) != count) { 1212 wrerr = YES; 1213 wrerrno = errno; 1214 } 1215 if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) && 1216 ftruncate(ofd, size) != 0) { 1217 run_err("%s: truncate: %s", np, strerror(errno)); 1218 wrerr = DISPLAYED; 1219 } 1220 if (pflag) { 1221 if (exists || omode != mode) 1222 #ifdef HAVE_FCHMOD 1223 if (fchmod(ofd, omode)) { 1224 #else /* HAVE_FCHMOD */ 1225 if (chmod(np, omode)) { 1226 #endif /* HAVE_FCHMOD */ 1227 run_err("%s: set mode: %s", 1228 np, strerror(errno)); 1229 wrerr = DISPLAYED; 1230 } 1231 } else { 1232 if (!exists && omode != mode) 1233 #ifdef HAVE_FCHMOD 1234 if (fchmod(ofd, omode & ~mask)) { 1235 #else /* HAVE_FCHMOD */ 1236 if (chmod(np, omode & ~mask)) { 1237 #endif /* HAVE_FCHMOD */ 1238 run_err("%s: set mode: %s", 1239 np, strerror(errno)); 1240 wrerr = DISPLAYED; 1241 } 1242 } 1243 if (close(ofd) == -1) { 1244 wrerr = YES; 1245 wrerrno = errno; 1246 } 1247 (void) response(); 1248 if (showprogress) 1249 stop_progress_meter(); 1250 if (setimes && wrerr == NO) { 1251 setimes = 0; 1252 if (utimes(np, tv) < 0) { 1253 run_err("%s: set times: %s", 1254 np, strerror(errno)); 1255 wrerr = DISPLAYED; 1256 } 1257 } 1258 switch (wrerr) { 1259 case YES: 1260 run_err("%s: %s", np, strerror(wrerrno)); 1261 break; 1262 case NO: 1263 (void) atomicio(vwrite, remout, "", 1); 1264 break; 1265 case DISPLAYED: 1266 break; 1267 } 1268 } 1269 screwup: 1270 run_err("protocol error: %s", why); 1271 exit(1); 1272 } 1273 1274 int 1275 response(void) 1276 { 1277 char ch, *cp, resp, rbuf[2048], visbuf[2048]; 1278 1279 if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) 1280 lostconn(0); 1281 1282 cp = rbuf; 1283 switch (resp) { 1284 case 0: /* ok */ 1285 return (0); 1286 default: 1287 *cp++ = resp; 1288 /* FALLTHROUGH */ 1289 case 1: /* error, followed by error msg */ 1290 case 2: /* fatal error, "" */ 1291 do { 1292 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) 1293 lostconn(0); 1294 *cp++ = ch; 1295 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); 1296 1297 if (!iamremote) { 1298 cp[-1] = '\0'; 1299 (void) snmprintf(visbuf, sizeof(visbuf), 1300 NULL, "%s\n", rbuf); 1301 (void) atomicio(vwrite, STDERR_FILENO, 1302 visbuf, strlen(visbuf)); 1303 } 1304 ++errs; 1305 if (resp == 1) 1306 return (-1); 1307 exit(1); 1308 } 1309 /* NOTREACHED */ 1310 } 1311 1312 void 1313 usage(void) 1314 { 1315 (void) fprintf(stderr, 1316 "usage: scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" 1317 " [-l limit] [-o ssh_option] [-P port] [-S program] source ... target\n"); 1318 exit(1); 1319 } 1320 1321 void 1322 run_err(const char *fmt,...) 1323 { 1324 static FILE *fp; 1325 va_list ap; 1326 1327 ++errs; 1328 if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) { 1329 (void) fprintf(fp, "%c", 0x01); 1330 (void) fprintf(fp, "scp: "); 1331 va_start(ap, fmt); 1332 (void) vfprintf(fp, fmt, ap); 1333 va_end(ap); 1334 (void) fprintf(fp, "\n"); 1335 (void) fflush(fp); 1336 } 1337 1338 if (!iamremote) { 1339 va_start(ap, fmt); 1340 vfmprintf(stderr, fmt, ap); 1341 va_end(ap); 1342 fprintf(stderr, "\n"); 1343 } 1344 } 1345 1346 void 1347 verifydir(char *cp) 1348 { 1349 struct stat stb; 1350 1351 if (!stat(cp, &stb)) { 1352 if (S_ISDIR(stb.st_mode)) 1353 return; 1354 errno = ENOTDIR; 1355 } 1356 run_err("%s: %s", cp, strerror(errno)); 1357 killchild(0); 1358 } 1359 1360 int 1361 okname(char *cp0) 1362 { 1363 int c; 1364 char *cp; 1365 1366 cp = cp0; 1367 do { 1368 c = (int)*cp; 1369 if (c & 0200) 1370 goto bad; 1371 if (!isalpha(c) && !isdigit((unsigned char)c)) { 1372 switch (c) { 1373 case '\'': 1374 case '"': 1375 case '`': 1376 case ' ': 1377 case '#': 1378 goto bad; 1379 default: 1380 break; 1381 } 1382 } 1383 } while (*++cp); 1384 return (1); 1385 1386 bad: fmprintf(stderr, "%s: invalid user name\n", cp0); 1387 return (0); 1388 } 1389 1390 BUF * 1391 allocbuf(BUF *bp, int fd, int blksize) 1392 { 1393 size_t size; 1394 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1395 struct stat stb; 1396 1397 if (fstat(fd, &stb) < 0) { 1398 run_err("fstat: %s", strerror(errno)); 1399 return (0); 1400 } 1401 size = ROUNDUP(stb.st_blksize, blksize); 1402 if (size == 0) 1403 size = blksize; 1404 #else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1405 size = blksize; 1406 #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1407 if (bp->cnt >= size) 1408 return (bp); 1409 bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1); 1410 bp->cnt = size; 1411 return (bp); 1412 } 1413 1414 void 1415 lostconn(int signo) 1416 { 1417 if (!iamremote) 1418 (void)write(STDERR_FILENO, "lost connection\n", 16); 1419 if (signo) 1420 _exit(1); 1421 else 1422 exit(1); 1423 } 1424