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