1*190cef3dSDag-Erling Smørgrav# $OpenBSD: forward-control.sh,v 1.7 2018/06/07 14:29:43 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 \ 70*190cef3dSDag-Erling Smørgrav -R127.0.0.1:$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 103*190cef3dSDag-Erling Smørgrav# Usage: lperm_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N 104*190cef3dSDag-Erling Smørgravlperm_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 112*190cef3dSDag-Erling Smørgrav _badfwd1=127.0.0.1:22 113*190cef3dSDag-Erling Smørgrav _badfwd2=127.0.0.2:22 114ce3adf43SDag-Erling Smørgrav _goodfwd=127.0.0.1:${PORT} 1154f52dfbbSDag-Erling Smørgrav cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER} 1164f52dfbbSDag-Erling Smørgrav _prefix="AllowTcpForwarding=$_tcpfwd" 117*190cef3dSDag-Erling Smørgrav 118ce3adf43SDag-Erling Smørgrav # No PermitOpen 119ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 120ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 121ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1224f52dfbbSDag-Erling Smørgrav check_lfwd $_plain_lfwd "$_prefix" 1234f52dfbbSDag-Erling Smørgrav check_rfwd $_plain_rfwd "$_prefix" 124*190cef3dSDag-Erling Smørgrav 125ce3adf43SDag-Erling Smørgrav # PermitOpen via sshd_config that doesn't match 126ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 127ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ; 128*190cef3dSDag-Erling Smørgrav echo "PermitOpen $_badfwd1 $_badfwd2" ) \ 129ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1304f52dfbbSDag-Erling Smørgrav check_lfwd $_nopermit_lfwd "$_prefix, !PermitOpen" 1314f52dfbbSDag-Erling Smørgrav check_rfwd $_nopermit_rfwd "$_prefix, !PermitOpen" 132ce3adf43SDag-Erling Smørgrav # PermitOpen via sshd_config that does match 133ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 134ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ; 135*190cef3dSDag-Erling Smørgrav echo "PermitOpen $_badfwd1 $_goodfwd $_badfwd2" ) \ 136ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 137*190cef3dSDag-Erling Smørgrav check_lfwd $_plain_lfwd "$_prefix, PermitOpen" 138*190cef3dSDag-Erling Smørgrav check_rfwd $_plain_rfwd "$_prefix, PermitOpen" 139*190cef3dSDag-Erling Smørgrav 140*190cef3dSDag-Erling Smørgrav # permitopen keys option. 141ce3adf43SDag-Erling Smørgrav # NB. permitopen via authorized_keys should have same 142ce3adf43SDag-Erling Smørgrav # success/fail as via sshd_config 143ce3adf43SDag-Erling Smørgrav # permitopen via authorized_keys that doesn't match 144*190cef3dSDag-Erling Smørgrav sed "s/^/permitopen=\"$_badfwd1\",permitopen=\"$_badfwd2\" /" \ 145ce3adf43SDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 146ce3adf43SDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 1 fail" 147ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 148ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 149ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1504f52dfbbSDag-Erling Smørgrav check_lfwd $_nopermit_lfwd "$_prefix, !permitopen" 1514f52dfbbSDag-Erling Smørgrav check_rfwd $_nopermit_rfwd "$_prefix, !permitopen" 152ce3adf43SDag-Erling Smørgrav # permitopen via authorized_keys that does match 153*190cef3dSDag-Erling Smørgrav sed "s/^/permitopen=\"$_badfwd1\",permitopen=\"$_goodfwd\" /" \ 154ce3adf43SDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 155ce3adf43SDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 2 fail" 156ce3adf43SDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 157ce3adf43SDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 158ce3adf43SDag-Erling Smørgrav > ${OBJ}/sshd_proxy 1594f52dfbbSDag-Erling Smørgrav check_lfwd $_permit_lfwd "$_prefix, permitopen" 1604f52dfbbSDag-Erling Smørgrav check_rfwd $_permit_rfwd "$_prefix, permitopen" 161*190cef3dSDag-Erling Smørgrav 16247dd1d1bSDag-Erling Smørgrav # Check port-forwarding flags in authorized_keys. 16347dd1d1bSDag-Erling Smørgrav # These two should refuse all. 16447dd1d1bSDag-Erling Smørgrav sed "s/^/no-port-forwarding /" \ 16547dd1d1bSDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 16647dd1d1bSDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 3 fail" 16747dd1d1bSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 16847dd1d1bSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 16947dd1d1bSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 17047dd1d1bSDag-Erling Smørgrav check_lfwd N "$_prefix, no-port-forwarding" 17147dd1d1bSDag-Erling Smørgrav check_rfwd N "$_prefix, no-port-forwarding" 17247dd1d1bSDag-Erling Smørgrav sed "s/^/restrict /" \ 17347dd1d1bSDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 17447dd1d1bSDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 4 fail" 17547dd1d1bSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 17647dd1d1bSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 17747dd1d1bSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 17847dd1d1bSDag-Erling Smørgrav check_lfwd N "$_prefix, restrict" 17947dd1d1bSDag-Erling Smørgrav check_rfwd N "$_prefix, restrict" 18047dd1d1bSDag-Erling Smørgrav # This should pass the same cases as _nopermit* 18147dd1d1bSDag-Erling Smørgrav sed "s/^/restrict,port-forwarding /" \ 18247dd1d1bSDag-Erling Smørgrav < ${OBJ}/authorized_keys_${USER}.bak \ 18347dd1d1bSDag-Erling Smørgrav > ${OBJ}/authorized_keys_${USER} || fatal "sed 5 fail" 18447dd1d1bSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 18547dd1d1bSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ) \ 18647dd1d1bSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 18747dd1d1bSDag-Erling Smørgrav check_lfwd $_plain_lfwd "$_prefix, restrict,port-forwarding" 18847dd1d1bSDag-Erling Smørgrav check_rfwd $_plain_rfwd "$_prefix, restrict,port-forwarding" 189ce3adf43SDag-Erling Smørgrav} 190ce3adf43SDag-Erling Smørgrav 191*190cef3dSDag-Erling Smørgrav# permit-open none mismatch match 192ce3adf43SDag-Erling Smørgrav# AllowTcpForwarding local remote local remote local remote 193*190cef3dSDag-Erling Smørgravlperm_tests yes Y Y N Y Y Y 194*190cef3dSDag-Erling Smørgravlperm_tests local Y N N N Y N 195*190cef3dSDag-Erling Smørgravlperm_tests remote N Y N Y N Y 196*190cef3dSDag-Erling Smørgravlperm_tests no N N N N N N 197*190cef3dSDag-Erling Smørgrav 198*190cef3dSDag-Erling Smørgrav# Usage: rperm_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N 199*190cef3dSDag-Erling Smørgravrperm_tests() { 200*190cef3dSDag-Erling Smørgrav _tcpfwd=$1 201*190cef3dSDag-Erling Smørgrav _plain_lfwd=$2 202*190cef3dSDag-Erling Smørgrav _plain_rfwd=$3 203*190cef3dSDag-Erling Smørgrav _nopermit_lfwd=$4 204*190cef3dSDag-Erling Smørgrav _nopermit_rfwd=$5 205*190cef3dSDag-Erling Smørgrav _permit_lfwd=$6 206*190cef3dSDag-Erling Smørgrav _permit_rfwd=$7 207*190cef3dSDag-Erling Smørgrav _badfwd1=127.0.0.1:22 208*190cef3dSDag-Erling Smørgrav _badfwd2=127.0.0.2:${RFWD_PORT} 209*190cef3dSDag-Erling Smørgrav _goodfwd=127.0.0.1:${RFWD_PORT} 210*190cef3dSDag-Erling Smørgrav cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER} 211*190cef3dSDag-Erling Smørgrav _prefix="AllowTcpForwarding=$_tcpfwd" 212*190cef3dSDag-Erling Smørgrav 213*190cef3dSDag-Erling Smørgrav # PermitListen via sshd_config that doesn't match 214*190cef3dSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 215*190cef3dSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ; 216*190cef3dSDag-Erling Smørgrav echo "PermitListen $_badfwd1 $_badfwd2" ) \ 217*190cef3dSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 218*190cef3dSDag-Erling Smørgrav check_lfwd $_nopermit_lfwd "$_prefix, !PermitListen" 219*190cef3dSDag-Erling Smørgrav check_rfwd $_nopermit_rfwd "$_prefix, !PermitListen" 220*190cef3dSDag-Erling Smørgrav # PermitListen via sshd_config that does match 221*190cef3dSDag-Erling Smørgrav ( cat ${OBJ}/sshd_proxy.bak ; 222*190cef3dSDag-Erling Smørgrav echo "AllowTcpForwarding $_tcpfwd" ; 223*190cef3dSDag-Erling Smørgrav echo "PermitListen $_badfwd1 $_goodfwd $_badfwd2" ) \ 224*190cef3dSDag-Erling Smørgrav > ${OBJ}/sshd_proxy 225*190cef3dSDag-Erling Smørgrav check_lfwd $_plain_lfwd "$_prefix, PermitListen" 226*190cef3dSDag-Erling Smørgrav check_rfwd $_plain_rfwd "$_prefix, PermitListen" 227*190cef3dSDag-Erling Smørgrav} 228*190cef3dSDag-Erling Smørgrav 229*190cef3dSDag-Erling Smørgrav# permit-remote-open none mismatch match 230*190cef3dSDag-Erling Smørgrav# AllowTcpForwarding local remote local remote local remote 231*190cef3dSDag-Erling Smørgravrperm_tests yes Y Y Y N Y Y 232*190cef3dSDag-Erling Smørgravrperm_tests local Y N Y N Y N 233*190cef3dSDag-Erling Smørgravrperm_tests remote N Y N N N Y 234*190cef3dSDag-Erling Smørgravrperm_tests no N N N N N N 235*190cef3dSDag-Erling Smørgrav 236