Switch to SFTP protocol in scp utility by default - various improvements

Workaround for RHEL 8 incompatibility in scp utility in SFTP mode
Related: rhbz#2001002
Related: rhbz#2038854
This commit is contained in:
Dmitry Belyavskiy 2022-02-07 13:07:00 +01:00
parent 0b7faaf14a
commit 14950508f7
2 changed files with 187 additions and 2 deletions

View File

@ -0,0 +1,173 @@
diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c
--- openssh-8.7p1/scp.c.scp-sftpdirs 2022-02-07 12:31:07.407740407 +0100
+++ openssh-8.7p1/scp.c 2022-02-07 12:31:07.409740424 +0100
@@ -1324,7 +1324,7 @@ source_sftp(int argc, char *src, char *t
if (src_is_dir && iamrecursive) {
if (upload_dir(conn, src, abs_dst, pflag,
- SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) {
+ SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
error("failed to upload directory %s to %s",
src, abs_dst);
errs = 1;
diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c
--- openssh-8.7p1/sftp-client.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
+++ openssh-8.7p1/sftp-client.c 2022-02-07 12:47:59.117516131 +0100
@@ -971,7 +971,7 @@ do_fsetstat(struct sftp_conn *conn, cons
/* Implements both the realpath and expand-path operations */
static char *
-do_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
+do_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir)
{
struct sshbuf *msg;
u_int expected_id, count, id;
@@ -1012,9 +1012,37 @@ do_realpath_expand(struct sftp_conn *con
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal_fr(r, "parse status");
- error("Couldn't canonicalize: %s", fx2txt(status));
- sshbuf_free(msg);
- return NULL;
+ if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) {
+ if ((r = do_mkdir(conn, path, &a, 0)) != 0) {
+ sshbuf_free(msg);
+ return NULL;
+ }
+
+ send_string_request(conn, id, SSH2_FXP_REALPATH,
+ path, strlen(path));
+
+ get_msg(conn, msg);
+ if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+ (r = sshbuf_get_u32(msg, &id)) != 0)
+ fatal_fr(r, "parse");
+
+ if (id != expected_id)
+ fatal("ID mismatch (%u != %u)", id, expected_id);
+
+ if (type == SSH2_FXP_STATUS) {
+ u_int status;
+
+ if ((r = sshbuf_get_u32(msg, &status)) != 0)
+ fatal_fr(r, "parse status");
+ error("Couldn't canonicalize: %s", fx2txt(status));
+ sshbuf_free(msg);
+ return NULL;
+ }
+ } else {
+ error("Couldn't canonicalize: %s", fx2txt(status));
+ sshbuf_free(msg);
+ return NULL;
+ }
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
SSH2_FXP_NAME, type);
@@ -1039,9 +1067,9 @@ do_realpath_expand(struct sftp_conn *con
}
char *
-do_realpath(struct sftp_conn *conn, const char *path)
+do_realpath(struct sftp_conn *conn, const char *path, int create_dir)
{
- return do_realpath_expand(conn, path, 0);
+ return do_realpath_expand(conn, path, 0, create_dir);
}
int
@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c
{
if (!can_expand_path(conn)) {
debug3_f("no server support, fallback to realpath");
- return do_realpath_expand(conn, path, 0);
+ return do_realpath_expand(conn, path, 0, 0);
}
- return do_realpath_expand(conn, path, 1);
+ return do_realpath_expand(conn, path, 1, 0);
}
int
@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con
char *src_canon;
int ret;
- if ((src_canon = do_realpath(conn, src)) == NULL) {
+ if ((src_canon = do_realpath(conn, src, 0)) == NULL) {
error("Unable to canonicalize path \"%s\"", src);
return -1;
}
@@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co
int
upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
int preserve_flag, int print_flag, int resume, int fsync_flag,
- int follow_link_flag)
+ int follow_link_flag, int create_dir)
{
char *dst_canon;
int ret;
- if ((dst_canon = do_realpath(conn, dst)) == NULL) {
+ if ((dst_canon = do_realpath(conn, dst, create_dir)) == NULL) {
error("Unable to canonicalize path \"%s\"", dst);
return -1;
}
@@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st
char *from_path_canon;
int ret;
- if ((from_path_canon = do_realpath(from, from_path)) == NULL) {
+ if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) {
error("Unable to canonicalize path \"%s\"", from_path);
return -1;
}
diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h
--- openssh-8.7p1/sftp-client.h.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
+++ openssh-8.7p1/sftp-client.h 2022-02-07 12:31:07.410740433 +0100
@@ -111,7 +111,7 @@ int do_fsetstat(struct sftp_conn *, cons
int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
/* Canonicalise 'path' - caller must free result */
-char *do_realpath(struct sftp_conn *, const char *);
+char *do_realpath(struct sftp_conn *, const char *, int);
/* Canonicalisation with tilde expansion (requires server extension) */
char *do_expand_path(struct sftp_conn *, const char *);
@@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const
* times if 'pflag' is set
*/
int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
- int, int);
+ int, int, int);
/*
* Download a 'from_path' from the 'from' connection and upload it to
diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c
--- openssh-8.7p1/sftp.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
+++ openssh-8.7p1/sftp.c 2022-02-07 12:31:07.411740442 +0100
@@ -760,7 +760,7 @@ process_put(struct sftp_conn *conn, cons
if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, 1, resume,
- fflag || global_fflag, 0) == -1)
+ fflag || global_fflag, 0, 0) == -1)
err = -1;
} else {
if (do_upload(conn, g.gl_pathv[i], abs_dst,
@@ -1577,7 +1577,7 @@ parse_dispatch_command(struct sftp_conn
if (path1 == NULL || *path1 == '\0')
path1 = xstrdup(startdir);
path1 = make_absolute(path1, *pwd);
- if ((tmp = do_realpath(conn, path1)) == NULL) {
+ if ((tmp = do_realpath(conn, path1, 0)) == NULL) {
err = 1;
break;
}
@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn,
}
#endif /* USE_LIBEDIT */
- remote_path = do_realpath(conn, ".");
+ remote_path = do_realpath(conn, ".", 0);
if (remote_path == NULL)
fatal("Need cwd");
startdir = xstrdup(remote_path);

View File

@ -201,8 +201,17 @@ Patch977: openssh-8.7p1-scp-kill-switch.patch
Patch978: openssh-8.7p1-upstream-cve-2021-41617.patch
# fix for `ssh-keygen -Y find-principals -f /dev/null -s /dev/null` (#2024902)
Patch979: openssh-8.7p1-find-principals-fix.patch
# Create non-existent directories when scp works in sftp mode
# Create non-existent directories when scp works in sftp mode and some more minor fixes
# upstream commits:
# ba61123eef9c6356d438c90c1199a57a0d7bcb0a
# 63670d4e9030bcee490d5a9cce561373ac5b3b23
# ac7c9ec894ed0825d04ef69c55babb49bab1d32e
Patch980: openssh-8.7p1-sftpscp-dir-create.patch
# Workaround for lack of sftp_realpath in older versions of RHEL
# https://bugzilla.redhat.com/show_bug.cgi?id=2038854
# https://github.com/openssh/openssh-portable/pull/299
# downstream only
Patch981: openssh-8.7p1-recursive-scp.patch
Patch1000: openssh-8.7p1-minimize-sha1-use.patch
@ -385,6 +394,7 @@ popd
%patch978 -p1 -b .cve-2021-41617
%patch979 -p1 -b .find-principals
%patch980 -p1 -b .sftpdirs
%patch981 -p1 -b .scp-sftpdirs
%patch200 -p1 -b .audit
%patch201 -p1 -b .audit-race
@ -671,9 +681,11 @@ test -f %{sysconfig_anaconda} && \
%endif
%changelog
* Wed Feb 02 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-7
* Mon Feb 07 2022 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-7
- Switch to SFTP protocol in scp utility by default - upstream fixes
Related: rhbz#2001002
- Workaround for RHEL 8 incompatibility in scp utility in SFTP mode
Related: rhbz#2038854
* Tue Dec 21 2021 Dmitry Belyavskiy <dbelyavs@redhat.com> - 8.7p1-6
- Fix SSH connection to localhost not possible in FIPS