1#	$OpenBSD: multiplex.sh,v 1.21 2013/05/17 04:29:14 dtucker Exp $
2#	Placed in the Public Domain.
3
4CTL=/tmp/openssh.regress.ctl-sock.$$
5
6tid="connection multiplexing"
7
8if config_defined DISABLE_FD_PASSING ; then
9	echo "skipped (not supported on this platform)"
10	exit 0
11fi
12
13P=3301  # test port
14
15wait_for_mux_master_ready()
16{
17	for i in 1 2 3 4 5; do
18		${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost \
19		    >/dev/null 2>&1 && return 0
20		sleep $i
21	done
22	fatal "mux master never becomes ready"
23}
24
25start_sshd
26
27start_mux_master()
28{
29	trace "start master, fork to background"
30	${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \
31	    -E $TEST_REGRESS_LOGFILE 2>&1 &
32	MASTER_PID=$!
33	wait_for_mux_master_ready
34}
35
36start_mux_master
37
38verbose "test $tid: envpass"
39trace "env passing over multiplexed connection"
40_XXX_TEST=blah ${SSH} -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" -S$CTL otherhost sh << 'EOF'
41	test X"$_XXX_TEST" = X"blah"
42EOF
43if [ $? -ne 0 ]; then
44	fail "environment not found"
45fi
46
47verbose "test $tid: transfer"
48rm -f ${COPY}
49trace "ssh transfer over multiplexed connection and check result"
50${SSH} -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY}
51test -f ${COPY}			|| fail "ssh -Sctl: failed copy ${DATA}" 
52cmp ${DATA} ${COPY}		|| fail "ssh -Sctl: corrupted copy of ${DATA}"
53
54rm -f ${COPY}
55trace "ssh transfer over multiplexed connection and check result"
56${SSH} -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY}
57test -f ${COPY}			|| fail "ssh -S ctl: failed copy ${DATA}" 
58cmp ${DATA} ${COPY}		|| fail "ssh -S ctl: corrupted copy of ${DATA}"
59
60rm -f ${COPY}
61trace "sftp transfer over multiplexed connection and check result"
62echo "get ${DATA} ${COPY}" | \
63	${SFTP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost >>$TEST_REGRESS_LOGFILE 2>&1
64test -f ${COPY}			|| fail "sftp: failed copy ${DATA}" 
65cmp ${DATA} ${COPY}		|| fail "sftp: corrupted copy of ${DATA}"
66
67rm -f ${COPY}
68trace "scp transfer over multiplexed connection and check result"
69${SCP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost:${DATA} ${COPY} >>$TEST_REGRESS_LOGFILE 2>&1
70test -f ${COPY}			|| fail "scp: failed copy ${DATA}" 
71cmp ${DATA} ${COPY}		|| fail "scp: corrupted copy of ${DATA}"
72
73rm -f ${COPY}
74
75for s in 0 1 4 5 44; do
76	trace "exit status $s over multiplexed connection"
77	verbose "test $tid: status $s"
78	${SSH} -F $OBJ/ssh_config -S $CTL otherhost exit $s
79	r=$?
80	if [ $r -ne $s ]; then
81		fail "exit code mismatch for protocol $p: $r != $s"
82	fi
83
84	# same with early close of stdout/err
85	trace "exit status $s with early close over multiplexed connection"
86	${SSH} -F $OBJ/ssh_config -S $CTL -n otherhost \
87                exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\'
88	r=$?
89	if [ $r -ne $s ]; then
90		fail "exit code (with sleep) mismatch for protocol $p: $r != $s"
91	fi
92done
93
94verbose "test $tid: cmd check"
95${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
96    || fail "check command failed" 
97
98verbose "test $tid: cmd forward local"
99${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \
100     || fail "request local forward failed"
101${SSH} -F $OBJ/ssh_config -p$P otherhost true \
102     || fail "connect to local forward port failed"
103${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \
104     || fail "cancel local forward failed"
105${SSH} -F $OBJ/ssh_config -p$P otherhost true \
106     && fail "local forward port still listening"
107
108verbose "test $tid: cmd forward remote"
109${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \
110     || fail "request remote forward failed"
111${SSH} -F $OBJ/ssh_config -p$P otherhost true \
112     || fail "connect to remote forwarded port failed"
113${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \
114     || fail "cancel remote forward failed"
115${SSH} -F $OBJ/ssh_config -p$P otherhost true \
116     && fail "remote forward port still listening"
117
118verbose "test $tid: cmd exit"
119${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
120    || fail "send exit command failed" 
121
122# Wait for master to exit
123wait $MASTER_PID
124kill -0 $MASTER_PID >/dev/null 2>&1 && fail "exit command failed"
125
126# Restart master and test -O stop command with master using -N
127verbose "test $tid: cmd stop"
128trace "restart master, fork to background"
129start_mux_master
130
131# start a long-running command then immediately request a stop
132${SSH} -F $OBJ/ssh_config -S $CTL otherhost "sleep 10; exit 0" \
133     >>$TEST_REGRESS_LOGFILE 2>&1 &
134SLEEP_PID=$!
135${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
136    || fail "send stop command failed"
137
138# wait until both long-running command and master have exited.
139wait $SLEEP_PID
140[ $! != 0 ] || fail "waiting for concurrent command"
141wait $MASTER_PID
142[ $! != 0 ] || fail "waiting for master stop"
143kill -0 $MASTER_PID >/dev/null 2>&1 && fail "stop command failed"
144