summaryrefslogtreecommitdiff
path: root/sftp.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2011-01-24 12:43:25 +0000
committerColin Watson <cjwatson@debian.org>2011-01-24 12:43:25 +0000
commit626f1d986ff72aa514da63e34744e1de9cf21b9a (patch)
treed215a5280bc2e57251e4a9e08bfd3674ad824a94 /sftp.c
parent6ed622cb6fe8f71bbe0d998cdd12280410bfb420 (diff)
parent0970072c89b079b022538e3c366fbfa2c53fc821 (diff)
* New upstream release (http://www.openssh.org/txt/release-5.7):
- Implement Elliptic Curve Cryptography modes for key exchange (ECDH) and host/user keys (ECDSA) as specified by RFC5656. ECDH and ECDSA offer better performance than plain DH and DSA at the same equivalent symmetric key length, as well as much shorter keys. - sftp(1)/sftp-server(8): add a protocol extension to support a hard link operation. It is available through the "ln" command in the client. The old "ln" behaviour of creating a symlink is available using its "-s" option or through the preexisting "symlink" command. - scp(1): Add a new -3 option to scp: Copies between two remote hosts are transferred through the local host (closes: #508613). - ssh(1): "atomically" create the listening mux socket by binding it on a temporary name and then linking it into position after listen() has succeeded. This allows the mux clients to determine that the server socket is either ready or stale without races (closes: #454784). Stale server sockets are now automatically removed (closes: #523250). - ssh(1): install a SIGCHLD handler to reap expired child process (closes: #594687). - ssh(1)/ssh-agent(1): honour $TMPDIR for client xauth and ssh-agent temporary directories (closes: #357469, although only if you arrange for ssh-agent to actually see $TMPDIR since the setgid bit will cause it to be stripped off).
Diffstat (limited to 'sftp.c')
-rw-r--r--sftp.c141
1 files changed, 82 insertions, 59 deletions
diff --git a/sftp.c b/sftp.c
index 229f12987..ab667f5a5 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.c,v 1.125 2010/06/18 00:58:39 djm Exp $ */ 1/* $OpenBSD: sftp.c,v 1.132 2010/12/04 00:18:01 djm 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 *
@@ -132,6 +132,7 @@ extern char *__progname;
132#define I_GET 5 132#define I_GET 5
133#define I_HELP 6 133#define I_HELP 6
134#define I_LCHDIR 7 134#define I_LCHDIR 7
135#define I_LINK 25
135#define I_LLS 8 136#define I_LLS 8
136#define I_LMKDIR 9 137#define I_LMKDIR 9
137#define I_LPWD 10 138#define I_LPWD 10
@@ -176,7 +177,7 @@ static const struct CMD cmds[] = {
176 { "lchdir", I_LCHDIR, LOCAL }, 177 { "lchdir", I_LCHDIR, LOCAL },
177 { "lls", I_LLS, LOCAL }, 178 { "lls", I_LLS, LOCAL },
178 { "lmkdir", I_LMKDIR, LOCAL }, 179 { "lmkdir", I_LMKDIR, LOCAL },
179 { "ln", I_SYMLINK, REMOTE }, 180 { "ln", I_LINK, REMOTE },
180 { "lpwd", I_LPWD, LOCAL }, 181 { "lpwd", I_LPWD, LOCAL },
181 { "ls", I_LS, REMOTE }, 182 { "ls", I_LS, REMOTE },
182 { "lumask", I_LUMASK, NOARGS }, 183 { "lumask", I_LUMASK, NOARGS },
@@ -240,7 +241,7 @@ help(void)
240 "lcd path Change local directory to 'path'\n" 241 "lcd path Change local directory to 'path'\n"
241 "lls [ls-options [path]] Display local directory listing\n" 242 "lls [ls-options [path]] Display local directory listing\n"
242 "lmkdir path Create local directory\n" 243 "lmkdir path Create local directory\n"
243 "ln oldpath newpath Symlink remote file\n" 244 "ln [-s] oldpath newpath Link remote file (-s for symlink)\n"
244 "lpwd Print local working directory\n" 245 "lpwd Print local working directory\n"
245 "ls [-1afhlnrSt] [path] Display remote directory listing\n" 246 "ls [-1afhlnrSt] [path] Display remote directory listing\n"
246 "lumask umask Set local umask to 'umask'\n" 247 "lumask umask Set local umask to 'umask'\n"
@@ -269,7 +270,7 @@ local_do_shell(const char *args)
269 if (!*args) 270 if (!*args)
270 args = NULL; 271 args = NULL;
271 272
272 if ((shell = getenv("SHELL")) == NULL) 273 if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
273 shell = _PATH_BSHELL; 274 shell = _PATH_BSHELL;
274 275
275 if ((pid = fork()) == -1) 276 if ((pid = fork()) == -1)
@@ -377,6 +378,30 @@ parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
377} 378}
378 379
379static int 380static int
381parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
382{
383 extern int opterr, optind, optopt, optreset;
384 int ch;
385
386 optind = optreset = 1;
387 opterr = 0;
388
389 *sflag = 0;
390 while ((ch = getopt(argc, argv, "s")) != -1) {
391 switch (ch) {
392 case 's':
393 *sflag = 1;
394 break;
395 default:
396 error("%s: Invalid flag -%c", cmd, optopt);
397 return -1;
398 }
399 }
400
401 return optind;
402}
403
404static int
380parse_ls_flags(char **argv, int argc, int *lflag) 405parse_ls_flags(char **argv, int argc, int *lflag)
381{ 406{
382 extern int opterr, optind, optopt, optreset; 407 extern int opterr, optind, optopt, optreset;
@@ -758,18 +783,22 @@ static int
758do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, 783do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
759 int lflag) 784 int lflag)
760{ 785{
761 glob_t g;
762 u_int i, c = 1, colspace = 0, columns = 1;
763 Attrib *a = NULL; 786 Attrib *a = NULL;
787 char *fname, *lname;
788 glob_t g;
789 int err;
790 struct winsize ws;
791 u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
764 792
765 memset(&g, 0, sizeof(g)); 793 memset(&g, 0, sizeof(g));
766 794
767 if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE, 795 if (remote_glob(conn, path,
768 NULL, &g) || (g.gl_pathc && !g.gl_matchc)) { 796 GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT, NULL, &g) ||
797 (g.gl_pathc && !g.gl_matchc)) {
769 if (g.gl_pathc) 798 if (g.gl_pathc)
770 globfree(&g); 799 globfree(&g);
771 error("Can't ls: \"%s\" not found", path); 800 error("Can't ls: \"%s\" not found", path);
772 return (-1); 801 return -1;
773 } 802 }
774 803
775 if (interrupted) 804 if (interrupted)
@@ -779,59 +808,35 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
779 * If the glob returns a single match and it is a directory, 808 * If the glob returns a single match and it is a directory,
780 * then just list its contents. 809 * then just list its contents.
781 */ 810 */
782 if (g.gl_matchc == 1) { 811 if (g.gl_matchc == 1 && g.gl_statv[0] != NULL &&
783 if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) { 812 S_ISDIR(g.gl_statv[0]->st_mode)) {
784 globfree(&g); 813 err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
785 return (-1); 814 globfree(&g);
786 } 815 return err;
787 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
788 S_ISDIR(a->perm)) {
789 int err;
790
791 err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
792 globfree(&g);
793 return (err);
794 }
795 } 816 }
796 817
797 if (!(lflag & LS_SHORT_VIEW)) { 818 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
798 u_int m = 0, width = 80; 819 width = ws.ws_col;
799 struct winsize ws;
800 820
821 if (!(lflag & LS_SHORT_VIEW)) {
801 /* Count entries for sort and find longest filename */ 822 /* Count entries for sort and find longest filename */
802 for (i = 0; g.gl_pathv[i]; i++) 823 for (i = 0; g.gl_pathv[i]; i++)
803 m = MAX(m, strlen(g.gl_pathv[i])); 824 m = MAX(m, strlen(g.gl_pathv[i]));
804 825
805 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
806 width = ws.ws_col;
807
808 columns = width / (m + 2); 826 columns = width / (m + 2);
809 columns = MAX(columns, 1); 827 columns = MAX(columns, 1);
810 colspace = width / columns; 828 colspace = width / columns;
811 } 829 }
812 830
813 for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) { 831 for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) {
814 char *fname;
815
816 fname = path_strip(g.gl_pathv[i], strip_path); 832 fname = path_strip(g.gl_pathv[i], strip_path);
817
818 if (lflag & LS_LONG_VIEW) { 833 if (lflag & LS_LONG_VIEW) {
819 char *lname; 834 if (g.gl_statv[i] == NULL) {
820 struct stat sb; 835 error("no stat information for %s", fname);
821 836 continue;
822 /* 837 }
823 * XXX: this is slow - 1 roundtrip per path 838 lname = ls_file(fname, g.gl_statv[i], 1,
824 * A solution to this is to fork glob() and 839 (lflag & LS_SI_UNITS));
825 * build a sftp specific version which keeps the
826 * attribs (which currently get thrown away)
827 * that the server returns as well as the filenames.
828 */
829 memset(&sb, 0, sizeof(sb));
830 if (a == NULL)
831 a = do_lstat(conn, g.gl_pathv[i], 1);
832 if (a != NULL)
833 attrib_to_stat(a, &sb);
834 lname = ls_file(fname, &sb, 1, (lflag & LS_SI_UNITS));
835 printf("%s\n", lname); 840 printf("%s\n", lname);
836 xfree(lname); 841 xfree(lname);
837 } else { 842 } else {
@@ -852,7 +857,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
852 if (g.gl_pathc) 857 if (g.gl_pathc)
853 globfree(&g); 858 globfree(&g);
854 859
855 return (0); 860 return 0;
856} 861}
857 862
858static int 863static int
@@ -1108,7 +1113,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1108 1113
1109static int 1114static int
1110parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, 1115parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
1111 int *hflag, unsigned long *n_arg, char **path1, char **path2) 1116 int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2)
1112{ 1117{
1113 const char *cmd, *cp = *cpp; 1118 const char *cmd, *cp = *cpp;
1114 char *cp2, **argv; 1119 char *cp2, **argv;
@@ -1158,7 +1163,8 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
1158 switch (cmdnum) { 1163 switch (cmdnum) {
1159 case I_GET: 1164 case I_GET:
1160 case I_PUT: 1165 case I_PUT:
1161 if ((optidx = parse_getput_flags(cmd, argv, argc, pflag, rflag)) == -1) 1166 if ((optidx = parse_getput_flags(cmd, argv, argc,
1167 pflag, rflag)) == -1)
1162 return -1; 1168 return -1;
1163 /* Get first pathname (mandatory) */ 1169 /* Get first pathname (mandatory) */
1164 if (argc - optidx < 1) { 1170 if (argc - optidx < 1) {
@@ -1174,8 +1180,11 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
1174 undo_glob_escape(*path2); 1180 undo_glob_escape(*path2);
1175 } 1181 }
1176 break; 1182 break;
1177 case I_RENAME: 1183 case I_LINK:
1184 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
1185 return -1;
1178 case I_SYMLINK: 1186 case I_SYMLINK:
1187 case I_RENAME:
1179 if (argc - optidx < 2) { 1188 if (argc - optidx < 2) {
1180 error("You must specify two paths after a %s " 1189 error("You must specify two paths after a %s "
1181 "command.", cmd); 1190 "command.", cmd);
@@ -1278,7 +1287,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1278 int err_abort) 1287 int err_abort)
1279{ 1288{
1280 char *path1, *path2, *tmp; 1289 char *path1, *path2, *tmp;
1281 int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i; 1290 int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
1291 int cmdnum, i;
1282 unsigned long n_arg = 0; 1292 unsigned long n_arg = 0;
1283 Attrib a, *aa; 1293 Attrib a, *aa;
1284 char path_buf[MAXPATHLEN]; 1294 char path_buf[MAXPATHLEN];
@@ -1286,8 +1296,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1286 glob_t g; 1296 glob_t g;
1287 1297
1288 path1 = path2 = NULL; 1298 path1 = path2 = NULL;
1289 cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, &n_arg, 1299 cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag,
1290 &path1, &path2); 1300 &sflag, &n_arg, &path1, &path2);
1291 1301
1292 if (iflag != 0) 1302 if (iflag != 0)
1293 err_abort = 0; 1303 err_abort = 0;
@@ -1315,8 +1325,11 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1315 err = do_rename(conn, path1, path2); 1325 err = do_rename(conn, path1, path2);
1316 break; 1326 break;
1317 case I_SYMLINK: 1327 case I_SYMLINK:
1328 sflag = 1;
1329 case I_LINK:
1330 path1 = make_absolute(path1, *pwd);
1318 path2 = make_absolute(path2, *pwd); 1331 path2 = make_absolute(path2, *pwd);
1319 err = do_symlink(conn, path1, path2); 1332 err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
1320 break; 1333 break;
1321 case I_RM: 1334 case I_RM:
1322 path1 = make_absolute(path1, *pwd); 1335 path1 = make_absolute(path1, *pwd);
@@ -1745,6 +1758,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1745 case '"': 1758 case '"':
1746 case '\\': 1759 case '\\':
1747 case '\t': 1760 case '\t':
1761 case '[':
1748 case ' ': 1762 case ' ':
1749 if (quote == '\0' || tmp2[i] == quote) { 1763 if (quote == '\0' || tmp2[i] == quote) {
1750 if (el_insertstr(el, ins) == -1) 1764 if (el_insertstr(el, ins) == -1)
@@ -1874,7 +1888,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
1874 1888
1875 /* Tab Completion */ 1889 /* Tab Completion */
1876 el_set(el, EL_ADDFN, "ftp-complete", 1890 el_set(el, EL_ADDFN, "ftp-complete",
1877 "Context senstive argument completion", complete); 1891 "Context sensitive argument completion", complete);
1878 complete_ctx.conn = conn; 1892 complete_ctx.conn = conn;
1879 complete_ctx.remote_pathp = &remote_path; 1893 complete_ctx.remote_pathp = &remote_path;
1880 el_set(el, EL_CLIENTDATA, (void*)&complete_ctx); 1894 el_set(el, EL_CLIENTDATA, (void*)&complete_ctx);
@@ -2054,7 +2068,7 @@ usage(void)
2054 fprintf(stderr, 2068 fprintf(stderr,
2055 "usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" 2069 "usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
2056 " [-D sftp_server_path] [-F ssh_config] " 2070 " [-D sftp_server_path] [-F ssh_config] "
2057 "[-i identity_file]\n" 2071 "[-i identity_file] [-l limit]\n"
2058 " [-o ssh_option] [-P port] [-R num_requests] " 2072 " [-o ssh_option] [-P port] [-R num_requests] "
2059 "[-S program]\n" 2073 "[-S program]\n"
2060 " [-s subsystem | sftp_server] host\n" 2074 " [-s subsystem | sftp_server] host\n"
@@ -2073,6 +2087,7 @@ main(int argc, char **argv)
2073 int debug_level = 0, sshver = 2; 2087 int debug_level = 0, sshver = 2;
2074 char *file1 = NULL, *sftp_server = NULL; 2088 char *file1 = NULL, *sftp_server = NULL;
2075 char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; 2089 char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
2090 const char *errstr;
2076 LogLevel ll = SYSLOG_LEVEL_INFO; 2091 LogLevel ll = SYSLOG_LEVEL_INFO;
2077 arglist args; 2092 arglist args;
2078 extern int optind; 2093 extern int optind;
@@ -2080,6 +2095,7 @@ main(int argc, char **argv)
2080 struct sftp_conn *conn; 2095 struct sftp_conn *conn;
2081 size_t copy_buffer_len = DEFAULT_COPY_BUFLEN; 2096 size_t copy_buffer_len = DEFAULT_COPY_BUFLEN;
2082 size_t num_requests = DEFAULT_NUM_REQUESTS; 2097 size_t num_requests = DEFAULT_NUM_REQUESTS;
2098 long long limit_kbps = 0;
2083 2099
2084 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 2100 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2085 sanitise_stdfd(); 2101 sanitise_stdfd();
@@ -2097,7 +2113,7 @@ main(int argc, char **argv)
2097 infile = stdin; 2113 infile = stdin;
2098 2114
2099 while ((ch = getopt(argc, argv, 2115 while ((ch = getopt(argc, argv,
2100 "1246hpqrvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) { 2116 "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
2101 switch (ch) { 2117 switch (ch) {
2102 /* Passed through to ssh(1) */ 2118 /* Passed through to ssh(1) */
2103 case '4': 2119 case '4':
@@ -2158,6 +2174,13 @@ main(int argc, char **argv)
2158 case 'D': 2174 case 'D':
2159 sftp_direct = optarg; 2175 sftp_direct = optarg;
2160 break; 2176 break;
2177 case 'l':
2178 limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
2179 &errstr);
2180 if (errstr != NULL)
2181 usage();
2182 limit_kbps *= 1024; /* kbps */
2183 break;
2161 case 'r': 2184 case 'r':
2162 global_rflag = 1; 2185 global_rflag = 1;
2163 break; 2186 break;
@@ -2235,7 +2258,7 @@ main(int argc, char **argv)
2235 } 2258 }
2236 freeargs(&args); 2259 freeargs(&args);
2237 2260
2238 conn = do_init(in, out, copy_buffer_len, num_requests); 2261 conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps);
2239 if (conn == NULL) 2262 if (conn == NULL)
2240 fatal("Couldn't initialise connection to server"); 2263 fatal("Couldn't initialise connection to server");
2241 2264