summaryrefslogtreecommitdiff
path: root/sftp.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 /sftp.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 'sftp.c')
-rw-r--r--sftp.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/sftp.c b/sftp.c
index 3d2d13aaf..6a7048431 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.c,v 1.173 2016/04/08 08:19:17 djm Exp $ */ 1/* $OpenBSD: sftp.c,v 1.174 2016/05/25 23:48:45 schwarze Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -49,6 +49,7 @@ typedef void EditLine;
49#endif 49#endif
50#include <limits.h> 50#include <limits.h>
51#include <signal.h> 51#include <signal.h>
52#include <stdarg.h>
52#include <stdlib.h> 53#include <stdlib.h>
53#include <stdio.h> 54#include <stdio.h>
54#include <string.h> 55#include <string.h>
@@ -63,6 +64,7 @@ typedef void EditLine;
63#include "log.h" 64#include "log.h"
64#include "pathnames.h" 65#include "pathnames.h"
65#include "misc.h" 66#include "misc.h"
67#include "utf8.h"
66 68
67#include "sftp.h" 69#include "sftp.h"
68#include "ssherr.h" 70#include "ssherr.h"
@@ -644,9 +646,11 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
644 646
645 resume |= global_aflag; 647 resume |= global_aflag;
646 if (!quiet && resume) 648 if (!quiet && resume)
647 printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst); 649 mprintf("Resuming %s to %s\n",
650 g.gl_pathv[i], abs_dst);
648 else if (!quiet && !resume) 651 else if (!quiet && !resume)
649 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 652 mprintf("Fetching %s to %s\n",
653 g.gl_pathv[i], abs_dst);
650 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 654 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
651 if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 655 if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
652 pflag || global_pflag, 1, resume, 656 pflag || global_pflag, 1, resume,
@@ -735,10 +739,11 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
735 739
736 resume |= global_aflag; 740 resume |= global_aflag;
737 if (!quiet && resume) 741 if (!quiet && resume)
738 printf("Resuming upload of %s to %s\n", g.gl_pathv[i], 742 mprintf("Resuming upload of %s to %s\n",
739 abs_dst); 743 g.gl_pathv[i], abs_dst);
740 else if (!quiet && !resume) 744 else if (!quiet && !resume)
741 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); 745 mprintf("Uploading %s to %s\n",
746 g.gl_pathv[i], abs_dst);
742 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 747 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
743 if (upload_dir(conn, g.gl_pathv[i], abs_dst, 748 if (upload_dir(conn, g.gl_pathv[i], abs_dst,
744 pflag || global_pflag, 1, resume, 749 pflag || global_pflag, 1, resume,
@@ -839,12 +844,12 @@ do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
839 attrib_to_stat(&d[n]->a, &sb); 844 attrib_to_stat(&d[n]->a, &sb);
840 lname = ls_file(fname, &sb, 1, 845 lname = ls_file(fname, &sb, 1,
841 (lflag & LS_SI_UNITS)); 846 (lflag & LS_SI_UNITS));
842 printf("%s\n", lname); 847 mprintf("%s\n", lname);
843 free(lname); 848 free(lname);
844 } else 849 } else
845 printf("%s\n", d[n]->longname); 850 mprintf("%s\n", d[n]->longname);
846 } else { 851 } else {
847 printf("%-*s", colspace, fname); 852 mprintf("%-*s", colspace, fname);
848 if (c >= columns) { 853 if (c >= columns) {
849 printf("\n"); 854 printf("\n");
850 c = 1; 855 c = 1;
@@ -925,10 +930,10 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
925 } 930 }
926 lname = ls_file(fname, g.gl_statv[i], 1, 931 lname = ls_file(fname, g.gl_statv[i], 1,
927 (lflag & LS_SI_UNITS)); 932 (lflag & LS_SI_UNITS));
928 printf("%s\n", lname); 933 mprintf("%s\n", lname);
929 free(lname); 934 free(lname);
930 } else { 935 } else {
931 printf("%-*s", colspace, fname); 936 mprintf("%-*s", colspace, fname);
932 if (c >= columns) { 937 if (c >= columns) {
933 printf("\n"); 938 printf("\n");
934 c = 1; 939 c = 1;
@@ -1456,7 +1461,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1456 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 1461 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1457 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 1462 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1458 if (!quiet) 1463 if (!quiet)
1459 printf("Removing %s\n", g.gl_pathv[i]); 1464 mprintf("Removing %s\n", g.gl_pathv[i]);
1460 err = do_rm(conn, g.gl_pathv[i]); 1465 err = do_rm(conn, g.gl_pathv[i]);
1461 if (err != 0 && err_abort) 1466 if (err != 0 && err_abort)
1462 break; 1467 break;
@@ -1556,7 +1561,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1556 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 1561 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1557 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 1562 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1558 if (!quiet) 1563 if (!quiet)
1559 printf("Changing mode on %s\n", g.gl_pathv[i]); 1564 mprintf("Changing mode on %s\n",
1565 g.gl_pathv[i]);
1560 err = do_setstat(conn, g.gl_pathv[i], &a); 1566 err = do_setstat(conn, g.gl_pathv[i], &a);
1561 if (err != 0 && err_abort) 1567 if (err != 0 && err_abort)
1562 break; 1568 break;
@@ -1586,12 +1592,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1586 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; 1592 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
1587 if (cmdnum == I_CHOWN) { 1593 if (cmdnum == I_CHOWN) {
1588 if (!quiet) 1594 if (!quiet)
1589 printf("Changing owner on %s\n", 1595 mprintf("Changing owner on %s\n",
1590 g.gl_pathv[i]); 1596 g.gl_pathv[i]);
1591 aa->uid = n_arg; 1597 aa->uid = n_arg;
1592 } else { 1598 } else {
1593 if (!quiet) 1599 if (!quiet)
1594 printf("Changing group on %s\n", 1600 mprintf("Changing group on %s\n",
1595 g.gl_pathv[i]); 1601 g.gl_pathv[i]);
1596 aa->gid = n_arg; 1602 aa->gid = n_arg;
1597 } 1603 }
@@ -1601,7 +1607,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1601 } 1607 }
1602 break; 1608 break;
1603 case I_PWD: 1609 case I_PWD:
1604 printf("Remote working directory: %s\n", *pwd); 1610 mprintf("Remote working directory: %s\n", *pwd);
1605 break; 1611 break;
1606 case I_LPWD: 1612 case I_LPWD:
1607 if (!getcwd(path_buf, sizeof(path_buf))) { 1613 if (!getcwd(path_buf, sizeof(path_buf))) {
@@ -1609,7 +1615,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1609 err = -1; 1615 err = -1;
1610 break; 1616 break;
1611 } 1617 }
1612 printf("Local working directory: %s\n", path_buf); 1618 mprintf("Local working directory: %s\n", path_buf);
1613 break; 1619 break;
1614 case I_QUIT: 1620 case I_QUIT:
1615 /* Processed below */ 1621 /* Processed below */
@@ -1678,7 +1684,7 @@ complete_display(char **list, u_int len)
1678 for (y = 0; list[y]; y++) { 1684 for (y = 0; list[y]; y++) {
1679 llen = strlen(list[y]); 1685 llen = strlen(list[y]);
1680 tmp = llen > len ? list[y] + len : ""; 1686 tmp = llen > len ? list[y] + len : "";
1681 printf("%-*s", colspace, tmp); 1687 mprintf("%-*s", colspace, tmp);
1682 if (m >= columns) { 1688 if (m >= columns) {
1683 printf("\n"); 1689 printf("\n");
1684 m = 1; 1690 m = 1;
@@ -2062,7 +2068,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
2062 2068
2063 if (remote_is_dir(conn, dir) && file2 == NULL) { 2069 if (remote_is_dir(conn, dir) && file2 == NULL) {
2064 if (!quiet) 2070 if (!quiet)
2065 printf("Changing to: %s\n", dir); 2071 mprintf("Changing to: %s\n", dir);
2066 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); 2072 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
2067 if (parse_dispatch_command(conn, cmd, 2073 if (parse_dispatch_command(conn, cmd,
2068 &remote_path, 1) != 0) { 2074 &remote_path, 1) != 0) {
@@ -2106,7 +2112,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
2106 break; 2112 break;
2107 } 2113 }
2108 if (!interactive) { /* Echo command */ 2114 if (!interactive) { /* Echo command */
2109 printf("sftp> %s", cmd); 2115 mprintf("sftp> %s", cmd);
2110 if (strlen(cmd) > 0 && 2116 if (strlen(cmd) > 0 &&
2111 cmd[strlen(cmd) - 1] != '\n') 2117 cmd[strlen(cmd) - 1] != '\n')
2112 printf("\n"); 2118 printf("\n");