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