Bug Summary

File:src/usr.bin/ssh/scp/../scp.c
Warning:line 1351, column 5
Value stored to 'fd' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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