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