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