1# $OpenBSD: forward-control.sh,v 1.5 2018/03/02 02:51:55 djm 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 Y|N message 36check_lfwd() { 37 _expected=$1 38 _message=$2 39 rm -f $READY 40 ${SSH} -F $OBJ/ssh_proxy \ 41 -L$LFWD_PORT:127.0.0.1:$PORT \ 42 -o ExitOnForwardFailure=yes \ 43 -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ 44 >/dev/null 2>&1 & 45 _sshpid=$! 46 wait_for_file_to_appear $READY || \ 47 fatal "check_lfwd ssh fail: $_message" 48 ${SSH} -F $OBJ/ssh_config -p $LFWD_PORT \ 49 -oConnectionAttempts=4 host true >/dev/null 2>&1 50 _result=$? 51 kill $_sshpid `cat $READY` 2>/dev/null 52 wait_for_process_to_exit $_sshpid 53 if test "x$_expected" = "xY" -a $_result -ne 0 ; then 54 fail "check_lfwd failed (expecting success): $_message" 55 elif test "x$_expected" = "xN" -a $_result -eq 0 ; then 56 fail "check_lfwd succeeded (expecting failure): $_message" 57 elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then 58 fatal "check_lfwd invalid argument \"$_expected\"" 59 else 60 verbose "check_lfwd done (expecting $_expected): $_message" 61 fi 62} 63 64# usage: check_rfwd Y|N message 65check_rfwd() { 66 _expected=$1 67 _message=$2 68 rm -f $READY 69 ${SSH} -F $OBJ/ssh_proxy \ 70 -R$RFWD_PORT:127.0.0.1:$PORT \ 71 -o ExitOnForwardFailure=yes \ 72 -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ 73 >/dev/null 2>&1 & 74 _sshpid=$! 75 wait_for_file_to_appear $READY 76 _result=$? 77 if test $_result -eq 0 ; then 78 ${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \ 79 -oConnectionAttempts=4 host true >/dev/null 2>&1 80 _result=$? 81 kill $_sshpid `cat $READY` 2>/dev/null 82 wait_for_process_to_exit $_sshpid 83 fi 84 if test "x$_expected" = "xY" -a $_result -ne 0 ; then 85 fail "check_rfwd failed (expecting success): $_message" 86 elif test "x$_expected" = "xN" -a $_result -eq 0 ; then 87 fail "check_rfwd succeeded (expecting failure): $_message" 88 elif test "x$_expected" != "xY" -a "x$_expected" != "xN" ; then 89 fatal "check_rfwd invalid argument \"$_expected\"" 90 else 91 verbose "check_rfwd done (expecting $_expected): $_message" 92 fi 93} 94 95start_sshd 96cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak 97cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak 98 99# Sanity check: ensure the default config allows forwarding 100check_lfwd Y "default configuration" 101check_rfwd Y "default configuration" 102 103# Usage: all_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N 104all_tests() { 105 _tcpfwd=$1 106 _plain_lfwd=$2 107 _plain_rfwd=$3 108 _nopermit_lfwd=$4 109 _nopermit_rfwd=$5 110 _permit_lfwd=$6 111 _permit_rfwd=$7 112 _badfwd=127.0.0.1:22 113 _goodfwd=127.0.0.1:${PORT} 114 cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER} 115 _prefix="AllowTcpForwarding=$_tcpfwd" 116 # No PermitOpen 117 ( cat ${OBJ}/sshd_proxy.bak ; 118 echo "AllowTcpForwarding $_tcpfwd" ) \ 119 > ${OBJ}/sshd_proxy 120 check_lfwd $_plain_lfwd "$_prefix" 121 check_rfwd $_plain_rfwd "$_prefix" 122 # PermitOpen via sshd_config that doesn't match 123 ( cat ${OBJ}/sshd_proxy.bak ; 124 echo "AllowTcpForwarding $_tcpfwd" ; 125 echo "PermitOpen $_badfwd" ) \ 126 > ${OBJ}/sshd_proxy 127 check_lfwd $_nopermit_lfwd "$_prefix, !PermitOpen" 128 check_rfwd $_nopermit_rfwd "$_prefix, !PermitOpen" 129 # PermitOpen via sshd_config that does match 130 ( cat ${OBJ}/sshd_proxy.bak ; 131 echo "AllowTcpForwarding $_tcpfwd" ; 132 echo "PermitOpen $_badfwd $_goodfwd" ) \ 133 > ${OBJ}/sshd_proxy 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=\"$_badfwd\" /" \ 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" ) \ 142 > ${OBJ}/sshd_proxy 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=\"$_badfwd\",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" ) \ 151 > ${OBJ}/sshd_proxy 152 check_lfwd $_permit_lfwd "$_prefix, permitopen" 153 check_rfwd $_permit_rfwd "$_prefix, permitopen" 154 # Check port-forwarding flags in authorized_keys. 155 # These two should refuse all. 156 sed "s/^/no-port-forwarding /" \ 157 < ${OBJ}/authorized_keys_${USER}.bak \ 158 > ${OBJ}/authorized_keys_${USER} || fatal "sed 3 fail" 159 ( cat ${OBJ}/sshd_proxy.bak ; 160 echo "AllowTcpForwarding $_tcpfwd" ) \ 161 > ${OBJ}/sshd_proxy 162 check_lfwd N "$_prefix, no-port-forwarding" 163 check_rfwd N "$_prefix, no-port-forwarding" 164 sed "s/^/restrict /" \ 165 < ${OBJ}/authorized_keys_${USER}.bak \ 166 > ${OBJ}/authorized_keys_${USER} || fatal "sed 4 fail" 167 ( cat ${OBJ}/sshd_proxy.bak ; 168 echo "AllowTcpForwarding $_tcpfwd" ) \ 169 > ${OBJ}/sshd_proxy 170 check_lfwd N "$_prefix, restrict" 171 check_rfwd N "$_prefix, restrict" 172 # This should pass the same cases as _nopermit* 173 sed "s/^/restrict,port-forwarding /" \ 174 < ${OBJ}/authorized_keys_${USER}.bak \ 175 > ${OBJ}/authorized_keys_${USER} || fatal "sed 5 fail" 176 ( cat ${OBJ}/sshd_proxy.bak ; 177 echo "AllowTcpForwarding $_tcpfwd" ) \ 178 > ${OBJ}/sshd_proxy 179 check_lfwd $_plain_lfwd "$_prefix, restrict,port-forwarding" 180 check_rfwd $_plain_rfwd "$_prefix, restrict,port-forwarding" 181} 182 183# no-permitopen mismatch-permitopen match-permitopen 184# AllowTcpForwarding local remote local remote local remote 185all_tests yes Y Y N Y Y Y 186all_tests local Y N N N Y N 187all_tests remote N Y N Y N Y 188all_tests no N N N N N N 189