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