1 # $OpenBSD: forward-control.sh,v 1.12 2023/07/28 05:33:15 djm Exp $
2 # Placed in the Public Domain.
4 tid="sshd control of local and remote forwarding"
11 wait_for_process_to_exit() {
14 while kill -0 $_pid 2>/dev/null ; do
15 test $_n -eq 1 && trace "waiting for $_pid to exit"
17 test $_n -ge $WAIT_SECONDS && return 1
24 ${SSH} -F $OBJ/ssh_proxy -S $CTL -O $1 host 2>&1
28 mux_cmd check | cut -f2 -d= | cut -f1 -d')'
31 # usage: check_lfwd Y|N message
35 ${SSH} -F $OBJ/ssh_proxy \
36 -L$LFWD_PORT:127.0.0.1:$PORT \
37 -o ExitOnForwardFailure=yes \
38 -MS $CTL -o ControlPersist=yes \
40 mux_cmd check >/dev/null || fatal "check_lfwd ssh fail: $_message"
41 ${SSH} -F $OBJ/ssh_config -p $LFWD_PORT \
42 -oConnectionAttempts=10 host true >/dev/null 2>&1
44 _sshpid=`controlmaster_pid`
45 mux_cmd exit >/dev/null
46 wait_for_process_to_exit $_sshpid
47 if test "x$_expected" = "xY" -a $_result -ne 0 ; then
48 fail "check_lfwd failed (expecting success): $_message"
49 elif test "x$_expected" = "xN" -a $_result -eq 0 ; then
50 fail "check_lfwd succeeded (expecting failure): $_message"
51 elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then
52 fatal "check_lfwd invalid argument \"$_expected\""
54 verbose "check_lfwd done (expecting $_expected): $_message"
58 # usage: check_rfwd Y|N message
62 ${SSH} -F $OBJ/ssh_proxy \
63 -R127.0.0.1:$RFWD_PORT:127.0.0.1:$PORT \
64 -o ExitOnForwardFailure=yes \
65 -MS $CTL -o ControlPersist=yes \
67 mux_cmd check >/dev/null
69 _sshpid=`controlmaster_pid`
70 if test $_result -eq 0; then
71 ${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \
72 -oConnectionAttempts=10 host true >/dev/null 2>&1
74 mux_cmd exit >/dev/null
75 wait_for_process_to_exit $_sshpid
77 if test "x$_expected" = "xY" -a $_result -ne 0 ; then
78 fail "check_rfwd failed (expecting success): $_message"
79 elif test "x$_expected" = "xN" -a $_result -eq 0 ; then
80 fail "check_rfwd succeeded (expecting failure): $_message"
81 elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then
82 fatal "check_rfwd invalid argument \"$_expected\""
84 verbose "check_rfwd done (expecting $_expected): $_message"
89 cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak
90 cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak
92 # Sanity check: ensure the default config allows forwarding
93 check_lfwd Y "default configuration"
94 check_rfwd Y "default configuration"
96 # Usage: lperm_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N
105 _badfwd1=127.0.0.1:22
106 _badfwd2=127.0.0.2:22
107 _goodfwd=127.0.0.1:${PORT}
108 cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER}
109 _prefix="AllowTcpForwarding=$_tcpfwd"
112 ( cat ${OBJ}/sshd_proxy.bak ;
113 echo "AllowTcpForwarding $_tcpfwd" ) \
115 check_lfwd $_plain_lfwd "$_prefix"
116 check_rfwd $_plain_rfwd "$_prefix"
118 # PermitOpen via sshd_config that doesn't match
119 ( cat ${OBJ}/sshd_proxy.bak ;
120 echo "AllowTcpForwarding $_tcpfwd" ;
121 echo "PermitOpen $_badfwd1 $_badfwd2" ) \
123 check_lfwd $_nopermit_lfwd "$_prefix, !PermitOpen"
124 check_rfwd $_nopermit_rfwd "$_prefix, !PermitOpen"
125 # PermitOpen via sshd_config that does match
126 ( cat ${OBJ}/sshd_proxy.bak ;
127 echo "AllowTcpForwarding $_tcpfwd" ;
128 echo "PermitOpen $_badfwd1 $_goodfwd $_badfwd2" ) \
130 check_lfwd $_plain_lfwd "$_prefix, PermitOpen"
131 check_rfwd $_plain_rfwd "$_prefix, PermitOpen"
133 # permitopen keys option.
134 # NB. permitopen via authorized_keys should have same
135 # success/fail as via sshd_config
136 # permitopen via authorized_keys that doesn't match
137 sed "s/^/permitopen=\"$_badfwd1\",permitopen=\"$_badfwd2\" /" \
138 < ${OBJ}/authorized_keys_${USER}.bak \
139 > ${OBJ}/authorized_keys_${USER} || fatal "sed 1 fail"
140 ( cat ${OBJ}/sshd_proxy.bak ;
141 echo "AllowTcpForwarding $_tcpfwd" ) \
143 check_lfwd $_nopermit_lfwd "$_prefix, !permitopen"
144 check_rfwd $_nopermit_rfwd "$_prefix, !permitopen"
145 # permitopen via authorized_keys that does match
146 sed "s/^/permitopen=\"$_badfwd1\",permitopen=\"$_goodfwd\" /" \
147 < ${OBJ}/authorized_keys_${USER}.bak \
148 > ${OBJ}/authorized_keys_${USER} || fatal "sed 2 fail"
149 ( cat ${OBJ}/sshd_proxy.bak ;
150 echo "AllowTcpForwarding $_tcpfwd" ) \
152 check_lfwd $_permit_lfwd "$_prefix, permitopen"
153 check_rfwd $_permit_rfwd "$_prefix, permitopen"
155 # Check port-forwarding flags in authorized_keys.
156 # These two should refuse all.
157 sed "s/^/no-port-forwarding /" \
158 < ${OBJ}/authorized_keys_${USER}.bak \
159 > ${OBJ}/authorized_keys_${USER} || fatal "sed 3 fail"
160 ( cat ${OBJ}/sshd_proxy.bak ;
161 echo "AllowTcpForwarding $_tcpfwd" ) \
163 check_lfwd N "$_prefix, no-port-forwarding"
164 check_rfwd N "$_prefix, no-port-forwarding"
165 sed "s/^/restrict /" \
166 < ${OBJ}/authorized_keys_${USER}.bak \
167 > ${OBJ}/authorized_keys_${USER} || fatal "sed 4 fail"
168 ( cat ${OBJ}/sshd_proxy.bak ;
169 echo "AllowTcpForwarding $_tcpfwd" ) \
171 check_lfwd N "$_prefix, restrict"
172 check_rfwd N "$_prefix, restrict"
173 # This should pass the same cases as _nopermit*
174 sed "s/^/restrict,port-forwarding /" \
175 < ${OBJ}/authorized_keys_${USER}.bak \
176 > ${OBJ}/authorized_keys_${USER} || fatal "sed 5 fail"
177 ( cat ${OBJ}/sshd_proxy.bak ;
178 echo "AllowTcpForwarding $_tcpfwd" ) \
180 check_lfwd $_plain_lfwd "$_prefix, restrict,port-forwarding"
181 check_rfwd $_plain_rfwd "$_prefix, restrict,port-forwarding"
184 # permit-open none mismatch match
185 # AllowTcpForwarding local remote local remote local remote
186 lperm_tests yes Y Y N Y Y Y
187 lperm_tests local Y N N N Y N
188 lperm_tests remote N Y N Y N Y
189 lperm_tests no N N N N N N
191 # Usage: rperm_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N
200 _badfwd1=127.0.0.1:22
201 _badfwd2=127.0.0.2:${RFWD_PORT}
202 _goodfwd=127.0.0.1:${RFWD_PORT}
203 cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER}
204 _prefix="AllowTcpForwarding=$_tcpfwd"
206 # PermitListen via sshd_config that doesn't match
207 ( cat ${OBJ}/sshd_proxy.bak ;
208 echo "AllowTcpForwarding $_tcpfwd" ;
209 echo "PermitListen $_badfwd1 $_badfwd2" ) \
211 check_lfwd $_nopermit_lfwd "$_prefix, !PermitListen"
212 check_rfwd $_nopermit_rfwd "$_prefix, !PermitListen"
213 # PermitListen via sshd_config that does match
214 ( cat ${OBJ}/sshd_proxy.bak ;
215 echo "AllowTcpForwarding $_tcpfwd" ;
216 echo "PermitListen $_badfwd1 $_goodfwd $_badfwd2" ) \
218 check_lfwd $_plain_lfwd "$_prefix, PermitListen"
219 check_rfwd $_plain_rfwd "$_prefix, PermitListen"
222 # permit-remote-open none mismatch match
223 # AllowTcpForwarding local remote local remote local remote
224 rperm_tests yes Y Y Y N Y Y
225 rperm_tests local Y N Y N Y N
226 rperm_tests remote N Y N N N Y
227 rperm_tests no N N N N N N