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