summaryrefslogtreecommitdiff
path: root/scp.c
diff options
context:
space:
mode:
Diffstat (limited to 'scp.c')
-rw-r--r--scp.c152
1 files changed, 102 insertions, 50 deletions
diff --git a/scp.c b/scp.c
index 1407aa71d..620024ea7 100644
--- a/scp.c
+++ b/scp.c
@@ -71,7 +71,7 @@
71 */ 71 */
72 72
73#include "includes.h" 73#include "includes.h"
74RCSID("$OpenBSD: scp.c,v 1.125 2005/07/27 10:39:03 dtucker Exp $"); 74RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");
75 75
76#include "xmalloc.h" 76#include "xmalloc.h"
77#include "atomicio.h" 77#include "atomicio.h"
@@ -118,6 +118,48 @@ killchild(int signo)
118 exit(1); 118 exit(1);
119} 119}
120 120
121static int
122do_local_cmd(arglist *a)
123{
124 u_int i;
125 int status;
126 pid_t pid;
127
128 if (a->num == 0)
129 fatal("do_local_cmd: no arguments");
130
131 if (verbose_mode) {
132 fprintf(stderr, "Executing:");
133 for (i = 0; i < a->num; i++)
134 fprintf(stderr, " %s", a->list[i]);
135 fprintf(stderr, "\n");
136 }
137 if ((pid = fork()) == -1)
138 fatal("do_local_cmd: fork: %s", strerror(errno));
139
140 if (pid == 0) {
141 execvp(a->list[0], a->list);
142 perror(a->list[0]);
143 exit(1);
144 }
145
146 do_cmd_pid = pid;
147 signal(SIGTERM, killchild);
148 signal(SIGINT, killchild);
149 signal(SIGHUP, killchild);
150
151 while (waitpid(pid, &status, 0) == -1)
152 if (errno != EINTR)
153 fatal("do_local_cmd: waitpid: %s", strerror(errno));
154
155 do_cmd_pid = -1;
156
157 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
158 return (-1);
159
160 return (0);
161}
162
121/* 163/*
122 * This function executes the given command as the specified user on the 164 * This function executes the given command as the specified user on the
123 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 165 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
@@ -162,7 +204,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
162 close(pin[0]); 204 close(pin[0]);
163 close(pout[1]); 205 close(pout[1]);
164 206
165 args.list[0] = ssh_program; 207 replacearg(&args, 0, "%s", ssh_program);
166 if (remuser != NULL) 208 if (remuser != NULL)
167 addargs(&args, "-l%s", remuser); 209 addargs(&args, "-l%s", remuser);
168 addargs(&args, "%s", host); 210 addargs(&args, "%s", host);
@@ -222,12 +264,17 @@ main(int argc, char **argv)
222 extern char *optarg; 264 extern char *optarg;
223 extern int optind; 265 extern int optind;
224 266
267 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
268 sanitise_stdfd();
269
225 __progname = ssh_get_progname(argv[0]); 270 __progname = ssh_get_progname(argv[0]);
226 271
272 memset(&args, '\0', sizeof(args));
227 args.list = NULL; 273 args.list = NULL;
228 addargs(&args, "ssh"); /* overwritten with ssh_program */ 274 addargs(&args, "%s", ssh_program);
229 addargs(&args, "-x"); 275 addargs(&args, "-x");
230 addargs(&args, "-oForwardAgent no"); 276 addargs(&args, "-oForwardAgent no");
277 addargs(&args, "-oPermitLocalCommand no");
231 addargs(&args, "-oClearAllForwardings yes"); 278 addargs(&args, "-oClearAllForwardings yes");
232 279
233 fflag = tflag = 0; 280 fflag = tflag = 0;
@@ -336,9 +383,9 @@ main(int argc, char **argv)
336 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ 383 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
337 toremote(targ, argc, argv); 384 toremote(targ, argc, argv);
338 else { 385 else {
339 tolocal(argc, argv); /* Dest is local host. */
340 if (targetshouldbedirectory) 386 if (targetshouldbedirectory)
341 verifydir(argv[argc - 1]); 387 verifydir(argv[argc - 1]);
388 tolocal(argc, argv); /* Dest is local host. */
342 } 389 }
343 /* 390 /*
344 * Finally check the exit status of the ssh process, if one was forked 391 * Finally check the exit status of the ssh process, if one was forked
@@ -364,6 +411,10 @@ toremote(char *targ, int argc, char **argv)
364{ 411{
365 int i, len; 412 int i, len;
366 char *bp, *host, *src, *suser, *thost, *tuser, *arg; 413 char *bp, *host, *src, *suser, *thost, *tuser, *arg;
414 arglist alist;
415
416 memset(&alist, '\0', sizeof(alist));
417 alist.list = NULL;
367 418
368 *targ++ = 0; 419 *targ++ = 0;
369 if (*targ == 0) 420 if (*targ == 0)
@@ -381,56 +432,48 @@ toremote(char *targ, int argc, char **argv)
381 tuser = NULL; 432 tuser = NULL;
382 } 433 }
383 434
435 if (tuser != NULL && !okname(tuser)) {
436 xfree(arg);
437 return;
438 }
439
384 for (i = 0; i < argc - 1; i++) { 440 for (i = 0; i < argc - 1; i++) {
385 src = colon(argv[i]); 441 src = colon(argv[i]);
386 if (src) { /* remote to remote */ 442 if (src) { /* remote to remote */
387 static char *ssh_options = 443 freeargs(&alist);
388 "-x -o'ClearAllForwardings yes'"; 444 addargs(&alist, "%s", ssh_program);
445 if (verbose_mode)
446 addargs(&alist, "-v");
447 addargs(&alist, "-x");
448 addargs(&alist, "-oClearAllForwardings yes");
449 addargs(&alist, "-n");
450
389 *src++ = 0; 451 *src++ = 0;
390 if (*src == 0) 452 if (*src == 0)
391 src = "."; 453 src = ".";
392 host = strrchr(argv[i], '@'); 454 host = strrchr(argv[i], '@');
393 len = strlen(ssh_program) + strlen(argv[i]) + 455
394 strlen(src) + (tuser ? strlen(tuser) : 0) +
395 strlen(thost) + strlen(targ) +
396 strlen(ssh_options) + CMDNEEDS + 20;
397 bp = xmalloc(len);
398 if (host) { 456 if (host) {
399 *host++ = 0; 457 *host++ = 0;
400 host = cleanhostname(host); 458 host = cleanhostname(host);
401 suser = argv[i]; 459 suser = argv[i];
402 if (*suser == '\0') 460 if (*suser == '\0')
403 suser = pwd->pw_name; 461 suser = pwd->pw_name;
404 else if (!okname(suser)) { 462 else if (!okname(suser))
405 xfree(bp);
406 continue; 463 continue;
407 } 464 addargs(&alist, "-l");
408 if (tuser && !okname(tuser)) { 465 addargs(&alist, "%s", suser);
409 xfree(bp);
410 continue;
411 }
412 snprintf(bp, len,
413 "%s%s %s -n "
414 "-l %s %s %s %s '%s%s%s:%s'",
415 ssh_program, verbose_mode ? " -v" : "",
416 ssh_options, suser, host, cmd, src,
417 tuser ? tuser : "", tuser ? "@" : "",
418 thost, targ);
419 } else { 466 } else {
420 host = cleanhostname(argv[i]); 467 host = cleanhostname(argv[i]);
421 snprintf(bp, len,
422 "exec %s%s %s -n %s "
423 "%s %s '%s%s%s:%s'",
424 ssh_program, verbose_mode ? " -v" : "",
425 ssh_options, host, cmd, src,
426 tuser ? tuser : "", tuser ? "@" : "",
427 thost, targ);
428 } 468 }
429 if (verbose_mode) 469 addargs(&alist, "%s", host);
430 fprintf(stderr, "Executing: %s\n", bp); 470 addargs(&alist, "%s", cmd);
431 if (system(bp) != 0) 471 addargs(&alist, "%s", src);
472 addargs(&alist, "%s%s%s:%s",
473 tuser ? tuser : "", tuser ? "@" : "",
474 thost, targ);
475 if (do_local_cmd(&alist) != 0)
432 errs = 1; 476 errs = 1;
433 (void) xfree(bp);
434 } else { /* local to remote */ 477 } else { /* local to remote */
435 if (remin == -1) { 478 if (remin == -1) {
436 len = strlen(targ) + CMDNEEDS + 20; 479 len = strlen(targ) + CMDNEEDS + 20;
@@ -454,20 +497,23 @@ tolocal(int argc, char **argv)
454{ 497{
455 int i, len; 498 int i, len;
456 char *bp, *host, *src, *suser; 499 char *bp, *host, *src, *suser;
500 arglist alist;
501
502 memset(&alist, '\0', sizeof(alist));
503 alist.list = NULL;
457 504
458 for (i = 0; i < argc - 1; i++) { 505 for (i = 0; i < argc - 1; i++) {
459 if (!(src = colon(argv[i]))) { /* Local to local. */ 506 if (!(src = colon(argv[i]))) { /* Local to local. */
460 len = strlen(_PATH_CP) + strlen(argv[i]) + 507 freeargs(&alist);
461 strlen(argv[argc - 1]) + 20; 508 addargs(&alist, "%s", _PATH_CP);
462 bp = xmalloc(len); 509 if (iamrecursive)
463 (void) snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, 510 addargs(&alist, "-r");
464 iamrecursive ? " -r" : "", pflag ? " -p" : "", 511 if (pflag)
465 argv[i], argv[argc - 1]); 512 addargs(&alist, "-p");
466 if (verbose_mode) 513 addargs(&alist, "%s", argv[i]);
467 fprintf(stderr, "Executing: %s\n", bp); 514 addargs(&alist, "%s", argv[argc-1]);
468 if (system(bp)) 515 if (do_local_cmd(&alist))
469 ++errs; 516 ++errs;
470 (void) xfree(bp);
471 continue; 517 continue;
472 } 518 }
473 *src++ = 0; 519 *src++ = 0;
@@ -560,7 +606,7 @@ syserr: run_err("%s: %s", name, strerror(errno));
560#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 606#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
561 snprintf(buf, sizeof buf, "C%04o %lld %s\n", 607 snprintf(buf, sizeof buf, "C%04o %lld %s\n",
562 (u_int) (stb.st_mode & FILEMODEMASK), 608 (u_int) (stb.st_mode & FILEMODEMASK),
563 (int64_t)stb.st_size, last); 609 (long long)stb.st_size, last);
564 if (verbose_mode) { 610 if (verbose_mode) {
565 fprintf(stderr, "Sending file modes: %s", buf); 611 fprintf(stderr, "Sending file modes: %s", buf);
566 } 612 }
@@ -568,7 +614,10 @@ syserr: run_err("%s: %s", name, strerror(errno));
568 if (response() < 0) 614 if (response() < 0)
569 goto next; 615 goto next;
570 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { 616 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
571next: (void) close(fd); 617next: if (fd != -1) {
618 (void) close(fd);
619 fd = -1;
620 }
572 continue; 621 continue;
573 } 622 }
574 if (showprogress) 623 if (showprogress)
@@ -597,8 +646,11 @@ next: (void) close(fd);
597 if (showprogress) 646 if (showprogress)
598 stop_progress_meter(); 647 stop_progress_meter();
599 648
600 if (close(fd) < 0 && !haderr) 649 if (fd != -1) {
601 haderr = errno; 650 if (close(fd) < 0 && !haderr)
651 haderr = errno;
652 fd = -1;
653 }
602 if (!haderr) 654 if (!haderr)
603 (void) atomicio(vwrite, remout, "", 1); 655 (void) atomicio(vwrite, remout, "", 1);
604 else 656 else