diff options
author | Colin Watson <cjwatson@debian.org> | 2006-05-12 08:53:37 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2006-05-12 08:53:37 +0000 |
commit | 2ee73b36b9a35daeaa4b065046882dc1f5f551b6 (patch) | |
tree | f64a4ace625514e94759878c0b94ab0a79805bbd /scp.c | |
parent | 3c190ec8e469477ea65fbf4cc83062c65c281434 (diff) | |
parent | 3e2e0ac10674d77618c4c7339e18b83ced247492 (diff) |
Merge 4.3p2 to the trunk.
Diffstat (limited to 'scp.c')
-rw-r--r-- | scp.c | 152 |
1 files changed, 102 insertions, 50 deletions
@@ -71,7 +71,7 @@ | |||
71 | */ | 71 | */ |
72 | 72 | ||
73 | #include "includes.h" | 73 | #include "includes.h" |
74 | RCSID("$OpenBSD: scp.c,v 1.125 2005/07/27 10:39:03 dtucker Exp $"); | 74 | RCSID("$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 | ||
121 | static int | ||
122 | do_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) { |
571 | next: (void) close(fd); | 617 | next: 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 |