1# $OpenBSD: test-exec.sh,v 1.54 2016/08/23 06:36:23 djm Exp $ 2# Placed in the Public Domain. 3 4USER=`id -un` 5#SUDO=sudo 6 7if [ ! -z "$TEST_SSH_PORT" ]; then 8 PORT="$TEST_SSH_PORT" 9else 10 PORT=4242 11fi 12 13OBJ=$1 14if [ "x$OBJ" = "x" ]; then 15 echo '$OBJ not defined' 16 exit 2 17fi 18if [ ! -d $OBJ ]; then 19 echo "not a directory: $OBJ" 20 exit 2 21fi 22SCRIPT=$2 23if [ "x$SCRIPT" = "x" ]; then 24 echo '$SCRIPT not defined' 25 exit 2 26fi 27if [ ! -f $SCRIPT ]; then 28 echo "not a file: $SCRIPT" 29 exit 2 30fi 31if sh -n $SCRIPT; then 32 true 33else 34 echo "syntax error in $SCRIPT" 35 exit 2 36fi 37unset SSH_AUTH_SOCK 38 39SRC=`dirname ${SCRIPT}` 40 41# defaults 42SSH=ssh 43SSHD=sshd 44SSHAGENT=ssh-agent 45SSHADD=ssh-add 46SSHKEYGEN=ssh-keygen 47SSHKEYSCAN=ssh-keyscan 48SFTP=sftp 49SFTPSERVER=/usr/libexec/sftp-server 50SCP=scp 51 52# Interop testing 53PLINK=/usr/local/bin/plink 54PUTTYGEN=/usr/local/bin/puttygen 55CONCH=/usr/local/bin/conch 56 57if [ "x$TEST_SSH_SSH" != "x" ]; then 58 SSH="${TEST_SSH_SSH}" 59fi 60if [ "x$TEST_SSH_SSHD" != "x" ]; then 61 SSHD="${TEST_SSH_SSHD}" 62fi 63if [ "x$TEST_SSH_SSHAGENT" != "x" ]; then 64 SSHAGENT="${TEST_SSH_SSHAGENT}" 65fi 66if [ "x$TEST_SSH_SSHADD" != "x" ]; then 67 SSHADD="${TEST_SSH_SSHADD}" 68fi 69if [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then 70 SSHKEYGEN="${TEST_SSH_SSHKEYGEN}" 71fi 72if [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then 73 SSHKEYSCAN="${TEST_SSH_SSHKEYSCAN}" 74fi 75if [ "x$TEST_SSH_SFTP" != "x" ]; then 76 SFTP="${TEST_SSH_SFTP}" 77fi 78if [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then 79 SFTPSERVER="${TEST_SSH_SFTPSERVER}" 80fi 81if [ "x$TEST_SSH_SCP" != "x" ]; then 82 SCP="${TEST_SSH_SCP}" 83fi 84if [ "x$TEST_SSH_PLINK" != "x" ]; then 85 PLINK="${TEST_SSH_PLINK}" 86fi 87if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then 88 PUTTYGEN="${TEST_SSH_PUTTYGEN}" 89fi 90if [ "x$TEST_SSH_CONCH" != "x" ]; then 91 CONCH="${TEST_SSH_CONCH}" 92fi 93 94SSH_PROTOCOLS=2 95#SSH_PROTOCOLS=`$SSH -Q protocol-version` 96if [ "x$TEST_SSH_PROTOCOLS" != "x" ]; then 97 SSH_PROTOCOLS="${TEST_SSH_PROTOCOLS}" 98fi 99 100# Path to sshd must be absolute for rexec 101case "$SSHD" in 102/*) ;; 103*) SSHD=`which $SSHD` ;; 104esac 105 106case "$SSHAGENT" in 107/*) ;; 108*) SSHAGENT=`which $SSHAGENT` ;; 109esac 110 111# Logfiles. 112# SSH_LOGFILE should be the debug output of ssh(1) only 113# SSHD_LOGFILE should be the debug output of sshd(8) only 114# REGRESS_LOGFILE is the output of the test itself stdout and stderr 115if [ "x$TEST_SSH_LOGFILE" = "x" ]; then 116 TEST_SSH_LOGFILE=$OBJ/ssh.log 117fi 118if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then 119 TEST_SSHD_LOGFILE=$OBJ/sshd.log 120fi 121if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then 122 TEST_REGRESS_LOGFILE=$OBJ/regress.log 123fi 124 125# truncate logfiles 126>$TEST_SSH_LOGFILE 127>$TEST_SSHD_LOGFILE 128>$TEST_REGRESS_LOGFILE 129 130# Create wrapper ssh with logging. We can't just specify "SSH=ssh -E..." 131# because sftp and scp don't handle spaces in arguments. 132SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh 133echo "#!/bin/sh" > $SSHLOGWRAP 134echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP 135 136chmod a+rx $OBJ/ssh-log-wrapper.sh 137REAL_SSH="$SSH" 138SSH="$SSHLOGWRAP" 139 140# Some test data. We make a copy because some tests will overwrite it. 141# The tests may assume that $DATA exists and is writable and $COPY does 142# not exist. Tests requiring larger data files can call increase_datafile_size 143# [kbytes] to ensure the file is at least that large. 144DATANAME=data 145DATA=$OBJ/${DATANAME} 146cat ${SSHAGENT} >${DATA} 147COPY=$OBJ/copy 148rm -f ${COPY} 149 150increase_datafile_size() 151{ 152 while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do 153 cat ${SSHAGENT} >>${DATA} 154 done 155} 156 157# these should be used in tests 158export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP 159#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP 160 161# helper 162cleanup () 163{ 164 if [ "x$SSH_PID" != "x" ]; then 165 if [ $SSH_PID -lt 2 ]; then 166 echo bad pid for ssh: $SSH_PID 167 else 168 kill $SSH_PID 169 fi 170 fi 171 if [ -f $PIDFILE ]; then 172 pid=`$SUDO cat $PIDFILE` 173 if [ "X$pid" = "X" ]; then 174 echo no sshd running 175 else 176 if [ $pid -lt 2 ]; then 177 echo bad pid for sshd: $pid 178 else 179 $SUDO kill $pid 180 trace "wait for sshd to exit" 181 i=0; 182 while [ -f $PIDFILE -a $i -lt 5 ]; do 183 i=`expr $i + 1` 184 sleep $i 185 done 186 test -f $PIDFILE && \ 187 fatal "sshd didn't exit port $PORT pid $pid" 188 fi 189 fi 190 fi 191} 192 193start_debug_log () 194{ 195 echo "trace: $@" >$TEST_REGRESS_LOGFILE 196 echo "trace: $@" >$TEST_SSH_LOGFILE 197 echo "trace: $@" >$TEST_SSHD_LOGFILE 198} 199 200save_debug_log () 201{ 202 echo $@ >>$TEST_REGRESS_LOGFILE 203 echo $@ >>$TEST_SSH_LOGFILE 204 echo $@ >>$TEST_SSHD_LOGFILE 205 (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log 206 (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log 207 (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log 208} 209 210trace () 211{ 212 start_debug_log $@ 213 if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then 214 echo "$@" 215 fi 216} 217 218verbose () 219{ 220 start_debug_log $@ 221 if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then 222 echo "$@" 223 fi 224} 225 226 227fail () 228{ 229 save_debug_log "FAIL: $@" 230 RESULT=1 231 echo "$@" 232 233} 234 235fatal () 236{ 237 save_debug_log "FATAL: $@" 238 printf "FATAL: " 239 fail "$@" 240 cleanup 241 exit $RESULT 242} 243 244ssh_version () 245{ 246 echo ${SSH_PROTOCOLS} | grep -q "$1" 247} 248 249RESULT=0 250PIDFILE=$OBJ/pidfile 251 252trap fatal 3 2 253 254if ssh_version 1; then 255 PROTO="2,1" 256else 257 PROTO="2" 258fi 259 260# create server config 261cat << EOF > $OBJ/sshd_config 262 Port $PORT 263 AddressFamily inet 264 ListenAddress 127.0.0.1 265 #ListenAddress ::1 266 PidFile $PIDFILE 267 AuthorizedKeysFile $OBJ/authorized_keys_%u 268 LogLevel DEBUG3 269 AcceptEnv _XXX_TEST_* 270 AcceptEnv _XXX_TEST 271 Subsystem sftp $SFTPSERVER 272EOF 273 274# This may be necessary if /usr/src and/or /usr/obj are group-writable, 275# but if you aren't careful with permissions then the unit tests could 276# be abused to locally escalate privileges. 277if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then 278 echo "StrictModes no" >> $OBJ/sshd_config 279fi 280 281if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then 282 trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" 283 echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config 284fi 285 286# server config for proxy connects 287cp $OBJ/sshd_config $OBJ/sshd_proxy 288 289# allow group-writable directories in proxy-mode 290echo 'StrictModes no' >> $OBJ/sshd_proxy 291 292# create client config 293cat << EOF > $OBJ/ssh_config 294Host * 295 Hostname 127.0.0.1 296 HostKeyAlias localhost-with-alias 297 Port $PORT 298 User $USER 299 GlobalKnownHostsFile $OBJ/known_hosts 300 UserKnownHostsFile $OBJ/known_hosts 301 RSAAuthentication yes 302 PubkeyAuthentication yes 303 ChallengeResponseAuthentication no 304 HostbasedAuthentication no 305 PasswordAuthentication no 306 RhostsRSAAuthentication no 307 BatchMode yes 308 StrictHostKeyChecking yes 309 LogLevel DEBUG3 310EOF 311 312if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then 313 trace "adding ssh_config option $TEST_SSH_SSHD_CONFOPTS" 314 echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config 315fi 316 317rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER 318 319if ssh_version 1; then 320 SSH_KEYTYPES="rsa rsa1" 321else 322 SSH_KEYTYPES="rsa ed25519" 323fi 324trace "generate keys" 325for t in ${SSH_KEYTYPES}; do 326 # generate user key 327 if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then 328 rm -f $OBJ/$t 329 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ 330 fail "ssh-keygen for $t failed" 331 fi 332 333 # known hosts file for client 334 ( 335 printf 'localhost-with-alias,127.0.0.1,::1 ' 336 cat $OBJ/$t.pub 337 ) >> $OBJ/known_hosts 338 339 # setup authorized keys 340 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER 341 echo IdentityFile $OBJ/$t >> $OBJ/ssh_config 342 343 # use key as host key, too 344 $SUDO cp $OBJ/$t $OBJ/host.$t 345 echo HostKey $OBJ/host.$t >> $OBJ/sshd_config 346 347 # don't use SUDO for proxy connect 348 echo HostKey $OBJ/$t >> $OBJ/sshd_proxy 349done 350chmod 644 $OBJ/authorized_keys_$USER 351 352# Activate Twisted Conch tests if the binary is present 353REGRESS_INTEROP_CONCH=no 354if test -x "$CONCH" ; then 355 REGRESS_INTEROP_CONCH=yes 356fi 357 358# If PuTTY is present and we are running a PuTTY test, prepare keys and 359# configuration 360REGRESS_INTEROP_PUTTY=no 361if test -x "$PUTTYGEN" -a -x "$PLINK" ; then 362 REGRESS_INTEROP_PUTTY=yes 363fi 364case "$SCRIPT" in 365*putty*) ;; 366*) REGRESS_INTEROP_PUTTY=no ;; 367esac 368 369if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then 370 mkdir -p ${OBJ}/.putty 371 372 # Add a PuTTY key to authorized_keys 373 rm -f ${OBJ}/putty.rsa2 374 puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null 375 puttygen -O public-openssh ${OBJ}/putty.rsa2 \ 376 >> $OBJ/authorized_keys_$USER 377 378 # Convert rsa2 host key to PuTTY format 379 ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/rsa > \ 380 ${OBJ}/.putty/sshhostkeys 381 ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/rsa >> \ 382 ${OBJ}/.putty/sshhostkeys 383 384 # Setup proxied session 385 mkdir -p ${OBJ}/.putty/sessions 386 rm -f ${OBJ}/.putty/sessions/localhost_proxy 387 echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy 388 echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy 389 echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy 390 echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy 391 392 REGRESS_INTEROP_PUTTY=yes 393fi 394 395# create a proxy version of the client config 396( 397 cat $OBJ/ssh_config 398 echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy 399) > $OBJ/ssh_proxy 400 401# check proxy config 402${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" 403 404start_sshd () 405{ 406 # start sshd 407 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" 408 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE 409 410 trace "wait for sshd" 411 i=0; 412 while [ ! -f $PIDFILE -a $i -lt 10 ]; do 413 i=`expr $i + 1` 414 sleep $i 415 done 416 417 test -f $PIDFILE || fatal "no sshd running on port $PORT" 418} 419 420# source test body 421. $SCRIPT 422 423# kill sshd 424cleanup 425if [ $RESULT -eq 0 ]; then 426 verbose ok $tid 427else 428 echo failed $tid 429fi 430exit $RESULT 431