mirror of
git://anongit.mindrot.org/openssh.git
synced 2024-11-28 07:14:31 +08:00
de08335a4c
Currently when the multiplex client requests a forward it returns once the request has been sent but not necessarily when the forward is up. This causes intermittent text failures due to this race, so add some sleeps to mitigate this until we can fix it properly. OpenBSD-Regress-ID: 384c7d209d2443d25ea941d7f677e932621fb253
200 lines
7.3 KiB
Bash
200 lines
7.3 KiB
Bash
# $OpenBSD: multiplex.sh,v 1.30 2019/07/05 04:03:13 dtucker Exp $
|
|
# Placed in the Public Domain.
|
|
|
|
make_tmpdir
|
|
CTL=${SSH_REGRESS_TMP}/ctl-sock
|
|
|
|
tid="connection multiplexing"
|
|
|
|
NC=$OBJ/netcat
|
|
|
|
trace "will use ProxyCommand $proxycmd"
|
|
if config_defined DISABLE_FD_PASSING ; then
|
|
echo "skipped (not supported on this platform)"
|
|
exit 0
|
|
fi
|
|
|
|
P=3301 # test port
|
|
|
|
wait_for_mux_master_ready()
|
|
{
|
|
for i in 1 2 3 4 5; do
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost \
|
|
>/dev/null 2>&1 && return 0
|
|
sleep $i
|
|
done
|
|
fatal "mux master never becomes ready"
|
|
}
|
|
|
|
start_sshd
|
|
|
|
start_mux_master()
|
|
{
|
|
trace "start master, fork to background"
|
|
${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \
|
|
-E $TEST_REGRESS_LOGFILE 2>&1 &
|
|
# NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors.
|
|
SSH_PID=$!
|
|
wait_for_mux_master_ready
|
|
}
|
|
|
|
start_mux_master
|
|
|
|
verbose "test $tid: envpass"
|
|
trace "env passing over multiplexed connection"
|
|
_XXX_TEST=blah ${SSH} -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" -S$CTL otherhost sh << 'EOF'
|
|
test X"$_XXX_TEST" = X"blah"
|
|
EOF
|
|
if [ $? -ne 0 ]; then
|
|
fail "environment not found"
|
|
fi
|
|
|
|
verbose "test $tid: transfer"
|
|
rm -f ${COPY}
|
|
trace "ssh transfer over multiplexed connection and check result"
|
|
${SSH} -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY}
|
|
test -f ${COPY} || fail "ssh -Sctl: failed copy ${DATA}"
|
|
cmp ${DATA} ${COPY} || fail "ssh -Sctl: corrupted copy of ${DATA}"
|
|
|
|
rm -f ${COPY}
|
|
trace "ssh transfer over multiplexed connection and check result"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY}
|
|
test -f ${COPY} || fail "ssh -S ctl: failed copy ${DATA}"
|
|
cmp ${DATA} ${COPY} || fail "ssh -S ctl: corrupted copy of ${DATA}"
|
|
|
|
rm -f ${COPY}
|
|
trace "sftp transfer over multiplexed connection and check result"
|
|
echo "get ${DATA} ${COPY}" | \
|
|
${SFTP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost >>$TEST_REGRESS_LOGFILE 2>&1
|
|
test -f ${COPY} || fail "sftp: failed copy ${DATA}"
|
|
cmp ${DATA} ${COPY} || fail "sftp: corrupted copy of ${DATA}"
|
|
|
|
rm -f ${COPY}
|
|
trace "scp transfer over multiplexed connection and check result"
|
|
${SCP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost:${DATA} ${COPY} >>$TEST_REGRESS_LOGFILE 2>&1
|
|
test -f ${COPY} || fail "scp: failed copy ${DATA}"
|
|
cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}"
|
|
|
|
rm -f ${COPY}
|
|
verbose "test $tid: forward"
|
|
trace "forward over TCP/IP and check result"
|
|
$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null &
|
|
netcat_pid=$!
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1
|
|
sleep 1 # XXX remove once race fixed
|
|
$NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY}
|
|
cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
|
|
kill $netcat_pid 2>/dev/null
|
|
rm -f ${COPY} $OBJ/unix-[123].fwd
|
|
|
|
trace "forward over UNIX and check result"
|
|
$NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null &
|
|
netcat_pid=$!
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
|
|
sleep 1 # XXX remove once race fixed
|
|
$NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY}
|
|
cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
|
|
kill $netcat_pid 2>/dev/null
|
|
rm -f ${COPY} $OBJ/unix-[123].fwd
|
|
|
|
for s in 0 1 4 5 44; do
|
|
trace "exit status $s over multiplexed connection"
|
|
verbose "test $tid: status $s"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL otherhost exit $s
|
|
r=$?
|
|
if [ $r -ne $s ]; then
|
|
fail "exit code mismatch: $r != $s"
|
|
fi
|
|
|
|
# same with early close of stdout/err
|
|
trace "exit status $s with early close over multiplexed connection"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -n otherhost \
|
|
exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\'
|
|
r=$?
|
|
if [ $r -ne $s ]; then
|
|
fail "exit code (with sleep) mismatch: $r != $s"
|
|
fi
|
|
done
|
|
|
|
verbose "test $tid: cmd check"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
|
|
|| fail "check command failed"
|
|
|
|
verbose "test $tid: cmd forward local (TCP)"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \
|
|
|| fail "request local forward failed"
|
|
sleep 1 # XXX remove once race fixed
|
|
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
|
|
|| fail "connect to local forward port failed"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \
|
|
|| fail "cancel local forward failed"
|
|
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
|
|
&& fail "local forward port still listening"
|
|
|
|
verbose "test $tid: cmd forward remote (TCP)"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \
|
|
|| fail "request remote forward failed"
|
|
sleep 1 # XXX remove once race fixed
|
|
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
|
|
|| fail "connect to remote forwarded port failed"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \
|
|
|| fail "cancel remote forward failed"
|
|
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
|
|
&& fail "remote forward port still listening"
|
|
|
|
verbose "test $tid: cmd forward local (UNIX)"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|
|
|| fail "request local forward failed"
|
|
sleep 1 # XXX remove once race fixed
|
|
echo "" | $NC -U $OBJ/unix-1.fwd | \
|
|
grep "Invalid SSH identification string" >/dev/null 2>&1 \
|
|
|| fail "connect to local forward path failed"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|
|
|| fail "cancel local forward failed"
|
|
N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
|
|
test ${N} -eq 0 || fail "local forward path still listening"
|
|
rm -f $OBJ/unix-1.fwd
|
|
|
|
verbose "test $tid: cmd forward remote (UNIX)"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|
|
|| fail "request remote forward failed"
|
|
sleep 1 # XXX remove once race fixed
|
|
echo "" | $NC -U $OBJ/unix-1.fwd | \
|
|
grep "Invalid SSH identification string" >/dev/null 2>&1 \
|
|
|| fail "connect to remote forwarded path failed"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|
|
|| fail "cancel remote forward failed"
|
|
N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
|
|
test ${N} -eq 0 || fail "remote forward path still listening"
|
|
rm -f $OBJ/unix-1.fwd
|
|
|
|
verbose "test $tid: cmd exit"
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
|
|
|| fail "send exit command failed"
|
|
|
|
# Wait for master to exit
|
|
wait $SSH_PID
|
|
kill -0 $SSH_PID >/dev/null 2>&1 && fail "exit command failed"
|
|
|
|
# Restart master and test -O stop command with master using -N
|
|
verbose "test $tid: cmd stop"
|
|
trace "restart master, fork to background"
|
|
start_mux_master
|
|
|
|
# start a long-running command then immediately request a stop
|
|
${SSH} -F $OBJ/ssh_config -S $CTL otherhost "sleep 10; exit 0" \
|
|
>>$TEST_REGRESS_LOGFILE 2>&1 &
|
|
SLEEP_PID=$!
|
|
${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
|
|
|| fail "send stop command failed"
|
|
|
|
# wait until both long-running command and master have exited.
|
|
wait $SLEEP_PID
|
|
[ $! != 0 ] || fail "waiting for concurrent command"
|
|
wait $SSH_PID
|
|
[ $! != 0 ] || fail "waiting for master stop"
|
|
kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed"
|
|
SSH_PID="" # Already gone, so don't kill in cleanup
|
|
|