1# $OpenBSD: percent.sh,v 1.21 2025/04/08 23:10:46 djm Exp $ 2# Placed in the Public Domain. 3 4tid="percent expansions" 5 6USER=`id -u -n` 7USERID=`id -u` 8HOST=`hostname | cut -f1 -d.` 9HOSTNAME=`hostname` 10HASH="" 11 12# Localcommand is evaluated after connection because %T is not available 13# until then. Because of this we use a different method of exercising it, 14# and we can't override the remote user otherwise authentication will fail. 15# We also have to explicitly enable it. 16echo "permitlocalcommand yes" >> $OBJ/ssh_proxy 17 18trial() 19{ 20 opt="$1"; arg="$2" 21 expect=`echo "$3" | sed 's|^//|/|'` # approximate realpath 22 23 trace "test $opt=$arg $expect" 24 rm -f $OBJ/actual 25 got="" 26 case "$opt" in 27 localcommand) 28 ${SSH} -F $OBJ/ssh_proxy -o $opt="echo '$arg' >$OBJ/actual" \ 29 somehost true 30 got=`cat $OBJ/actual` 31 ;; 32 user|user-l|user-at) 33 if [ "$arg" = '%r' ] || [ "$arg" = '%C' ]; then 34 # User does not support %r, ie itself or %C. Skip test. 35 got="$expect" 36 elif [ "$i" = "user" ]; then 37 got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \ 38 remuser@somehost | awk '$1=="'$opt'"{print $2}'` 39 elif [ "$i" = "user-l" ]; then 40 # Also test ssh -l 41 got=`${SSH} -F $OBJ/ssh_proxy -l "$arg" -G \ 42 somehost | awk '$1=="'user'"{print $2}'` 43 elif [ "$i" = "user-at" ]; then 44 # Also test user@host 45 got=`${SSH} -F $OBJ/ssh_proxy -G "$arg@somehost" | \ 46 awk '$1=="'user'"{print $2}'` 47 fi 48 ;; 49 userknownhostsfile) 50 # Move the userknownhosts file to what the expansion says, 51 # make sure ssh works then put it back. 52 mv "$OBJ/known_hosts" "$OBJ/$expect" 53 ${SSH} -F $OBJ/ssh_proxy -o $opt="$OBJ/$arg" somehost true && \ 54 got="$expect" 55 mv "$OBJ/$expect" "$OBJ/known_hosts" 56 ;; 57 matchexec) 58 (cat $OBJ/ssh_proxy && \ 59 echo "Match Exec \"echo '$arg' >$OBJ/actual\"") \ 60 >$OBJ/ssh_proxy_match 61 ${SSH} -F $OBJ/ssh_proxy_match remuser@somehost true || true 62 got=`cat $OBJ/actual` 63 ;; 64 *forward) 65 # LocalForward and RemoteForward take two args and only 66 # operate on Unix domain socket paths 67 got=`${SSH} -F $OBJ/ssh_proxy -o $opt="/$arg /$arg" -G \ 68 remuser@somehost | awk '$1=="'$opt'"{print $2" "$3}'` 69 expect="/$expect /$expect" 70 ;; 71 setenv) 72 # First make sure we don't expand variable names. 73 got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg=TESTVAL" -G \ 74 remuser@somehost | awk '$1=="'$opt'"{print $2}'` 75 if [ "$got" != "$arg=TESTVAL" ]; then 76 fatal "incorrectly expanded setenv variable name" 77 fi 78 # Now check that the value expands as expected. 79 got=`${SSH} -F $OBJ/ssh_proxy -o $opt=TESTVAL="$arg" -G \ 80 remuser@somehost | awk '$1=="'$opt'"{print $2}'` 81 got=`echo "$got" | sed 's/^TESTVAL=//'` 82 ;; 83 *) 84 got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \ 85 remuser@somehost | awk '$1=="'$opt'"{print $2}'` 86 esac 87 if [ "$got" != "$expect" ]; then 88 fail "$opt=$arg expect $expect got $got" 89 fi 90} 91 92for i in matchexec localcommand remotecommand controlpath identityagent \ 93 forwardagent localforward remoteforward revokedhostkeys \ 94 user user-l user-at setenv userknownhostsfile; do 95 verbose $tid $i percent 96 case "$i" in 97 localcommand|userknownhostsfile) 98 # Any test that's going to actually make a connection needs 99 # to use the real username. 100 REMUSER=$USER ;; 101 *) 102 REMUSER=remuser ;; 103 esac 104 if [ "$i" = "$localcommand" ]; then 105 trial $i '%T' NONE 106 fi 107 # Matches implementation in readconf.c:ssh_connection_hash() 108 if [ ! -z "${OPENSSL_BIN}" ]; then 109 HASH=`printf "${HOSTNAME}127.0.0.1${PORT}${REMUSER}" | 110 $OPENSSL_BIN sha1 | cut -f2 -d' '` 111 trial $i '%C' $HASH 112 fi 113 trial $i '%%' '%' 114 trial $i '%i' $USERID 115 trial $i '%h' 127.0.0.1 116 trial $i '%L' $HOST 117 trial $i '%l' $HOSTNAME 118 trial $i '%n' somehost 119 trial $i '%k' localhost-with-alias 120 trial $i '%p' $PORT 121 trial $i '%r' $REMUSER 122 trial $i '%u' $USER 123 # We can't specify a full path outside the regress dir, so skip tests 124 # containing %d for UserKnownHostsFile, and %r can't refer to itself. 125 if [ "$i" != "userknownhostsfile" ] && [ "$i" != "user" ] && \ 126 [ "$i" != "user-l" ] && [ "$i" != "user-at" ]; then 127 trial $i '%d' $HOME 128 in='%%/%i/%h/%d/%L/%l/%n/%p/%r/%u' 129 out="%/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" 130 if [ ! -z "${HASH}" ]; then 131 in="$in/%C" 132 out="$out/$HASH" 133 fi 134 trial $i "$in" "$out" 135 fi 136done 137 138# Subset of above since we don't expand shell-style variables on anything that 139# runs a command because the shell will expand those. 140for i in controlpath identityagent forwardagent localforward remoteforward \ 141 user user-l user-at setenv userknownhostsfile; do 142 verbose $tid $i dollar 143 FOO=bar 144 export FOO 145 trial $i '${FOO}' $FOO 146done 147 148 149# A subset of options support tilde expansion 150for i in controlpath identityagent forwardagent; do 151 verbose $tid $i tilde 152 trial $i '~' $HOME/ 153 trial $i '~/.ssh' $HOME/.ssh 154done 155