diff options
author | djm@openbsd.org <djm@openbsd.org> | 2022-05-09 00:32:36 +0200 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2022-05-09 00:33:59 +0200 |
commit | deb506d00da8d11fb04c1e7b9b1e1cc379c1705c (patch) | |
tree | 4b6347cbbba0a66e306ff64ddba562beb0fe56ea /sftp.c | |
parent | Also retest OpenBSD upstream on .yml changes. (diff) | |
download | openssh-deb506d00da8d11fb04c1e7b9b1e1cc379c1705c.tar.xz openssh-deb506d00da8d11fb04c1e7b9b1e1cc379c1705c.zip |
upstream: When performing operations that glob(3) a remote path, ensure
that the implicit working directory used to construct that path escapes
glob(3) characters.
This prevents glob characters from being processed in places they
shouldn't, e.g. "cd /tmp/a*/", "get *.txt" should have the get operation
treat the path "/tmp/a*" literally and not attempt to expand it.
Reported by Lusia Kundel; ok markus@
OpenBSD-Commit-ID: 4f647f58482cbad3d58b1eab7f6a1691433deeef
Diffstat (limited to 'sftp.c')
-rw-r--r-- | sftp.c | 49 |
1 files changed, 38 insertions, 11 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.214 2022/03/31 03:07:03 djm Exp $ */ +/* $OpenBSD: sftp.c,v 1.215 2022/05/08 22:32:36 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> * @@ -601,18 +601,45 @@ parse_no_flags(const char *cmd, char **argv, int argc) return optind; } +static char * +escape_glob(const char *s) +{ + size_t i, o, len; + char *ret; + + len = strlen(s); + ret = xcalloc(2, len + 1); + for (i = o = 0; i < len; i++) { + if (strchr("[]?*\\", s[i]) != NULL) + ret[o++] = '\\'; + ret[o++] = s[i]; + } + ret[o++] = '\0'; + return ret; +} + +static char * +make_absolute_pwd_glob(const char *p, const char *pwd) +{ + char *ret, *escpwd; + + escpwd = escape_glob(pwd); + if (p == NULL) + return escpwd; + ret = make_absolute(xstrdup(p), escpwd); + free(escpwd); + return ret; +} + static int process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, int pflag, int rflag, int resume, int fflag) { - char *abs_src = NULL; - char *abs_dst = NULL; + char *filename, *abs_src = NULL, *abs_dst = NULL, *tmp = NULL; glob_t g; - char *filename, *tmp=NULL; int i, r, err = 0; - abs_src = xstrdup(src); - abs_src = make_absolute(abs_src, pwd); + abs_src = make_absolute_pwd_glob(src, pwd); memset(&g, 0, sizeof(g)); debug3("Looking up %s", abs_src); @@ -1565,7 +1592,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2); break; case I_RM: - path1 = make_absolute(path1, *pwd); + path1 = make_absolute_pwd_glob(path1, *pwd); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!quiet) @@ -1626,7 +1653,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, if (!path_absolute(path1)) tmp = *pwd; - path1 = make_absolute(path1, *pwd); + path1 = make_absolute_pwd_glob(path1, *pwd); err = do_globbed_ls(conn, path1, tmp, lflag); break; case I_DF: @@ -1666,7 +1693,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, printf("Local umask: %03lo\n", n_arg); break; case I_CHMOD: - path1 = make_absolute(path1, *pwd); + path1 = make_absolute_pwd_glob(path1, *pwd); attrib_clear(&a); a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = n_arg; @@ -1683,7 +1710,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, break; case I_CHOWN: case I_CHGRP: - path1 = make_absolute(path1, *pwd); + path1 = make_absolute_pwd_glob(path1, *pwd); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); for (i = 0; g.gl_pathv[i] && !interrupted; i++) { if (!(aa = (hflag ? do_lstat : do_stat)(conn, @@ -1958,7 +1985,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, memset(&g, 0, sizeof(g)); if (remote != LOCAL) { - tmp = make_absolute(tmp, remote_path); + tmp = make_absolute_pwd_glob(tmp, remote_path); remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); } else glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); |