Apply by doing: cd /usr/src patch -p0 < 011_ssh.patch And then rebuild and install ssh: cd usr.bin/ssh make obj make make install Index: usr.bin/ssh/misc.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/misc.c,v retrieving revision 1.29 diff -u -p -r1.29 misc.c --- usr.bin/ssh/misc.c 10 Mar 2005 22:01:05 -0000 1.29 +++ usr.bin/ssh/misc.c 11 Feb 2006 04:28:41 -0000 @@ -349,12 +349,15 @@ void addargs(arglist *args, char *fmt, ...) { va_list ap; - char buf[1024]; + char *cp; u_int nalloc; + int r; va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); + r = vasprintf(&cp, fmt, ap); va_end(ap); + if (r == -1) + fatal("addargs: argument too long"); nalloc = args->nalloc; if (args->list == NULL) { @@ -365,8 +368,42 @@ addargs(arglist *args, char *fmt, ...) args->list = xrealloc(args->list, nalloc * sizeof(char *)); args->nalloc = nalloc; - args->list[args->num++] = xstrdup(buf); + args->list[args->num++] = cp; args->list[args->num] = NULL; +} + +void +replacearg(arglist *args, u_int which, char *fmt, ...) +{ + va_list ap; + char *cp; + int r; + + va_start(ap, fmt); + r = vasprintf(&cp, fmt, ap); + va_end(ap); + if (r == -1) + fatal("replacearg: argument too long"); + + if (which >= args->num) + fatal("replacearg: tried to replace invalid arg %d >= %d", + which, args->num); + xfree(args->list[which]); + args->list[which] = cp; +} + +void +freeargs(arglist *args) +{ + u_int i; + + if (args->list != NULL) { + for (i = 0; i < args->num; i++) + xfree(args->list[i]); + xfree(args->list); + args->nalloc = args->num = 0; + args->list = NULL; + } } /* Index: usr.bin/ssh/misc.h =================================================================== RCS file: /cvs/src/usr.bin/ssh/misc.h,v retrieving revision 1.21 diff -u -p -r1.21 misc.h --- usr.bin/ssh/misc.h 1 Mar 2005 10:09:52 -0000 1.21 +++ usr.bin/ssh/misc.h 11 Feb 2006 04:28:41 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.21 2005/03/01 10:09:52 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.29 2006/01/31 10:19:02 djm Exp $ */ /* * Author: Tatu Ylonen @@ -33,7 +33,11 @@ struct arglist { u_int num; u_int nalloc; }; -void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3))); +void addargs(arglist *, char *, ...) + __attribute__((format(printf, 2, 3))); +void replacearg(arglist *, u_int, char *, ...) + __attribute__((format(printf, 3, 4))); +void freeargs(arglist *); /* tildexpand.c */ Index: usr.bin/ssh/scp.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/scp.c,v retrieving revision 1.119 diff -u -p -r1.119 scp.c --- usr.bin/ssh/scp.c 24 Jan 2005 10:22:06 -0000 1.119 +++ usr.bin/ssh/scp.c 11 Feb 2006 04:28:41 -0000 @@ -116,6 +116,48 @@ killchild(int signo) _exit(1); } +static int +do_local_cmd(arglist *a) +{ + u_int i; + int status; + pid_t pid; + + if (a->num == 0) + fatal("do_local_cmd: no arguments"); + + if (verbose_mode) { + fprintf(stderr, "Executing:"); + for (i = 0; i < a->num; i++) + fprintf(stderr, " %s", a->list[i]); + fprintf(stderr, "\n"); + } + if ((pid = fork()) == -1) + fatal("do_local_cmd: fork: %s", strerror(errno)); + + if (pid == 0) { + execvp(a->list[0], a->list); + perror(a->list[0]); + exit(1); + } + + do_cmd_pid = pid; + signal(SIGTERM, killchild); + signal(SIGINT, killchild); + signal(SIGHUP, killchild); + + while (waitpid(pid, &status, 0) == -1) + if (errno != EINTR) + fatal("do_local_cmd: waitpid: %s", strerror(errno)); + + do_cmd_pid = -1; + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + return (-1); + + return (0); +} + /* * This function executes the given command as the specified user on the * given host. This returns < 0 if execution fails, and >= 0 otherwise. This @@ -160,7 +202,7 @@ do_cmd(char *host, char *remuser, char * close(pin[0]); close(pout[1]); - args.list[0] = ssh_program; + replacearg(&args, 0, "%s", ssh_program); if (remuser != NULL) addargs(&args, "-l%s", remuser); addargs(&args, "%s", host); @@ -220,8 +262,9 @@ main(int argc, char **argv) extern char *optarg; extern int optind; + memset(&args, '\0', sizeof(args)); args.list = NULL; - addargs(&args, "ssh"); /* overwritten with ssh_program */ + addargs(&args, "%s", ssh_program); addargs(&args, "-x"); addargs(&args, "-oForwardAgent no"); addargs(&args, "-oClearAllForwardings yes"); @@ -356,73 +399,70 @@ void toremote(char *targ, int argc, char **argv) { int i, len; - char *bp, *host, *src, *suser, *thost, *tuser; + char *bp, *host, *src, *suser, *thost, *tuser, *arg; + arglist alist; + + memset(&alist, '\0', sizeof(alist)); + alist.list = NULL; *targ++ = 0; if (*targ == 0) targ = "."; - if ((thost = strrchr(argv[argc - 1], '@'))) { + arg = xstrdup(argv[argc - 1]); + if ((thost = strrchr(arg, '@'))) { /* user@host */ *thost++ = 0; - tuser = argv[argc - 1]; + tuser = arg; if (*tuser == '\0') tuser = NULL; } else { - thost = argv[argc - 1]; + thost = arg; tuser = NULL; } + if (tuser != NULL && !okname(tuser)) { + xfree(arg); + return; + } + for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src) { /* remote to remote */ - static char *ssh_options = - "-x -o'ClearAllForwardings yes'"; + freeargs(&alist); + addargs(&alist, "%s", ssh_program); + if (verbose_mode) + addargs(&alist, "-v"); + addargs(&alist, "-x"); + addargs(&alist, "-oClearAllForwardings yes"); + addargs(&alist, "-n"); + *src++ = 0; if (*src == 0) src = "."; host = strrchr(argv[i], '@'); - len = strlen(ssh_program) + strlen(argv[i]) + - strlen(src) + (tuser ? strlen(tuser) : 0) + - strlen(thost) + strlen(targ) + - strlen(ssh_options) + CMDNEEDS + 20; - bp = xmalloc(len); + if (host) { *host++ = 0; host = cleanhostname(host); suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; - else if (!okname(suser)) { - xfree(bp); - continue; - } - if (tuser && !okname(tuser)) { - xfree(bp); + else if (!okname(suser)) continue; - } - snprintf(bp, len, - "%s%s %s -n " - "-l %s %s %s %s '%s%s%s:%s'", - ssh_program, verbose_mode ? " -v" : "", - ssh_options, suser, host, cmd, src, - tuser ? tuser : "", tuser ? "@" : "", - thost, targ); + addargs(&alist, "-l"); + addargs(&alist, "%s", suser); } else { host = cleanhostname(argv[i]); - snprintf(bp, len, - "exec %s%s %s -n %s " - "%s %s '%s%s%s:%s'", - ssh_program, verbose_mode ? " -v" : "", - ssh_options, host, cmd, src, - tuser ? tuser : "", tuser ? "@" : "", - thost, targ); } - if (verbose_mode) - fprintf(stderr, "Executing: %s\n", bp); - if (system(bp) != 0) + addargs(&alist, "%s", host); + addargs(&alist, "%s", cmd); + addargs(&alist, "%s", src); + addargs(&alist, "%s%s%s:%s", + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + if (do_local_cmd(&alist) != 0) errs = 1; - (void) xfree(bp); } else { /* local to remote */ if (remin == -1) { len = strlen(targ) + CMDNEEDS + 20; @@ -446,20 +486,23 @@ tolocal(int argc, char **argv) { int i, len; char *bp, *host, *src, *suser; + arglist alist; + + memset(&alist, '\0', sizeof(alist)); + alist.list = NULL; for (i = 0; i < argc - 1; i++) { if (!(src = colon(argv[i]))) { /* Local to local. */ - len = strlen(_PATH_CP) + strlen(argv[i]) + - strlen(argv[argc - 1]) + 20; - bp = xmalloc(len); - (void) snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, - iamrecursive ? " -r" : "", pflag ? " -p" : "", - argv[i], argv[argc - 1]); - if (verbose_mode) - fprintf(stderr, "Executing: %s\n", bp); - if (system(bp)) + freeargs(&alist); + addargs(&alist, "%s", _PATH_CP); + if (iamrecursive) + addargs(&alist, "-r"); + if (pflag) + addargs(&alist, "-p"); + addargs(&alist, "%s", argv[i]); + addargs(&alist, "%s", argv[argc-1]); + if (do_local_cmd(&alist)) ++errs; - (void) xfree(bp); continue; } *src++ = 0; Index: usr.bin/ssh/sftp.c =================================================================== RCS file: /cvs/src/usr.bin/ssh/sftp.c,v retrieving revision 1.63 diff -u -p -r1.63 sftp.c --- usr.bin/ssh/sftp.c 10 Mar 2005 22:01:05 -0000 1.63 +++ usr.bin/ssh/sftp.c 11 Feb 2006 04:28:41 -0000 @@ -1415,8 +1415,9 @@ main(int argc, char **argv) extern int optind; extern char *optarg; + memset(&args, '\0', sizeof(args)); args.list = NULL; - addargs(&args, "ssh"); /* overwritten with ssh_program */ + addargs(&args, ssh_program); addargs(&args, "-oForwardX11 no"); addargs(&args, "-oForwardAgent no"); addargs(&args, "-oClearAllForwardings yes"); @@ -1450,6 +1451,7 @@ main(int argc, char **argv) break; case 'S': ssh_program = optarg; + replacearg(&args, 0, "%s", ssh_program); break; case 'b': if (batchmode) @@ -1526,7 +1528,6 @@ main(int argc, char **argv) addargs(&args, "%s", host); addargs(&args, "%s", (sftp_server != NULL ? sftp_server : "sftp")); - args.list[0] = ssh_program; if (!batchmode) fprintf(stderr, "Connecting to %s...\n", host); @@ -1539,6 +1540,7 @@ main(int argc, char **argv) fprintf(stderr, "Attaching to %s...\n", sftp_direct); connect_to_server(sftp_direct, args.list, &in, &out); } + freeargs(&args); err = interactive_loop(in, out, file1, file2);