scp.c (d366f891b12ce2802752fe6cde1e39e5003eb656) scp.c (afde5170533a488a5404d1dba7650598aa41fc65)
1/* $OpenBSD: scp.c,v 1.197 2018/06/01 04:31:48 dtucker Exp $ */
1/* $OpenBSD: scp.c,v 1.203 2019/01/27 07:14:11 jmc 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>

--- 79 unchanged lines hidden (view full) ---

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>
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>

--- 79 unchanged lines hidden (view full) ---

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>
97#include <limits.h>
98#include <locale.h>
99#include <pwd.h>
100#include <signal.h>
101#include <stdarg.h>
102#ifdef HAVE_STDINT_H
103#include <stdint.h>
104#endif

--- 265 unchanged lines hidden (view full) ---

370void lostconn(int);
371int okname(char *);
372void run_err(const char *,...);
373void verifydir(char *);
374
375struct passwd *pwd;
376uid_t userid;
377int errs, remin, remout;
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

--- 265 unchanged lines hidden (view full) ---

371void lostconn(int);
372int okname(char *);
373void run_err(const char *,...);
374void verifydir(char *);
375
376struct passwd *pwd;
377uid_t userid;
378int errs, remin, remout;
378int pflag, iamremote, iamrecursive, targetshouldbedirectory;
379int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
379
380#define CMDNEEDS 64
381char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
382
383int response(void);
384void rsource(char *, struct stat *);
380
381#define CMDNEEDS 64
382char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
383
384int response(void);
385void rsource(char *, struct stat *);
385void sink(int, char *[]);
386void sink(int, char *[], const char *);
386void source(int, char *[]);
387void tolocal(int, char *[]);
388void toremote(int, char *[]);
389void usage(void);
390
391int
392main(int argc, char **argv)
393{

--- 22 unchanged lines hidden (view full) ---

416 addargs(&args, "%s", ssh_program);
417 addargs(&args, "-x");
418 addargs(&args, "-oForwardAgent=no");
419 addargs(&args, "-oPermitLocalCommand=no");
420 addargs(&args, "-oClearAllForwardings=yes");
421 addargs(&args, "-oRemoteCommand=none");
422 addargs(&args, "-oRequestTTY=no");
423
387void source(int, char *[]);
388void tolocal(int, char *[]);
389void toremote(int, char *[]);
390void usage(void);
391
392int
393main(int argc, char **argv)
394{

--- 22 unchanged lines hidden (view full) ---

417 addargs(&args, "%s", ssh_program);
418 addargs(&args, "-x");
419 addargs(&args, "-oForwardAgent=no");
420 addargs(&args, "-oPermitLocalCommand=no");
421 addargs(&args, "-oClearAllForwardings=yes");
422 addargs(&args, "-oRemoteCommand=none");
423 addargs(&args, "-oRequestTTY=no");
424
424 fflag = tflag = 0;
425 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
425 fflag = Tflag = tflag = 0;
426 while ((ch = getopt(argc, argv,
427 "dfl:prtTvBCc:i:P:q12346S:o:F:")) != -1) {
426 switch (ch) {
427 /* User-visible flags. */
428 case '1':
429 fatal("SSH protocol v.1 is no longer supported");
430 break;
431 case '2':
432 /* Ignored */
433 break;

--- 62 unchanged lines hidden (view full) ---

496 break;
497 case 't': /* "to" */
498 iamremote = 1;
499 tflag = 1;
500#ifdef HAVE_CYGWIN
501 setmode(0, O_BINARY);
502#endif
503 break;
428 switch (ch) {
429 /* User-visible flags. */
430 case '1':
431 fatal("SSH protocol v.1 is no longer supported");
432 break;
433 case '2':
434 /* Ignored */
435 break;

--- 62 unchanged lines hidden (view full) ---

498 break;
499 case 't': /* "to" */
500 iamremote = 1;
501 tflag = 1;
502#ifdef HAVE_CYGWIN
503 setmode(0, O_BINARY);
504#endif
505 break;
506 case 'T':
507 Tflag = 1;
508 break;
504 default:
505 usage();
506 }
509 default:
510 usage();
511 }
512 }
507 argc -= optind;
508 argv += optind;
509
510 if ((pwd = getpwuid(userid = getuid())) == NULL)
511 fatal("unknown user %u", (u_int) userid);
512
513 if (!isatty(STDOUT_FILENO))
514 showprogress = 0;

--- 14 unchanged lines hidden (view full) ---

529 if (fflag) {
530 /* Follow "protocol", send data. */
531 (void) response();
532 source(argc, argv);
533 exit(errs != 0);
534 }
535 if (tflag) {
536 /* Receive data. */
513 argc -= optind;
514 argv += optind;
515
516 if ((pwd = getpwuid(userid = getuid())) == NULL)
517 fatal("unknown user %u", (u_int) userid);
518
519 if (!isatty(STDOUT_FILENO))
520 showprogress = 0;

--- 14 unchanged lines hidden (view full) ---

535 if (fflag) {
536 /* Follow "protocol", send data. */
537 (void) response();
538 source(argc, argv);
539 exit(errs != 0);
540 }
541 if (tflag) {
542 /* Receive data. */
537 sink(argc, argv);
543 sink(argc, argv, NULL);
538 exit(errs != 0);
539 }
540 if (argc < 2)
541 usage();
542 if (argc > 2)
543 targetshouldbedirectory = 1;
544
545 remin = remout = -1;

--- 240 unchanged lines hidden (view full) ---

786 xasprintf(&bp, "%s -f %s%s",
787 cmd, *src == '-' ? "-- " : "", src);
788 if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) {
789 free(bp);
790 ++errs;
791 continue;
792 }
793 free(bp);
544 exit(errs != 0);
545 }
546 if (argc < 2)
547 usage();
548 if (argc > 2)
549 targetshouldbedirectory = 1;
550
551 remin = remout = -1;

--- 240 unchanged lines hidden (view full) ---

792 xasprintf(&bp, "%s -f %s%s",
793 cmd, *src == '-' ? "-- " : "", src);
794 if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) {
795 free(bp);
796 ++errs;
797 continue;
798 }
799 free(bp);
794 sink(1, argv + argc - 1);
800 sink(1, argv + argc - 1, src);
795 (void) close(remin);
796 remin = remout = -1;
797 }
798 free(suser);
799 free(host);
800 free(src);
801}
802

--- 159 unchanged lines hidden (view full) ---

962}
963
964#define TYPE_OVERFLOW(type, val) \
965 ((sizeof(type) == 4 && (val) > INT32_MAX) || \
966 (sizeof(type) == 8 && (val) > INT64_MAX) || \
967 (sizeof(type) != 4 && sizeof(type) != 8))
968
969void
801 (void) close(remin);
802 remin = remout = -1;
803 }
804 free(suser);
805 free(host);
806 free(src);
807}
808

--- 159 unchanged lines hidden (view full) ---

968}
969
970#define TYPE_OVERFLOW(type, val) \
971 ((sizeof(type) == 4 && (val) > INT32_MAX) || \
972 (sizeof(type) == 8 && (val) > INT64_MAX) || \
973 (sizeof(type) != 4 && sizeof(type) != 8))
974
975void
970sink(int argc, char **argv)
976sink(int argc, char **argv, const char *src)
971{
972 static BUF buffer;
973 struct stat stb;
974 enum {
975 YES, NO, DISPLAYED
976 } wrerr;
977 BUF *bp;
978 off_t i;
979 size_t j, count;
980 int amt, exists, first, ofd;
981 mode_t mode, omode, mask;
982 off_t size, statbytes;
983 unsigned long long ull;
984 int setimes, targisdir, wrerrno = 0;
985 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
977{
978 static BUF buffer;
979 struct stat stb;
980 enum {
981 YES, NO, DISPLAYED
982 } wrerr;
983 BUF *bp;
984 off_t i;
985 size_t j, count;
986 int amt, exists, first, ofd;
987 mode_t mode, omode, mask;
988 off_t size, statbytes;
989 unsigned long long ull;
990 int setimes, targisdir, wrerrno = 0;
991 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
992 char *src_copy = NULL, *restrict_pattern = NULL;
986 struct timeval tv[2];
987
988#define atime tv[0]
989#define mtime tv[1]
990#define SCREWUP(str) { why = str; goto screwup; }
991
992 if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0))
993 SCREWUP("Unexpected off_t/time_t size");

--- 8 unchanged lines hidden (view full) ---

1002 }
1003 targ = *argv;
1004 if (targetshouldbedirectory)
1005 verifydir(targ);
1006
1007 (void) atomicio(vwrite, remout, "", 1);
1008 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
1009 targisdir = 1;
993 struct timeval tv[2];
994
995#define atime tv[0]
996#define mtime tv[1]
997#define SCREWUP(str) { why = str; goto screwup; }
998
999 if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0))
1000 SCREWUP("Unexpected off_t/time_t size");

--- 8 unchanged lines hidden (view full) ---

1009 }
1010 targ = *argv;
1011 if (targetshouldbedirectory)
1012 verifydir(targ);
1013
1014 (void) atomicio(vwrite, remout, "", 1);
1015 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
1016 targisdir = 1;
1017 if (src != NULL && !iamrecursive && !Tflag) {
1018 /*
1019 * Prepare to try to restrict incoming filenames to match
1020 * the requested destination file glob.
1021 */
1022 if ((src_copy = strdup(src)) == NULL)
1023 fatal("strdup failed");
1024 if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
1025 *restrict_pattern++ = '\0';
1026 }
1027 }
1010 for (first = 1;; first = 0) {
1011 cp = buf;
1012 if (atomicio(read, remin, cp, 1) != 1)
1013 return;
1014 if (*cp++ == '\n')
1015 SCREWUP("unexpected <newline>");
1016 do {
1017 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))

--- 88 unchanged lines hidden (view full) ---

1106 SCREWUP("size out of range");
1107 size = (off_t)ull;
1108
1109 if (*cp == '\0' || strchr(cp, '/') != NULL ||
1110 strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
1111 run_err("error: unexpected filename: %s", cp);
1112 exit(1);
1113 }
1028 for (first = 1;; first = 0) {
1029 cp = buf;
1030 if (atomicio(read, remin, cp, 1) != 1)
1031 return;
1032 if (*cp++ == '\n')
1033 SCREWUP("unexpected <newline>");
1034 do {
1035 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))

--- 88 unchanged lines hidden (view full) ---

1124 SCREWUP("size out of range");
1125 size = (off_t)ull;
1126
1127 if (*cp == '\0' || strchr(cp, '/') != NULL ||
1128 strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
1129 run_err("error: unexpected filename: %s", cp);
1130 exit(1);
1131 }
1132 if (restrict_pattern != NULL &&
1133 fnmatch(restrict_pattern, cp, 0) != 0)
1134 SCREWUP("filename does not match request");
1114 if (targisdir) {
1115 static char *namebuf;
1116 static size_t cursize;
1117 size_t need;
1118
1119 need = strlen(targ) + strlen(cp) + 250;
1120 if (need > cursize) {
1121 free(namebuf);

--- 21 unchanged lines hidden (view full) ---

1143 } else {
1144 /* Handle copying from a read-only
1145 directory */
1146 mod_flag = 1;
1147 if (mkdir(np, mode | S_IRWXU) < 0)
1148 goto bad;
1149 }
1150 vect[0] = xstrdup(np);
1135 if (targisdir) {
1136 static char *namebuf;
1137 static size_t cursize;
1138 size_t need;
1139
1140 need = strlen(targ) + strlen(cp) + 250;
1141 if (need > cursize) {
1142 free(namebuf);

--- 21 unchanged lines hidden (view full) ---

1164 } else {
1165 /* Handle copying from a read-only
1166 directory */
1167 mod_flag = 1;
1168 if (mkdir(np, mode | S_IRWXU) < 0)
1169 goto bad;
1170 }
1171 vect[0] = xstrdup(np);
1151 sink(1, vect);
1172 sink(1, vect, src);
1152 if (setimes) {
1153 setimes = 0;
1154 if (utimes(vect[0], tv) < 0)
1155 run_err("%s: set times: %s",
1156 vect[0], strerror(errno));
1157 }
1158 if (mod_flag)
1159 (void) chmod(vect[0], mode);

--- 151 unchanged lines hidden (view full) ---

1311 }
1312 /* NOTREACHED */
1313}
1314
1315void
1316usage(void)
1317{
1318 (void) fprintf(stderr,
1173 if (setimes) {
1174 setimes = 0;
1175 if (utimes(vect[0], tv) < 0)
1176 run_err("%s: set times: %s",
1177 vect[0], strerror(errno));
1178 }
1179 if (mod_flag)
1180 (void) chmod(vect[0], mode);

--- 151 unchanged lines hidden (view full) ---

1332 }
1333 /* NOTREACHED */
1334}
1335
1336void
1337usage(void)
1338{
1339 (void) fprintf(stderr,
1319 "usage: scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
1340 "usage: scp [-346BCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
1320 " [-l limit] [-o ssh_option] [-P port] [-S program] source ... target\n");
1321 exit(1);
1322}
1323
1324void
1325run_err(const char *fmt,...)
1326{
1327 static FILE *fp;

--- 99 unchanged lines hidden ---
1341 " [-l limit] [-o ssh_option] [-P port] [-S program] source ... target\n");
1342 exit(1);
1343}
1344
1345void
1346run_err(const char *fmt,...)
1347{
1348 static FILE *fp;

--- 99 unchanged lines hidden ---