summaryrefslogtreecommitdiff
path: root/scp.c
diff options
context:
space:
mode:
authorschwarze@openbsd.org <schwarze@openbsd.org>2016-05-25 23:48:45 +0000
committerDarren Tucker <dtucker@zip.com.au>2016-06-06 11:27:38 +1000
commit0e059cdf5fd86297546c63fa8607c24059118832 (patch)
tree830942b6fd6f34250a42f265c1c90b9a398a6ab4 /scp.c
parent8c02e3639acefe1e447e293dbe23a0917abd3734 (diff)
upstream commit
To prevent screwing up terminal settings when printing to the terminal, for ASCII and UTF-8, escape bytes not forming characters and bytes forming non-printable characters with vis(3) VIS_OCTAL. For other character sets, abort printing of the current string in these cases. In particular, * let scp(1) respect the local user's LC_CTYPE locale(1); * sanitize data received from the remote host; * sanitize filenames, usernames, and similar data even locally; * take character display widths into account for the progressmeter. This is believed to be sufficient to keep the local terminal safe on OpenBSD, but bad things can still happen on other systems with state-dependent locales because many places in the code print unencoded ASCII characters into the output stream. Using feedback from djm@ and martijn@, various aspects discussed with many others. deraadt@ says it should go in now, i probably already hesitated too long Upstream-ID: e66afbc94ee396ddcaffd433b9a3b80f387647e0
Diffstat (limited to 'scp.c')
-rw-r--r--scp.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/scp.c b/scp.c
index 3f0d75090..43ca3fa09 100644
--- a/scp.c
+++ b/scp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: scp.c,v 1.185 2016/03/02 22:43:52 dtucker Exp $ */ 1/* $OpenBSD: scp.c,v 1.186 2016/05/25 23:48:45 schwarze Exp $ */
2/* 2/*
3 * scp - secure remote copy. This is basically patched BSD rcp which 3 * scp - secure remote copy. This is basically patched BSD rcp which
4 * uses ssh to do the data transfer (instead of using rcmd). 4 * uses ssh to do the data transfer (instead of using rcmd).
@@ -96,6 +96,7 @@
96#include <errno.h> 96#include <errno.h>
97#include <fcntl.h> 97#include <fcntl.h>
98#include <limits.h> 98#include <limits.h>
99#include <locale.h>
99#include <pwd.h> 100#include <pwd.h>
100#include <signal.h> 101#include <signal.h>
101#include <stdarg.h> 102#include <stdarg.h>
@@ -114,6 +115,7 @@
114#include "log.h" 115#include "log.h"
115#include "misc.h" 116#include "misc.h"
116#include "progressmeter.h" 117#include "progressmeter.h"
118#include "utf8.h"
117 119
118extern char *__progname; 120extern char *__progname;
119 121
@@ -191,7 +193,7 @@ do_local_cmd(arglist *a)
191 if (verbose_mode) { 193 if (verbose_mode) {
192 fprintf(stderr, "Executing:"); 194 fprintf(stderr, "Executing:");
193 for (i = 0; i < a->num; i++) 195 for (i = 0; i < a->num; i++)
194 fprintf(stderr, " %s", a->list[i]); 196 fmprintf(stderr, " %s", a->list[i]);
195 fprintf(stderr, "\n"); 197 fprintf(stderr, "\n");
196 } 198 }
197 if ((pid = fork()) == -1) 199 if ((pid = fork()) == -1)
@@ -232,7 +234,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
232 int pin[2], pout[2], reserved[2]; 234 int pin[2], pout[2], reserved[2];
233 235
234 if (verbose_mode) 236 if (verbose_mode)
235 fprintf(stderr, 237 fmprintf(stderr,
236 "Executing: program %s host %s, user %s, command %s\n", 238 "Executing: program %s host %s, user %s, command %s\n",
237 ssh_program, host, 239 ssh_program, host,
238 remuser ? remuser : "(unspecified)", cmd); 240 remuser ? remuser : "(unspecified)", cmd);
@@ -307,7 +309,7 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
307 int status; 309 int status;
308 310
309 if (verbose_mode) 311 if (verbose_mode)
310 fprintf(stderr, 312 fmprintf(stderr,
311 "Executing: 2nd program %s host %s, user %s, command %s\n", 313 "Executing: 2nd program %s host %s, user %s, command %s\n",
312 ssh_program, host, 314 ssh_program, host,
313 remuser ? remuser : "(unspecified)", cmd); 315 remuser ? remuser : "(unspecified)", cmd);
@@ -378,6 +380,8 @@ main(int argc, char **argv)
378 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 380 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
379 sanitise_stdfd(); 381 sanitise_stdfd();
380 382
383 setlocale(LC_CTYPE, "");
384
381 /* Copy argv, because we modify it */ 385 /* Copy argv, because we modify it */
382 newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv)); 386 newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv));
383 for (n = 0; n < argc; n++) 387 for (n = 0; n < argc; n++)
@@ -810,9 +814,8 @@ syserr: run_err("%s: %s", name, strerror(errno));
810 snprintf(buf, sizeof buf, "C%04o %lld %s\n", 814 snprintf(buf, sizeof buf, "C%04o %lld %s\n",
811 (u_int) (stb.st_mode & FILEMODEMASK), 815 (u_int) (stb.st_mode & FILEMODEMASK),
812 (long long)stb.st_size, last); 816 (long long)stb.st_size, last);
813 if (verbose_mode) { 817 if (verbose_mode)
814 fprintf(stderr, "Sending file modes: %s", buf); 818 fmprintf(stderr, "Sending file modes: %s", buf);
815 }
816 (void) atomicio(vwrite, remout, buf, strlen(buf)); 819 (void) atomicio(vwrite, remout, buf, strlen(buf));
817 if (response() < 0) 820 if (response() < 0)
818 goto next; 821 goto next;
@@ -889,7 +892,7 @@ rsource(char *name, struct stat *statp)
889 (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", 892 (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
890 (u_int) (statp->st_mode & FILEMODEMASK), 0, last); 893 (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
891 if (verbose_mode) 894 if (verbose_mode)
892 fprintf(stderr, "Entering directory: %s", path); 895 fmprintf(stderr, "Entering directory: %s", path);
893 (void) atomicio(vwrite, remout, path, strlen(path)); 896 (void) atomicio(vwrite, remout, path, strlen(path));
894 if (response() < 0) { 897 if (response() < 0) {
895 closedir(dirp); 898 closedir(dirp);
@@ -929,7 +932,7 @@ sink(int argc, char **argv)
929 off_t size, statbytes; 932 off_t size, statbytes;
930 unsigned long long ull; 933 unsigned long long ull;
931 int setimes, targisdir, wrerrno = 0; 934 int setimes, targisdir, wrerrno = 0;
932 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; 935 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
933 struct timeval tv[2]; 936 struct timeval tv[2];
934 937
935#define atime tv[0] 938#define atime tv[0]
@@ -964,12 +967,15 @@ sink(int argc, char **argv)
964 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); 967 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
965 *cp = 0; 968 *cp = 0;
966 if (verbose_mode) 969 if (verbose_mode)
967 fprintf(stderr, "Sink: %s", buf); 970 fmprintf(stderr, "Sink: %s", buf);
968 971
969 if (buf[0] == '\01' || buf[0] == '\02') { 972 if (buf[0] == '\01' || buf[0] == '\02') {
970 if (iamremote == 0) 973 if (iamremote == 0) {
974 (void) snmprintf(visbuf, sizeof(visbuf),
975 NULL, "%s", buf + 1);
971 (void) atomicio(vwrite, STDERR_FILENO, 976 (void) atomicio(vwrite, STDERR_FILENO,
972 buf + 1, strlen(buf + 1)); 977 visbuf, strlen(visbuf));
978 }
973 if (buf[0] == '\02') 979 if (buf[0] == '\02')
974 exit(1); 980 exit(1);
975 ++errs; 981 ++errs;
@@ -1212,7 +1218,7 @@ screwup:
1212int 1218int
1213response(void) 1219response(void)
1214{ 1220{
1215 char ch, *cp, resp, rbuf[2048]; 1221 char ch, *cp, resp, rbuf[2048], visbuf[2048];
1216 1222
1217 if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) 1223 if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
1218 lostconn(0); 1224 lostconn(0);
@@ -1232,8 +1238,13 @@ response(void)
1232 *cp++ = ch; 1238 *cp++ = ch;
1233 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); 1239 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
1234 1240
1235 if (!iamremote) 1241 if (!iamremote) {
1236 (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf); 1242 cp[-1] = '\0';
1243 (void) snmprintf(visbuf, sizeof(visbuf),
1244 NULL, "%s\n", rbuf);
1245 (void) atomicio(vwrite, STDERR_FILENO,
1246 visbuf, strlen(visbuf));
1247 }
1237 ++errs; 1248 ++errs;
1238 if (resp == 1) 1249 if (resp == 1)
1239 return (-1); 1250 return (-1);
@@ -1271,7 +1282,7 @@ run_err(const char *fmt,...)
1271 1282
1272 if (!iamremote) { 1283 if (!iamremote) {
1273 va_start(ap, fmt); 1284 va_start(ap, fmt);
1274 vfprintf(stderr, fmt, ap); 1285 vfmprintf(stderr, fmt, ap);
1275 va_end(ap); 1286 va_end(ap);
1276 fprintf(stderr, "\n"); 1287 fprintf(stderr, "\n");
1277 } 1288 }
@@ -1317,7 +1328,7 @@ okname(char *cp0)
1317 } while (*++cp); 1328 } while (*++cp);
1318 return (1); 1329 return (1);
1319 1330
1320bad: fprintf(stderr, "%s: invalid user name\n", cp0); 1331bad: fmprintf(stderr, "%s: invalid user name\n", cp0);
1321 return (0); 1332 return (0);
1322} 1333}
1323 1334