Note appropriate krb5 build dependency
[openssh.git] / scp.c
1 /* $OpenBSD: scp.c,v 1.170 2010/12/09 14:13:33 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>
10  *
11  * As far as I am concerned, the code I have written for this software
12  * can be used freely for any purpose.  Any derived versions of this
13  * software must be clearly marked as such, and if the derived work is
14  * incompatible with the protocol description in the RFC file, it must be
15  * called by a name other than "ssh" or "Secure Shell".
16  */
17 /*
18  * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
19  * Copyright (c) 1999 Aaron Campbell.  All rights reserved.
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions
23  * are met:
24  * 1. Redistributions of source code must retain the above copyright
25  *    notice, this list of conditions and the following disclaimer.
26  * 2. Redistributions in binary form must reproduce the above copyright
27  *    notice, this list of conditions and the following disclaimer in the
28  *    documentation and/or other materials provided with the distribution.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
31  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
34  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  */
41
42 /*
43  * Parts from:
44  *
45  * Copyright (c) 1983, 1990, 1992, 1993, 1995
46  *      The Regents of the University of California.  All rights reserved.
47  *
48  * Redistribution and use in source and binary forms, with or without
49  * modification, are permitted provided that the following conditions
50  * are met:
51  * 1. Redistributions of source code must retain the above copyright
52  *    notice, this list of conditions and the following disclaimer.
53  * 2. Redistributions in binary form must reproduce the above copyright
54  *    notice, this list of conditions and the following disclaimer in the
55  *    documentation and/or other materials provided with the distribution.
56  * 3. Neither the name of the University nor the names of its contributors
57  *    may be used to endorse or promote products derived from this software
58  *    without specific prior written permission.
59  *
60  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70  * SUCH DAMAGE.
71  *
72  */
73
74 #include "includes.h"
75
76 #include <sys/types.h>
77 #include <sys/param.h>
78 #ifdef HAVE_SYS_STAT_H
79 # include <sys/stat.h>
80 #endif
81 #ifdef HAVE_POLL_H
82 #include <poll.h>
83 #else
84 # ifdef HAVE_SYS_POLL_H
85 #  include <sys/poll.h>
86 # endif
87 #endif
88 #ifdef HAVE_SYS_TIME_H
89 # include <sys/time.h>
90 #endif
91 #include <sys/wait.h>
92 #include <sys/uio.h>
93
94 #include <ctype.h>
95 #include <dirent.h>
96 #include <errno.h>
97 #include <fcntl.h>
98 #include <pwd.h>
99 #include <signal.h>
100 #include <stdarg.h>
101 #include <stdio.h>
102 #include <stdlib.h>
103 #include <string.h>
104 #include <time.h>
105 #include <unistd.h>
106 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
107 #include <vis.h>
108 #endif
109
110 #include "xmalloc.h"
111 #include "atomicio.h"
112 #include "pathnames.h"
113 #include "log.h"
114 #include "misc.h"
115 #include "progressmeter.h"
116
117 extern char *__progname;
118
119 #define COPY_BUFLEN     16384
120
121 int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
122 int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout);
123
124 /* Struct for addargs */
125 arglist args;
126 arglist remote_remote_args;
127
128 /* Bandwidth limit */
129 long long limit_kbps = 0;
130 struct bwlimit bwlimit;
131
132 /* Name of current file being transferred. */
133 char *curfile;
134
135 /* This is set to non-zero to enable verbose mode. */
136 int verbose_mode = 0;
137
138 /* This is set to zero if the progressmeter is not desired. */
139 int showprogress = 1;
140
141 /*
142  * This is set to non-zero if remote-remote copy should be piped
143  * through this process.
144  */
145 int throughlocal = 0;
146
147 /* This is the program to execute for the secured connection. ("ssh" or -S) */
148 char *ssh_program = _PATH_SSH_PROGRAM;
149
150 /* This is used to store the pid of ssh_program */
151 pid_t do_cmd_pid = -1;
152
153 static void
154 killchild(int signo)
155 {
156         if (do_cmd_pid > 1) {
157                 kill(do_cmd_pid, signo ? signo : SIGTERM);
158                 waitpid(do_cmd_pid, NULL, 0);
159         }
160
161         if (signo)
162                 _exit(1);
163         exit(1);
164 }
165
166 static void
167 suspchild(int signo)
168 {
169         int status;
170
171         if (do_cmd_pid > 1) {
172                 kill(do_cmd_pid, signo);
173                 while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 &&
174                     errno == EINTR)
175                         ;
176                 kill(getpid(), SIGSTOP);
177         }
178 }
179
180 static int
181 do_local_cmd(arglist *a)
182 {
183         u_int i;
184         int status;
185         pid_t pid;
186
187         if (a->num == 0)
188                 fatal("do_local_cmd: no arguments");
189
190         if (verbose_mode) {
191                 fprintf(stderr, "Executing:");
192                 for (i = 0; i < a->num; i++) {
193                         if (i == 0)
194                                 fprintf(stderr, " %s", a->list[i]);
195                         else
196                                 /*
197                                  * TODO: misbehaves if a->list[i] contains a
198                                  * single quote
199                                  */
200                                 fprintf(stderr, " '%s'", a->list[i]);
201                 }
202                 fprintf(stderr, "\n");
203         }
204         if ((pid = fork()) == -1)
205                 fatal("do_local_cmd: fork: %s", strerror(errno));
206
207         if (pid == 0) {
208                 execvp(a->list[0], a->list);
209                 perror(a->list[0]);
210                 exit(1);
211         }
212
213         do_cmd_pid = pid;
214         signal(SIGTERM, killchild);
215         signal(SIGINT, killchild);
216         signal(SIGHUP, killchild);
217
218         while (waitpid(pid, &status, 0) == -1)
219                 if (errno != EINTR)
220                         fatal("do_local_cmd: waitpid: %s", strerror(errno));
221
222         do_cmd_pid = -1;
223
224         if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
225                 return (-1);
226
227         return (0);
228 }
229
230 /*
231  * This function executes the given command as the specified user on the
232  * given host.  This returns < 0 if execution fails, and >= 0 otherwise. This
233  * assigns the input and output file descriptors on success.
234  */
235
236 int
237 do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
238 {
239         int pin[2], pout[2], reserved[2];
240
241         if (verbose_mode)
242                 fprintf(stderr,
243                     "Executing: program %s host %s, user %s, command %s\n",
244                     ssh_program, host,
245                     remuser ? remuser : "(unspecified)", cmd);
246
247         /*
248          * Reserve two descriptors so that the real pipes won't get
249          * descriptors 0 and 1 because that will screw up dup2 below.
250          */
251         if (pipe(reserved) < 0)
252                 fatal("pipe: %s", strerror(errno));
253
254         /* Create a socket pair for communicating with ssh. */
255         if (pipe(pin) < 0)
256                 fatal("pipe: %s", strerror(errno));
257         if (pipe(pout) < 0)
258                 fatal("pipe: %s", strerror(errno));
259
260         /* Free the reserved descriptors. */
261         close(reserved[0]);
262         close(reserved[1]);
263
264         signal(SIGTSTP, suspchild);
265         signal(SIGTTIN, suspchild);
266         signal(SIGTTOU, suspchild);
267
268         /* Fork a child to execute the command on the remote host using ssh. */
269         do_cmd_pid = fork();
270         if (do_cmd_pid == 0) {
271                 /* Child. */
272                 close(pin[1]);
273                 close(pout[0]);
274                 dup2(pin[0], 0);
275                 dup2(pout[1], 1);
276                 close(pin[0]);
277                 close(pout[1]);
278
279                 replacearg(&args, 0, "%s", ssh_program);
280                 if (remuser != NULL) {
281                         addargs(&args, "-l");
282                         addargs(&args, "%s", remuser);
283                 }
284                 addargs(&args, "--");
285                 addargs(&args, "%s", host);
286                 addargs(&args, "%s", cmd);
287
288                 execvp(ssh_program, args.list);
289                 perror(ssh_program);
290                 exit(1);
291         } else if (do_cmd_pid == -1) {
292                 fatal("fork: %s", strerror(errno));
293         }
294         /* Parent.  Close the other side, and return the local side. */
295         close(pin[0]);
296         *fdout = pin[1];
297         close(pout[1]);
298         *fdin = pout[0];
299         signal(SIGTERM, killchild);
300         signal(SIGINT, killchild);
301         signal(SIGHUP, killchild);
302         return 0;
303 }
304
305 /*
306  * This functions executes a command simlar to do_cmd(), but expects the
307  * input and output descriptors to be setup by a previous call to do_cmd().
308  * This way the input and output of two commands can be connected.
309  */
310 int
311 do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
312 {
313         pid_t pid;
314         int status;
315
316         if (verbose_mode)
317                 fprintf(stderr,
318                     "Executing: 2nd program %s host %s, user %s, command %s\n",
319                     ssh_program, host,
320                     remuser ? remuser : "(unspecified)", cmd);
321
322         /* Fork a child to execute the command on the remote host using ssh. */
323         pid = fork();
324         if (pid == 0) {
325                 dup2(fdin, 0);
326                 dup2(fdout, 1);
327
328                 replacearg(&args, 0, "%s", ssh_program);
329                 if (remuser != NULL) {
330                         addargs(&args, "-l");
331                         addargs(&args, "%s", remuser);
332                 }
333                 addargs(&args, "--");
334                 addargs(&args, "%s", host);
335                 addargs(&args, "%s", cmd);
336
337                 execvp(ssh_program, args.list);
338                 perror(ssh_program);
339                 exit(1);
340         } else if (pid == -1) {
341                 fatal("fork: %s", strerror(errno));
342         }
343         while (waitpid(pid, &status, 0) == -1)
344                 if (errno != EINTR)
345                         fatal("do_cmd2: waitpid: %s", strerror(errno));
346         return 0;
347 }
348
349 typedef struct {
350         size_t cnt;
351         char *buf;
352 } BUF;
353
354 BUF *allocbuf(BUF *, int, int);
355 void lostconn(int);
356 int okname(char *);
357 void run_err(const char *,...);
358 void verifydir(char *);
359
360 struct passwd *pwd;
361 uid_t userid;
362 int errs, remin, remout;
363 int pflag, iamremote, iamrecursive, targetshouldbedirectory;
364
365 #define CMDNEEDS        64
366 char cmd[CMDNEEDS];             /* must hold "rcp -r -p -d\0" */
367
368 int response(void);
369 void rsource(char *, struct stat *);
370 void sink(int, char *[]);
371 void source(int, char *[]);
372 void tolocal(int, char *[]);
373 void toremote(char *, int, char *[]);
374 void usage(void);
375
376 int
377 main(int argc, char **argv)
378 {
379         int ch, fflag, tflag, status, n;
380         char *targ, **newargv;
381         const char *errstr;
382         extern char *optarg;
383         extern int optind;
384
385         /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
386         sanitise_stdfd();
387
388         /* Copy argv, because we modify it */
389         newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv));
390         for (n = 0; n < argc; n++)
391                 newargv[n] = xstrdup(argv[n]);
392         argv = newargv;
393
394         __progname = ssh_get_progname(argv[0]);
395
396         memset(&args, '\0', sizeof(args));
397         memset(&remote_remote_args, '\0', sizeof(remote_remote_args));
398         args.list = remote_remote_args.list = NULL;
399         addargs(&args, "%s", ssh_program);
400         addargs(&args, "-x");
401         addargs(&args, "-oForwardAgent=no");
402         addargs(&args, "-oPermitLocalCommand=no");
403         addargs(&args, "-oClearAllForwardings=yes");
404
405         fflag = tflag = 0;
406         while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
407                 switch (ch) {
408                 /* User-visible flags. */
409                 case '1':
410                 case '2':
411                 case '4':
412                 case '6':
413                 case 'C':
414                         addargs(&args, "-%c", ch);
415                         addargs(&remote_remote_args, "-%c", ch);
416                         break;
417                 case '3':
418                         throughlocal = 1;
419                         break;
420                 case 'o':
421                 case 'c':
422                 case 'i':
423                 case 'F':
424                         addargs(&remote_remote_args, "-%c", ch);
425                         addargs(&remote_remote_args, "%s", optarg);
426                         addargs(&args, "-%c", ch);
427                         addargs(&args, "%s", optarg);
428                         break;
429                 case 'P':
430                         addargs(&remote_remote_args, "-p");
431                         addargs(&remote_remote_args, "%s", optarg);
432                         addargs(&args, "-p");
433                         addargs(&args, "%s", optarg);
434                         break;
435                 case 'B':
436                         addargs(&remote_remote_args, "-oBatchmode=yes");
437                         addargs(&args, "-oBatchmode=yes");
438                         break;
439                 case 'l':
440                         limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
441                             &errstr);
442                         if (errstr != NULL)
443                                 usage();
444                         limit_kbps *= 1024; /* kbps */
445                         bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN);
446                         break;
447                 case 'p':
448                         pflag = 1;
449                         break;
450                 case 'r':
451                         iamrecursive = 1;
452                         break;
453                 case 'S':
454                         ssh_program = xstrdup(optarg);
455                         break;
456                 case 'v':
457                         addargs(&args, "-v");
458                         addargs(&remote_remote_args, "-v");
459                         verbose_mode = 1;
460                         break;
461                 case 'q':
462                         addargs(&args, "-q");
463                         addargs(&remote_remote_args, "-q");
464                         showprogress = 0;
465                         break;
466
467                 /* Server options. */
468                 case 'd':
469                         targetshouldbedirectory = 1;
470                         break;
471                 case 'f':       /* "from" */
472                         iamremote = 1;
473                         fflag = 1;
474                         break;
475                 case 't':       /* "to" */
476                         iamremote = 1;
477                         tflag = 1;
478 #ifdef HAVE_CYGWIN
479                         setmode(0, O_BINARY);
480 #endif
481                         break;
482                 default:
483                         usage();
484                 }
485         argc -= optind;
486         argv += optind;
487
488         if ((pwd = getpwuid(userid = getuid())) == NULL)
489                 fatal("unknown user %u", (u_int) userid);
490
491         if (!isatty(STDOUT_FILENO))
492                 showprogress = 0;
493
494         remin = STDIN_FILENO;
495         remout = STDOUT_FILENO;
496
497         if (fflag) {
498                 /* Follow "protocol", send data. */
499                 (void) response();
500                 source(argc, argv);
501                 exit(errs != 0);
502         }
503         if (tflag) {
504                 /* Receive data. */
505                 sink(argc, argv);
506                 exit(errs != 0);
507         }
508         if (argc < 2)
509                 usage();
510         if (argc > 2)
511                 targetshouldbedirectory = 1;
512
513         remin = remout = -1;
514         do_cmd_pid = -1;
515         /* Command to be executed on remote system using "ssh". */
516         (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
517             verbose_mode ? " -v" : "",
518             iamrecursive ? " -r" : "", pflag ? " -p" : "",
519             targetshouldbedirectory ? " -d" : "");
520
521         (void) signal(SIGPIPE, lostconn);
522
523         if ((targ = colon(argv[argc - 1])))     /* Dest is remote host. */
524                 toremote(targ, argc, argv);
525         else {
526                 if (targetshouldbedirectory)
527                         verifydir(argv[argc - 1]);
528                 tolocal(argc, argv);    /* Dest is local host. */
529         }
530         /*
531          * Finally check the exit status of the ssh process, if one was forked
532          * and no error has occurred yet
533          */
534         if (do_cmd_pid != -1 && errs == 0) {
535                 if (remin != -1)
536                     (void) close(remin);
537                 if (remout != -1)
538                     (void) close(remout);
539                 if (waitpid(do_cmd_pid, &status, 0) == -1)
540                         errs = 1;
541                 else {
542                         if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
543                                 errs = 1;
544                 }
545         }
546         exit(errs != 0);
547 }
548
549 /* Callback from atomicio6 to update progress meter and limit bandwidth */
550 static int
551 scpio(void *_cnt, size_t s)
552 {
553         off_t *cnt = (off_t *)_cnt;
554
555         *cnt += s;
556         if (limit_kbps > 0)
557                 bandwidth_limit(&bwlimit, s);
558         return 0;
559 }
560
561 void
562 toremote(char *targ, int argc, char **argv)
563 {
564         char *bp, *host, *src, *suser, *thost, *tuser, *arg;
565         arglist alist;
566         int i;
567         u_int j;
568
569         memset(&alist, '\0', sizeof(alist));
570         alist.list = NULL;
571
572         *targ++ = 0;
573         if (*targ == 0)
574                 targ = ".";
575
576         arg = xstrdup(argv[argc - 1]);
577         if ((thost = strrchr(arg, '@'))) {
578                 /* user@host */
579                 *thost++ = 0;
580                 tuser = arg;
581                 if (*tuser == '\0')
582                         tuser = NULL;
583         } else {
584                 thost = arg;
585                 tuser = NULL;
586         }
587
588         if (tuser != NULL && !okname(tuser)) {
589                 xfree(arg);
590                 return;
591         }
592
593         for (i = 0; i < argc - 1; i++) {
594                 src = colon(argv[i]);
595                 if (src && throughlocal) {      /* extended remote to remote */
596                         *src++ = 0;
597                         if (*src == 0)
598                                 src = ".";
599                         host = strrchr(argv[i], '@');
600                         if (host) {
601                                 *host++ = 0;
602                                 host = cleanhostname(host);
603                                 suser = argv[i];
604                                 if (*suser == '\0')
605                                         suser = pwd->pw_name;
606                                 else if (!okname(suser))
607                                         continue;
608                         } else {
609                                 host = cleanhostname(argv[i]);
610                                 suser = NULL;
611                         }
612                         xasprintf(&bp, "%s -f -- %s", cmd, src);
613                         if (do_cmd(host, suser, bp, &remin, &remout) < 0)
614                                 exit(1);
615                         (void) xfree(bp);
616                         host = cleanhostname(thost);
617                         xasprintf(&bp, "%s -t -- %s", cmd, targ);
618                         if (do_cmd2(host, tuser, bp, remin, remout) < 0)
619                                 exit(1);
620                         (void) xfree(bp);
621                         (void) close(remin);
622                         (void) close(remout);
623                         remin = remout = -1;
624                 } else if (src) {       /* standard remote to remote */
625                         freeargs(&alist);
626                         addargs(&alist, "%s", ssh_program);
627                         addargs(&alist, "-x");
628                         addargs(&alist, "-oClearAllForwardings=yes");
629                         addargs(&alist, "-n");
630                         for (j = 0; j < remote_remote_args.num; j++) {
631                                 addargs(&alist, "%s",
632                                     remote_remote_args.list[j]);
633                         }
634                         *src++ = 0;
635                         if (*src == 0)
636                                 src = ".";
637                         host = strrchr(argv[i], '@');
638
639                         if (host) {
640                                 *host++ = 0;
641                                 host = cleanhostname(host);
642                                 suser = argv[i];
643                                 if (*suser == '\0')
644                                         suser = pwd->pw_name;
645                                 else if (!okname(suser))
646                                         continue;
647                                 addargs(&alist, "-l");
648                                 addargs(&alist, "%s", suser);
649                         } else {
650                                 host = cleanhostname(argv[i]);
651                         }
652                         addargs(&alist, "--");
653                         addargs(&alist, "%s", host);
654                         addargs(&alist, "%s", cmd);
655                         addargs(&alist, "%s", src);
656                         addargs(&alist, "%s%s%s:%s",
657                             tuser ? tuser : "", tuser ? "@" : "",
658                             thost, targ);
659                         if (do_local_cmd(&alist) != 0)
660                                 errs = 1;
661                 } else {        /* local to remote */
662                         if (remin == -1) {
663                                 xasprintf(&bp, "%s -t -- %s", cmd, targ);
664                                 host = cleanhostname(thost);
665                                 if (do_cmd(host, tuser, bp, &remin,
666                                     &remout) < 0)
667                                         exit(1);
668                                 if (response() < 0)
669                                         exit(1);
670                                 (void) xfree(bp);
671                         }
672                         source(1, argv + i);
673                 }
674         }
675         xfree(arg);
676 }
677
678 void
679 tolocal(int argc, char **argv)
680 {
681         char *bp, *host, *src, *suser;
682         arglist alist;
683         int i;
684
685         memset(&alist, '\0', sizeof(alist));
686         alist.list = NULL;
687
688         for (i = 0; i < argc - 1; i++) {
689                 if (!(src = colon(argv[i]))) {  /* Local to local. */
690                         freeargs(&alist);
691                         addargs(&alist, "%s", _PATH_CP);
692                         if (iamrecursive)
693                                 addargs(&alist, "-r");
694                         if (pflag)
695                                 addargs(&alist, "-p");
696                         addargs(&alist, "--");
697                         addargs(&alist, "%s", argv[i]);
698                         addargs(&alist, "%s", argv[argc-1]);
699                         if (do_local_cmd(&alist))
700                                 ++errs;
701                         continue;
702                 }
703                 *src++ = 0;
704                 if (*src == 0)
705                         src = ".";
706                 if ((host = strrchr(argv[i], '@')) == NULL) {
707                         host = argv[i];
708                         suser = NULL;
709                 } else {
710                         *host++ = 0;
711                         suser = argv[i];
712                         if (*suser == '\0')
713                                 suser = pwd->pw_name;
714                 }
715                 host = cleanhostname(host);
716                 xasprintf(&bp, "%s -f -- %s", cmd, src);
717                 if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
718                         (void) xfree(bp);
719                         ++errs;
720                         continue;
721                 }
722                 xfree(bp);
723                 sink(1, argv + argc - 1);
724                 (void) close(remin);
725                 remin = remout = -1;
726         }
727 }
728
729 void
730 source(int argc, char **argv)
731 {
732         struct stat stb;
733         static BUF buffer;
734         BUF *bp;
735         off_t i, statbytes;
736         size_t amt;
737         int fd = -1, haderr, indx;
738         char *last, *name, buf[2048], encname[MAXPATHLEN];
739         int len;
740
741         for (indx = 0; indx < argc; ++indx) {
742                 name = argv[indx];
743                 statbytes = 0;
744                 len = strlen(name);
745                 while (len > 1 && name[len-1] == '/')
746                         name[--len] = '\0';
747                 if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
748                         goto syserr;
749                 if (strchr(name, '\n') != NULL) {
750                         strnvis(encname, name, sizeof(encname), VIS_NL);
751                         name = encname;
752                 }
753                 if (fstat(fd, &stb) < 0) {
754 syserr:                 run_err("%s: %s", name, strerror(errno));
755                         goto next;
756                 }
757                 if (stb.st_size < 0) {
758                         run_err("%s: %s", name, "Negative file size");
759                         goto next;
760                 }
761                 unset_nonblock(fd);
762                 switch (stb.st_mode & S_IFMT) {
763                 case S_IFREG:
764                         break;
765                 case S_IFDIR:
766                         if (iamrecursive) {
767                                 rsource(name, &stb);
768                                 goto next;
769                         }
770                         /* FALLTHROUGH */
771                 default:
772                         run_err("%s: not a regular file", name);
773                         goto next;
774                 }
775                 if ((last = strrchr(name, '/')) == NULL)
776                         last = name;
777                 else
778                         ++last;
779                 curfile = last;
780                 if (pflag) {
781                         /*
782                          * Make it compatible with possible future
783                          * versions expecting microseconds.
784                          */
785                         (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",
786                             (u_long) (stb.st_mtime < 0 ? 0 : stb.st_mtime),
787                             (u_long) (stb.st_atime < 0 ? 0 : stb.st_atime));
788                         if (verbose_mode) {
789                                 fprintf(stderr, "File mtime %ld atime %ld\n",
790                                     (long)stb.st_mtime, (long)stb.st_atime);
791                                 fprintf(stderr, "Sending file timestamps: %s",
792                                     buf);
793                         }
794                         (void) atomicio(vwrite, remout, buf, strlen(buf));
795                         if (response() < 0)
796                                 goto next;
797                 }
798 #define FILEMODEMASK    (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
799                 snprintf(buf, sizeof buf, "C%04o %lld %s\n",
800                     (u_int) (stb.st_mode & FILEMODEMASK),
801                     (long long)stb.st_size, last);
802                 if (verbose_mode) {
803                         fprintf(stderr, "Sending file modes: %s", buf);
804                 }
805                 (void) atomicio(vwrite, remout, buf, strlen(buf));
806                 if (response() < 0)
807                         goto next;
808                 if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
809 next:                   if (fd != -1) {
810                                 (void) close(fd);
811                                 fd = -1;
812                         }
813                         continue;
814                 }
815                 if (showprogress)
816                         start_progress_meter(curfile, stb.st_size, &statbytes);
817                 set_nonblock(remout);
818                 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
819                         amt = bp->cnt;
820                         if (i + (off_t)amt > stb.st_size)
821                                 amt = stb.st_size - i;
822                         if (!haderr) {
823                                 if (atomicio(read, fd, bp->buf, amt) != amt)
824                                         haderr = errno;
825                         }
826                         /* Keep writing after error to retain sync */
827                         if (haderr) {
828                                 (void)atomicio(vwrite, remout, bp->buf, amt);
829                                 continue;
830                         }
831                         if (atomicio6(vwrite, remout, bp->buf, amt, scpio,
832                             &statbytes) != amt)
833                                 haderr = errno;
834                 }
835                 unset_nonblock(remout);
836                 if (showprogress)
837                         stop_progress_meter();
838
839                 if (fd != -1) {
840                         if (close(fd) < 0 && !haderr)
841                                 haderr = errno;
842                         fd = -1;
843                 }
844                 if (!haderr)
845                         (void) atomicio(vwrite, remout, "", 1);
846                 else
847                         run_err("%s: %s", name, strerror(haderr));
848                 (void) response();
849         }
850 }
851
852 void
853 rsource(char *name, struct stat *statp)
854 {
855         DIR *dirp;
856         struct dirent *dp;
857         char *last, *vect[1], path[1100];
858
859         if (!(dirp = opendir(name))) {
860                 run_err("%s: %s", name, strerror(errno));
861                 return;
862         }
863         last = strrchr(name, '/');
864         if (last == 0)
865                 last = name;
866         else
867                 last++;
868         if (pflag) {
869                 (void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n",
870                     (u_long) statp->st_mtime,
871                     (u_long) statp->st_atime);
872                 (void) atomicio(vwrite, remout, path, strlen(path));
873                 if (response() < 0) {
874                         closedir(dirp);
875                         return;
876                 }
877         }
878         (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
879             (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
880         if (verbose_mode)
881                 fprintf(stderr, "Entering directory: %s", path);
882         (void) atomicio(vwrite, remout, path, strlen(path));
883         if (response() < 0) {
884                 closedir(dirp);
885                 return;
886         }
887         while ((dp = readdir(dirp)) != NULL) {
888                 if (dp->d_ino == 0)
889                         continue;
890                 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
891                         continue;
892                 if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
893                         run_err("%s/%s: name too long", name, dp->d_name);
894                         continue;
895                 }
896                 (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
897                 vect[0] = path;
898                 source(1, vect);
899         }
900         (void) closedir(dirp);
901         (void) atomicio(vwrite, remout, "E\n", 2);
902         (void) response();
903 }
904
905 void
906 sink(int argc, char **argv)
907 {
908         static BUF buffer;
909         struct stat stb;
910         enum {
911                 YES, NO, DISPLAYED
912         } wrerr;
913         BUF *bp;
914         off_t i;
915         size_t j, count;
916         int amt, exists, first, ofd;
917         mode_t mode, omode, mask;
918         off_t size, statbytes;
919         int setimes, targisdir, wrerrno = 0;
920         char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
921         struct timeval tv[2];
922
923 #define atime   tv[0]
924 #define mtime   tv[1]
925 #define SCREWUP(str)    { why = str; goto screwup; }
926
927         setimes = targisdir = 0;
928         mask = umask(0);
929         if (!pflag)
930                 (void) umask(mask);
931         if (argc != 1) {
932                 run_err("ambiguous target");
933                 exit(1);
934         }
935         targ = *argv;
936         if (targetshouldbedirectory)
937                 verifydir(targ);
938
939         (void) atomicio(vwrite, remout, "", 1);
940         if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
941                 targisdir = 1;
942         for (first = 1;; first = 0) {
943                 cp = buf;
944                 if (atomicio(read, remin, cp, 1) != 1)
945                         return;
946                 if (*cp++ == '\n')
947                         SCREWUP("unexpected <newline>");
948                 do {
949                         if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
950                                 SCREWUP("lost connection");
951                         *cp++ = ch;
952                 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
953                 *cp = 0;
954                 if (verbose_mode)
955                         fprintf(stderr, "Sink: %s", buf);
956
957                 if (buf[0] == '\01' || buf[0] == '\02') {
958                         if (iamremote == 0)
959                                 (void) atomicio(vwrite, STDERR_FILENO,
960                                     buf + 1, strlen(buf + 1));
961                         if (buf[0] == '\02')
962                                 exit(1);
963                         ++errs;
964                         continue;
965                 }
966                 if (buf[0] == 'E') {
967                         (void) atomicio(vwrite, remout, "", 1);
968                         return;
969                 }
970                 if (ch == '\n')
971                         *--cp = 0;
972
973                 cp = buf;
974                 if (*cp == 'T') {
975                         setimes++;
976                         cp++;
977                         mtime.tv_sec = strtol(cp, &cp, 10);
978                         if (!cp || *cp++ != ' ')
979                                 SCREWUP("mtime.sec not delimited");
980                         mtime.tv_usec = strtol(cp, &cp, 10);
981                         if (!cp || *cp++ != ' ')
982                                 SCREWUP("mtime.usec not delimited");
983                         atime.tv_sec = strtol(cp, &cp, 10);
984                         if (!cp || *cp++ != ' ')
985                                 SCREWUP("atime.sec not delimited");
986                         atime.tv_usec = strtol(cp, &cp, 10);
987                         if (!cp || *cp++ != '\0')
988                                 SCREWUP("atime.usec not delimited");
989                         (void) atomicio(vwrite, remout, "", 1);
990                         continue;
991                 }
992                 if (*cp != 'C' && *cp != 'D') {
993                         /*
994                          * Check for the case "rcp remote:foo\* local:bar".
995                          * In this case, the line "No match." can be returned
996                          * by the shell before the rcp command on the remote is
997                          * executed so the ^Aerror_message convention isn't
998                          * followed.
999                          */
1000                         if (first) {
1001                                 run_err("%s", cp);
1002                                 exit(1);
1003                         }
1004                         SCREWUP("expected control record");
1005                 }
1006                 mode = 0;
1007                 for (++cp; cp < buf + 5; cp++) {
1008                         if (*cp < '0' || *cp > '7')
1009                                 SCREWUP("bad mode");
1010                         mode = (mode << 3) | (*cp - '0');
1011                 }
1012                 if (*cp++ != ' ')
1013                         SCREWUP("mode not delimited");
1014
1015                 for (size = 0; isdigit(*cp);)
1016                         size = size * 10 + (*cp++ - '0');
1017                 if (*cp++ != ' ')
1018                         SCREWUP("size not delimited");
1019                 if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
1020                         run_err("error: unexpected filename: %s", cp);
1021                         exit(1);
1022                 }
1023                 if (targisdir) {
1024                         static char *namebuf;
1025                         static size_t cursize;
1026                         size_t need;
1027
1028                         need = strlen(targ) + strlen(cp) + 250;
1029                         if (need > cursize) {
1030                                 if (namebuf)
1031                                         xfree(namebuf);
1032                                 namebuf = xmalloc(need);
1033                                 cursize = need;
1034                         }
1035                         (void) snprintf(namebuf, need, "%s%s%s", targ,
1036                             strcmp(targ, "/") ? "/" : "", cp);
1037                         np = namebuf;
1038                 } else
1039                         np = targ;
1040                 curfile = cp;
1041                 exists = stat(np, &stb) == 0;
1042                 if (buf[0] == 'D') {
1043                         int mod_flag = pflag;
1044                         if (!iamrecursive)
1045                                 SCREWUP("received directory without -r");
1046                         if (exists) {
1047                                 if (!S_ISDIR(stb.st_mode)) {
1048                                         errno = ENOTDIR;
1049                                         goto bad;
1050                                 }
1051                                 if (pflag)
1052                                         (void) chmod(np, mode);
1053                         } else {
1054                                 /* Handle copying from a read-only
1055                                    directory */
1056                                 mod_flag = 1;
1057                                 if (mkdir(np, mode | S_IRWXU) < 0)
1058                                         goto bad;
1059                         }
1060                         vect[0] = xstrdup(np);
1061                         sink(1, vect);
1062                         if (setimes) {
1063                                 setimes = 0;
1064                                 if (utimes(vect[0], tv) < 0)
1065                                         run_err("%s: set times: %s",
1066                                             vect[0], strerror(errno));
1067                         }
1068                         if (mod_flag)
1069                                 (void) chmod(vect[0], mode);
1070                         if (vect[0])
1071                                 xfree(vect[0]);
1072                         continue;
1073                 }
1074                 omode = mode;
1075                 mode |= S_IWRITE;
1076                 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
1077 bad:                    run_err("%s: %s", np, strerror(errno));
1078                         continue;
1079                 }
1080                 (void) atomicio(vwrite, remout, "", 1);
1081                 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
1082                         (void) close(ofd);
1083                         continue;
1084                 }
1085                 cp = bp->buf;
1086                 wrerr = NO;
1087
1088                 statbytes = 0;
1089                 if (showprogress)
1090                         start_progress_meter(curfile, size, &statbytes);
1091                 set_nonblock(remin);
1092                 for (count = i = 0; i < size; i += bp->cnt) {
1093                         amt = bp->cnt;
1094                         if (i + amt > size)
1095                                 amt = size - i;
1096                         count += amt;
1097                         do {
1098                                 j = atomicio6(read, remin, cp, amt,
1099                                     scpio, &statbytes);
1100                                 if (j == 0) {
1101                                         run_err("%s", j != EPIPE ?
1102                                             strerror(errno) :
1103                                             "dropped connection");
1104                                         exit(1);
1105                                 }
1106                                 amt -= j;
1107                                 cp += j;
1108                         } while (amt > 0);
1109
1110                         if (count == bp->cnt) {
1111                                 /* Keep reading so we stay sync'd up. */
1112                                 if (wrerr == NO) {
1113                                         if (atomicio(vwrite, ofd, bp->buf,
1114                                             count) != count) {
1115                                                 wrerr = YES;
1116                                                 wrerrno = errno;
1117                                         }
1118                                 }
1119                                 count = 0;
1120                                 cp = bp->buf;
1121                         }
1122                 }
1123                 unset_nonblock(remin);
1124                 if (showprogress)
1125                         stop_progress_meter();
1126                 if (count != 0 && wrerr == NO &&
1127                     atomicio(vwrite, ofd, bp->buf, count) != count) {
1128                         wrerr = YES;
1129                         wrerrno = errno;
1130                 }
1131                 if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) &&
1132                     ftruncate(ofd, size) != 0) {
1133                         run_err("%s: truncate: %s", np, strerror(errno));
1134                         wrerr = DISPLAYED;
1135                 }
1136                 if (pflag) {
1137                         if (exists || omode != mode)
1138 #ifdef HAVE_FCHMOD
1139                                 if (fchmod(ofd, omode)) {
1140 #else /* HAVE_FCHMOD */
1141                                 if (chmod(np, omode)) {
1142 #endif /* HAVE_FCHMOD */
1143                                         run_err("%s: set mode: %s",
1144                                             np, strerror(errno));
1145                                         wrerr = DISPLAYED;
1146                                 }
1147                 } else {
1148                         if (!exists && omode != mode)
1149 #ifdef HAVE_FCHMOD
1150                                 if (fchmod(ofd, omode & ~mask)) {
1151 #else /* HAVE_FCHMOD */
1152                                 if (chmod(np, omode & ~mask)) {
1153 #endif /* HAVE_FCHMOD */
1154                                         run_err("%s: set mode: %s",
1155                                             np, strerror(errno));
1156                                         wrerr = DISPLAYED;
1157                                 }
1158                 }
1159                 if (close(ofd) == -1) {
1160                         wrerr = YES;
1161                         wrerrno = errno;
1162                 }
1163                 (void) response();
1164                 if (setimes && wrerr == NO) {
1165                         setimes = 0;
1166                         if (utimes(np, tv) < 0) {
1167                                 run_err("%s: set times: %s",
1168                                     np, strerror(errno));
1169                                 wrerr = DISPLAYED;
1170                         }
1171                 }
1172                 switch (wrerr) {
1173                 case YES:
1174                         run_err("%s: %s", np, strerror(wrerrno));
1175                         break;
1176                 case NO:
1177                         (void) atomicio(vwrite, remout, "", 1);
1178                         break;
1179                 case DISPLAYED:
1180                         break;
1181                 }
1182         }
1183 screwup:
1184         run_err("protocol error: %s", why);
1185         exit(1);
1186 }
1187
1188 int
1189 response(void)
1190 {
1191         char ch, *cp, resp, rbuf[2048];
1192
1193         if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
1194                 lostconn(0);
1195
1196         cp = rbuf;
1197         switch (resp) {
1198         case 0:         /* ok */
1199                 return (0);
1200         default:
1201                 *cp++ = resp;
1202                 /* FALLTHROUGH */
1203         case 1:         /* error, followed by error msg */
1204         case 2:         /* fatal error, "" */
1205                 do {
1206                         if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
1207                                 lostconn(0);
1208                         *cp++ = ch;
1209                 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
1210
1211                 if (!iamremote)
1212                         (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf);
1213                 ++errs;
1214                 if (resp == 1)
1215                         return (-1);
1216                 exit(1);
1217         }
1218         /* NOTREACHED */
1219 }
1220
1221 void
1222 usage(void)
1223 {
1224         (void) fprintf(stderr,
1225             "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
1226             "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
1227             "           [[user@]host1:]file1 ... [[user@]host2:]file2\n");
1228         exit(1);
1229 }
1230
1231 void
1232 run_err(const char *fmt,...)
1233 {
1234         static FILE *fp;
1235         va_list ap;
1236
1237         ++errs;
1238         if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) {
1239                 (void) fprintf(fp, "%c", 0x01);
1240                 (void) fprintf(fp, "scp: ");
1241                 va_start(ap, fmt);
1242                 (void) vfprintf(fp, fmt, ap);
1243                 va_end(ap);
1244                 (void) fprintf(fp, "\n");
1245                 (void) fflush(fp);
1246         }
1247
1248         if (!iamremote) {
1249                 va_start(ap, fmt);
1250                 vfprintf(stderr, fmt, ap);
1251                 va_end(ap);
1252                 fprintf(stderr, "\n");
1253         }
1254 }
1255
1256 void
1257 verifydir(char *cp)
1258 {
1259         struct stat stb;
1260
1261         if (!stat(cp, &stb)) {
1262                 if (S_ISDIR(stb.st_mode))
1263                         return;
1264                 errno = ENOTDIR;
1265         }
1266         run_err("%s: %s", cp, strerror(errno));
1267         killchild(0);
1268 }
1269
1270 int
1271 okname(char *cp0)
1272 {
1273         int c;
1274         char *cp;
1275
1276         cp = cp0;
1277         do {
1278                 c = (int)*cp;
1279                 if (c & 0200)
1280                         goto bad;
1281                 if (!isalpha(c) && !isdigit(c)) {
1282                         switch (c) {
1283                         case '\'':
1284                         case '"':
1285                         case '`':
1286                         case ' ':
1287                         case '#':
1288                                 goto bad;
1289                         default:
1290                                 break;
1291                         }
1292                 }
1293         } while (*++cp);
1294         return (1);
1295
1296 bad:    fprintf(stderr, "%s: invalid user name\n", cp0);
1297         return (0);
1298 }
1299
1300 BUF *
1301 allocbuf(BUF *bp, int fd, int blksize)
1302 {
1303         size_t size;
1304 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1305         struct stat stb;
1306
1307         if (fstat(fd, &stb) < 0) {
1308                 run_err("fstat: %s", strerror(errno));
1309                 return (0);
1310         }
1311         size = roundup(stb.st_blksize, blksize);
1312         if (size == 0)
1313                 size = blksize;
1314 #else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
1315         size = blksize;
1316 #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
1317         if (bp->cnt >= size)
1318                 return (bp);
1319         if (bp->buf == NULL)
1320                 bp->buf = xmalloc(size);
1321         else
1322                 bp->buf = xrealloc(bp->buf, 1, size);
1323         memset(bp->buf, 0, size);
1324         bp->cnt = size;
1325         return (bp);
1326 }
1327
1328 void
1329 lostconn(int signo)
1330 {
1331         if (!iamremote)
1332                 write(STDERR_FILENO, "lost connection\n", 16);
1333         if (signo)
1334                 _exit(1);
1335         else
1336                 exit(1);
1337 }