diff options
Diffstat (limited to 'scp.c')
-rw-r--r-- | scp.c | 91 |
1 files changed, 52 insertions, 39 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: scp.c,v 1.171 2011/09/09 22:37:01 djm Exp $ */ | 1 | /* $OpenBSD: scp.c,v 1.178 2013/06/22 06:31:57 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * scp - secure remote copy. This is basically patched BSD rcp which | 3 | * scp - secure remote copy. This is basically patched BSD rcp which |
4 | * uses ssh to do the data transfer (instead of using rcmd). | 4 | * uses ssh to do the data transfer (instead of using rcmd). |
@@ -558,6 +558,24 @@ scpio(void *_cnt, size_t s) | |||
558 | return 0; | 558 | return 0; |
559 | } | 559 | } |
560 | 560 | ||
561 | static int | ||
562 | do_times(int fd, int verb, const struct stat *sb) | ||
563 | { | ||
564 | /* strlen(2^64) == 20; strlen(10^6) == 7 */ | ||
565 | char buf[(20 + 7 + 2) * 2 + 2]; | ||
566 | |||
567 | (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n", | ||
568 | (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime), | ||
569 | (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime)); | ||
570 | if (verb) { | ||
571 | fprintf(stderr, "File mtime %lld atime %lld\n", | ||
572 | (long long)sb->st_mtime, (long long)sb->st_atime); | ||
573 | fprintf(stderr, "Sending file timestamps: %s", buf); | ||
574 | } | ||
575 | (void) atomicio(vwrite, fd, buf, strlen(buf)); | ||
576 | return (response()); | ||
577 | } | ||
578 | |||
561 | void | 579 | void |
562 | toremote(char *targ, int argc, char **argv) | 580 | toremote(char *targ, int argc, char **argv) |
563 | { | 581 | { |
@@ -586,7 +604,7 @@ toremote(char *targ, int argc, char **argv) | |||
586 | } | 604 | } |
587 | 605 | ||
588 | if (tuser != NULL && !okname(tuser)) { | 606 | if (tuser != NULL && !okname(tuser)) { |
589 | xfree(arg); | 607 | free(arg); |
590 | return; | 608 | return; |
591 | } | 609 | } |
592 | 610 | ||
@@ -613,13 +631,13 @@ toremote(char *targ, int argc, char **argv) | |||
613 | *src == '-' ? "-- " : "", src); | 631 | *src == '-' ? "-- " : "", src); |
614 | if (do_cmd(host, suser, bp, &remin, &remout) < 0) | 632 | if (do_cmd(host, suser, bp, &remin, &remout) < 0) |
615 | exit(1); | 633 | exit(1); |
616 | (void) xfree(bp); | 634 | free(bp); |
617 | host = cleanhostname(thost); | 635 | host = cleanhostname(thost); |
618 | xasprintf(&bp, "%s -t %s%s", cmd, | 636 | xasprintf(&bp, "%s -t %s%s", cmd, |
619 | *targ == '-' ? "-- " : "", targ); | 637 | *targ == '-' ? "-- " : "", targ); |
620 | if (do_cmd2(host, tuser, bp, remin, remout) < 0) | 638 | if (do_cmd2(host, tuser, bp, remin, remout) < 0) |
621 | exit(1); | 639 | exit(1); |
622 | (void) xfree(bp); | 640 | free(bp); |
623 | (void) close(remin); | 641 | (void) close(remin); |
624 | (void) close(remout); | 642 | (void) close(remout); |
625 | remin = remout = -1; | 643 | remin = remout = -1; |
@@ -670,12 +688,12 @@ toremote(char *targ, int argc, char **argv) | |||
670 | exit(1); | 688 | exit(1); |
671 | if (response() < 0) | 689 | if (response() < 0) |
672 | exit(1); | 690 | exit(1); |
673 | (void) xfree(bp); | 691 | free(bp); |
674 | } | 692 | } |
675 | source(1, argv + i); | 693 | source(1, argv + i); |
676 | } | 694 | } |
677 | } | 695 | } |
678 | xfree(arg); | 696 | free(arg); |
679 | } | 697 | } |
680 | 698 | ||
681 | void | 699 | void |
@@ -719,11 +737,11 @@ tolocal(int argc, char **argv) | |||
719 | xasprintf(&bp, "%s -f %s%s", | 737 | xasprintf(&bp, "%s -f %s%s", |
720 | cmd, *src == '-' ? "-- " : "", src); | 738 | cmd, *src == '-' ? "-- " : "", src); |
721 | if (do_cmd(host, suser, bp, &remin, &remout) < 0) { | 739 | if (do_cmd(host, suser, bp, &remin, &remout) < 0) { |
722 | (void) xfree(bp); | 740 | free(bp); |
723 | ++errs; | 741 | ++errs; |
724 | continue; | 742 | continue; |
725 | } | 743 | } |
726 | xfree(bp); | 744 | free(bp); |
727 | sink(1, argv + argc - 1); | 745 | sink(1, argv + argc - 1); |
728 | (void) close(remin); | 746 | (void) close(remin); |
729 | remin = remout = -1; | 747 | remin = remout = -1; |
@@ -782,21 +800,7 @@ syserr: run_err("%s: %s", name, strerror(errno)); | |||
782 | ++last; | 800 | ++last; |
783 | curfile = last; | 801 | curfile = last; |
784 | if (pflag) { | 802 | if (pflag) { |
785 | /* | 803 | if (do_times(remout, verbose_mode, &stb) < 0) |
786 | * Make it compatible with possible future | ||
787 | * versions expecting microseconds. | ||
788 | */ | ||
789 | (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n", | ||
790 | (u_long) (stb.st_mtime < 0 ? 0 : stb.st_mtime), | ||
791 | (u_long) (stb.st_atime < 0 ? 0 : stb.st_atime)); | ||
792 | if (verbose_mode) { | ||
793 | fprintf(stderr, "File mtime %ld atime %ld\n", | ||
794 | (long)stb.st_mtime, (long)stb.st_atime); | ||
795 | fprintf(stderr, "Sending file timestamps: %s", | ||
796 | buf); | ||
797 | } | ||
798 | (void) atomicio(vwrite, remout, buf, strlen(buf)); | ||
799 | if (response() < 0) | ||
800 | goto next; | 804 | goto next; |
801 | } | 805 | } |
802 | #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) | 806 | #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) |
@@ -858,7 +862,7 @@ rsource(char *name, struct stat *statp) | |||
858 | { | 862 | { |
859 | DIR *dirp; | 863 | DIR *dirp; |
860 | struct dirent *dp; | 864 | struct dirent *dp; |
861 | char *last, *vect[1], path[1100]; | 865 | char *last, *vect[1], path[MAXPATHLEN]; |
862 | 866 | ||
863 | if (!(dirp = opendir(name))) { | 867 | if (!(dirp = opendir(name))) { |
864 | run_err("%s: %s", name, strerror(errno)); | 868 | run_err("%s: %s", name, strerror(errno)); |
@@ -870,11 +874,7 @@ rsource(char *name, struct stat *statp) | |||
870 | else | 874 | else |
871 | last++; | 875 | last++; |
872 | if (pflag) { | 876 | if (pflag) { |
873 | (void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n", | 877 | if (do_times(remout, verbose_mode, statp) < 0) { |
874 | (u_long) statp->st_mtime, | ||
875 | (u_long) statp->st_atime); | ||
876 | (void) atomicio(vwrite, remout, path, strlen(path)); | ||
877 | if (response() < 0) { | ||
878 | closedir(dirp); | 878 | closedir(dirp); |
879 | return; | 879 | return; |
880 | } | 880 | } |
@@ -920,6 +920,7 @@ sink(int argc, char **argv) | |||
920 | int amt, exists, first, ofd; | 920 | int amt, exists, first, ofd; |
921 | mode_t mode, omode, mask; | 921 | mode_t mode, omode, mask; |
922 | off_t size, statbytes; | 922 | off_t size, statbytes; |
923 | unsigned long long ull; | ||
923 | int setimes, targisdir, wrerrno = 0; | 924 | int setimes, targisdir, wrerrno = 0; |
924 | char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; | 925 | char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; |
925 | struct timeval tv[2]; | 926 | struct timeval tv[2]; |
@@ -978,17 +979,31 @@ sink(int argc, char **argv) | |||
978 | if (*cp == 'T') { | 979 | if (*cp == 'T') { |
979 | setimes++; | 980 | setimes++; |
980 | cp++; | 981 | cp++; |
981 | mtime.tv_sec = strtol(cp, &cp, 10); | 982 | if (!isdigit((unsigned char)*cp)) |
983 | SCREWUP("mtime.sec not present"); | ||
984 | ull = strtoull(cp, &cp, 10); | ||
982 | if (!cp || *cp++ != ' ') | 985 | if (!cp || *cp++ != ' ') |
983 | SCREWUP("mtime.sec not delimited"); | 986 | SCREWUP("mtime.sec not delimited"); |
987 | if ((time_t)ull < 0 || | ||
988 | (unsigned long long)(time_t)ull != ull) | ||
989 | setimes = 0; /* out of range */ | ||
990 | mtime.tv_sec = ull; | ||
984 | mtime.tv_usec = strtol(cp, &cp, 10); | 991 | mtime.tv_usec = strtol(cp, &cp, 10); |
985 | if (!cp || *cp++ != ' ') | 992 | if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 || |
993 | mtime.tv_usec > 999999) | ||
986 | SCREWUP("mtime.usec not delimited"); | 994 | SCREWUP("mtime.usec not delimited"); |
987 | atime.tv_sec = strtol(cp, &cp, 10); | 995 | if (!isdigit((unsigned char)*cp)) |
996 | SCREWUP("atime.sec not present"); | ||
997 | ull = strtoull(cp, &cp, 10); | ||
988 | if (!cp || *cp++ != ' ') | 998 | if (!cp || *cp++ != ' ') |
989 | SCREWUP("atime.sec not delimited"); | 999 | SCREWUP("atime.sec not delimited"); |
1000 | if ((time_t)ull < 0 || | ||
1001 | (unsigned long long)(time_t)ull != ull) | ||
1002 | setimes = 0; /* out of range */ | ||
1003 | atime.tv_sec = ull; | ||
990 | atime.tv_usec = strtol(cp, &cp, 10); | 1004 | atime.tv_usec = strtol(cp, &cp, 10); |
991 | if (!cp || *cp++ != '\0') | 1005 | if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || |
1006 | atime.tv_usec > 999999) | ||
992 | SCREWUP("atime.usec not delimited"); | 1007 | SCREWUP("atime.usec not delimited"); |
993 | (void) atomicio(vwrite, remout, "", 1); | 1008 | (void) atomicio(vwrite, remout, "", 1); |
994 | continue; | 1009 | continue; |
@@ -1031,8 +1046,7 @@ sink(int argc, char **argv) | |||
1031 | 1046 | ||
1032 | need = strlen(targ) + strlen(cp) + 250; | 1047 | need = strlen(targ) + strlen(cp) + 250; |
1033 | if (need > cursize) { | 1048 | if (need > cursize) { |
1034 | if (namebuf) | 1049 | free(namebuf); |
1035 | xfree(namebuf); | ||
1036 | namebuf = xmalloc(need); | 1050 | namebuf = xmalloc(need); |
1037 | cursize = need; | 1051 | cursize = need; |
1038 | } | 1052 | } |
@@ -1071,12 +1085,11 @@ sink(int argc, char **argv) | |||
1071 | } | 1085 | } |
1072 | if (mod_flag) | 1086 | if (mod_flag) |
1073 | (void) chmod(vect[0], mode); | 1087 | (void) chmod(vect[0], mode); |
1074 | if (vect[0]) | 1088 | free(vect[0]); |
1075 | xfree(vect[0]); | ||
1076 | continue; | 1089 | continue; |
1077 | } | 1090 | } |
1078 | omode = mode; | 1091 | omode = mode; |
1079 | mode |= S_IWRITE; | 1092 | mode |= S_IWUSR; |
1080 | if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { | 1093 | if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { |
1081 | bad: run_err("%s: %s", np, strerror(errno)); | 1094 | bad: run_err("%s: %s", np, strerror(errno)); |
1082 | continue; | 1095 | continue; |
@@ -1333,7 +1346,7 @@ void | |||
1333 | lostconn(int signo) | 1346 | lostconn(int signo) |
1334 | { | 1347 | { |
1335 | if (!iamremote) | 1348 | if (!iamremote) |
1336 | write(STDERR_FILENO, "lost connection\n", 16); | 1349 | (void)write(STDERR_FILENO, "lost connection\n", 16); |
1337 | if (signo) | 1350 | if (signo) |
1338 | _exit(1); | 1351 | _exit(1); |
1339 | else | 1352 | else |