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