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