Home | History | Annotate | Download | only in regress
      1 #	$OpenBSD: multiplex.sh,v 1.27 2014/12/22 06:14:29 djm Exp $
      2 #	Placed in the Public Domain.
      3 
      4 CTL=/tmp/openssh.regress.ctl-sock.$$
      5 
      6 tid="connection multiplexing"
      7 
      8 NC=$OBJ/netcat
      9 
     10 trace "will use ProxyCommand $proxycmd"
     11 if config_defined DISABLE_FD_PASSING ; then
     12 	echo "skipped (not supported on this platform)"
     13 	exit 0
     14 fi
     15 
     16 P=3301  # test port
     17 
     18 wait_for_mux_master_ready()
     19 {
     20 	for i in 1 2 3 4 5; do
     21 		${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost \
     22 		    >/dev/null 2>&1 && return 0
     23 		sleep $i
     24 	done
     25 	fatal "mux master never becomes ready"
     26 }
     27 
     28 start_sshd
     29 
     30 start_mux_master()
     31 {
     32 	trace "start master, fork to background"
     33 	${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \
     34 	    -E $TEST_REGRESS_LOGFILE 2>&1 &
     35 	# NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors.
     36 	SSH_PID=$!
     37 	wait_for_mux_master_ready
     38 }
     39 
     40 start_mux_master
     41 
     42 verbose "test $tid: envpass"
     43 trace "env passing over multiplexed connection"
     44 _XXX_TEST=blah ${SSH} -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" -S$CTL otherhost sh << 'EOF'
     45 	test X"$_XXX_TEST" = X"blah"
     46 EOF
     47 if [ $? -ne 0 ]; then
     48 	fail "environment not found"
     49 fi
     50 
     51 verbose "test $tid: transfer"
     52 rm -f ${COPY}
     53 trace "ssh transfer over multiplexed connection and check result"
     54 ${SSH} -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY}
     55 test -f ${COPY}			|| fail "ssh -Sctl: failed copy ${DATA}" 
     56 cmp ${DATA} ${COPY}		|| fail "ssh -Sctl: corrupted copy of ${DATA}"
     57 
     58 rm -f ${COPY}
     59 trace "ssh transfer over multiplexed connection and check result"
     60 ${SSH} -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY}
     61 test -f ${COPY}			|| fail "ssh -S ctl: failed copy ${DATA}" 
     62 cmp ${DATA} ${COPY}		|| fail "ssh -S ctl: corrupted copy of ${DATA}"
     63 
     64 rm -f ${COPY}
     65 trace "sftp transfer over multiplexed connection and check result"
     66 echo "get ${DATA} ${COPY}" | \
     67 	${SFTP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost >>$TEST_REGRESS_LOGFILE 2>&1
     68 test -f ${COPY}			|| fail "sftp: failed copy ${DATA}" 
     69 cmp ${DATA} ${COPY}		|| fail "sftp: corrupted copy of ${DATA}"
     70 
     71 rm -f ${COPY}
     72 trace "scp transfer over multiplexed connection and check result"
     73 ${SCP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost:${DATA} ${COPY} >>$TEST_REGRESS_LOGFILE 2>&1
     74 test -f ${COPY}			|| fail "scp: failed copy ${DATA}" 
     75 cmp ${DATA} ${COPY}		|| fail "scp: corrupted copy of ${DATA}"
     76 
     77 rm -f ${COPY}
     78 verbose "test $tid: forward"
     79 trace "forward over TCP/IP and check result"
     80 $NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null &
     81 netcat_pid=$!
     82 ${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
     83 $NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY}
     84 cmp ${DATA} ${COPY}		|| fail "ssh: corrupted copy of ${DATA}"
     85 kill $netcat_pid 2>/dev/null
     86 rm -f ${COPY} $OBJ/unix-[123].fwd
     87 
     88 trace "forward over UNIX and check result"
     89 $NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null &
     90 netcat_pid=$!
     91 ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
     92 ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
     93 $NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY} 2>/dev/null
     94 cmp ${DATA} ${COPY}		|| fail "ssh: corrupted copy of ${DATA}"
     95 kill $netcat_pid 2>/dev/null
     96 rm -f ${COPY} $OBJ/unix-[123].fwd
     97 
     98 for s in 0 1 4 5 44; do
     99 	trace "exit status $s over multiplexed connection"
    100 	verbose "test $tid: status $s"
    101 	${SSH} -F $OBJ/ssh_config -S $CTL otherhost exit $s
    102 	r=$?
    103 	if [ $r -ne $s ]; then
    104 		fail "exit code mismatch for protocol $p: $r != $s"
    105 	fi
    106 
    107 	# same with early close of stdout/err
    108 	trace "exit status $s with early close over multiplexed connection"
    109 	${SSH} -F $OBJ/ssh_config -S $CTL -n otherhost \
    110                 exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\'
    111 	r=$?
    112 	if [ $r -ne $s ]; then
    113 		fail "exit code (with sleep) mismatch for protocol $p: $r != $s"
    114 	fi
    115 done
    116 
    117 verbose "test $tid: cmd check"
    118 ${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
    119     || fail "check command failed" 
    120 
    121 verbose "test $tid: cmd forward local (TCP)"
    122 ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \
    123      || fail "request local forward failed"
    124 ${SSH} -F $OBJ/ssh_config -p$P otherhost true \
    125      || fail "connect to local forward port failed"
    126 ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \
    127      || fail "cancel local forward failed"
    128 ${SSH} -F $OBJ/ssh_config -p$P otherhost true \
    129      && fail "local forward port still listening"
    130 
    131 verbose "test $tid: cmd forward remote (TCP)"
    132 ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \
    133      || fail "request remote forward failed"
    134 ${SSH} -F $OBJ/ssh_config -p$P otherhost true \
    135      || fail "connect to remote forwarded port failed"
    136 ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \
    137      || fail "cancel remote forward failed"
    138 ${SSH} -F $OBJ/ssh_config -p$P otherhost true \
    139      && fail "remote forward port still listening"
    140 
    141 verbose "test $tid: cmd forward local (UNIX)"
    142 ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
    143      || fail "request local forward failed"
    144 echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \
    145      || fail "connect to local forward path failed"
    146 ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
    147      || fail "cancel local forward failed"
    148 N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
    149 test ${N} -eq 0 || fail "local forward path still listening"
    150 rm -f $OBJ/unix-1.fwd
    151 
    152 verbose "test $tid: cmd forward remote (UNIX)"
    153 ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
    154      || fail "request remote forward failed"
    155 echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \
    156      || fail "connect to remote forwarded path failed"
    157 ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
    158      || fail "cancel remote forward failed"
    159 N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
    160 test ${N} -eq 0 || fail "remote forward path still listening"
    161 rm -f $OBJ/unix-1.fwd
    162 
    163 verbose "test $tid: cmd exit"
    164 ${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
    165     || fail "send exit command failed" 
    166 
    167 # Wait for master to exit
    168 wait $SSH_PID
    169 kill -0 $SSH_PID >/dev/null 2>&1 && fail "exit command failed"
    170 
    171 # Restart master and test -O stop command with master using -N
    172 verbose "test $tid: cmd stop"
    173 trace "restart master, fork to background"
    174 start_mux_master
    175 
    176 # start a long-running command then immediately request a stop
    177 ${SSH} -F $OBJ/ssh_config -S $CTL otherhost "sleep 10; exit 0" \
    178      >>$TEST_REGRESS_LOGFILE 2>&1 &
    179 SLEEP_PID=$!
    180 ${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
    181     || fail "send stop command failed"
    182 
    183 # wait until both long-running command and master have exited.
    184 wait $SLEEP_PID
    185 [ $! != 0 ] || fail "waiting for concurrent command"
    186 wait $SSH_PID
    187 [ $! != 0 ] || fail "waiting for master stop"
    188 kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed"
    189 SSH_PID="" # Already gone, so don't kill in cleanup
    190 
    191