markus@openbsd.org | dad2b18 | 2015-03-03 22:35:19 +0000 | [diff] [blame] | 1 | # $OpenBSD: forward-control.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 2 | # Placed in the Public Domain. |
| 3 | |
| 4 | tid="sshd control of local and remote forwarding" |
| 5 | |
| 6 | LFWD_PORT=3320 |
| 7 | RFWD_PORT=3321 |
| 8 | CTL=$OBJ/ctl-sock |
| 9 | READY=$OBJ/ready |
| 10 | |
| 11 | wait_for_file_to_appear() { |
| 12 | _path=$1 |
| 13 | _n=0 |
Tim Rice | 0ec7423 | 2013-02-20 21:37:55 -0800 | [diff] [blame] | 14 | while test ! -f $_path ; do |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 15 | test $_n -eq 1 && trace "waiting for $_path to appear" |
| 16 | _n=`expr $_n + 1` |
Darren Tucker | 834a0d6 | 2013-03-06 14:06:48 +1100 | [diff] [blame] | 17 | test $_n -ge 20 && return 1 |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 18 | sleep 1 |
| 19 | done |
| 20 | return 0 |
| 21 | } |
| 22 | |
| 23 | wait_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` |
Darren Tucker | 834a0d6 | 2013-03-06 14:06:48 +1100 | [diff] [blame] | 29 | test $_n -ge 20 && return 1 |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 30 | sleep 1 |
| 31 | done |
| 32 | return 0 |
| 33 | } |
| 34 | |
| 35 | # usage: check_lfwd protocol Y|N message |
| 36 | check_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 \ |
Tim Rice | a514bc0 | 2013-02-26 19:35:26 -0800 | [diff] [blame] | 44 | -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 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 |
| 66 | check_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 \ |
Tim Rice | a514bc0 | 2013-02-26 19:35:26 -0800 | [diff] [blame] | 74 | -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 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 | |
| 97 | start_sshd |
| 98 | cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak |
| 99 | cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak |
| 100 | |
| 101 | # Sanity check: ensure the default config allows forwarding |
markus@openbsd.org | dad2b18 | 2015-03-03 22:35:19 +0000 | [diff] [blame] | 102 | for p in ${SSH_PROTOCOLS} ; do |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 103 | check_lfwd $p Y "proto $p, default configuration" |
| 104 | check_rfwd $p Y "proto $p, default configuration" |
| 105 | done |
| 106 | |
| 107 | # Usage: all_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N |
| 108 | all_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} |
markus@openbsd.org | dad2b18 | 2015-03-03 22:35:19 +0000 | [diff] [blame] | 118 | for _proto in ${SSH_PROTOCOLS} ; do |
Damien Miller | 999bd2d | 2012-12-03 10:13:39 +1100 | [diff] [blame] | 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 |
| 165 | all_tests yes Y Y N Y Y Y |
| 166 | all_tests local Y N N N Y N |
| 167 | all_tests remote N Y N Y N Y |
| 168 | all_tests no N N N N N N |