1*47dd1d1bSDag-Erling Smørgrav# $OpenBSD: forward-control.sh,v 1.5 2018/03/02 02:51:55 djm Exp $ 2ce3adf43SDag-Erling Smørgrav# Placed in the Public Domain. 3ce3adf43SDag-Erling Smørgrav 4ce3adf43SDag-Erling Smørgravtid="sshd control of local and remote forwarding" 5ce3adf43SDag-Erling Smørgrav 6ce3adf43SDag-Erling SmørgravLFWD_PORT=3320 7ce3adf43SDag-Erling SmørgravRFWD_PORT=3321 8ce3adf43SDag-Erling SmørgravCTL=$OBJ/ctl-sock 9ce3adf43SDag-Erling SmørgravREADY=$OBJ/ready 10ce3adf43SDag-Erling Smørgrav 11ce3adf43SDag-Erling Smørgravwait_for_file_to_appear() { 12ce3adf43SDag-Erling Smørgrav _path=$1 13ce3adf43SDag-Erling Smørgrav _n=0 14ce3adf43SDag-Erling Smørgrav while test ! -f $_path ; do 15ce3adf43SDag-Erling Smørgrav test $_n -eq 1 && trace "waiting for $_path to appear" 16ce3adf43SDag-Erling Smørgrav _n=`expr $_n + 1` 17ce3adf43SDag-Erling Smørgrav test $_n -ge 20 && return 1 18ce3adf43SDag-Erling Smørgrav sleep 1 19ce3adf43SDag-Erling Smørgrav done 20ce3adf43SDag-Erling Smørgrav return 0 21ce3adf43SDag-Erling Smørgrav} 22ce3adf43SDag-Erling Smørgrav 23ce3adf43SDag-Erling Smørgravwait_for_process_to_exit() { 24ce3adf43SDag-Erling Smørgrav _pid=$1 25ce3adf43SDag-Erling Smørgrav _n=0 26ce3adf43SDag-Erling Smørgrav while kill -0 $_pid 2>/dev/null ; do 27ce3adf43SDag-Erling Smørgrav test $_n -eq 1 && trace "waiting for $_pid to exit" 28ce3adf43SDag-Erling Smørgrav _n=`expr $_n + 1` 29ce3adf43SDag-Erling Smørgrav test $_n -ge 20 && return 1 30ce3adf43SDag-Erling Smørgrav sleep 1 31ce3adf43SDag-Erling Smørgrav done 32ce3adf43SDag-Erling Smørgrav return 0 33ce3adf43SDag-Erling Smørgrav} 34ce3adf43SDag-Erling Smørgrav 354f52dfbbSDag-Erling Smørgrav# usage: check_lfwd Y|N message 36ce3adf43SDag-Erling Smørgravcheck_lfwd() { 374f52dfbbSDag-Erling Smørgrav _expected=$1 384f52dfbbSDag-Erling Smørgrav _message=$2 39ce3adf43SDag-Erling Smørgrav rm -f $READY 404f52dfbbSDag-Erling Smørgrav ${SSH} -F $OBJ/ssh_proxy \ 41ce3adf43SDag-Erling Smørgrav -L$LFWD_PORT:127.0.0.1:$PORT \ 42ce3adf43SDag-Erling Smørgrav -o ExitOnForwardFailure=yes \ 43ce3adf43SDag-Erling Smørgrav -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ 44ce3adf43SDag-Erling Smørgrav >/dev/null 2>&1 & 45ce3adf43SDag-Erling Smørgrav _sshpid=$! 46ce3adf43SDag-Erling Smørgrav wait_for_file_to_appear $READY || \ 47ce3adf43SDag-Erling Smørgrav fatal "check_lfwd ssh fail: $_message" 48ce3adf43SDag-Erling Smørgrav ${SSH} -F $OBJ/ssh_config -p $LFWD_PORT \ 49ce3adf43SDag-Erling Smørgrav -oConnectionAttempts=4 host true >/dev/null 2>&1 50ce3adf43SDag-Erling Smørgrav _result=$? 51ce3adf43SDag-Erling Smørgrav kill $_sshpid `cat $READY` 2>/dev/null 52ce3adf43SDag-Erling Smørgrav wait_for_process_to_exit $_sshpid 53ce3adf43SDag-Erling Smørgrav if test "x$_expected" = "xY" -a $_result -ne 0 ; then 54ce3adf43SDag-Erling Smørgrav fail "check_lfwd failed (expecting success): $_message" 55ce3adf43SDag-Erling Smørgrav elif test "x$_expected" = "xN" -a $_result -eq 0 ; then 56ce3adf43SDag-Erling Smørgrav fail "check_lfwd succeeded (expecting failure): $_message" 57ce3adf43SDag-Erling Smørgrav elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then 58ce3adf43SDag-Erling Smørgrav fatal "check_lfwd invalid argument \"$_expected\"" 59ce3adf43SDag-Erling Smørgrav else 60ce3adf43SDag-Erling Smørgrav verbose "check_lfwd done (expecting $_expected): $_message" 61ce3adf43SDag-Erling Smørgrav fi 62ce3adf43SDag-Erling Smørgrav} 63ce3adf43SDag-Erling Smørgrav 644f52dfbbSDag-Erling Smørgrav# usage: check_rfwd Y|N message 65ce3adf43SDag-Erling Smørgravcheck_rfwd() { 664f52dfbbSDag-Erling Smørgrav _expected=$1 674f52dfbbSDag-Erling Smørgrav _message=$2 68ce3adf43SDag-Erling Smørgrav rm -f $READY 694f52dfbbSDag-Erling Smørgrav ${SSH} -F $OBJ/ssh_proxy \ 70ce3adf43SDag-Erling Smørgrav -R$RFWD_PORT:127.0.0.1:$PORT \ 71ce3adf43SDag-Erling Smørgrav -o ExitOnForwardFailure=yes \ 72ce3adf43SDag-Erling Smørgrav -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ 73ce3adf43SDag-Erling Smørgrav >/dev/null 2>&1 & 74ce3adf43SDag-Erling Smørgrav _sshpid=$! 75ce3adf43SDag-Erling Smørgrav wait_for_file_to_appear $READY 76ce3adf43SDag-Erling Smørgrav _result=$? 77ce3adf43SDag-Erling Smørgrav if test $_result -eq 0 ; then 78ce3adf43SDag-Erling Smørgrav ${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \ 79ce3adf43SDag-Erling Smørgrav -oConnectionAttempts=4 host true >/dev/null 2>&1 80ce3adf43SDag-Erling Smørgrav _result=$? 81ce3adf43SDag-Erling Smørgrav kill $_sshpid `cat $READY` 2>/dev/null 82ce3adf43SDag-Erling Smørgrav wait_for_process_to_exit $_sshpid 83ce3adf43SDag-Erling Smørgrav fi 84ce3adf43SDag-Erling Smørgrav if test "x$_expected" = "xY" -a $_result -ne 0 ; then 85ce3adf43SDag-Erling Smørgrav fail "check_rfwd failed (expecting success): $_message" 86ce3adf43SDag-Erling Smørgrav elif test "x$_expected" = "xN" -a $_result -eq 0 ; then 87ce3adf43SDag-Erling Smørgrav fail "check_rfwd succeeded (expecting failure): $_message" 88ce3adf43SDag-Erling Smørgrav elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then 89ce3adf43SDag-Erling Smørgrav fatal "check_rfwd invalid argument \"$_expected\"" 90ce3adf43SDag-Erling Smørgrav else 91ce3adf43SDag-Erling Smørgrav verbose "check_rfwd done (expecting $_expected): $_message" 92ce3adf43SDag-Erling Smørgrav fi 93ce3adf43SDag-Erling Smørgrav} 94ce3adf43SDag-Erling Smørgrav 95ce3adf43SDag-Erling Smørgravstart_sshd 96ce3adf43SDag-Erling Smørgravcp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak 97ce3adf43SDag-Erling Smørgravcp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak 98ce3adf43SDag-Erling Smørgrav 99ce3adf43SDag-Erling Smørgrav# Sanity check: ensure the default config allows forwarding 1004f52dfbbSDag-Erling Smørgravcheck_lfwd Y "default configuration" 1014f52dfbbSDag-Erling Smørgravcheck_rfwd Y "default configuration" 102ce3adf43SDag-Erling Smørgrav 103ce3adf43SDag-Erling Smørgrav# Usage: all_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N 104ce3adf43SDag-Erling Smørgravall_tests() { 105ce3adf43SDag-Erling Smørgrav _tcpfwd=$1 106ce3adf43SDag-Erling Smørgrav _plain_lfwd=$2 107ce3adf43SDag-Erling Smørgrav _plain_rfwd=$3 108ce3adf43SDag-Erling Smørgrav _nopermit_lfwd=$4 109ce3adf43SDag-Erling Smørgrav _nopermit_rfwd=$5 110ce3adf43SDag-Erling Smørgrav _permit_lfwd=$6 111ce3adf43SDag-Erling Smørgrav _permit_rfwd=$7 112ce3adf43SDag-Erling Smørgrav _badfwd=127.0.0.1:22 113ce3adf43SDag-Erling Smørgrav _goodfwd=127.0.0.1:${PORT} 1144f52dfbbSDag-Erling Smørgrav cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER} 1154f52dfbbSDag-Erling Smørgrav _prefix="AllowTcpForwarding=$_tcpfwd" 116ce3adf43SDag-Erling Smørgrav # No PermitOpen 117ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 118ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 119ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1204f52dfbbSDag-Erling Smørgrav check_lfwd $_plain_lfwd "$_prefix" 1214f52dfbbSDag-Erling Smørgrav check_rfwd $_plain_rfwd "$_prefix" 122ce3adf43SDag-Erling Smørgrav # PermitOpen via sshd_config that doesn't match 123ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 124ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ; 125ce3adf43SDag-Erling Smørgrav echo "PermitOpen $_badfwd" ) \ 126ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1274f52dfbbSDag-Erling Smørgrav check_lfwd $_nopermit_lfwd "$_prefix, !PermitOpen" 1284f52dfbbSDag-Erling Smørgrav check_rfwd $_nopermit_rfwd "$_prefix, !PermitOpen" 129ce3adf43SDag-Erling Smørgrav # PermitOpen via sshd_config that does match 130ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 131ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ; 132ce3adf43SDag-Erling Smørgrav echo "PermitOpen $_badfwd $_goodfwd" ) \ 133ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 134ce3adf43SDag-Erling Smørgrav # NB. permitopen via authorized_keys should have same 135ce3adf43SDag-Erling Smørgrav # success/fail as via sshd_config 136ce3adf43SDag-Erling Smørgrav # permitopen via authorized_keys that doesn't match 137ce3adf43SDag-Erling Smørgrav sed "s/^/permitopen=\"$_badfwd\" /" \ 138ce3adf43SDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 139ce3adf43SDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 1 fail" 140ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 141ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 142ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1434f52dfbbSDag-Erling Smørgrav check_lfwd $_nopermit_lfwd "$_prefix, !permitopen" 1444f52dfbbSDag-Erling Smørgrav check_rfwd $_nopermit_rfwd "$_prefix, !permitopen" 145ce3adf43SDag-Erling Smørgrav # permitopen via authorized_keys that does match 146ce3adf43SDag-Erling Smørgrav sed "s/^/permitopen=\"$_badfwd\",permitopen=\"$_goodfwd\" /" \ 147ce3adf43SDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 148ce3adf43SDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 2 fail" 149ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 150ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 151ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1524f52dfbbSDag-Erling Smørgrav check_lfwd $_permit_lfwd "$_prefix, permitopen" 1534f52dfbbSDag-Erling Smørgrav check_rfwd $_permit_rfwd "$_prefix, permitopen" 154*47dd1d1bSDag-Erling Smørgrav # Check port-forwarding flags in authorized_keys. 155*47dd1d1bSDag-Erling Smørgrav # These two should refuse all. 156*47dd1d1bSDag-Erling Smørgrav sed "s/^/no-port-forwarding /" \ 157*47dd1d1bSDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 158*47dd1d1bSDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 3 fail" 159*47dd1d1bSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 160*47dd1d1bSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 161*47dd1d1bSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 162*47dd1d1bSDag-Erling Smørgrav check_lfwd N "$_prefix, no-port-forwarding" 163*47dd1d1bSDag-Erling Smørgrav check_rfwd N "$_prefix, no-port-forwarding" 164*47dd1d1bSDag-Erling Smørgrav sed "s/^/restrict /" \ 165*47dd1d1bSDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 166*47dd1d1bSDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 4 fail" 167*47dd1d1bSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 168*47dd1d1bSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 169*47dd1d1bSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 170*47dd1d1bSDag-Erling Smørgrav check_lfwd N "$_prefix, restrict" 171*47dd1d1bSDag-Erling Smørgrav check_rfwd N "$_prefix, restrict" 172*47dd1d1bSDag-Erling Smørgrav # This should pass the same cases as _nopermit* 173*47dd1d1bSDag-Erling Smørgrav sed "s/^/restrict,port-forwarding /" \ 174*47dd1d1bSDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 175*47dd1d1bSDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 5 fail" 176*47dd1d1bSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 177*47dd1d1bSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 178*47dd1d1bSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 179*47dd1d1bSDag-Erling Smørgrav check_lfwd $_plain_lfwd "$_prefix, restrict,port-forwarding" 180*47dd1d1bSDag-Erling Smørgrav check_rfwd $_plain_rfwd "$_prefix, restrict,port-forwarding" 181ce3adf43SDag-Erling Smørgrav} 182ce3adf43SDag-Erling Smørgrav 183ce3adf43SDag-Erling Smørgrav# no-permitopen mismatch-permitopen match-permitopen 184ce3adf43SDag-Erling Smørgrav# AllowTcpForwarding local remote local remote local remote 185ce3adf43SDag-Erling Smørgravall_tests yes Y Y N Y Y Y 186ce3adf43SDag-Erling Smørgravall_tests local Y N N N Y N 187ce3adf43SDag-Erling Smørgravall_tests remote N Y N Y N Y 188ce3adf43SDag-Erling Smørgravall_tests no N N N N N N 189