1 /* $OpenBSD: scp.c,v 1.273 2026/04/02 07:42:16 djm 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/stat.h>
78 #include <sys/time.h>
79 #include <sys/wait.h>
80 #include <sys/uio.h>
81
82 #include <ctype.h>
83 #include <dirent.h>
84 #include <errno.h>
85 #include <fcntl.h>
86 #ifdef HAVE_FNMATCH_H
87 #include <fnmatch.h>
88 #endif
89 #include <glob.h>
90 #include <libgen.h>
91 #include <locale.h>
92 #include <poll.h>
93 #include <pwd.h>
94 #include <signal.h>
95 #include <stdarg.h>
96 #include <stdint.h>
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include <time.h>
101 #include <unistd.h>
102 #include <limits.h>
103 #include <util.h>
104 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
105 #include <vis.h>
106 #endif
107
108 #include "xmalloc.h"
109 #include "ssh.h"
110 #include "atomicio.h"
111 #include "pathnames.h"
112 #include "log.h"
113 #include "misc.h"
114 #include "progressmeter.h"
115 #include "utf8.h"
116 #include "sftp.h"
117
118 #include "sftp-common.h"
119 #include "sftp-client.h"
120
121 extern char *__progname;
122
123 #define COPY_BUFLEN 16384
124
125 int do_cmd(char *, char *, char *, int, int, char *, int *, int *, pid_t *);
126 int do_cmd2(char *, char *, int, char *, int, int);
127
128 /* Struct for addargs */
129 arglist args;
130 arglist remote_remote_args;
131
132 /* Bandwidth limit */
133 long long limit_kbps = 0;
134 struct bwlimit bwlimit;
135
136 /* Name of current file being transferred. */
137 char *curfile;
138
139 /* This is set to non-zero to enable verbose mode. */
140 int verbose_mode = 0;
141 LogLevel log_level = SYSLOG_LEVEL_INFO;
142
143 /* This is set to zero if the progressmeter is not desired. */
144 int showprogress = 1;
145
146 /*
147 * This is set to non-zero if remote-remote copy should be piped
148 * through this process.
149 */
150 int throughlocal = 1;
151
152 /* Non-standard port to use for the ssh connection or -1. */
153 int sshport = -1;
154
155 /* This is the program to execute for the secure connection. ("ssh" or -S) */
156 char *ssh_program = _PATH_SSH_PROGRAM;
157
158 /* This is used to store the pid of ssh_program */
159 pid_t do_cmd_pid = -1;
160 pid_t do_cmd_pid2 = -1;
161
162 /* SFTP copy parameters */
163 size_t sftp_copy_buflen;
164 size_t sftp_nrequests;
165
166 /* Needed for sftp */
167 volatile sig_atomic_t interrupted = 0;
168
169 int sftp_glob(struct sftp_conn *, const char *, int,
170 int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
171
172 static void
killchild(int signo)173 killchild(int signo)
174 {
175 if (do_cmd_pid > 1) {
176 kill(do_cmd_pid, signo ? signo : SIGTERM);
177 (void)waitpid(do_cmd_pid, NULL, 0);
178 }
179 if (do_cmd_pid2 > 1) {
180 kill(do_cmd_pid2, signo ? signo : SIGTERM);
181 (void)waitpid(do_cmd_pid2, NULL, 0);
182 }
183
184 if (signo)
185 _exit(1);
186 exit(1);
187 }
188
189 static void
suspone(int pid,int signo)190 suspone(int pid, int signo)
191 {
192 int status;
193
194 if (pid > 1) {
195 kill(pid, signo);
196 while (waitpid(pid, &status, WUNTRACED) == -1 &&
197 errno == EINTR)
198 ;
199 }
200 }
201
202 static void
suspchild(int signo)203 suspchild(int signo)
204 {
205 int save_errno = errno;
206 suspone(do_cmd_pid, signo);
207 suspone(do_cmd_pid2, signo);
208 kill(getpid(), SIGSTOP);
209 errno = save_errno;
210 }
211
212 static int
do_local_cmd(arglist * a)213 do_local_cmd(arglist *a)
214 {
215 char *cp;
216 int status;
217 pid_t pid;
218
219 if (a->num == 0)
220 fatal("do_local_cmd: no arguments");
221
222 if (verbose_mode) {
223 cp = argv_assemble(a->num, a->list);
224 fmprintf(stderr, "Executing: %s\n", cp);
225 free(cp);
226 }
227 if ((pid = fork()) == -1)
228 fatal("do_local_cmd: fork: %s", strerror(errno));
229
230 if (pid == 0) {
231 execvp(a->list[0], a->list);
232 perror(a->list[0]);
233 exit(1);
234 }
235
236 do_cmd_pid = pid;
237 ssh_signal(SIGTERM, killchild);
238 ssh_signal(SIGINT, killchild);
239 ssh_signal(SIGHUP, killchild);
240
241 while (waitpid(pid, &status, 0) == -1)
242 if (errno != EINTR)
243 fatal("do_local_cmd: waitpid: %s", strerror(errno));
244
245 do_cmd_pid = -1;
246
247 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
248 return (-1);
249
250 return (0);
251 }
252
253 /*
254 * This function executes the given command as the specified user on the
255 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
256 * assigns the input and output file descriptors on success.
257 */
258
259 int
do_cmd(char * program,char * host,char * remuser,int port,int subsystem,char * cmd,int * fdin,int * fdout,pid_t * pid)260 do_cmd(char *program, char *host, char *remuser, int port, int subsystem,
261 char *cmd, int *fdin, int *fdout, pid_t *pid)
262 {
263 #ifdef USE_PIPES
264 int pin[2], pout[2];
265 #else
266 int sv[2];
267 #endif
268
269 if (verbose_mode)
270 fmprintf(stderr,
271 "Executing: program %s host %s, user %s, command %s\n",
272 program, host,
273 remuser ? remuser : "(unspecified)", cmd);
274
275 if (port == -1)
276 port = sshport;
277
278 #ifdef USE_PIPES
279 if (pipe(pin) == -1 || pipe(pout) == -1)
280 fatal("pipe: %s", strerror(errno));
281 #else
282 /* Create a socket pair for communicating with ssh. */
283 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1)
284 fatal("socketpair: %s", strerror(errno));
285 #endif
286
287 ssh_signal(SIGTSTP, suspchild);
288 ssh_signal(SIGTTIN, suspchild);
289 ssh_signal(SIGTTOU, suspchild);
290
291 /* Fork a child to execute the command on the remote host using ssh. */
292 *pid = fork();
293 switch (*pid) {
294 case -1:
295 fatal("fork: %s", strerror(errno));
296 case 0:
297 /* Child. */
298 #ifdef USE_PIPES
299 if (dup2(pin[0], STDIN_FILENO) == -1 ||
300 dup2(pout[1], STDOUT_FILENO) == -1) {
301 error("dup2: %s", strerror(errno));
302 _exit(1);
303 }
304 close(pin[0]);
305 close(pin[1]);
306 close(pout[0]);
307 close(pout[1]);
308 #else
309 if (dup2(sv[0], STDIN_FILENO) == -1 ||
310 dup2(sv[0], STDOUT_FILENO) == -1) {
311 error("dup2: %s", strerror(errno));
312 _exit(1);
313 }
314 close(sv[0]);
315 close(sv[1]);
316 #endif
317 replacearg(&args, 0, "%s", program);
318 if (port != -1) {
319 addargs(&args, "-p");
320 addargs(&args, "%d", port);
321 }
322 if (remuser != NULL) {
323 addargs(&args, "-l");
324 addargs(&args, "%s", remuser);
325 }
326 if (subsystem)
327 addargs(&args, "-s");
328 addargs(&args, "--");
329 addargs(&args, "%s", host);
330 addargs(&args, "%s", cmd);
331
332 execvp(program, args.list);
333 perror(program);
334 _exit(1);
335 default:
336 /* Parent. Close the other side, and return the local side. */
337 #ifdef USE_PIPES
338 close(pin[0]);
339 close(pout[1]);
340 *fdout = pin[1];
341 *fdin = pout[0];
342 #else
343 close(sv[0]);
344 *fdin = sv[1];
345 *fdout = sv[1];
346 #endif
347 ssh_signal(SIGTERM, killchild);
348 ssh_signal(SIGINT, killchild);
349 ssh_signal(SIGHUP, killchild);
350 return 0;
351 }
352 }
353
354 /*
355 * This function executes a command similar to do_cmd(), but expects the
356 * input and output descriptors to be setup by a previous call to do_cmd().
357 * This way the input and output of two commands can be connected.
358 */
359 int
do_cmd2(char * host,char * remuser,int port,char * cmd,int fdin,int fdout)360 do_cmd2(char *host, char *remuser, int port, char *cmd,
361 int fdin, int fdout)
362 {
363 int status;
364 pid_t pid;
365
366 if (verbose_mode)
367 fmprintf(stderr,
368 "Executing: 2nd program %s host %s, user %s, command %s\n",
369 ssh_program, host,
370 remuser ? remuser : "(unspecified)", cmd);
371
372 if (port == -1)
373 port = sshport;
374
375 /* Fork a child to execute the command on the remote host using ssh. */
376 pid = fork();
377 if (pid == 0) {
378 if (dup2(fdin, 0) == -1)
379 perror("dup2");
380 if (dup2(fdout, 1) == -1)
381 perror("dup2");
382
383 replacearg(&args, 0, "%s", ssh_program);
384 if (port != -1) {
385 addargs(&args, "-p");
386 addargs(&args, "%d", port);
387 }
388 if (remuser != NULL) {
389 addargs(&args, "-l");
390 addargs(&args, "%s", remuser);
391 }
392 addargs(&args, "-oBatchMode=yes");
393 addargs(&args, "--");
394 addargs(&args, "%s", host);
395 addargs(&args, "%s", cmd);
396
397 execvp(ssh_program, args.list);
398 perror(ssh_program);
399 exit(1);
400 } else if (pid == -1) {
401 fatal("fork: %s", strerror(errno));
402 }
403 while (waitpid(pid, &status, 0) == -1)
404 if (errno != EINTR)
405 fatal("do_cmd2: waitpid: %s", strerror(errno));
406 return 0;
407 }
408
409 typedef struct {
410 size_t cnt;
411 char *buf;
412 } BUF;
413
414 BUF *allocbuf(BUF *, int, int);
415 void lostconn(int);
416 int okname(char *);
417 void run_err(const char *,...)
418 __attribute__((__format__ (printf, 1, 2)))
419 __attribute__((__nonnull__ (1)));
420 int note_err(const char *,...)
421 __attribute__((__format__ (printf, 1, 2)));
422 void verifydir(char *);
423
424 struct passwd *pwd;
425 uid_t userid;
426 int errs, remin, remout, remin2, remout2;
427 int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
428
429 #define CMDNEEDS 64
430 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
431
432 enum scp_mode_e {
433 MODE_SCP,
434 MODE_SFTP
435 };
436
437 int response(void);
438 void rsource(char *, struct stat *);
439 void sink(int, char *[], const char *);
440 void source(int, char *[]);
441 void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct);
442 void toremote(int, char *[], enum scp_mode_e, char *sftp_direct);
443 void usage(void);
444
445 void source_sftp(int, char *, char *, struct sftp_conn *);
446 void sink_sftp(int, char *, const char *, struct sftp_conn *);
447 void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *,
448 char *, char *);
449
450 int
main(int argc,char ** argv)451 main(int argc, char **argv)
452 {
453 int ch, fflag, tflag, status, r, n;
454 char **newargv, *argv0;
455 const char *errstr;
456 extern char *optarg;
457 extern int optind;
458 enum scp_mode_e mode = MODE_SFTP;
459 char *sftp_direct = NULL;
460 long long llv;
461
462 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
463 sanitise_stdfd();
464
465 msetlocale();
466
467 /* Copy argv, because we modify it */
468 argv0 = argv[0];
469 newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
470 for (n = 0; n < argc; n++)
471 newargv[n] = xstrdup(argv[n]);
472 argv = newargv;
473
474 __progname = ssh_get_progname(argv[0]);
475
476 log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2);
477
478 memset(&args, '\0', sizeof(args));
479 memset(&remote_remote_args, '\0', sizeof(remote_remote_args));
480 args.list = remote_remote_args.list = NULL;
481 addargs(&args, "%s", ssh_program);
482 addargs(&args, "-x");
483 addargs(&args, "-oPermitLocalCommand=no");
484 addargs(&args, "-oClearAllForwardings=yes");
485 addargs(&args, "-oRemoteCommand=none");
486 addargs(&args, "-oRequestTTY=no");
487 addargs(&args, "-oControlMaster=no");
488
489 fflag = Tflag = tflag = 0;
490 while ((ch = getopt(argc, argv,
491 "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:X:")) != -1) {
492 switch (ch) {
493 /* User-visible flags. */
494 case '1':
495 fatal("SSH protocol v.1 is no longer supported");
496 break;
497 case '2':
498 /* Ignored */
499 break;
500 case 'A':
501 case '4':
502 case '6':
503 case 'C':
504 addargs(&args, "-%c", ch);
505 addargs(&remote_remote_args, "-%c", ch);
506 break;
507 case 'D':
508 sftp_direct = optarg;
509 break;
510 case '3':
511 throughlocal = 1;
512 break;
513 case 'R':
514 throughlocal = 0;
515 break;
516 case 'o':
517 case 'c':
518 case 'i':
519 case 'F':
520 case 'J':
521 addargs(&remote_remote_args, "-%c", ch);
522 addargs(&remote_remote_args, "%s", optarg);
523 addargs(&args, "-%c", ch);
524 addargs(&args, "%s", optarg);
525 break;
526 case 'O':
527 mode = MODE_SCP;
528 break;
529 case 's':
530 mode = MODE_SFTP;
531 break;
532 case 'P':
533 sshport = a2port(optarg);
534 if (sshport <= 0)
535 fatal("bad port \"%s\"\n", optarg);
536 break;
537 case 'B':
538 addargs(&remote_remote_args, "-oBatchmode=yes");
539 addargs(&args, "-oBatchmode=yes");
540 break;
541 case 'l':
542 limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
543 &errstr);
544 if (errstr != NULL)
545 usage();
546 limit_kbps *= 1024; /* kbps */
547 bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN);
548 break;
549 case 'p':
550 pflag = 1;
551 break;
552 case 'r':
553 iamrecursive = 1;
554 break;
555 case 'S':
556 ssh_program = xstrdup(optarg);
557 break;
558 case 'v':
559 addargs(&args, "-v");
560 addargs(&remote_remote_args, "-v");
561 if (verbose_mode == 0)
562 log_level = SYSLOG_LEVEL_DEBUG1;
563 else if (log_level < SYSLOG_LEVEL_DEBUG3)
564 log_level++;
565 verbose_mode = 1;
566 break;
567 case 'q':
568 addargs(&args, "-q");
569 addargs(&remote_remote_args, "-q");
570 showprogress = 0;
571 break;
572 case 'X':
573 /* Please keep in sync with sftp.c -X */
574 if (strncmp(optarg, "buffer=", 7) == 0) {
575 r = scan_scaled(optarg + 7, &llv);
576 if (r == 0 && (llv <= 0 || llv > 256 * 1024)) {
577 r = -1;
578 errno = EINVAL;
579 }
580 if (r == -1) {
581 fatal("Invalid buffer size \"%s\": %s",
582 optarg + 7, strerror(errno));
583 }
584 sftp_copy_buflen = (size_t)llv;
585 } else if (strncmp(optarg, "nrequests=", 10) == 0) {
586 llv = strtonum(optarg + 10, 1, 256 * 1024,
587 &errstr);
588 if (errstr != NULL) {
589 fatal("Invalid number of requests "
590 "\"%s\": %s", optarg + 10, errstr);
591 }
592 sftp_nrequests = (size_t)llv;
593 } else {
594 fatal("Invalid -X option");
595 }
596 break;
597
598 /* Server options. */
599 case 'd':
600 targetshouldbedirectory = 1;
601 break;
602 case 'f': /* "from" */
603 iamremote = 1;
604 fflag = 1;
605 break;
606 case 't': /* "to" */
607 iamremote = 1;
608 tflag = 1;
609 #ifdef HAVE_CYGWIN
610 setmode(0, O_BINARY);
611 #endif
612 break;
613 case 'T':
614 Tflag = 1;
615 break;
616 default:
617 usage();
618 }
619 }
620 argc -= optind;
621 argv += optind;
622
623 log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2);
624
625 /* Do this last because we want the user to be able to override it */
626 addargs(&args, "-oForwardAgent=no");
627
628 if (iamremote)
629 mode = MODE_SCP;
630
631 if ((pwd = getpwuid(userid = getuid())) == NULL)
632 fatal("unknown user %u", (u_int) userid);
633
634 if (!isatty(STDOUT_FILENO))
635 showprogress = 0;
636
637 if (pflag) {
638 /* Cannot pledge: -p allows setuid/setgid files... */
639 } else {
640 if (pledge("stdio rpath wpath cpath fattr tty proc exec",
641 NULL) == -1) {
642 perror("pledge");
643 exit(1);
644 }
645 }
646
647 remin = STDIN_FILENO;
648 remout = STDOUT_FILENO;
649
650 if (fflag) {
651 /* Follow "protocol", send data. */
652 (void) response();
653 source(argc, argv);
654 exit(errs != 0);
655 }
656 if (tflag) {
657 /* Receive data. */
658 sink(argc, argv, NULL);
659 exit(errs != 0);
660 }
661 if (argc < 2)
662 usage();
663 if (argc > 2)
664 targetshouldbedirectory = 1;
665
666 remin = remout = -1;
667 do_cmd_pid = -1;
668 /* Command to be executed on remote system using "ssh". */
669 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
670 verbose_mode ? " -v" : "",
671 iamrecursive ? " -r" : "", pflag ? " -p" : "",
672 targetshouldbedirectory ? " -d" : "");
673
674 (void) ssh_signal(SIGPIPE, lostconn);
675
676 if (colon(argv[argc - 1])) /* Dest is remote host. */
677 toremote(argc, argv, mode, sftp_direct);
678 else {
679 if (targetshouldbedirectory)
680 verifydir(argv[argc - 1]);
681 tolocal(argc, argv, mode, sftp_direct); /* Dest is local host. */
682 }
683 /*
684 * Finally check the exit status of the ssh process, if one was forked
685 * and no error has occurred yet
686 */
687 if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) {
688 if (remin != -1)
689 (void) close(remin);
690 if (remout != -1)
691 (void) close(remout);
692 if (waitpid(do_cmd_pid, &status, 0) == -1)
693 errs = 1;
694 else {
695 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
696 errs = 1;
697 }
698 }
699 exit(errs != 0);
700 }
701
702 /* Callback from atomicio6 to update progress meter and limit bandwidth */
703 static int
scpio(void * _cnt,size_t s)704 scpio(void *_cnt, size_t s)
705 {
706 off_t *cnt = (off_t *)_cnt;
707
708 *cnt += s;
709 refresh_progress_meter(0);
710 if (limit_kbps > 0)
711 bandwidth_limit(&bwlimit, s);
712 return 0;
713 }
714
715 static int
do_times(int fd,int verb,const struct stat * sb)716 do_times(int fd, int verb, const struct stat *sb)
717 {
718 /* strlen(2^64) == 20; strlen(10^6) == 7 */
719 char buf[(20 + 7 + 2) * 2 + 2];
720
721 (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n",
722 (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime),
723 (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime));
724 if (verb) {
725 fprintf(stderr, "File mtime %lld atime %lld\n",
726 (long long)sb->st_mtime, (long long)sb->st_atime);
727 fprintf(stderr, "Sending file timestamps: %s", buf);
728 }
729 (void) atomicio(vwrite, fd, buf, strlen(buf));
730 return (response());
731 }
732
733 static int
parse_scp_uri(const char * uri,char ** userp,char ** hostp,int * portp,char ** pathp)734 parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
735 char **pathp)
736 {
737 int r;
738
739 r = parse_uri("scp", uri, userp, hostp, portp, pathp);
740 if (r == 0 && *pathp == NULL)
741 *pathp = xstrdup(".");
742 return r;
743 }
744
745 /* Appends a string to an array; returns 0 on success, -1 on alloc failure */
746 static int
append(char * cp,char *** ap,size_t * np)747 append(char *cp, char ***ap, size_t *np)
748 {
749 char **tmp;
750
751 if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL)
752 return -1;
753 tmp[(*np)] = cp;
754 (*np)++;
755 *ap = tmp;
756 return 0;
757 }
758
759 /*
760 * Finds the start and end of the first brace pair in the pattern.
761 * returns 0 on success or -1 for invalid patterns.
762 */
763 static int
find_brace(const char * pattern,int * startp,int * endp)764 find_brace(const char *pattern, int *startp, int *endp)
765 {
766 int i;
767 int in_bracket, brace_level;
768
769 *startp = *endp = -1;
770 in_bracket = brace_level = 0;
771 for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) {
772 switch (pattern[i]) {
773 case '\\':
774 /* skip next character */
775 if (pattern[i + 1] != '\0')
776 i++;
777 break;
778 case '[':
779 in_bracket = 1;
780 break;
781 case ']':
782 in_bracket = 0;
783 break;
784 case '{':
785 if (in_bracket)
786 break;
787 if (pattern[i + 1] == '}') {
788 /* Protect a single {}, for find(1), like csh */
789 i++; /* skip */
790 break;
791 }
792 if (*startp == -1)
793 *startp = i;
794 brace_level++;
795 break;
796 case '}':
797 if (in_bracket)
798 break;
799 if (*startp < 0) {
800 /* Unbalanced brace */
801 return -1;
802 }
803 if (--brace_level <= 0)
804 *endp = i;
805 break;
806 }
807 }
808 /* unbalanced brackets/braces */
809 if (*endp < 0 && (*startp >= 0 || in_bracket))
810 return -1;
811 return 0;
812 }
813
814 /*
815 * Assembles and records a successfully-expanded pattern, returns -1 on
816 * alloc failure.
817 */
818 static int
emit_expansion(const char * pattern,int brace_start,int brace_end,int sel_start,int sel_end,char *** patternsp,size_t * npatternsp)819 emit_expansion(const char *pattern, int brace_start, int brace_end,
820 int sel_start, int sel_end, char ***patternsp, size_t *npatternsp)
821 {
822 char *cp;
823 size_t pattern_len;
824 int o = 0, tail_len;
825
826 if ((pattern_len = strlen(pattern)) == 0 || pattern_len >= INT_MAX)
827 return -1;
828
829 tail_len = strlen(pattern + brace_end + 1);
830 if ((cp = malloc(brace_start + (sel_end - sel_start) +
831 tail_len + 1)) == NULL)
832 return -1;
833
834 /* Pattern before initial brace */
835 if (brace_start > 0) {
836 memcpy(cp, pattern, brace_start);
837 o = brace_start;
838 }
839 /* Current braced selection */
840 if (sel_end - sel_start > 0) {
841 memcpy(cp + o, pattern + sel_start,
842 sel_end - sel_start);
843 o += sel_end - sel_start;
844 }
845 /* Remainder of pattern after closing brace */
846 if (tail_len > 0) {
847 memcpy(cp + o, pattern + brace_end + 1, tail_len);
848 o += tail_len;
849 }
850 cp[o] = '\0';
851 if (append(cp, patternsp, npatternsp) != 0) {
852 free(cp);
853 return -1;
854 }
855 return 0;
856 }
857
858 /*
859 * Expand the first encountered brace in pattern, appending the expanded
860 * patterns it yielded to the *patternsp array.
861 *
862 * Returns 0 on success or -1 on allocation failure.
863 *
864 * Signals whether expansion was performed via *expanded and whether
865 * pattern was invalid via *invalid.
866 */
867 static int
brace_expand_one(const char * pattern,char *** patternsp,size_t * npatternsp,int * expanded,int * invalid)868 brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp,
869 int *expanded, int *invalid)
870 {
871 int i;
872 int in_bracket, brace_start, brace_end, brace_level;
873 int sel_start, sel_end;
874
875 *invalid = *expanded = 0;
876
877 if (find_brace(pattern, &brace_start, &brace_end) != 0) {
878 *invalid = 1;
879 return 0;
880 } else if (brace_start == -1)
881 return 0;
882
883 in_bracket = brace_level = 0;
884 for (i = sel_start = brace_start + 1; i < brace_end; i++) {
885 switch (pattern[i]) {
886 case '{':
887 if (in_bracket)
888 break;
889 brace_level++;
890 break;
891 case '}':
892 if (in_bracket)
893 break;
894 brace_level--;
895 break;
896 case '[':
897 in_bracket = 1;
898 break;
899 case ']':
900 in_bracket = 0;
901 break;
902 case '\\':
903 if (i < brace_end - 1)
904 i++; /* skip */
905 break;
906 }
907 if (pattern[i] == ',' || i == brace_end - 1) {
908 if (in_bracket || brace_level > 0)
909 continue;
910 /* End of a selection, emit an expanded pattern */
911
912 /* Adjust end index for last selection */
913 sel_end = (i == brace_end - 1) ? brace_end : i;
914 if (emit_expansion(pattern, brace_start, brace_end,
915 sel_start, sel_end, patternsp, npatternsp) != 0)
916 return -1;
917 /* move on to the next selection */
918 sel_start = i + 1;
919 continue;
920 }
921 }
922 if (in_bracket || brace_level > 0) {
923 *invalid = 1;
924 return 0;
925 }
926 /* success */
927 *expanded = 1;
928 return 0;
929 }
930
931 /* Expand braces from pattern. Returns 0 on success, -1 on failure */
932 static int
brace_expand(const char * pattern,char *** patternsp,size_t * npatternsp)933 brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
934 {
935 char *cp, *cp2, **active = NULL, **done = NULL;
936 size_t i, nactive = 0, ndone = 0;
937 int ret = -1, invalid = 0, expanded = 0;
938
939 *patternsp = NULL;
940 *npatternsp = 0;
941
942 /* Start the worklist with the original pattern */
943 if ((cp = strdup(pattern)) == NULL)
944 return -1;
945 if (append(cp, &active, &nactive) != 0) {
946 free(cp);
947 return -1;
948 }
949 while (nactive > 0) {
950 cp = active[nactive - 1];
951 nactive--;
952 if (brace_expand_one(cp, &active, &nactive,
953 &expanded, &invalid) == -1) {
954 free(cp);
955 goto fail;
956 }
957 if (invalid)
958 fatal_f("invalid brace pattern \"%s\"", cp);
959 if (expanded) {
960 /*
961 * Current entry expanded to new entries on the
962 * active list; discard the progenitor pattern.
963 */
964 free(cp);
965 continue;
966 }
967 /*
968 * Pattern did not expand; append the filename component to
969 * the completed list
970 */
971 if ((cp2 = strrchr(cp, '/')) != NULL)
972 *cp2++ = '\0';
973 else
974 cp2 = cp;
975 if (append(xstrdup(cp2), &done, &ndone) != 0) {
976 free(cp);
977 goto fail;
978 }
979 free(cp);
980 }
981 /* success */
982 *patternsp = done;
983 *npatternsp = ndone;
984 done = NULL;
985 ndone = 0;
986 ret = 0;
987 fail:
988 for (i = 0; i < nactive; i++)
989 free(active[i]);
990 free(active);
991 for (i = 0; i < ndone; i++)
992 free(done[i]);
993 free(done);
994 return ret;
995 }
996
997 static struct sftp_conn *
do_sftp_connect(char * host,char * user,int port,char * sftp_direct,int * reminp,int * remoutp,int * pidp)998 do_sftp_connect(char *host, char *user, int port, char *sftp_direct,
999 int *reminp, int *remoutp, int *pidp)
1000 {
1001 if (sftp_direct == NULL) {
1002 if (do_cmd(ssh_program, host, user, port, 1, "sftp",
1003 reminp, remoutp, pidp) < 0)
1004 return NULL;
1005
1006 } else {
1007 freeargs(&args);
1008 addargs(&args, "sftp-server");
1009 if (do_cmd(sftp_direct, host, NULL, -1, 0, "sftp",
1010 reminp, remoutp, pidp) < 0)
1011 return NULL;
1012 }
1013 return sftp_init(*reminp, *remoutp,
1014 sftp_copy_buflen, sftp_nrequests, limit_kbps);
1015 }
1016
1017 void
toremote(int argc,char ** argv,enum scp_mode_e mode,char * sftp_direct)1018 toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
1019 {
1020 char *suser = NULL, *host = NULL, *src = NULL;
1021 char *bp, *tuser, *thost, *targ;
1022 int sport = -1, tport = -1;
1023 struct sftp_conn *conn = NULL, *conn2 = NULL;
1024 arglist alist;
1025 int i, r, status;
1026 struct stat sb;
1027 u_int j;
1028
1029 memset(&alist, '\0', sizeof(alist));
1030 alist.list = NULL;
1031
1032 /* Parse target */
1033 r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ);
1034 if (r == -1) {
1035 fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]);
1036 ++errs;
1037 goto out;
1038 }
1039 if (r != 0) {
1040 if (parse_user_host_path(argv[argc - 1], &tuser, &thost,
1041 &targ) == -1) {
1042 fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]);
1043 ++errs;
1044 goto out;
1045 }
1046 }
1047
1048 /* Parse source files */
1049 for (i = 0; i < argc - 1; i++) {
1050 free(suser);
1051 free(host);
1052 free(src);
1053 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
1054 if (r == -1) {
1055 fmprintf(stderr, "%s: invalid uri\n", argv[i]);
1056 ++errs;
1057 continue;
1058 }
1059 if (r != 0) {
1060 parse_user_host_path(argv[i], &suser, &host, &src);
1061 }
1062 if (suser != NULL && !okname(suser)) {
1063 ++errs;
1064 continue;
1065 }
1066 if (host && throughlocal) { /* extended remote to remote */
1067 if (mode == MODE_SFTP) {
1068 if (remin == -1 || conn == NULL) {
1069 /* Connect to dest now */
1070 sftp_free(conn);
1071 conn = do_sftp_connect(thost, tuser,
1072 tport, sftp_direct,
1073 &remin, &remout, &do_cmd_pid);
1074 if (conn == NULL) {
1075 fatal("Unable to open "
1076 "destination connection");
1077 }
1078 debug3_f("origin in %d out %d pid %ld",
1079 remin, remout, (long)do_cmd_pid);
1080 }
1081 /*
1082 * XXX remember suser/host/sport and only
1083 * reconnect if they change between arguments.
1084 * would save reconnections for cases like
1085 * scp -3 hosta:/foo hosta:/bar hostb:
1086 */
1087 /* Connect to origin now */
1088 sftp_free(conn2);
1089 conn2 = do_sftp_connect(host, suser,
1090 sport, sftp_direct,
1091 &remin2, &remout2, &do_cmd_pid2);
1092 if (conn2 == NULL) {
1093 fatal("Unable to open "
1094 "source connection");
1095 }
1096 debug3_f("destination in %d out %d pid %ld",
1097 remin2, remout2, (long)do_cmd_pid2);
1098 throughlocal_sftp(conn2, conn, src, targ);
1099 (void) close(remin2);
1100 (void) close(remout2);
1101 remin2 = remout2 = -1;
1102 if (waitpid(do_cmd_pid2, &status, 0) == -1)
1103 ++errs;
1104 else if (!WIFEXITED(status) ||
1105 WEXITSTATUS(status) != 0)
1106 ++errs;
1107 do_cmd_pid2 = -1;
1108 continue;
1109 } else {
1110 xasprintf(&bp, "%s -f %s%s", cmd,
1111 *src == '-' ? "-- " : "", src);
1112 if (do_cmd(ssh_program, host, suser, sport, 0,
1113 bp, &remin, &remout, &do_cmd_pid) < 0)
1114 exit(1);
1115 free(bp);
1116 xasprintf(&bp, "%s -t %s%s", cmd,
1117 *targ == '-' ? "-- " : "", targ);
1118 if (do_cmd2(thost, tuser, tport, bp,
1119 remin, remout) < 0)
1120 exit(1);
1121 free(bp);
1122 (void) close(remin);
1123 (void) close(remout);
1124 remin = remout = -1;
1125 }
1126 } else if (host) { /* standard remote to remote */
1127 /*
1128 * Second remote user is passed to first remote side
1129 * via scp command-line. Ensure it contains no obvious
1130 * shell characters.
1131 */
1132 if (tuser != NULL && !okname(tuser)) {
1133 ++errs;
1134 continue;
1135 }
1136 if (tport != -1 && tport != SSH_DEFAULT_PORT) {
1137 /* This would require the remote support URIs */
1138 fatal("target port not supported with two "
1139 "remote hosts and the -R option");
1140 }
1141
1142 freeargs(&alist);
1143 addargs(&alist, "%s", ssh_program);
1144 addargs(&alist, "-x");
1145 addargs(&alist, "-oClearAllForwardings=yes");
1146 addargs(&alist, "-n");
1147 for (j = 0; j < remote_remote_args.num; j++) {
1148 addargs(&alist, "%s",
1149 remote_remote_args.list[j]);
1150 }
1151
1152 if (sport != -1) {
1153 addargs(&alist, "-p");
1154 addargs(&alist, "%d", sport);
1155 }
1156 if (suser) {
1157 addargs(&alist, "-l");
1158 addargs(&alist, "%s", suser);
1159 }
1160 addargs(&alist, "--");
1161 addargs(&alist, "%s", host);
1162 addargs(&alist, "%s", cmd);
1163 addargs(&alist, "%s", src);
1164 addargs(&alist, "%s%s%s:%s",
1165 tuser ? tuser : "", tuser ? "@" : "",
1166 thost, targ);
1167 if (do_local_cmd(&alist) != 0)
1168 errs = 1;
1169 } else { /* local to remote */
1170 if (mode == MODE_SFTP) {
1171 /* no need to glob: already done by shell */
1172 if (stat(argv[i], &sb) != 0) {
1173 fatal("stat local \"%s\": %s", argv[i],
1174 strerror(errno));
1175 }
1176 if (remin == -1) {
1177 /* Connect to remote now */
1178 sftp_free(conn);
1179 conn = do_sftp_connect(thost, tuser,
1180 tport, sftp_direct,
1181 &remin, &remout, &do_cmd_pid);
1182 if (conn == NULL) {
1183 fatal("Unable to open sftp "
1184 "connection");
1185 }
1186 }
1187
1188 /* The protocol */
1189 source_sftp(1, argv[i], targ, conn);
1190 continue;
1191 }
1192 /* SCP */
1193 if (remin == -1) {
1194 xasprintf(&bp, "%s -t %s%s", cmd,
1195 *targ == '-' ? "-- " : "", targ);
1196 if (do_cmd(ssh_program, thost, tuser, tport, 0,
1197 bp, &remin, &remout, &do_cmd_pid) < 0)
1198 exit(1);
1199 if (response() < 0)
1200 exit(1);
1201 free(bp);
1202 }
1203 source(1, argv + i);
1204 }
1205 }
1206 out:
1207 freeargs(&alist);
1208 free(tuser);
1209 free(thost);
1210 free(targ);
1211 free(suser);
1212 free(host);
1213 free(src);
1214 sftp_free(conn);
1215 sftp_free(conn2);
1216 }
1217
1218 void
tolocal(int argc,char ** argv,enum scp_mode_e mode,char * sftp_direct)1219 tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
1220 {
1221 char *bp, *host = NULL, *src = NULL, *suser = NULL;
1222 arglist alist;
1223 struct sftp_conn *conn = NULL;
1224 int i, r, sport = -1;
1225
1226 memset(&alist, '\0', sizeof(alist));
1227 alist.list = NULL;
1228
1229 for (i = 0; i < argc - 1; i++) {
1230 free(suser);
1231 free(host);
1232 free(src);
1233 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
1234 if (r == -1) {
1235 fmprintf(stderr, "%s: invalid uri\n", argv[i]);
1236 ++errs;
1237 continue;
1238 }
1239 if (r != 0)
1240 parse_user_host_path(argv[i], &suser, &host, &src);
1241 if (suser != NULL && !okname(suser)) {
1242 ++errs;
1243 continue;
1244 }
1245 if (!host) { /* Local to local. */
1246 freeargs(&alist);
1247 addargs(&alist, "%s", _PATH_CP);
1248 if (iamrecursive)
1249 addargs(&alist, "-r");
1250 if (pflag)
1251 addargs(&alist, "-p");
1252 addargs(&alist, "--");
1253 addargs(&alist, "%s", argv[i]);
1254 addargs(&alist, "%s", argv[argc-1]);
1255 if (do_local_cmd(&alist))
1256 ++errs;
1257 continue;
1258 }
1259 /* Remote to local. */
1260 if (mode == MODE_SFTP) {
1261 sftp_free(conn);
1262 conn = do_sftp_connect(host, suser, sport,
1263 sftp_direct, &remin, &remout, &do_cmd_pid);
1264 if (conn == NULL) {
1265 error("sftp connection failed");
1266 ++errs;
1267 continue;
1268 }
1269
1270 /* The protocol */
1271 sink_sftp(1, argv[argc - 1], src, conn);
1272
1273 (void) close(remin);
1274 (void) close(remout);
1275 remin = remout = -1;
1276 continue;
1277 }
1278 /* SCP */
1279 xasprintf(&bp, "%s -f %s%s",
1280 cmd, *src == '-' ? "-- " : "", src);
1281 if (do_cmd(ssh_program, host, suser, sport, 0, bp,
1282 &remin, &remout, &do_cmd_pid) < 0) {
1283 free(bp);
1284 ++errs;
1285 continue;
1286 }
1287 free(bp);
1288 sink(1, argv + argc - 1, src);
1289 (void) close(remin);
1290 remin = remout = -1;
1291 }
1292 freeargs(&alist);
1293 free(suser);
1294 free(host);
1295 free(src);
1296 sftp_free(conn);
1297 }
1298
1299 /* Prepare remote path, handling ~ by assuming cwd is the homedir */
1300 static char *
prepare_remote_path(struct sftp_conn * conn,const char * path)1301 prepare_remote_path(struct sftp_conn *conn, const char *path)
1302 {
1303 size_t nslash;
1304
1305 /* Handle ~ prefixed paths */
1306 if (*path == '\0' || strcmp(path, "~") == 0)
1307 return xstrdup(".");
1308 if (*path != '~')
1309 return xstrdup(path);
1310 if (strncmp(path, "~/", 2) == 0) {
1311 if ((nslash = strspn(path + 2, "/")) == strlen(path + 2))
1312 return xstrdup(".");
1313 return xstrdup(path + 2 + nslash);
1314 }
1315 if (sftp_can_expand_path(conn))
1316 return sftp_expand_path(conn, path);
1317 /* No protocol extension */
1318 error("server expand-path extension is required "
1319 "for ~user paths in SFTP mode");
1320 return NULL;
1321 }
1322
1323 void
source_sftp(int argc,char * src,char * targ,struct sftp_conn * conn)1324 source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn)
1325 {
1326 char *target = NULL, *filename = NULL, *abs_dst = NULL;
1327 int src_is_dir, target_is_dir;
1328 Attrib a;
1329 struct stat st;
1330
1331 memset(&a, '\0', sizeof(a));
1332 if (stat(src, &st) != 0)
1333 fatal("stat local \"%s\": %s", src, strerror(errno));
1334 src_is_dir = S_ISDIR(st.st_mode);
1335 if ((filename = basename(src)) == NULL)
1336 fatal("basename \"%s\": %s", src, strerror(errno));
1337
1338 /* Special handling for source of '..' */
1339 if (strcmp(filename, "..") == 0)
1340 filename = "."; /* Upload to dest, not dest/.. */
1341
1342 /*
1343 * No need to glob here - the local shell already took care of
1344 * the expansions
1345 */
1346 if ((target = prepare_remote_path(conn, targ)) == NULL)
1347 cleanup_exit(255);
1348 target_is_dir = sftp_remote_is_dir(conn, target);
1349 if (targetshouldbedirectory && !target_is_dir) {
1350 debug("target directory \"%s\" does not exist", target);
1351 a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS;
1352 a.perm = st.st_mode | 0700; /* ensure writable */
1353 if (sftp_mkdir(conn, target, &a, 1) != 0)
1354 cleanup_exit(255); /* error already logged */
1355 target_is_dir = 1;
1356 }
1357 if (target_is_dir)
1358 abs_dst = sftp_path_append(target, filename);
1359 else {
1360 abs_dst = target;
1361 target = NULL;
1362 }
1363 debug3_f("copying local %s to remote %s", src, abs_dst);
1364
1365 if (src_is_dir && iamrecursive) {
1366 if (sftp_upload_dir(conn, src, abs_dst, pflag,
1367 SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
1368 error("failed to upload directory %s to %s", src, targ);
1369 errs = 1;
1370 }
1371 } else if (sftp_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) {
1372 error("failed to upload file %s to %s", src, targ);
1373 errs = 1;
1374 }
1375
1376 free(abs_dst);
1377 free(target);
1378 }
1379
1380 void
source(int argc,char ** argv)1381 source(int argc, char **argv)
1382 {
1383 struct stat stb;
1384 static BUF buffer;
1385 BUF *bp;
1386 off_t i, statbytes;
1387 size_t amt, nr;
1388 int fd = -1, haderr, indx;
1389 char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX];
1390 int len;
1391
1392 for (indx = 0; indx < argc; ++indx) {
1393 name = argv[indx];
1394 statbytes = 0;
1395 len = strlen(name);
1396 while (len > 1 && name[len-1] == '/')
1397 name[--len] = '\0';
1398 if ((fd = open(name, O_RDONLY|O_NONBLOCK)) == -1)
1399 goto syserr;
1400 if (strchr(name, '\n') != NULL) {
1401 strnvis(encname, name, sizeof(encname), VIS_NL);
1402 name = encname;
1403 }
1404 if (fstat(fd, &stb) == -1) {
1405 syserr: run_err("%s: %s", name, strerror(errno));
1406 goto next;
1407 }
1408 if (stb.st_size < 0) {
1409 run_err("%s: %s", name, "Negative file size");
1410 goto next;
1411 }
1412 unset_nonblock(fd);
1413 switch (stb.st_mode & S_IFMT) {
1414 case S_IFREG:
1415 break;
1416 case S_IFDIR:
1417 if (iamrecursive) {
1418 rsource(name, &stb);
1419 goto next;
1420 }
1421 /* FALLTHROUGH */
1422 default:
1423 run_err("%s: not a regular file", name);
1424 goto next;
1425 }
1426 if ((last = strrchr(name, '/')) == NULL)
1427 last = name;
1428 else
1429 ++last;
1430 curfile = last;
1431 if (pflag) {
1432 if (do_times(remout, verbose_mode, &stb) < 0)
1433 goto next;
1434 }
1435 #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
1436 snprintf(buf, sizeof buf, "C%04o %lld %s\n",
1437 (u_int) (stb.st_mode & FILEMODEMASK),
1438 (long long)stb.st_size, last);
1439 if (verbose_mode)
1440 fmprintf(stderr, "Sending file modes: %s", buf);
1441 (void) atomicio(vwrite, remout, buf, strlen(buf));
1442 if (response() < 0)
1443 goto next;
1444 if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
1445 next: if (fd != -1) {
1446 (void) close(fd);
1447 fd = -1;
1448 }
1449 continue;
1450 }
1451 if (showprogress)
1452 start_progress_meter(curfile, stb.st_size, &statbytes);
1453 set_nonblock(remout);
1454 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
1455 amt = bp->cnt;
1456 if (i + (off_t)amt > stb.st_size)
1457 amt = stb.st_size - i;
1458 if (!haderr) {
1459 if ((nr = atomicio(read, fd,
1460 bp->buf, amt)) != amt) {
1461 haderr = errno;
1462 memset(bp->buf + nr, 0, amt - nr);
1463 }
1464 }
1465 /* Keep writing after error to retain sync */
1466 if (haderr) {
1467 (void)atomicio(vwrite, remout, bp->buf, amt);
1468 memset(bp->buf, 0, amt);
1469 continue;
1470 }
1471 if (atomicio6(vwrite, remout, bp->buf, amt, scpio,
1472 &statbytes) != amt)
1473 haderr = errno;
1474 }
1475 unset_nonblock(remout);
1476
1477 if (fd != -1) {
1478 if (close(fd) == -1 && !haderr)
1479 haderr = errno;
1480 fd = -1;
1481 }
1482 if (!haderr)
1483 (void) atomicio(vwrite, remout, "", 1);
1484 else
1485 run_err("%s: %s", name, strerror(haderr));
1486 (void) response();
1487 if (showprogress)
1488 stop_progress_meter();
1489 }
1490 }
1491
1492 void
rsource(char * name,struct stat * statp)1493 rsource(char *name, struct stat *statp)
1494 {
1495 DIR *dirp;
1496 struct dirent *dp;
1497 char *last, *vect[1], path[PATH_MAX];
1498
1499 if (!(dirp = opendir(name))) {
1500 run_err("%s: %s", name, strerror(errno));
1501 return;
1502 }
1503 last = strrchr(name, '/');
1504 if (last == NULL)
1505 last = name;
1506 else
1507 last++;
1508 if (pflag) {
1509 if (do_times(remout, verbose_mode, statp) < 0) {
1510 closedir(dirp);
1511 return;
1512 }
1513 }
1514 (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
1515 (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
1516 if (verbose_mode)
1517 fmprintf(stderr, "Entering directory: %s", path);
1518 (void) atomicio(vwrite, remout, path, strlen(path));
1519 if (response() < 0) {
1520 closedir(dirp);
1521 return;
1522 }
1523 while ((dp = readdir(dirp)) != NULL) {
1524 if (dp->d_ino == 0)
1525 continue;
1526 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
1527 continue;
1528 if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
1529 run_err("%s/%s: name too long", name, dp->d_name);
1530 continue;
1531 }
1532 (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
1533 vect[0] = path;
1534 source(1, vect);
1535 }
1536 (void) closedir(dirp);
1537 (void) atomicio(vwrite, remout, "E\n", 2);
1538 (void) response();
1539 }
1540
1541 void
sink_sftp(int argc,char * dst,const char * src,struct sftp_conn * conn)1542 sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn)
1543 {
1544 char *abs_src = NULL;
1545 char *abs_dst = NULL;
1546 glob_t g;
1547 char *filename, *tmp = NULL;
1548 int i, r, err = 0, dst_is_dir;
1549 struct stat st;
1550
1551 memset(&g, 0, sizeof(g));
1552
1553 /*
1554 * Here, we need remote glob as SFTP can not depend on remote shell
1555 * expansions
1556 */
1557 if ((abs_src = prepare_remote_path(conn, src)) == NULL) {
1558 err = -1;
1559 goto out;
1560 }
1561
1562 debug3_f("copying remote %s to local %s", abs_src, dst);
1563 if ((r = sftp_glob(conn, abs_src, GLOB_NOCHECK|GLOB_MARK,
1564 NULL, &g)) != 0) {
1565 if (r == GLOB_NOSPACE)
1566 error("%s: too many glob matches", src);
1567 else
1568 error("%s: %s", src, strerror(ENOENT));
1569 err = -1;
1570 goto out;
1571 }
1572
1573 /* Did we actually get any matches back from the glob? */
1574 if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != NULL) {
1575 /*
1576 * If nothing matched but a path returned, then it's probably
1577 * a GLOB_NOCHECK result. Check whether the unglobbed path
1578 * exists so we can give a nice error message early.
1579 */
1580 if (sftp_stat(conn, g.gl_pathv[0], 1, NULL) != 0) {
1581 error("%s: %s", src, strerror(ENOENT));
1582 err = -1;
1583 goto out;
1584 }
1585 }
1586
1587 if ((r = stat(dst, &st)) != 0)
1588 debug2_f("stat local \"%s\": %s", dst, strerror(errno));
1589 dst_is_dir = r == 0 && S_ISDIR(st.st_mode);
1590
1591 if (g.gl_matchc > 1 && !dst_is_dir) {
1592 if (r == 0) {
1593 error("Multiple files match pattern, but destination "
1594 "\"%s\" is not a directory", dst);
1595 err = -1;
1596 goto out;
1597 }
1598 debug2_f("creating destination \"%s\"", dst);
1599 if (mkdir(dst, 0777) != 0) {
1600 error("local mkdir \"%s\": %s", dst, strerror(errno));
1601 err = -1;
1602 goto out;
1603 }
1604 dst_is_dir = 1;
1605 }
1606
1607 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1608 tmp = xstrdup(g.gl_pathv[i]);
1609 if ((filename = basename(tmp)) == NULL) {
1610 error("basename %s: %s", tmp, strerror(errno));
1611 err = -1;
1612 goto out;
1613 }
1614
1615 /* Special handling for destination of '..' */
1616 if (strcmp(filename, "..") == 0)
1617 filename = "."; /* Download to dest, not dest/.. */
1618
1619 if (dst_is_dir)
1620 abs_dst = sftp_path_append(dst, filename);
1621 else
1622 abs_dst = xstrdup(dst);
1623
1624 debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
1625 if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
1626 if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst,
1627 NULL, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1)
1628 err = -1;
1629 } else {
1630 if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL,
1631 pflag, 0, 0, 1) == -1)
1632 err = -1;
1633 }
1634 free(abs_dst);
1635 abs_dst = NULL;
1636 free(tmp);
1637 tmp = NULL;
1638 }
1639
1640 out:
1641 free(abs_src);
1642 free(tmp);
1643 globfree(&g);
1644 if (err == -1)
1645 errs = 1;
1646 }
1647
1648
1649 #define TYPE_OVERFLOW(type, val) \
1650 ((sizeof(type) == 4 && (val) > INT32_MAX) || \
1651 (sizeof(type) == 8 && (val) > INT64_MAX) || \
1652 (sizeof(type) != 4 && sizeof(type) != 8))
1653
1654 void
sink(int argc,char ** argv,const char * src)1655 sink(int argc, char **argv, const char *src)
1656 {
1657 static BUF buffer;
1658 struct stat stb;
1659 BUF *bp;
1660 off_t i;
1661 size_t j, count;
1662 int amt, exists, first, ofd;
1663 mode_t mode, omode, mask;
1664 off_t size, statbytes;
1665 unsigned long long ull;
1666 int setimes, targisdir, wrerr;
1667 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
1668 char **patterns = NULL;
1669 size_t n, npatterns = 0;
1670 struct timeval tv[2];
1671
1672 #define atime tv[0]
1673 #define mtime tv[1]
1674 #define SCREWUP(str) { why = str; goto screwup; }
1675
1676 if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0))
1677 SCREWUP("Unexpected off_t/time_t size");
1678
1679 setimes = targisdir = 0;
1680 mask = umask(0);
1681 if (!pflag) {
1682 mask |= 07000;
1683 (void) umask(mask);
1684 }
1685 if (argc != 1) {
1686 run_err("ambiguous target");
1687 exit(1);
1688 }
1689 targ = *argv;
1690 if (targetshouldbedirectory)
1691 verifydir(targ);
1692
1693 (void) atomicio(vwrite, remout, "", 1);
1694 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
1695 targisdir = 1;
1696 if (src != NULL && !iamrecursive && !Tflag) {
1697 /*
1698 * Prepare to try to restrict incoming filenames to match
1699 * the requested destination file glob.
1700 */
1701 if (brace_expand(src, &patterns, &npatterns) != 0)
1702 fatal_f("could not expand pattern");
1703 }
1704 for (first = 1;; first = 0) {
1705 cp = buf;
1706 if (atomicio(read, remin, cp, 1) != 1)
1707 goto done;
1708 if (*cp++ == '\n')
1709 SCREWUP("unexpected <newline>");
1710 do {
1711 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
1712 SCREWUP("lost connection");
1713 *cp++ = ch;
1714 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
1715 *cp = 0;
1716 if (verbose_mode)
1717 fmprintf(stderr, "Sink: %s", buf);
1718
1719 if (buf[0] == '\01' || buf[0] == '\02') {
1720 if (iamremote == 0) {
1721 (void) snmprintf(visbuf, sizeof(visbuf),
1722 NULL, "%s", buf + 1);
1723 (void) atomicio(vwrite, STDERR_FILENO,
1724 visbuf, strlen(visbuf));
1725 }
1726 if (buf[0] == '\02')
1727 exit(1);
1728 ++errs;
1729 continue;
1730 }
1731 if (buf[0] == 'E') {
1732 (void) atomicio(vwrite, remout, "", 1);
1733 goto done;
1734 }
1735 if (ch == '\n')
1736 *--cp = 0;
1737
1738 cp = buf;
1739 if (*cp == 'T') {
1740 setimes++;
1741 cp++;
1742 if (!isdigit((unsigned char)*cp))
1743 SCREWUP("mtime.sec not present");
1744 ull = strtoull(cp, &cp, 10);
1745 if (!cp || *cp++ != ' ')
1746 SCREWUP("mtime.sec not delimited");
1747 if (TYPE_OVERFLOW(time_t, ull))
1748 setimes = 0; /* out of range */
1749 mtime.tv_sec = ull;
1750 mtime.tv_usec = strtol(cp, &cp, 10);
1751 if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 ||
1752 mtime.tv_usec > 999999)
1753 SCREWUP("mtime.usec not delimited");
1754 if (!isdigit((unsigned char)*cp))
1755 SCREWUP("atime.sec not present");
1756 ull = strtoull(cp, &cp, 10);
1757 if (!cp || *cp++ != ' ')
1758 SCREWUP("atime.sec not delimited");
1759 if (TYPE_OVERFLOW(time_t, ull))
1760 setimes = 0; /* out of range */
1761 atime.tv_sec = ull;
1762 atime.tv_usec = strtol(cp, &cp, 10);
1763 if (!cp || *cp++ != '\0' || atime.tv_usec < 0 ||
1764 atime.tv_usec > 999999)
1765 SCREWUP("atime.usec not delimited");
1766 (void) atomicio(vwrite, remout, "", 1);
1767 continue;
1768 }
1769 if (*cp != 'C' && *cp != 'D') {
1770 /*
1771 * Check for the case "rcp remote:foo\* local:bar".
1772 * In this case, the line "No match." can be returned
1773 * by the shell before the rcp command on the remote is
1774 * executed so the ^Aerror_message convention isn't
1775 * followed.
1776 */
1777 if (first) {
1778 run_err("%s", cp);
1779 exit(1);
1780 }
1781 SCREWUP("expected control record");
1782 }
1783 mode = 0;
1784 for (++cp; cp < buf + 5; cp++) {
1785 if (*cp < '0' || *cp > '7')
1786 SCREWUP("bad mode");
1787 mode = (mode << 3) | (*cp - '0');
1788 }
1789 if (!pflag)
1790 mode &= ~mask;
1791 if (*cp++ != ' ')
1792 SCREWUP("mode not delimited");
1793
1794 if (!isdigit((unsigned char)*cp))
1795 SCREWUP("size not present");
1796 ull = strtoull(cp, &cp, 10);
1797 if (!cp || *cp++ != ' ')
1798 SCREWUP("size not delimited");
1799 if (TYPE_OVERFLOW(off_t, ull))
1800 SCREWUP("size out of range");
1801 size = (off_t)ull;
1802
1803 if (*cp == '\0' || strchr(cp, '/') != NULL ||
1804 strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
1805 run_err("error: unexpected filename: %s", cp);
1806 exit(1);
1807 }
1808 if (npatterns > 0) {
1809 for (n = 0; n < npatterns; n++) {
1810 if (strcmp(patterns[n], cp) == 0 ||
1811 fnmatch(patterns[n], cp, 0) == 0)
1812 break;
1813 }
1814 if (n >= npatterns) {
1815 debug2_f("incoming filename \"%s\" does not "
1816 "match any of %zu expected patterns", cp,
1817 npatterns);
1818 for (n = 0; n < npatterns; n++) {
1819 debug3_f("expected pattern %zu: \"%s\"",
1820 n, patterns[n]);
1821 }
1822 SCREWUP("filename does not match request");
1823 }
1824 }
1825 if (targisdir) {
1826 static char *namebuf;
1827 static size_t cursize;
1828 size_t need;
1829
1830 need = strlen(targ) + strlen(cp) + 250;
1831 if (need > cursize) {
1832 free(namebuf);
1833 namebuf = xmalloc(need);
1834 cursize = need;
1835 }
1836 (void) snprintf(namebuf, need, "%s%s%s", targ,
1837 strcmp(targ, "/") ? "/" : "", cp);
1838 np = namebuf;
1839 } else
1840 np = targ;
1841 curfile = cp;
1842 exists = stat(np, &stb) == 0;
1843 if (buf[0] == 'D') {
1844 int mod_flag = pflag;
1845 if (!iamrecursive)
1846 SCREWUP("received directory without -r");
1847 if (exists) {
1848 if (!S_ISDIR(stb.st_mode)) {
1849 errno = ENOTDIR;
1850 goto bad;
1851 }
1852 if (pflag)
1853 (void) chmod(np, mode);
1854 } else {
1855 /* Handle copying from a read-only directory */
1856 mod_flag = 1;
1857 if (mkdir(np, mode | S_IRWXU) == -1)
1858 goto bad;
1859 }
1860 vect[0] = xstrdup(np);
1861 sink(1, vect, src);
1862 if (setimes) {
1863 setimes = 0;
1864 (void) utimes(vect[0], tv);
1865 }
1866 if (mod_flag)
1867 (void) chmod(vect[0], mode);
1868 free(vect[0]);
1869 continue;
1870 }
1871 omode = mode;
1872 mode |= S_IWUSR;
1873 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) {
1874 bad: run_err("%s: %s", np, strerror(errno));
1875 continue;
1876 }
1877 (void) atomicio(vwrite, remout, "", 1);
1878 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
1879 (void) close(ofd);
1880 continue;
1881 }
1882 cp = bp->buf;
1883 wrerr = 0;
1884
1885 /*
1886 * NB. do not use run_err() unless immediately followed by
1887 * exit() below as it may send a spurious reply that might
1888 * desynchronise us from the peer. Use note_err() instead.
1889 */
1890 statbytes = 0;
1891 if (showprogress)
1892 start_progress_meter(curfile, size, &statbytes);
1893 set_nonblock(remin);
1894 for (count = i = 0; i < size; i += bp->cnt) {
1895 amt = bp->cnt;
1896 if (i + amt > size)
1897 amt = size - i;
1898 count += amt;
1899 do {
1900 j = atomicio6(read, remin, cp, amt,
1901 scpio, &statbytes);
1902 if (j == 0) {
1903 run_err("%s", j != EPIPE ?
1904 strerror(errno) :
1905 "dropped connection");
1906 exit(1);
1907 }
1908 amt -= j;
1909 cp += j;
1910 } while (amt > 0);
1911
1912 if (count == bp->cnt) {
1913 /* Keep reading so we stay sync'd up. */
1914 if (!wrerr) {
1915 if (atomicio(vwrite, ofd, bp->buf,
1916 count) != count) {
1917 note_err("%s: %s", np,
1918 strerror(errno));
1919 wrerr = 1;
1920 }
1921 }
1922 count = 0;
1923 cp = bp->buf;
1924 }
1925 }
1926 unset_nonblock(remin);
1927 if (count != 0 && !wrerr &&
1928 atomicio(vwrite, ofd, bp->buf, count) != count) {
1929 note_err("%s: %s", np, strerror(errno));
1930 wrerr = 1;
1931 }
1932 if (!wrerr && (!exists || S_ISREG(stb.st_mode)) &&
1933 ftruncate(ofd, size) != 0)
1934 note_err("%s: truncate: %s", np, strerror(errno));
1935 if (pflag) {
1936 if (exists || omode != mode)
1937 #ifdef HAVE_FCHMOD
1938 if (fchmod(ofd, omode)) {
1939 #else /* HAVE_FCHMOD */
1940 if (chmod(np, omode)) {
1941 #endif /* HAVE_FCHMOD */
1942 note_err("%s: set mode: %s",
1943 np, strerror(errno));
1944 }
1945 } else {
1946 if (!exists && omode != mode)
1947 #ifdef HAVE_FCHMOD
1948 if (fchmod(ofd, omode & ~mask)) {
1949 #else /* HAVE_FCHMOD */
1950 if (chmod(np, omode & ~mask)) {
1951 #endif /* HAVE_FCHMOD */
1952 note_err("%s: set mode: %s",
1953 np, strerror(errno));
1954 }
1955 }
1956 if (close(ofd) == -1)
1957 note_err("%s: close: %s", np, strerror(errno));
1958 (void) response();
1959 if (showprogress)
1960 stop_progress_meter();
1961 if (setimes && !wrerr) {
1962 setimes = 0;
1963 if (utimes(np, tv) == -1) {
1964 note_err("%s: set times: %s",
1965 np, strerror(errno));
1966 }
1967 }
1968 /* If no error was noted then signal success for this file */
1969 if (note_err(NULL) == 0)
1970 (void) atomicio(vwrite, remout, "", 1);
1971 }
1972 done:
1973 for (n = 0; n < npatterns; n++)
1974 free(patterns[n]);
1975 free(patterns);
1976 return;
1977 screwup:
1978 for (n = 0; n < npatterns; n++)
1979 free(patterns[n]);
1980 free(patterns);
1981 run_err("protocol error: %s", why);
1982 exit(1);
1983 }
1984
1985 void
1986 throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
1987 char *src, char *targ)
1988 {
1989 char *target = NULL, *filename = NULL, *abs_dst = NULL;
1990 char *abs_src = NULL, *tmp = NULL;
1991 glob_t g;
1992 int i, r, targetisdir, err = 0;
1993
1994 if ((filename = basename(src)) == NULL)
1995 fatal("basename %s: %s", src, strerror(errno));
1996
1997 if ((abs_src = prepare_remote_path(from, src)) == NULL ||
1998 (target = prepare_remote_path(to, targ)) == NULL)
1999 cleanup_exit(255);
2000 memset(&g, 0, sizeof(g));
2001
2002 targetisdir = sftp_remote_is_dir(to, target);
2003 if (!targetisdir && targetshouldbedirectory) {
2004 error("%s: destination is not a directory", targ);
2005 err = -1;
2006 goto out;
2007 }
2008
2009 debug3_f("copying remote %s to remote %s", abs_src, target);
2010 if ((r = sftp_glob(from, abs_src, GLOB_NOCHECK|GLOB_MARK,
2011 NULL, &g)) != 0) {
2012 if (r == GLOB_NOSPACE)
2013 error("%s: too many glob matches", src);
2014 else
2015 error("%s: %s", src, strerror(ENOENT));
2016 err = -1;
2017 goto out;
2018 }
2019
2020 /* Did we actually get any matches back from the glob? */
2021 if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != NULL) {
2022 /*
2023 * If nothing matched but a path returned, then it's probably
2024 * a GLOB_NOCHECK result. Check whether the unglobbed path
2025 * exists so we can give a nice error message early.
2026 */
2027 if (sftp_stat(from, g.gl_pathv[0], 1, NULL) != 0) {
2028 error("%s: %s", src, strerror(ENOENT));
2029 err = -1;
2030 goto out;
2031 }
2032 }
2033
2034 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
2035 tmp = xstrdup(g.gl_pathv[i]);
2036 if ((filename = basename(tmp)) == NULL) {
2037 error("basename %s: %s", tmp, strerror(errno));
2038 err = -1;
2039 goto out;
2040 }
2041
2042 if (targetisdir)
2043 abs_dst = sftp_path_append(target, filename);
2044 else
2045 abs_dst = xstrdup(target);
2046
2047 debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
2048 if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
2049 if (sftp_crossload_dir(from, to, g.gl_pathv[i], abs_dst,
2050 NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1)
2051 err = -1;
2052 } else {
2053 if (sftp_crossload(from, to, g.gl_pathv[i], abs_dst,
2054 NULL, pflag) == -1)
2055 err = -1;
2056 }
2057 free(abs_dst);
2058 abs_dst = NULL;
2059 free(tmp);
2060 tmp = NULL;
2061 }
2062
2063 out:
2064 free(abs_src);
2065 free(abs_dst);
2066 free(target);
2067 free(tmp);
2068 globfree(&g);
2069 if (err == -1)
2070 errs = 1;
2071 }
2072
2073 int
2074 response(void)
2075 {
2076 char ch, *cp, resp, rbuf[2048], visbuf[2048];
2077
2078 if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
2079 lostconn(0);
2080
2081 cp = rbuf;
2082 switch (resp) {
2083 case 0: /* ok */
2084 return (0);
2085 default:
2086 *cp++ = resp;
2087 /* FALLTHROUGH */
2088 case 1: /* error, followed by error msg */
2089 case 2: /* fatal error, "" */
2090 do {
2091 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
2092 lostconn(0);
2093 *cp++ = ch;
2094 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
2095
2096 if (!iamremote) {
2097 cp[-1] = '\0';
2098 (void) snmprintf(visbuf, sizeof(visbuf),
2099 NULL, "%s\n", rbuf);
2100 (void) atomicio(vwrite, STDERR_FILENO,
2101 visbuf, strlen(visbuf));
2102 }
2103 ++errs;
2104 if (resp == 1)
2105 return (-1);
2106 exit(1);
2107 }
2108 /* NOTREACHED */
2109 }
2110
2111 void
2112 usage(void)
2113 {
2114 (void) fprintf(stderr,
2115 "usage: scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n"
2116 " [-i identity_file] [-J destination] [-l limit] [-o ssh_option]\n"
2117 " [-P port] [-S program] [-X sftp_option] source ... target\n");
2118 exit(1);
2119 }
2120
2121 void
2122 run_err(const char *fmt,...)
2123 {
2124 static FILE *fp;
2125 va_list ap;
2126
2127 ++errs;
2128 if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) {
2129 (void) fprintf(fp, "%c", 0x01);
2130 (void) fprintf(fp, "scp: ");
2131 va_start(ap, fmt);
2132 (void) vfprintf(fp, fmt, ap);
2133 va_end(ap);
2134 (void) fprintf(fp, "\n");
2135 (void) fflush(fp);
2136 }
2137
2138 if (!iamremote) {
2139 va_start(ap, fmt);
2140 vfmprintf(stderr, fmt, ap);
2141 va_end(ap);
2142 fprintf(stderr, "\n");
2143 }
2144 }
2145
2146 /*
2147 * Notes a sink error for sending at the end of a file transfer. Returns 0 if
2148 * no error has been noted or -1 otherwise. Use note_err(NULL) to flush
2149 * any active error at the end of the transfer.
2150 */
2151 int
2152 note_err(const char *fmt, ...)
2153 {
2154 static char *emsg;
2155 va_list ap;
2156
2157 /* Replay any previously-noted error */
2158 if (fmt == NULL) {
2159 if (emsg == NULL)
2160 return 0;
2161 run_err("%s", emsg);
2162 free(emsg);
2163 emsg = NULL;
2164 return -1;
2165 }
2166
2167 errs++;
2168 /* Prefer first-noted error */
2169 if (emsg != NULL)
2170 return -1;
2171
2172 va_start(ap, fmt);
2173 vasnmprintf(&emsg, INT_MAX, NULL, fmt, ap);
2174 va_end(ap);
2175 return -1;
2176 }
2177
2178 void
2179 verifydir(char *cp)
2180 {
2181 struct stat stb;
2182
2183 if (!stat(cp, &stb)) {
2184 if (S_ISDIR(stb.st_mode))
2185 return;
2186 errno = ENOTDIR;
2187 }
2188 run_err("%s: %s", cp, strerror(errno));
2189 killchild(0);
2190 }
2191
2192 int
2193 okname(char *cp0)
2194 {
2195 int c;
2196 char *cp;
2197
2198 cp = cp0;
2199 do {
2200 c = (int)*cp;
2201 if (c & 0200)
2202 goto bad;
2203 if (!isalpha(c) && !isdigit((unsigned char)c)) {
2204 switch (c) {
2205 case '\'':
2206 case '"':
2207 case '`':
2208 case ' ':
2209 case '#':
2210 goto bad;
2211 default:
2212 break;
2213 }
2214 }
2215 } while (*++cp);
2216 return (1);
2217
2218 bad: fmprintf(stderr, "%s: invalid user name\n", cp0);
2219 return (0);
2220 }
2221
2222 BUF *
2223 allocbuf(BUF *bp, int fd, int blksize)
2224 {
2225 size_t size;
2226 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2227 struct stat stb;
2228
2229 if (fstat(fd, &stb) == -1) {
2230 run_err("fstat: %s", strerror(errno));
2231 return (NULL);
2232 }
2233 size = ROUNDUP(stb.st_blksize, blksize);
2234 if (size == 0)
2235 size = blksize;
2236 #else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
2237 size = blksize;
2238 #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
2239 if (bp->cnt >= size)
2240 return (bp);
2241 bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1);
2242 bp->cnt = size;
2243 return (bp);
2244 }
2245
2246 void
2247 lostconn(int signo)
2248 {
2249 if (!iamremote)
2250 (void)write(STDERR_FILENO, "lost connection\n", 16);
2251 if (signo)
2252 _exit(1);
2253 else
2254 exit(1);
2255 }
2256
2257 void
2258 cleanup_exit(int i)
2259 {
2260 if (remin > 0)
2261 close(remin);
2262 if (remout > 0)
2263 close(remout);
2264 if (remin2 > 0)
2265 close(remin2);
2266 if (remout2 > 0)
2267 close(remout2);
2268 if (do_cmd_pid > 0)
2269 (void)waitpid(do_cmd_pid, NULL, 0);
2270 if (do_cmd_pid2 > 0)
2271 (void)waitpid(do_cmd_pid2, NULL, 0);
2272 exit(i);
2273 }
2274