1#	$OpenBSD: cfgmatchlisten.sh,v 1.3 2018/07/02 14:13:30 dtucker Exp $
2#	Placed in the Public Domain.
3
4tid="sshd_config matchlisten"
5
6pidfile=$OBJ/remote_pid
7fwdport=3301
8fwdspec="localhost:${fwdport}"
9fwd="-R $fwdport:127.0.0.1:$PORT"
10
11echo "ExitOnForwardFailure=yes" >> $OBJ/ssh_config
12echo "ExitOnForwardFailure=yes" >> $OBJ/ssh_proxy
13
14start_client()
15{
16	rm -f $pidfile
17	${SSH} -vvv $fwd "$@" somehost true >>$TEST_REGRESS_LOGFILE 2>&1
18	r=$?
19	if [ $r -ne 0 ]; then
20		return $r
21	fi
22	${SSH} -vvv $fwd "$@" somehost \
23	    exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' \
24	    >>$TEST_REGRESS_LOGFILE 2>&1 &
25	client_pid=$!
26	# Wait for remote end
27	n=0
28	while test ! -f $pidfile ; do
29		sleep 1
30		n=`expr $n + 1`
31		if test $n -gt 60; then
32			kill $client_pid
33			fatal "timeout waiting for background ssh"
34		fi
35	done
36	return $r
37}
38
39expect_client_ok()
40{
41	start_client "$@" ||
42	    fail "client did not start"
43}
44
45expect_client_fail()
46{
47	local failmsg="$1"
48	shift
49	start_client "$@" &&
50	    fail $failmsg
51}
52
53stop_client()
54{
55	pid=`cat $pidfile`
56	if [ ! -z "$pid" ]; then
57		kill $pid
58	fi
59	wait
60}
61
62cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
63echo "PermitListen 127.0.0.1:1" >>$OBJ/sshd_config
64echo "Match Address 127.0.0.1" >>$OBJ/sshd_config
65echo "PermitListen 127.0.0.1:2 127.0.0.1:3 $fwdspec" >>$OBJ/sshd_config
66
67grep -v AuthorizedKeysFile $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
68echo "AuthorizedKeysFile /dev/null" >>$OBJ/sshd_proxy
69echo "PermitListen 127.0.0.1:1" >>$OBJ/sshd_proxy
70echo "Match user $USER" >>$OBJ/sshd_proxy
71echo "AuthorizedKeysFile /dev/null $OBJ/authorized_keys_%u" >>$OBJ/sshd_proxy
72echo "Match Address 127.0.0.1" >>$OBJ/sshd_proxy
73echo "PermitListen 127.0.0.1:2 127.0.0.1:3 $fwdspec" >>$OBJ/sshd_proxy
74
75start_sshd
76
77#set -x
78
79# Test Match + PermitListen in sshd_config.  This should be permitted
80trace "match permitlisten localhost"
81expect_client_ok -F $OBJ/ssh_config
82${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
83    fail "match permitlisten permit"
84stop_client
85
86# Same but from different source.  This should not be permitted
87trace "match permitlisten proxy"
88expect_client_fail "match permitlisten deny" \
89    -F $OBJ/ssh_proxy
90
91# Retry previous with key option, should also be denied.
92cp /dev/null $OBJ/authorized_keys_$USER
93for t in ${SSH_KEYTYPES}; do
94	printf 'permitlisten="'$fwdspec'" ' >> $OBJ/authorized_keys_$USER
95	cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
96done
97trace "match permitlisten proxy w/key opts"
98expect_client_fail "match permitlisten deny w/key opt"\
99    -F $OBJ/ssh_proxy
100
101# Test both sshd_config and key options permitting the same dst/port pair.
102# Should be permitted.
103trace "match permitlisten localhost"
104expect_client_ok -F $OBJ/ssh_config
105${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
106    fail "match permitlisten permit"
107stop_client
108
109# Test that a bare port number is accepted in PermitListen
110cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
111echo "PermitListen 127.0.0.1:1 $fwdport 127.0.0.2:2" >>$OBJ/sshd_proxy
112trace "match permitlisten bare"
113expect_client_ok -F $OBJ/ssh_config
114${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
115    fail "match permitlisten bare"
116stop_client
117
118# Test that an incorrect bare port number is denied as expected
119cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
120echo "PermitListen 1 2 99" >>$OBJ/sshd_proxy
121trace "match permitlisten bare"
122expect_client_fail -F $OBJ/ssh_config
123
124cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
125echo "PermitListen 127.0.0.1:1 $fwdspec 127.0.0.2:2" >>$OBJ/sshd_proxy
126echo "Match User $USER" >>$OBJ/sshd_proxy
127echo "PermitListen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
128
129# Test that a Match overrides a PermitListen in the global section
130trace "match permitlisten proxy w/key opts"
131expect_client_fail "match override permitlisten" \
132    -F $OBJ/ssh_proxy
133
134cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
135echo "PermitListen 127.0.0.1:1 $fwdspec 127.0.0.2:2" >>$OBJ/sshd_proxy
136echo "Match User NoSuchUser" >>$OBJ/sshd_proxy
137echo "PermitListen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
138
139# Test that a rule that doesn't match doesn't override, plus test a
140# PermitListen entry that's not at the start of the list
141trace "nomatch permitlisten proxy w/key opts"
142expect_client_ok -F $OBJ/ssh_proxy
143${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
144    fail "nomatch override permitlisten"
145stop_client
146
147# bind to 127.0.0.1 instead of default localhost
148fwdspec2="127.0.0.1:${fwdport}"
149fwd="-R ${fwdspec2}:127.0.0.1:$PORT"
150
151# first try w/ old fwdspec both in server config and key opts
152cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
153echo "PermitListen 127.0.0.1:1 $fwdspec 127.0.0.2:2" >>$OBJ/sshd_proxy
154cp /dev/null $OBJ/authorized_keys_$USER
155for t in ${SSH_KEYTYPES}; do
156	printf 'permitlisten="'$fwdspec'" ' >> $OBJ/authorized_keys_$USER
157	cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
158done
159trace "nomatch permitlisten 127.0.0.1 server config and userkey"
160expect_client_fail "nomatch 127.0.0.1 server config and userkey" \
161    -F $OBJ/ssh_config
162
163# correct server config, denied by key opts
164cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
165echo "PermitListen 127.0.0.1:1 ${fwdspec2} 127.0.0.2:2" >>$OBJ/sshd_proxy
166trace "nomatch permitlisten 127.0.0.1 w/key opts"
167expect_client_fail "nomatch 127.0.0.1 w/key opts" \
168    -F $OBJ/ssh_config
169
170# fix key opts
171cp /dev/null $OBJ/authorized_keys_$USER
172for t in ${SSH_KEYTYPES}; do
173	printf 'permitlisten="'$fwdspec2'" ' >> $OBJ/authorized_keys_$USER
174	cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
175done
176trace "match permitlisten 127.0.0.1 server config w/key opts"
177expect_client_ok -F $OBJ/ssh_proxy
178${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
179    fail "match 127.0.0.1 server config w/key opts"
180stop_client
181
182# key opts with bare port number
183cp /dev/null $OBJ/authorized_keys_$USER
184for t in ${SSH_KEYTYPES}; do
185	printf 'permitlisten="'$fwdport'" ' >> $OBJ/authorized_keys_$USER
186	cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
187done
188trace "match permitlisten 127.0.0.1 server config w/key opts (bare)"
189expect_client_ok -F $OBJ/ssh_proxy
190${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \
191    fail "match 127.0.0.1 server config w/key opts (bare)"
192stop_client
193
194# key opts with incorrect bare port number
195cp /dev/null $OBJ/authorized_keys_$USER
196for t in ${SSH_KEYTYPES}; do
197	printf 'permitlisten="99" ' >> $OBJ/authorized_keys_$USER
198	cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
199done
200trace "match permitlisten 127.0.0.1 server config w/key opts (wrong bare)"
201expect_client_fail "nomatch 127.0.0.1 w/key opts (wrong bare)" \
202    -F $OBJ/ssh_config
203