forward-control.sh revision 295367
1#	$OpenBSD: forward-control.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
2#	Placed in the Public Domain.
3
4tid="sshd control of local and remote forwarding"
5
6LFWD_PORT=3320
7RFWD_PORT=3321
8CTL=$OBJ/ctl-sock
9READY=$OBJ/ready
10
11wait_for_file_to_appear() {
12	_path=$1
13	_n=0
14	while test ! -f $_path ; do
15		test $_n -eq 1 && trace "waiting for $_path to appear"
16		_n=`expr $_n + 1`
17		test $_n -ge 20 && return 1
18		sleep 1
19	done
20	return 0
21}
22
23wait_for_process_to_exit() {
24	_pid=$1
25	_n=0
26	while kill -0 $_pid 2>/dev/null ; do
27		test $_n -eq 1 && trace "waiting for $_pid to exit"
28		_n=`expr $_n + 1`
29		test $_n -ge 20 && return 1
30		sleep 1
31	done
32	return 0
33}
34
35# usage: check_lfwd protocol Y|N message
36check_lfwd() {
37	_proto=$1
38	_expected=$2
39	_message=$3
40	rm -f $READY
41	${SSH} -oProtocol=$_proto -F $OBJ/ssh_proxy \
42	    -L$LFWD_PORT:127.0.0.1:$PORT \
43	    -o ExitOnForwardFailure=yes \
44	    -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \
45	    >/dev/null 2>&1 &
46	_sshpid=$!
47	wait_for_file_to_appear $READY || \
48		fatal "check_lfwd ssh fail: $_message"
49	${SSH} -F $OBJ/ssh_config -p $LFWD_PORT \
50	    -oConnectionAttempts=4 host true >/dev/null 2>&1
51	_result=$?
52	kill $_sshpid `cat $READY` 2>/dev/null
53	wait_for_process_to_exit $_sshpid
54	if test "x$_expected" = "xY" -a $_result -ne 0 ; then
55		fail "check_lfwd failed (expecting success): $_message"
56	elif test "x$_expected" = "xN" -a $_result -eq 0 ; then
57		fail "check_lfwd succeeded (expecting failure): $_message"
58	elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then
59		fatal "check_lfwd invalid argument \"$_expected\""
60	else
61		verbose "check_lfwd done (expecting $_expected): $_message"
62	fi
63}
64
65# usage: check_rfwd protocol Y|N message
66check_rfwd() {
67	_proto=$1
68	_expected=$2
69	_message=$3
70	rm -f $READY
71	${SSH} -oProtocol=$_proto -F $OBJ/ssh_proxy \
72	    -R$RFWD_PORT:127.0.0.1:$PORT \
73	    -o ExitOnForwardFailure=yes \
74	    -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \
75	    >/dev/null 2>&1 &
76	_sshpid=$!
77	wait_for_file_to_appear $READY
78	_result=$?
79	if test $_result -eq 0 ; then
80		${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \
81		    -oConnectionAttempts=4 host true >/dev/null 2>&1
82		_result=$?
83		kill $_sshpid `cat $READY` 2>/dev/null
84		wait_for_process_to_exit $_sshpid
85	fi
86	if test "x$_expected" = "xY" -a $_result -ne 0 ; then
87		fail "check_rfwd failed (expecting success): $_message"
88	elif test "x$_expected" = "xN" -a $_result -eq 0 ; then
89		fail "check_rfwd succeeded (expecting failure): $_message"
90	elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then
91		fatal "check_rfwd invalid argument \"$_expected\""
92	else
93		verbose "check_rfwd done (expecting $_expected): $_message"
94	fi
95}
96
97start_sshd
98cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak
99cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak
100
101# Sanity check: ensure the default config allows forwarding
102for p in ${SSH_PROTOCOLS} ; do
103	check_lfwd $p Y "proto $p, default configuration"
104	check_rfwd $p Y "proto $p, default configuration"
105done
106
107# Usage: all_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N
108all_tests() {
109	_tcpfwd=$1
110	_plain_lfwd=$2
111	_plain_rfwd=$3
112	_nopermit_lfwd=$4
113	_nopermit_rfwd=$5
114	_permit_lfwd=$6
115	_permit_rfwd=$7
116	_badfwd=127.0.0.1:22
117	_goodfwd=127.0.0.1:${PORT}
118	for _proto in ${SSH_PROTOCOLS} ; do
119		cp ${OBJ}/authorized_keys_${USER}.bak \
120		    ${OBJ}/authorized_keys_${USER}
121		_prefix="proto $_proto, AllowTcpForwarding=$_tcpfwd"
122		# No PermitOpen
123		( cat ${OBJ}/sshd_proxy.bak ;
124		  echo "AllowTcpForwarding $_tcpfwd" ) \
125		    > ${OBJ}/sshd_proxy
126		check_lfwd $_proto $_plain_lfwd "$_prefix"
127		check_rfwd $_proto $_plain_rfwd "$_prefix"
128		# PermitOpen via sshd_config that doesn't match
129		( cat ${OBJ}/sshd_proxy.bak ;
130		  echo "AllowTcpForwarding $_tcpfwd" ;
131		  echo "PermitOpen $_badfwd" ) \
132		    > ${OBJ}/sshd_proxy
133		check_lfwd $_proto $_nopermit_lfwd "$_prefix, !PermitOpen"
134		check_rfwd $_proto $_nopermit_rfwd "$_prefix, !PermitOpen"
135		# PermitOpen via sshd_config that does match
136		( cat ${OBJ}/sshd_proxy.bak ;
137		  echo "AllowTcpForwarding $_tcpfwd" ;
138		  echo "PermitOpen $_badfwd $_goodfwd" ) \
139		    > ${OBJ}/sshd_proxy
140		# NB. permitopen via authorized_keys should have same
141		# success/fail as via sshd_config
142		# permitopen via authorized_keys that doesn't match
143		sed "s/^/permitopen=\"$_badfwd\" /" \
144		    < ${OBJ}/authorized_keys_${USER}.bak \
145		    > ${OBJ}/authorized_keys_${USER} || fatal "sed 1 fail"
146		( cat ${OBJ}/sshd_proxy.bak ;
147		  echo "AllowTcpForwarding $_tcpfwd" ) \
148		    > ${OBJ}/sshd_proxy
149		check_lfwd $_proto $_nopermit_lfwd "$_prefix, !permitopen"
150		check_rfwd $_proto $_nopermit_rfwd "$_prefix, !permitopen"
151		# permitopen via authorized_keys that does match
152		sed "s/^/permitopen=\"$_badfwd\",permitopen=\"$_goodfwd\" /" \
153		    < ${OBJ}/authorized_keys_${USER}.bak \
154		    > ${OBJ}/authorized_keys_${USER} || fatal "sed 2 fail"
155		( cat ${OBJ}/sshd_proxy.bak ;
156		  echo "AllowTcpForwarding $_tcpfwd" ) \
157		    > ${OBJ}/sshd_proxy
158		check_lfwd $_proto $_permit_lfwd "$_prefix, permitopen"
159		check_rfwd $_proto $_permit_rfwd "$_prefix, permitopen"
160	done
161}
162
163#                      no-permitopen mismatch-permitopen match-permitopen
164#   AllowTcpForwarding  local remote        local remote     local remote
165all_tests          yes      Y      Y            N      Y         Y      Y
166all_tests        local      Y      N            N      N         Y      N
167all_tests       remote      N      Y            N      Y         N      Y
168all_tests           no      N      N            N      N         N      N
169