summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/sftp.c
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2014-02-27 17:29:02 +0000
committerdes <des@FreeBSD.org>2014-02-27 17:29:02 +0000
commit255d8413daf4c3747aeb37e6a71bf2771beed29d (patch)
tree28087af50eaf299f287c7fe4b7050c317771c89e /crypto/openssh/sftp.c
parentea1005cca47f4d3aace134a0acd6809943e46acc (diff)
downloadFreeBSD-src-255d8413daf4c3747aeb37e6a71bf2771beed29d.zip
FreeBSD-src-255d8413daf4c3747aeb37e6a71bf2771beed29d.tar.gz
MFH (r261320): upgrade openssh to 6.5p1
MFH (r261340): enable sandboxing by default
Diffstat (limited to 'crypto/openssh/sftp.c')
-rw-r--r--crypto/openssh/sftp.c242
1 files changed, 162 insertions, 80 deletions
diff --git a/crypto/openssh/sftp.c b/crypto/openssh/sftp.c
index d6ac4cb..c6c88ef 100644
--- a/crypto/openssh/sftp.c
+++ b/crypto/openssh/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.148 2013/07/25 00:56:52 djm Exp $ */
+/* $OpenBSD: sftp.c,v 1.158 2013/11/20 20:54:10 deraadt Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@@ -95,6 +95,9 @@ int global_aflag = 0;
/* When this option is set, the file transfers will always preserve times */
int global_pflag = 0;
+/* When this option is set, transfers will have fsync() called on each file */
+int global_fflag = 0;
+
/* SIGINT received during command processing */
volatile sig_atomic_t interrupted = 0;
@@ -130,32 +133,34 @@ extern char *__progname;
#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT)
/* Commands for interactive mode */
-#define I_CHDIR 1
-#define I_CHGRP 2
-#define I_CHMOD 3
-#define I_CHOWN 4
-#define I_DF 24
-#define I_GET 5
-#define I_HELP 6
-#define I_LCHDIR 7
-#define I_LINK 25
-#define I_LLS 8
-#define I_LMKDIR 9
-#define I_LPWD 10
-#define I_LS 11
-#define I_LUMASK 12
-#define I_MKDIR 13
-#define I_PUT 14
-#define I_PWD 15
-#define I_QUIT 16
-#define I_RENAME 17
-#define I_RM 18
-#define I_RMDIR 19
-#define I_SHELL 20
-#define I_SYMLINK 21
-#define I_VERSION 22
-#define I_PROGRESS 23
-#define I_REGET 26
+enum sftp_command {
+ I_CHDIR = 1,
+ I_CHGRP,
+ I_CHMOD,
+ I_CHOWN,
+ I_DF,
+ I_GET,
+ I_HELP,
+ I_LCHDIR,
+ I_LINK,
+ I_LLS,
+ I_LMKDIR,
+ I_LPWD,
+ I_LS,
+ I_LUMASK,
+ I_MKDIR,
+ I_PUT,
+ I_PWD,
+ I_QUIT,
+ I_RENAME,
+ I_RM,
+ I_RMDIR,
+ I_SHELL,
+ I_SYMLINK,
+ I_VERSION,
+ I_PROGRESS,
+ I_REGET,
+};
struct CMD {
const char *c;
@@ -358,7 +363,7 @@ make_absolute(char *p, char *pwd)
static int
parse_getput_flags(const char *cmd, char **argv, int argc,
- int *aflag, int *pflag, int *rflag)
+ int *aflag, int *fflag, int *pflag, int *rflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
@@ -366,12 +371,15 @@ parse_getput_flags(const char *cmd, char **argv, int argc,
optind = optreset = 1;
opterr = 0;
- *aflag = *rflag = *pflag = 0;
- while ((ch = getopt(argc, argv, "aPpRr")) != -1) {
+ *aflag = *fflag = *rflag = *pflag = 0;
+ while ((ch = getopt(argc, argv, "afPpRr")) != -1) {
switch (ch) {
case 'a':
*aflag = 1;
break;
+ case 'f':
+ *fflag = 1;
+ break;
case 'p':
case 'P':
*pflag = 1;
@@ -414,6 +422,30 @@ parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
}
static int
+parse_rename_flags(const char *cmd, char **argv, int argc, int *lflag)
+{
+ extern int opterr, optind, optopt, optreset;
+ int ch;
+
+ optind = optreset = 1;
+ opterr = 0;
+
+ *lflag = 0;
+ while ((ch = getopt(argc, argv, "l")) != -1) {
+ switch (ch) {
+ case 'l':
+ *lflag = 1;
+ break;
+ default:
+ error("%s: Invalid flag -%c", cmd, optopt);
+ return -1;
+ }
+ }
+
+ return optind;
+}
+
+static int
parse_ls_flags(char **argv, int argc, int *lflag)
{
extern int opterr, optind, optopt, optreset;
@@ -494,6 +526,26 @@ parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
}
static int
+parse_no_flags(const char *cmd, char **argv, int argc)
+{
+ extern int opterr, optind, optopt, optreset;
+ int ch;
+
+ optind = optreset = 1;
+ opterr = 0;
+
+ while ((ch = getopt(argc, argv, "")) != -1) {
+ switch (ch) {
+ default:
+ error("%s: Invalid flag -%c", cmd, optopt);
+ return -1;
+ }
+ }
+
+ return optind;
+}
+
+static int
is_dir(char *path)
{
struct stat sb;
@@ -529,7 +581,7 @@ pathname_is_dir(char *pathname)
static int
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
- int pflag, int rflag, int resume)
+ int pflag, int rflag, int resume, int fflag)
{
char *abs_src = NULL;
char *abs_dst = NULL;
@@ -588,11 +640,13 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
- pflag || global_pflag, 1, resume) == -1)
+ pflag || global_pflag, 1, resume,
+ fflag || global_fflag) == -1)
err = -1;
} else {
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
- pflag || global_pflag, resume) == -1)
+ pflag || global_pflag, resume,
+ fflag || global_fflag) == -1)
err = -1;
}
free(abs_dst);
@@ -607,7 +661,7 @@ out:
static int
process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
- int pflag, int rflag)
+ int pflag, int rflag, int fflag)
{
char *tmp_dst = NULL;
char *abs_dst = NULL;
@@ -648,7 +702,7 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
error("stat %s: %s", g.gl_pathv[i], strerror(errno));
continue;
}
-
+
tmp = xstrdup(g.gl_pathv[i]);
if ((filename = basename(tmp)) == NULL) {
error("basename %s: %s", tmp, strerror(errno));
@@ -674,11 +728,13 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
- pflag || global_pflag, 1) == -1)
+ pflag || global_pflag, 1,
+ fflag || global_fflag) == -1)
err = -1;
} else {
if (do_upload(conn, g.gl_pathv[i], abs_dst,
- pflag || global_pflag) == -1)
+ pflag || global_pflag,
+ fflag || global_fflag) == -1)
err = -1;
}
}
@@ -976,7 +1032,7 @@ undo_glob_escape(char *s)
*
* If "lastquote" is not NULL, the quoting character used for the last
* argument is placed in *lastquote ("\0", "'" or "\"").
- *
+ *
* If "terminated" is not NULL, *terminated will be set to 1 when the
* last argument's quote has been properly terminated or 0 otherwise.
* This parameter is only of use if "sloppy" is set.
@@ -1010,7 +1066,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
error("Too many arguments.");
return NULL;
}
- if (isspace(arg[i])) {
+ if (isspace((unsigned char)arg[i])) {
if (state == MA_UNQUOTED) {
/* Terminate current argument */
argvs[j++] = '\0';
@@ -1025,7 +1081,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
state = q;
if (lastquote != NULL)
*lastquote = arg[i];
- } else if (state == MA_UNQUOTED)
+ } else if (state == MA_UNQUOTED)
state = q;
else if (state == q)
state = MA_UNQUOTED;
@@ -1131,9 +1187,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
}
static int
-parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
- int *pflag, int *rflag, int *sflag, unsigned long *n_arg,
- char **path1, char **path2)
+parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
+ int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag,
+ unsigned long *n_arg, char **path1, char **path2)
{
const char *cmd, *cp = *cpp;
char *cp2, **argv;
@@ -1145,9 +1201,9 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
cp = cp + strspn(cp, WHITESPACE);
/* Check for leading '-' (disable error processing) */
- *iflag = 0;
+ *ignore_errors = 0;
if (*cp == '-') {
- *iflag = 1;
+ *ignore_errors = 1;
cp++;
cp = cp + strspn(cp, WHITESPACE);
}
@@ -1177,7 +1233,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
}
/* Get arguments and parse flags */
- *aflag = *lflag = *pflag = *rflag = *hflag = *n_arg = 0;
+ *aflag = *fflag = *hflag = *iflag = *lflag = *pflag = 0;
+ *rflag = *sflag = 0;
*path1 = *path2 = NULL;
optidx = 1;
switch (cmdnum) {
@@ -1185,7 +1242,7 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
case I_REGET:
case I_PUT:
if ((optidx = parse_getput_flags(cmd, argv, argc,
- aflag, pflag, rflag)) == -1)
+ aflag, fflag, pflag, rflag)) == -1)
return -1;
/* Get first pathname (mandatory) */
if (argc - optidx < 1) {
@@ -1209,8 +1266,15 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
case I_LINK:
if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
return -1;
- case I_SYMLINK:
+ goto parse_two_paths;
case I_RENAME:
+ if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1)
+ return -1;
+ goto parse_two_paths;
+ case I_SYMLINK:
+ if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
+ return -1;
+ parse_two_paths:
if (argc - optidx < 2) {
error("You must specify two paths after a %s "
"command.", cmd);
@@ -1228,6 +1292,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
case I_CHDIR:
case I_LCHDIR:
case I_LMKDIR:
+ if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
+ return -1;
/* Get pathname (mandatory) */
if (argc - optidx < 1) {
error("You must specify a path after a %s command.",
@@ -1269,6 +1335,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
base = 8;
case I_CHOWN:
case I_CHGRP:
+ if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
+ return -1;
/* Get numeric arg (mandatory) */
if (argc - optidx < 1)
goto need_num_arg;
@@ -1299,6 +1367,8 @@ parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
case I_HELP:
case I_VERSION:
case I_PROGRESS:
+ if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
+ return -1;
break;
default:
fatal("Command not implemented");
@@ -1313,8 +1383,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
int err_abort)
{
char *path1, *path2, *tmp;
- int aflag = 0, hflag = 0, iflag = 0, lflag = 0, pflag = 0;
- int rflag = 0, sflag = 0;
+ int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0;
+ int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
int cmdnum, i;
unsigned long n_arg = 0;
Attrib a, *aa;
@@ -1323,9 +1393,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
glob_t g;
path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &aflag, &hflag, &iflag, &lflag, &pflag,
- &rflag, &sflag, &n_arg, &path1, &path2);
- if (iflag != 0)
+ cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
+ &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2);
+ if (ignore_errors != 0)
err_abort = 0;
memset(&g, 0, sizeof(g));
@@ -1344,20 +1414,22 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
/* FALLTHROUGH */
case I_GET:
err = process_get(conn, path1, path2, *pwd, pflag,
- rflag, aflag);
+ rflag, aflag, fflag);
break;
case I_PUT:
- err = process_put(conn, path1, path2, *pwd, pflag, rflag);
+ err = process_put(conn, path1, path2, *pwd, pflag,
+ rflag, fflag);
break;
case I_RENAME:
path1 = make_absolute(path1, *pwd);
path2 = make_absolute(path2, *pwd);
- err = do_rename(conn, path1, path2);
+ err = do_rename(conn, path1, path2, lflag);
break;
case I_SYMLINK:
sflag = 1;
case I_LINK:
- path1 = make_absolute(path1, *pwd);
+ if (!sflag)
+ path1 = make_absolute(path1, *pwd);
path2 = make_absolute(path2, *pwd);
err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
break;
@@ -1568,7 +1640,7 @@ complete_display(char **list, u_int len)
char *tmp;
/* Count entries for sort and find longest */
- for (y = 0; list[y]; y++)
+ for (y = 0; list[y]; y++)
m = MAX(m, strlen(list[y]));
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
@@ -1613,8 +1685,8 @@ complete_ambiguous(const char *word, char **list, size_t count)
for (y = 1; list[y]; y++) {
u_int x;
- for (x = 0; x < matchlen; x++)
- if (list[0][x] != list[y][x])
+ for (x = 0; x < matchlen; x++)
+ if (list[0][x] != list[y][x])
break;
matchlen = x;
@@ -1626,7 +1698,7 @@ complete_ambiguous(const char *word, char **list, size_t count)
tmp[matchlen] = '\0';
return tmp;
}
- }
+ }
return xstrdup(word);
}
@@ -1646,12 +1718,12 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
if (cmd == NULL) {
for (y = 0; cmds[y].c; y++)
list[count++] = xstrdup(cmds[y].c);
-
+
list[count] = NULL;
complete_display(list, 0);
- for (y = 0; list[y] != NULL; y++)
- free(list[y]);
+ for (y = 0; list[y] != NULL; y++)
+ free(list[y]);
free(list);
return count;
}
@@ -1659,7 +1731,7 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
/* Prepare subset of commands that start with "cmd" */
cmdlen = strlen(cmd);
for (y = 0; cmds[y].c; y++) {
- if (!strncasecmp(cmd, cmds[y].c, cmdlen))
+ if (!strncasecmp(cmd, cmds[y].c, cmdlen))
list[count++] = xstrdup(cmds[y].c);
}
list[count] = NULL;
@@ -1674,8 +1746,8 @@ complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
if (count > 1)
complete_display(list, 0);
- for (y = 0; list[y]; y++)
- free(list[y]);
+ for (y = 0; list[y]; y++)
+ free(list[y]);
free(list);
if (tmp != NULL) {
@@ -1715,7 +1787,7 @@ complete_is_remote(char *cmd) {
return -1;
for (i = 0; cmds[i].c; i++) {
- if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c)))
+ if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c)))
return cmds[i].t;
}
@@ -1732,7 +1804,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs;
int clen;
const LineInfo *lf;
-
+
/* Glob from "file" location */
if (file == NULL)
tmp = xstrdup("*");
@@ -1746,9 +1818,9 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
if (remote != LOCAL) {
tmp = make_absolute(tmp, remote_path);
remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
- } else
+ } else
glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
-
+
/* Determine length of pwd so we can trim completion display */
for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) {
/* Terminate counting on first unescaped glob metacharacter */
@@ -1764,7 +1836,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
}
free(tmp);
- if (g.gl_matchc == 0)
+ if (g.gl_matchc == 0)
goto out;
if (g.gl_matchc > 1)
@@ -1797,7 +1869,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
if (tmplen > (filelen - cesc)) {
tmp2 = tmp + filelen - cesc;
- len = strlen(tmp2);
+ len = strlen(tmp2);
/* quote argument on way out */
for (i = 0; i < len; i += clen) {
if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
@@ -1853,7 +1925,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
static unsigned char
complete(EditLine *el, int ch)
{
- char **argv, *line, quote;
+ char **argv, *line, quote;
int argc, carg;
u_int cursor, len, terminated, ret = CC_ERROR;
const LineInfo *lf;
@@ -1892,7 +1964,7 @@ complete(EditLine *el, int ch)
} else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ') {
/* Handle the command parsing */
if (complete_cmd_parse(el, argv[0], argc == carg,
- quote, terminated) != 0)
+ quote, terminated) != 0)
ret = CC_REDISPLAY;
} else if (carg >= 1) {
/* Handle file parsing */
@@ -1905,11 +1977,11 @@ complete(EditLine *el, int ch)
if (remote != 0 &&
complete_match(el, complete_ctx->conn,
*complete_ctx->remote_pathp, filematch,
- remote, carg == argc, quote, terminated) != 0)
+ remote, carg == argc, quote, terminated) != 0)
ret = CC_REDISPLAY;
}
- free(line);
+ free(line);
return ret;
}
#endif /* USE_LIBEDIT */
@@ -1943,12 +2015,19 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
el_source(el, NULL);
/* Tab Completion */
- el_set(el, EL_ADDFN, "ftp-complete",
+ el_set(el, EL_ADDFN, "ftp-complete",
"Context sensitive argument completion", complete);
complete_ctx.conn = conn;
complete_ctx.remote_pathp = &remote_path;
el_set(el, EL_CLIENTDATA, (void*)&complete_ctx);
el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
+ /* enable ctrl-left-arrow and ctrl-right-arrow */
+ el_set(el, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
+ el_set(el, EL_BIND, "\\e[5C", "em-next-word", NULL);
+ el_set(el, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
+ el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
+ /* make ^w match ksh behaviour */
+ el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL);
}
#endif /* USE_LIBEDIT */
@@ -2117,7 +2196,7 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
+ "usage: %s [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
" [-D sftp_server_path] [-F ssh_config] "
"[-i identity_file] [-l limit]\n"
" [-o ssh_option] [-P port] [-R num_requests] "
@@ -2165,7 +2244,7 @@ main(int argc, char **argv)
infile = stdin;
while ((ch = getopt(argc, argv,
- "1246ahpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
+ "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
case '4':
@@ -2225,6 +2304,9 @@ main(int argc, char **argv)
quiet = batchmode = 1;
addargs(&args, "-obatchmode yes");
break;
+ case 'f':
+ global_fflag = 1;
+ break;
case 'p':
global_pflag = 1;
break;
OpenPOWER on IntegriCloud