summaryrefslogtreecommitdiff
path: root/scp.c
diff options
context:
space:
mode:
Diffstat (limited to 'scp.c')
-rw-r--r--scp.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/scp.c b/scp.c
index 1971c80cd..035037bcc 100644
--- a/scp.c
+++ b/scp.c
@@ -94,6 +94,7 @@
94#include <dirent.h> 94#include <dirent.h>
95#include <errno.h> 95#include <errno.h>
96#include <fcntl.h> 96#include <fcntl.h>
97#include <fnmatch.h>
97#include <limits.h> 98#include <limits.h>
98#include <locale.h> 99#include <locale.h>
99#include <pwd.h> 100#include <pwd.h>
@@ -383,14 +384,14 @@ void verifydir(char *);
383struct passwd *pwd; 384struct passwd *pwd;
384uid_t userid; 385uid_t userid;
385int errs, remin, remout; 386int errs, remin, remout;
386int pflag, iamremote, iamrecursive, targetshouldbedirectory; 387int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
387 388
388#define CMDNEEDS 64 389#define CMDNEEDS 64
389char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ 390char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
390 391
391int response(void); 392int response(void);
392void rsource(char *, struct stat *); 393void rsource(char *, struct stat *);
393void sink(int, char *[]); 394void sink(int, char *[], const char *);
394void source(int, char *[]); 395void source(int, char *[]);
395void tolocal(int, char *[]); 396void tolocal(int, char *[]);
396void toremote(int, char *[]); 397void toremote(int, char *[]);
@@ -429,8 +430,9 @@ main(int argc, char **argv)
429 addargs(&args, "-oRemoteCommand=none"); 430 addargs(&args, "-oRemoteCommand=none");
430 addargs(&args, "-oRequestTTY=no"); 431 addargs(&args, "-oRequestTTY=no");
431 432
432 fflag = tflag = 0; 433 fflag = Tflag = tflag = 0;
433 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) 434 while ((ch = getopt(argc, argv,
435 "dfl:prtTvBCc:i:P:q12346S:o:F:")) != -1) {
434 switch (ch) { 436 switch (ch) {
435 /* User-visible flags. */ 437 /* User-visible flags. */
436 case '1': 438 case '1':
@@ -509,9 +511,13 @@ main(int argc, char **argv)
509 setmode(0, O_BINARY); 511 setmode(0, O_BINARY);
510#endif 512#endif
511 break; 513 break;
514 case 'T':
515 Tflag = 1;
516 break;
512 default: 517 default:
513 usage(); 518 usage();
514 } 519 }
520 }
515 argc -= optind; 521 argc -= optind;
516 argv += optind; 522 argv += optind;
517 523
@@ -542,7 +548,7 @@ main(int argc, char **argv)
542 } 548 }
543 if (tflag) { 549 if (tflag) {
544 /* Receive data. */ 550 /* Receive data. */
545 sink(argc, argv); 551 sink(argc, argv, NULL);
546 exit(errs != 0); 552 exit(errs != 0);
547 } 553 }
548 if (argc < 2) 554 if (argc < 2)
@@ -800,7 +806,7 @@ tolocal(int argc, char **argv)
800 continue; 806 continue;
801 } 807 }
802 free(bp); 808 free(bp);
803 sink(1, argv + argc - 1); 809 sink(1, argv + argc - 1, src);
804 (void) close(remin); 810 (void) close(remin);
805 remin = remout = -1; 811 remin = remout = -1;
806 } 812 }
@@ -976,7 +982,7 @@ rsource(char *name, struct stat *statp)
976 (sizeof(type) != 4 && sizeof(type) != 8)) 982 (sizeof(type) != 4 && sizeof(type) != 8))
977 983
978void 984void
979sink(int argc, char **argv) 985sink(int argc, char **argv, const char *src)
980{ 986{
981 static BUF buffer; 987 static BUF buffer;
982 struct stat stb; 988 struct stat stb;
@@ -992,6 +998,7 @@ sink(int argc, char **argv)
992 unsigned long long ull; 998 unsigned long long ull;
993 int setimes, targisdir, wrerrno = 0; 999 int setimes, targisdir, wrerrno = 0;
994 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; 1000 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
1001 char *src_copy = NULL, *restrict_pattern = NULL;
995 struct timeval tv[2]; 1002 struct timeval tv[2];
996 1003
997#define atime tv[0] 1004#define atime tv[0]
@@ -1016,6 +1023,17 @@ sink(int argc, char **argv)
1016 (void) atomicio(vwrite, remout, "", 1); 1023 (void) atomicio(vwrite, remout, "", 1);
1017 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 1024 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
1018 targisdir = 1; 1025 targisdir = 1;
1026 if (src != NULL && !iamrecursive && !Tflag) {
1027 /*
1028 * Prepare to try to restrict incoming filenames to match
1029 * the requested destination file glob.
1030 */
1031 if ((src_copy = strdup(src)) == NULL)
1032 fatal("strdup failed");
1033 if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
1034 *restrict_pattern++ = '\0';
1035 }
1036 }
1019 for (first = 1;; first = 0) { 1037 for (first = 1;; first = 0) {
1020 cp = buf; 1038 cp = buf;
1021 if (atomicio(read, remin, cp, 1) != 1) 1039 if (atomicio(read, remin, cp, 1) != 1)
@@ -1120,6 +1138,9 @@ sink(int argc, char **argv)
1120 run_err("error: unexpected filename: %s", cp); 1138 run_err("error: unexpected filename: %s", cp);
1121 exit(1); 1139 exit(1);
1122 } 1140 }
1141 if (restrict_pattern != NULL &&
1142 fnmatch(restrict_pattern, cp, 0) != 0)
1143 SCREWUP("filename does not match request");
1123 if (targisdir) { 1144 if (targisdir) {
1124 static char *namebuf; 1145 static char *namebuf;
1125 static size_t cursize; 1146 static size_t cursize;
@@ -1157,7 +1178,7 @@ sink(int argc, char **argv)
1157 goto bad; 1178 goto bad;
1158 } 1179 }
1159 vect[0] = xstrdup(np); 1180 vect[0] = xstrdup(np);
1160 sink(1, vect); 1181 sink(1, vect, src);
1161 if (setimes) { 1182 if (setimes) {
1162 setimes = 0; 1183 setimes = 0;
1163 if (utimes(vect[0], tv) < 0) 1184 if (utimes(vect[0], tv) < 0)