Unpatch Red Hat help message

This commit is contained in:
Koichiro Iwao 2025-10-31 03:05:48 +00:00 committed by root
commit 1617a4a445
3 changed files with 571 additions and 2 deletions

View File

@ -0,0 +1,120 @@
diff --color -ruNp a/auth.c b/auth.c
--- a/auth.c 2025-10-29 09:57:20.440640281 +0100
+++ b/auth.c 2025-10-29 09:57:54.747956792 +0100
@@ -476,8 +476,12 @@ getpwnamallow(struct ssh *ssh, const cha
u_int i;
ci = server_get_connection_info(ssh, 1, options.use_dns);
- ci->user = user;
- ci->user_invalid = getpwnam(user) == NULL;
+ pw = getpwnam(user);
+ if (pw != NULL && options.canonical_match_user)
+ ci->user = pw->pw_name;
+ else
+ ci->user = user;
+ ci->user_invalid = pw == NULL;
parse_server_match_config(&options, &includes, ci);
log_change_level(options.log_level);
log_verbose_reset();
diff --color -ruNp a/servconf.c b/servconf.c
--- a/servconf.c 2025-10-29 09:57:20.502465586 +0100
+++ b/servconf.c 2025-10-29 09:57:54.748205464 +0100
@@ -225,6 +225,7 @@ initialize_server_options(ServerOptions
options->unused_connection_timeout = -1;
options->sshd_session_path = NULL;
options->refuse_connection = -1;
+ options->canonical_match_user = -1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -526,6 +527,8 @@ fill_default_server_options(ServerOption
options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION);
if (options->refuse_connection == -1)
options->refuse_connection = 0;
+ if (options->canonical_match_user == -1)
+ options->canonical_match_user = 0;
assemble_algorithms(options);
@@ -609,7 +612,7 @@ typedef enum {
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout,
- sSshdSessionPath, sRefuseConnection,
+ sSshdSessionPath, sRefuseConnection, sCanonicalMatchUser,
sDeprecated, sIgnore, sUnsupported
} ServerOpCodes;
@@ -798,6 +801,7 @@ static struct {
{ "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
{ "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
{ "refuseconnection", sRefuseConnection, SSHCFG_ALL },
+ { "canonicalmatchuser", sCanonicalMatchUser, SSHCFG_GLOBAL },
{ NULL, sBadOption, 0 }
};
@@ -2807,6 +2811,11 @@ process_server_config_line_depth(ServerO
multistate_ptr = multistate_flag;
goto parse_multistate;
+ case sCanonicalMatchUser:
+ intptr = &options->canonical_match_user;
+ multistate_ptr = multistate_flag;
+ goto parse_multistate;
+
case sDeprecated:
case sIgnore:
case sUnsupported:
@@ -3028,6 +3037,7 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(required_rsa_size);
M_CP_INTOPT(unused_connection_timeout);
M_CP_INTOPT(refuse_connection);
+ M_CP_INTOPT(canonical_match_user);
/*
* The bind_mask is a mode_t that may be unsigned, so we can't use
@@ -3368,6 +3378,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
dump_cfg_fmtint(sRefuseConnection, o->refuse_connection);
+ dump_cfg_fmtint(sCanonicalMatchUser, o->canonical_match_user);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
diff --color -ruNp a/servconf.h b/servconf.h
--- a/servconf.h 2025-10-29 09:57:20.503199202 +0100
+++ b/servconf.h 2025-10-29 09:57:54.749236422 +0100
@@ -261,6 +261,8 @@ typedef struct {
char *sshd_session_path;
int refuse_connection;
+
+ int canonical_match_user;
} ServerOptions;
/* Information about the incoming connection as used by Match */
diff --color -ruNp a/sshd_config.5 b/sshd_config.5
--- a/sshd_config.5 2025-10-29 09:57:20.503465608 +0100
+++ b/sshd_config.5 2025-10-29 09:57:54.749544972 +0100
@@ -1384,6 +1384,7 @@ Available keywords are
.Cm PubkeyAuthentication ,
.Cm PubkeyAuthOptions ,
.Cm RefuseConnection ,
+.Cm CanonicalMatchUser ,
.Cm RekeyLimit ,
.Cm RevokedKeys ,
.Cm RDomain ,
@@ -1828,6 +1829,13 @@ are enabled.
This option is only really useful in a
.Cm Match
block.
+.It Cm CanonicalMatchUser
+Some password databases allow users to define aliases for their username.
+This directive indicates that
+.Xr sshd 8
+should attempt to first obtain a canonical username from a password database before evaluating a
+.Cm Match User
+conditional block.
.It Cm RekeyLimit
Specifies the maximum amount of data that may be transmitted or received
before the session key is renegotiated, optionally followed by a maximum

View File

@ -0,0 +1,437 @@
diff --color -ruNp a/regress/scp3.sh b/regress/scp3.sh
--- a/regress/scp3.sh 2024-09-20 00:20:48.000000000 +0200
+++ b/regress/scp3.sh 2025-10-29 16:00:59.815068193 +0100
@@ -6,6 +6,12 @@ tid="scp3"
COPY2=${OBJ}/copy2
DIR=${COPY}.dd
DIR2=${COPY}.dd2
+DIFFOPT="-rN"
+
+# Figure out if diff does not understand "-N"
+if ! diff -N ${SRC}/scp.sh ${SRC}/scp.sh 2>/dev/null; then
+ DIFFOPT="-r"
+fi
maybe_add_scp_path_to_sshd
@@ -63,6 +69,15 @@ for mode in scp sftp ; do
echo b > ${COPY2}
$SCP $scpopts -3 hostA:${DATA} hostA:${COPY} hostB:${COPY2}
cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
+
+ # scp /blah/.. is only supported via the sftp protocol.
+ # Original protocol scp just refuses it.
+ test $mode != sftp && continue
+ verbose "$tag: recursive .."
+ forest
+ $SCP $scpopts -r hostA:${DIR}/subdir/.. hostB:${DIR2} || \
+ fail "copy failed"
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
done
scpclean
diff --color -ruNp a/regress/scp.sh b/regress/scp.sh
--- a/regress/scp.sh 2024-09-20 00:20:48.000000000 +0200
+++ b/regress/scp.sh 2025-10-29 16:00:59.810765653 +0100
@@ -199,6 +199,19 @@ for mode in scp sftp ; do
echo b > ${COPY2}
$SCP $scpopts ${DATA} ${COPY} ${COPY2}
cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
+
+ # scp /blah/.. is only supported via the sftp protocol.
+ # Original protocol scp just refuses it.
+ test $mode != sftp && continue
+ verbose "$tag: recursive local .. to remote dir"
+ forest
+ $SCP $scpopts -r ${DIR}/subdir/.. somehost:${DIR2} || fail "copy failed"
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+
+ verbose "$tag: recursive remote .. to local dir"
+ forest
+ $SCP $scpopts -r somehost:${DIR}/subdir/.. ${DIR2} || fail "copy failed"
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
done
scpclean
diff --color -ruNp a/regress/sftp-cmds.sh b/regress/sftp-cmds.sh
--- a/regress/sftp-cmds.sh 2024-09-20 00:20:48.000000000 +0200
+++ b/regress/sftp-cmds.sh 2025-10-29 16:00:59.813392901 +0100
@@ -7,6 +7,12 @@
tid="sftp commands"
+DIFFOPT="-rN"
+# Figure out if diff does not understand "-N"
+if ! diff -N ${SRC}/sftp-cmds.sh ${SRC}/sftp-cmds.sh 2>/dev/null; then
+ DIFFOPT="-r"
+fi
+
# test that these files are readable!
for i in `(cd /bin;echo l*)`
do
@@ -24,207 +30,246 @@ SPACECOPY_ARG="${COPY}\ this\ has\ space
# File with glob metacharacters
GLOBMETACOPY="${COPY} [metachar].txt"
+sftpserver() {
+ ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1
+}
+
+sftpserver_with_stdout() {
+ ${SFTP} -D ${SFTPSERVER} 2>&1
+}
+
+forest() {
+ rm -rf ${COPY}.dd/*
+ rm -rf ${COPY}.dd2
+ mkdir -p ${COPY}.dd/a ${COPY}.dd/b ${COPY}.dd/c ${COPY}.dd/a/d
+ echo 'A' > ${COPY}.dd/a/A
+ echo 'B' > ${COPY}.dd/a/B
+ echo 'C' > ${COPY}.dd/a/C
+ echo 'D' > ${COPY}.dd/a/D
+}
+
rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
mkdir ${COPY}.dd
verbose "$tid: lls"
-printf "lcd ${OBJ}\nlls\n" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
+printf "lcd ${OBJ}\nlls\n" | sftpserver_with_stdout | \
grep copy.dd >/dev/null || fail "lls failed"
verbose "$tid: lls w/path"
-echo "lls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
+echo "lls ${OBJ}" | sftpserver_with_stdout | \
grep copy.dd >/dev/null || fail "lls w/path failed"
verbose "$tid: ls"
-echo "ls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "ls failed"
+echo "ls ${OBJ}" | sftpserver || fail "ls failed"
# XXX always successful
verbose "$tid: shell"
-echo "!echo hi there" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
+echo "!echo hi there" | sftpserver_with_stdout | \
egrep '^hi there$' >/dev/null || fail "shell failed"
verbose "$tid: pwd"
-echo "pwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "pwd failed"
+echo "pwd" | sftpserver || fail "pwd failed"
# XXX always successful
verbose "$tid: lpwd"
-echo "lpwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "lpwd failed"
+echo "lpwd" | sftpserver || fail "lpwd failed"
# XXX always successful
verbose "$tid: quit"
-echo "quit" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "quit failed"
+echo "quit" | sftpserver || fail "quit failed"
# XXX always successful
verbose "$tid: help"
-echo "help" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "help failed"
+echo "help" | sftpserver || fail "help failed"
# XXX always successful
rm -f ${COPY}
verbose "$tid: get"
-echo "get $DATA $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+echo "get $DATA $COPY" | sftpserver || fail "get failed"
cmp $DATA ${COPY} || fail "corrupted copy after get"
rm -f ${COPY}
verbose "$tid: get quoted"
-echo "get \"$DATA\" $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+echo "get \"$DATA\" $COPY" | sftpserver || fail "get failed"
cmp $DATA ${COPY} || fail "corrupted copy after get"
rm -f ${QUOTECOPY}
cp $DATA ${QUOTECOPY}
verbose "$tid: get filename with quotes"
-echo "get \"$QUOTECOPY_ARG\" ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+echo "get \"$QUOTECOPY_ARG\" ${COPY}" | sftpserver || fail "get failed"
cmp ${COPY} ${QUOTECOPY} || fail "corrupted copy after get with quotes"
rm -f ${QUOTECOPY} ${COPY}
rm -f "$SPACECOPY" ${COPY}
cp $DATA "$SPACECOPY"
verbose "$tid: get filename with spaces"
-echo "get ${SPACECOPY_ARG} ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+echo "get ${SPACECOPY_ARG} ${COPY}" | sftpserver || fail "get failed"
cmp ${COPY} "$SPACECOPY" || fail "corrupted copy after get with spaces"
rm -f "$GLOBMETACOPY" ${COPY}
cp $DATA "$GLOBMETACOPY"
verbose "$tid: get filename with glob metacharacters"
-echo "get \"${GLOBMETACOPY}\" ${COPY}" | \
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "get failed"
+echo "get \"${GLOBMETACOPY}\" ${COPY}" | sftpserver || fail "get failed"
cmp ${COPY} "$GLOBMETACOPY" || \
fail "corrupted copy after get with glob metacharacters"
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: get to directory"
-echo "get $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+echo "get $DATA ${COPY}.dd" | sftpserver || fail "get failed"
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after get"
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: glob get to directory"
-echo "get /bin/l* ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+echo "get /bin/l* ${COPY}.dd" | sftpserver || fail "get failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
done
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: get to local dir"
-printf "lcd ${COPY}.dd\nget $DATA\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+printf "lcd ${COPY}.dd\nget $DATA\n" | sftpserver || fail "get failed"
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after get"
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: glob get to local dir"
-printf "lcd ${COPY}.dd\nget /bin/l*\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "get failed"
+printf "lcd ${COPY}.dd\nget /bin/l*\n" | sftpserver || fail "get failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
done
+forest
+verbose "$tid: get recursive absolute"
+echo "get -R ${COPY}.dd ${COPY}.dd2" | sftpserver || fail "get failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
+forest
+verbose "$tid: get recursive relative src"
+printf "cd ${COPY}.dd\n get -R . ${COPY}.dd2\n" | sftpserver || \
+ fail "get failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
+forest
+verbose "$tid: get relative .."
+printf "cd ${COPY}.dd/b\n get -R .. ${COPY}.dd2\n" | sftpserver || \
+ fail "get failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
+forest
+mkdir ${COPY}.dd2
+verbose "$tid: get recursive relative .."
+printf "cd ${COPY}.dd/b\n lcd ${COPY}.dd2\n get -R ..\n" | sftpserver || \
+ fail "get failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
rm -f ${COPY}
verbose "$tid: put"
-echo "put $DATA $COPY" | \
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
+echo "put $DATA $COPY" | sftpserver || fail "put failed"
cmp $DATA ${COPY} || fail "corrupted copy after put"
rm -f ${QUOTECOPY}
verbose "$tid: put filename with quotes"
-echo "put $DATA \"$QUOTECOPY_ARG\"" | \
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
+echo "put $DATA \"$QUOTECOPY_ARG\"" | sftpserver || fail "put failed"
cmp $DATA ${QUOTECOPY} || fail "corrupted copy after put with quotes"
rm -f "$SPACECOPY"
verbose "$tid: put filename with spaces"
-echo "put $DATA ${SPACECOPY_ARG}" | \
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
+echo "put $DATA ${SPACECOPY_ARG}" | sftpserver || fail "put failed"
cmp $DATA "$SPACECOPY" || fail "corrupted copy after put with spaces"
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: put to directory"
-echo "put $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "put failed"
+echo "put $DATA ${COPY}.dd" | sftpserver || fail "put failed"
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after put"
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: glob put to directory"
-echo "put /bin/l? ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "put failed"
+echo "put /bin/l? ${COPY}.dd" | sftpserver || fail "put failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
done
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: put to local dir"
-printf "cd ${COPY}.dd\nput $DATA\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "put failed"
+printf "cd ${COPY}.dd\nput $DATA\n" | sftpserver || fail "put failed"
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after put"
-rm -f ${COPY}.dd/*
+rm -rf ${COPY}.dd/*
verbose "$tid: glob put to local dir"
-printf "cd ${COPY}.dd\nput /bin/l*\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "put failed"
+printf "cd ${COPY}.dd\nput /bin/l*\n" | sftpserver || fail "put failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
done
+forest
+verbose "$tid: put recursive absolute"
+echo "put -R ${COPY}.dd ${COPY}.dd2" | sftpserver || fail "put failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
+forest
+verbose "$tid: put recursive relative src"
+printf "lcd ${COPY}.dd\n put -R . ${COPY}.dd2\n" | sftpserver || \
+ fail "put failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
+forest
+verbose "$tid: put recursive .."
+printf "lcd ${COPY}.dd/b\n put -R .. ${COPY}.dd2\n" | sftpserver || \
+ fail "put failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
+forest
+mkdir ${COPY}.dd2
+verbose "$tid: put recursive .. relative"
+printf "lcd ${COPY}.dd/b\n cd ${COPY}.dd2\n put -R ..\n" | sftpserver || \
+ fail "put failed"
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
+
verbose "$tid: rename"
-echo "rename $COPY ${COPY}.1" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "rename failed"
+echo "rename $COPY ${COPY}.1" | sftpserver || fail "rename failed"
test -f ${COPY}.1 || fail "missing file after rename"
cmp $DATA ${COPY}.1 >/dev/null 2>&1 || fail "corrupted copy after rename"
verbose "$tid: rename directory"
-echo "rename ${COPY}.dd ${COPY}.dd2" | \
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || \
+rm -rf ${COPY}.dd2
+echo "rename ${COPY}.dd ${COPY}.dd2" | sftpserver || \
fail "rename directory failed"
test -d ${COPY}.dd && fail "oldname exists after rename directory"
test -d ${COPY}.dd2 || fail "missing newname after rename directory"
verbose "$tid: ln"
-echo "ln ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln failed"
+echo "ln ${COPY}.1 ${COPY}.2" | sftpserver || fail "ln failed"
test -f ${COPY}.2 || fail "missing file after ln"
cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after ln"
verbose "$tid: ln -s"
rm -f ${COPY}.2
-echo "ln -s ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln -s failed"
+echo "ln -s ${COPY}.1 ${COPY}.2" | sftpserver || fail "ln -s failed"
test -h ${COPY}.2 || fail "missing file after ln -s"
verbose "$tid: cp"
rm -f ${COPY}.2
-echo "cp ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "cp failed"
+echo "cp ${COPY}.1 ${COPY}.2" | sftpserver || fail "cp failed"
cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after cp"
verbose "$tid: mkdir"
-echo "mkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "mkdir failed"
+echo "mkdir ${COPY}.dd" | sftpserver || fail "mkdir failed"
test -d ${COPY}.dd || fail "missing directory after mkdir"
# XXX do more here
verbose "$tid: chdir"
-echo "chdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "chdir failed"
+echo "chdir ${COPY}.dd" | sftpserver || fail "chdir failed"
verbose "$tid: rmdir"
-echo "rmdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "rmdir failed"
+echo "rmdir ${COPY}.dd" | sftpserver || fail "rmdir failed"
test -d ${COPY}.1 && fail "present directory after rmdir"
verbose "$tid: lmkdir"
-echo "lmkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "lmkdir failed"
+echo "lmkdir ${COPY}.dd" | sftpserver || fail "lmkdir failed"
test -d ${COPY}.dd || fail "missing directory after lmkdir"
# XXX do more here
verbose "$tid: lchdir"
-echo "lchdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
- || fail "lchdir failed"
+echo "lchdir ${COPY}.dd" | sftpserver || fail "lchdir failed"
rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
rm -rf ${QUOTECOPY} "$SPACECOPY" "$GLOBMETACOPY"
diff --color -ruNp a/scp.c b/scp.c
--- a/scp.c 2025-10-29 15:49:51.795813258 +0100
+++ b/scp.c 2025-10-29 16:00:59.817393000 +0100
@@ -1362,6 +1362,10 @@ source_sftp(int argc, char *src, char *t
if ((filename = basename(src)) == NULL)
fatal("basename \"%s\": %s", src, strerror(errno));
+ /* Special handling for source of '..' */
+ if (strcmp(filename, "..") == 0)
+ filename = "."; /* Upload to dest, not dest/.. */
+
/*
* No need to glob here - the local shell already took care of
* the expansions
@@ -1635,6 +1639,10 @@ sink_sftp(int argc, char *dst, const cha
goto out;
}
+ /* Special handling for destination of '..' */
+ if (strcmp(filename, "..") == 0)
+ filename = "."; /* Download to dest, not dest/.. */
+
if (dst_is_dir)
abs_dst = sftp_path_append(dst, filename);
else
diff --color -ruNp a/sftp.c b/sftp.c
--- a/sftp.c 2025-10-29 15:49:51.796907436 +0100
+++ b/sftp.c 2025-10-29 16:00:59.819803948 +0100
@@ -687,6 +687,10 @@ process_get(struct sftp_conn *conn, cons
goto out;
}
+ /* Special handling for dest of '..' */
+ if (strcmp(filename, "..") == 0)
+ filename = "."; /* Download to dest, not dest/.. */
+
if (g.gl_matchc == 1 && dst) {
if (local_is_dir(dst)) {
abs_dst = sftp_path_append(dst, filename);
@@ -781,6 +785,9 @@ process_put(struct sftp_conn *conn, cons
err = -1;
goto out;
}
+ /* Special handling for source of '..' */
+ if (strcmp(filename, "..") == 0)
+ filename = "."; /* Upload to dest, not dest/.. */
free(abs_dst);
abs_dst = NULL;

View File

@ -43,7 +43,7 @@
Summary: An open source implementation of SSH protocol version 2
Name: openssh
Version: %{openssh_ver}
Release: 14%{?dist}.alma.1
Release: 15%{?dist}.alma.1
URL: http://www.openssh.com/portable.html
Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc
@ -216,6 +216,10 @@ Patch1026: openssh-9.9p1-bad-hostkey.patch
Patch1027: openssh-9.9p1-support-authentication-indicators-in-GSSAPI.patch
#
Patch1028: openssh-9.9p1-fips-gss.patch
#upstream 6432b9f6a216d0f5fb43df500e9bc30bebb3f58b
#upstream 4f14ca8633a2c8c0a1a19165663421f0ab32f6ab
Patch1029: openssh-9.9p1-scp-traversing.patch
Patch1030: openssh-9.9p1-canonical-match-user.patch
License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant
Requires: /sbin/nologin
@ -409,6 +413,8 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0}
%patch -P 1026 -p1 -b .bad-hostkey
%patch -P 1027 -p1 -b .gss-indicators
%patch -P 1028 -p1 -b .gss-fips
%patch -P 1029 -p1 -b .scp-traversing
%patch -P 1030 -p1 -b .canonical-match-user
%patch -P 100 -p1 -b .coverity
@ -689,9 +695,15 @@ test -f %{sysconfig_anaconda} && \
%attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so
%changelog
* Tue Sep 16 2025 Koichiro Iwao <meta@almalinux.org> - 9.9p1-14.alma.1
* Fri Oct 31 2025 Koichiro Iwao <meta@almalinux.org> - 9.9p1-15.alma.1
- Unpatch Red Hat help message
* Mon Oct 27 2025 Zoltan Fridrich <zfridric@redhat.com> - 9.9p1-15
- Fix implicit destination path selection when source path ends with ".."
Resolves: RHEL-118406
- Canonicalize username when matching a user
Resolves: RHEL-101440
* Mon Sep 15 2025 Dmitry Belyavskiy <dbelyavs@redhat.com> - 9.9p1-14
- Relax GSS Kex restriction in FIPS mode
Resolves: RHEL-91181