upstream: make scp in SFTP mode try to use relative paths as much
as possible. Previosuly, it would try to make relative and ~/-rooted paths absolute before requesting transfers. prompted by and much discussion deraadt@ ok markus@ OpenBSD-Commit-ID: 46639d382ea99546a4914b545fa7b00fa1be5566
This commit is contained in:
parent
2ab864010e
commit
2f7a3b51ce
97
scp.c
97
scp.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: scp.c,v 1.227 2021/08/09 23:47:44 djm Exp $ */
|
/* $OpenBSD: scp.c,v 1.228 2021/08/09 23:49:31 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* scp - secure remote copy. This is basically patched BSD rcp which
|
* scp - secure remote copy. This is basically patched BSD rcp which
|
||||||
* uses ssh to do the data transfer (instead of using rcmd).
|
* uses ssh to do the data transfer (instead of using rcmd).
|
||||||
|
@ -435,10 +435,10 @@ void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct);
|
||||||
void toremote(int, char *[], enum scp_mode_e, char *sftp_direct);
|
void toremote(int, char *[], enum scp_mode_e, char *sftp_direct);
|
||||||
void usage(void);
|
void usage(void);
|
||||||
|
|
||||||
void source_sftp(int, char *, char *, struct sftp_conn *, char **);
|
void source_sftp(int, char *, char *, struct sftp_conn *);
|
||||||
void sink_sftp(int, char *, const char *, struct sftp_conn *);
|
void sink_sftp(int, char *, const char *, struct sftp_conn *);
|
||||||
void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *,
|
void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *,
|
||||||
char *, char *, char **);
|
char *, char *);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
|
@ -982,7 +982,6 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
|
||||||
{
|
{
|
||||||
char *suser = NULL, *host = NULL, *src = NULL;
|
char *suser = NULL, *host = NULL, *src = NULL;
|
||||||
char *bp, *tuser, *thost, *targ;
|
char *bp, *tuser, *thost, *targ;
|
||||||
char *remote_path = NULL;
|
|
||||||
int sport = -1, tport = -1;
|
int sport = -1, tport = -1;
|
||||||
struct sftp_conn *conn = NULL, *conn2 = NULL;
|
struct sftp_conn *conn = NULL, *conn2 = NULL;
|
||||||
arglist alist;
|
arglist alist;
|
||||||
|
@ -1056,8 +1055,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
|
||||||
}
|
}
|
||||||
debug3_f("destination in %d out %d pid %ld",
|
debug3_f("destination in %d out %d pid %ld",
|
||||||
remin2, remout2, (long)do_cmd_pid2);
|
remin2, remout2, (long)do_cmd_pid2);
|
||||||
throughlocal_sftp(conn2, conn, src, targ,
|
throughlocal_sftp(conn2, conn, src, targ);
|
||||||
&remote_path);
|
|
||||||
(void) close(remin2);
|
(void) close(remin2);
|
||||||
(void) close(remout2);
|
(void) close(remout2);
|
||||||
remin2 = remout2 = -1;
|
remin2 = remout2 = -1;
|
||||||
|
@ -1142,8 +1140,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The protocol */
|
/* The protocol */
|
||||||
source_sftp(1, argv[i], targ, conn,
|
source_sftp(1, argv[i], targ, conn);
|
||||||
&remote_path);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* SCP */
|
/* SCP */
|
||||||
|
@ -1161,10 +1158,8 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (mode == MODE_SFTP) {
|
if (mode == MODE_SFTP)
|
||||||
free(remote_path);
|
|
||||||
free(conn);
|
free(conn);
|
||||||
}
|
|
||||||
free(tuser);
|
free(tuser);
|
||||||
free(thost);
|
free(thost);
|
||||||
free(targ);
|
free(targ);
|
||||||
|
@ -1253,46 +1248,30 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
|
||||||
free(src);
|
free(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Canonicalise a remote path, handling ~ by assuming cwd is the homedir */
|
/* Prepare remote path, handling ~ by assuming cwd is the homedir */
|
||||||
static char *
|
static char *
|
||||||
absolute_remote_path(struct sftp_conn *conn, const char *path,
|
prepare_remote_path(struct sftp_conn *conn, const char *path)
|
||||||
const char *remote_path)
|
|
||||||
{
|
{
|
||||||
char *ret;
|
|
||||||
|
|
||||||
if (can_expand_path(conn))
|
|
||||||
return do_expand_path(conn, path);
|
|
||||||
|
|
||||||
/* Handle ~ prefixed paths */
|
/* Handle ~ prefixed paths */
|
||||||
if (*path != '~')
|
if (*path != '~')
|
||||||
ret = xstrdup(path);
|
return xstrdup(path);
|
||||||
else {
|
if (*path == '\0' || strcmp(path, "~") == 0)
|
||||||
if (strcmp(path, "~") == 0)
|
return xstrdup(".");
|
||||||
ret = xstrdup("");
|
if (strncmp(path, "~/", 2) == 0)
|
||||||
else if (strncmp(path, "~/", 2) == 0)
|
return xstrdup(path + 2);
|
||||||
ret = xstrdup(path + 2);
|
if (can_expand_path(conn))
|
||||||
else {
|
return do_expand_path(conn, path);
|
||||||
/* XXX could be supported with protocol extension */
|
/* No protocol extension */
|
||||||
error("~user paths are not currently supported");
|
error("~user paths are not currently supported");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
|
||||||
return make_absolute(ret, remote_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
source_sftp(int argc, char *src, char *targ,
|
source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn)
|
||||||
struct sftp_conn *conn, char **remote_path)
|
|
||||||
{
|
{
|
||||||
char *target = NULL, *filename = NULL, *abs_dst = NULL;
|
char *target = NULL, *filename = NULL, *abs_dst = NULL;
|
||||||
int target_is_dir;
|
int target_is_dir;
|
||||||
|
|
||||||
if (*remote_path == NULL) {
|
|
||||||
*remote_path = do_realpath(conn, ".");
|
|
||||||
if (*remote_path == NULL)
|
|
||||||
fatal("Unable to determine remote working directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((filename = basename(src)) == NULL)
|
if ((filename = basename(src)) == NULL)
|
||||||
fatal("basename %s: %s", src, strerror(errno));
|
fatal("basename %s: %s", src, strerror(errno));
|
||||||
|
|
||||||
|
@ -1300,7 +1279,7 @@ source_sftp(int argc, char *src, char *targ,
|
||||||
* No need to glob here - the local shell already took care of
|
* No need to glob here - the local shell already took care of
|
||||||
* the expansions
|
* the expansions
|
||||||
*/
|
*/
|
||||||
if ((target = absolute_remote_path(conn, targ, *remote_path)) == NULL)
|
if ((target = prepare_remote_path(conn, targ)) == NULL)
|
||||||
cleanup_exit(255);
|
cleanup_exit(255);
|
||||||
target_is_dir = remote_is_dir(conn, target);
|
target_is_dir = remote_is_dir(conn, target);
|
||||||
if (targetshouldbedirectory && !target_is_dir) {
|
if (targetshouldbedirectory && !target_is_dir) {
|
||||||
|
@ -1495,7 +1474,7 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn)
|
||||||
char *abs_src = NULL;
|
char *abs_src = NULL;
|
||||||
char *abs_dst = NULL;
|
char *abs_dst = NULL;
|
||||||
glob_t g;
|
glob_t g;
|
||||||
char *filename, *tmp = NULL, *remote_path = NULL;
|
char *filename, *tmp = NULL;
|
||||||
int i, r, err = 0;
|
int i, r, err = 0;
|
||||||
|
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
|
@ -1504,20 +1483,11 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn)
|
||||||
* expansions
|
* expansions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
remote_path = do_realpath(conn, ".");
|
if ((abs_src = prepare_remote_path(conn, src)) == NULL) {
|
||||||
if (remote_path == NULL) {
|
|
||||||
error("Could not obtain remote working directory");
|
|
||||||
/* TODO - gracefully degrade by using relative paths ? */
|
|
||||||
err = -1;
|
err = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((abs_src = absolute_remote_path(conn, src, remote_path)) == NULL) {
|
|
||||||
err = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
free(remote_path);
|
|
||||||
|
|
||||||
debug3_f("copying remote %s to local %s", abs_src, dst);
|
debug3_f("copying remote %s to local %s", abs_src, dst);
|
||||||
if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
|
if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
|
||||||
if (r == GLOB_NOSPACE)
|
if (r == GLOB_NOSPACE)
|
||||||
|
@ -1901,34 +1871,19 @@ screwup:
|
||||||
|
|
||||||
void
|
void
|
||||||
throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
|
throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
|
||||||
char *src, char *targ, char **to_remote_path)
|
char *src, char *targ)
|
||||||
{
|
{
|
||||||
char *target = NULL, *filename = NULL, *abs_dst = NULL;
|
char *target = NULL, *filename = NULL, *abs_dst = NULL;
|
||||||
char *abs_src = NULL, *tmp = NULL, *from_remote_path;
|
char *abs_src = NULL, *tmp = NULL;
|
||||||
glob_t g;
|
glob_t g;
|
||||||
int i, r, targetisdir, err = 0;
|
int i, r, targetisdir, err = 0;
|
||||||
|
|
||||||
if (*to_remote_path == NULL) {
|
|
||||||
*to_remote_path = do_realpath(to, ".");
|
|
||||||
if (*to_remote_path == NULL) {
|
|
||||||
fatal("Unable to determine destination remote "
|
|
||||||
"working directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((from_remote_path = do_realpath(from, ".")) == NULL) {
|
|
||||||
fatal("Unable to determine source remote "
|
|
||||||
"working directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((filename = basename(src)) == NULL)
|
if ((filename = basename(src)) == NULL)
|
||||||
fatal("basename %s: %s", src, strerror(errno));
|
fatal("basename %s: %s", src, strerror(errno));
|
||||||
|
|
||||||
if ((abs_src = absolute_remote_path(from, src,
|
if ((abs_src = prepare_remote_path(from, src)) == NULL ||
|
||||||
from_remote_path)) == NULL ||
|
(target = prepare_remote_path(to, targ)) == NULL)
|
||||||
(target = absolute_remote_path(to, targ, *to_remote_path)) == NULL)
|
|
||||||
cleanup_exit(255);
|
cleanup_exit(255);
|
||||||
free(from_remote_path);
|
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
|
|
||||||
targetisdir = remote_is_dir(to, target);
|
targetisdir = remote_is_dir(to, target);
|
||||||
|
|
Loading…
Reference in New Issue