Bug Summary

File:src/usr.bin/ssh/scp/../scp.c
Warning:line 1927, column 7
Although the value stored to 'filename' is used in the enclosing expression, the value is never actually read from 'filename'

Annotated Source Code

Press '?' to see keyboard shortcuts

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