1# $OpenBSD: test-exec.sh,v 1.46 2013/06/21 02:26:26 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 139# Logfiles. 140# SSH_LOGFILE should be the debug output of ssh(1) only 141# SSHD_LOGFILE should be the debug output of sshd(8) only 142# REGRESS_LOGFILE is the output of the test itself stdout and stderr 143if [ "x$TEST_SSH_LOGFILE" = "x" ]; then 144 TEST_SSH_LOGFILE=$OBJ/ssh.log 145fi 146if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then 147 TEST_SSHD_LOGFILE=$OBJ/sshd.log 148fi 149if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then 150 TEST_REGRESS_LOGFILE=$OBJ/regress.log 151fi 152 153# truncate logfiles 154>$TEST_SSH_LOGFILE 155>$TEST_SSHD_LOGFILE 156>$TEST_REGRESS_LOGFILE 157 158# Create wrapper ssh with logging. We can't just specify "SSH=ssh -E..." 159# because sftp and scp don't handle spaces in arguments. 160SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh 161echo "#!/bin/sh" > $SSHLOGWRAP 162echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP 163 164chmod a+rx $OBJ/ssh-log-wrapper.sh 165SSH="$SSHLOGWRAP" 166 167# Some test data. We make a copy because some tests will overwrite it. 168# The tests may assume that $DATA exists and is writable and $COPY does 169# not exist. 170DATANAME=data 171DATA=$OBJ/${DATANAME} 172cat $SSHD $SSHD $SSHD $SSHD >${DATA} 173chmod u+w ${DATA} 174COPY=$OBJ/copy 175rm -f ${COPY} 176 177# these should be used in tests 178export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP 179#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP 180 181# Portable specific functions 182have_prog() 183{ 184 saved_IFS="$IFS" 185 IFS=":" 186 for i in $PATH 187 do 188 if [ -x $i/$1 ]; then 189 IFS="$saved_IFS" 190 return 0 191 fi 192 done 193 IFS="$saved_IFS" 194 return 1 195} 196 197jot() { 198 awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }" 199} 200 201# Check whether preprocessor symbols are defined in config.h. 202config_defined () 203{ 204 str=$1 205 while test "x$2" != "x" ; do 206 str="$str|$2" 207 shift 208 done 209 egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1 210} 211 212md5 () { 213 if have_prog md5sum; then 214 md5sum 215 elif have_prog openssl; then 216 openssl md5 217 elif have_prog cksum; then 218 cksum 219 elif have_prog sum; then 220 sum 221 else 222 wc -c 223 fi 224} 225# End of portable specific functions 226 227# helper 228cleanup () 229{ 230 if [ -f $PIDFILE ]; then 231 pid=`$SUDO cat $PIDFILE` 232 if [ "X$pid" = "X" ]; then 233 echo no sshd running 234 else 235 if [ $pid -lt 2 ]; then 236 echo bad pid for ssh: $pid 237 else 238 $SUDO kill $pid 239 trace "wait for sshd to exit" 240 i=0; 241 while [ -f $PIDFILE -a $i -lt 5 ]; do 242 i=`expr $i + 1` 243 sleep $i 244 done 245 test -f $PIDFILE && \ 246 fatal "sshd didn't exit port $PORT pid $pid" 247 fi 248 fi 249 fi 250} 251 252start_debug_log () 253{ 254 echo "trace: $@" >$TEST_REGRESS_LOGFILE 255 echo "trace: $@" >$TEST_SSH_LOGFILE 256 echo "trace: $@" >$TEST_SSHD_LOGFILE 257} 258 259save_debug_log () 260{ 261 echo $@ >>$TEST_REGRESS_LOGFILE 262 echo $@ >>$TEST_SSH_LOGFILE 263 echo $@ >>$TEST_SSHD_LOGFILE 264 (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log 265 (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log 266 (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log 267} 268 269trace () 270{ 271 start_debug_log $@ 272 if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then 273 echo "$@" 274 fi 275} 276 277verbose () 278{ 279 start_debug_log $@ 280 if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then 281 echo "$@" 282 fi 283} 284 285warn () 286{ 287 echo "WARNING: $@" >>$TEST_SSH_LOGFILE 288 echo "WARNING: $@" 289} 290 291fail () 292{ 293 save_debug_log "FAIL: $@" 294 RESULT=1 295 echo "$@" 296 297} 298 299fatal () 300{ 301 save_debug_log "FATAL: $@" 302 printf "FATAL: " 303 fail "$@" 304 cleanup 305 exit $RESULT 306} 307 308RESULT=0 309PIDFILE=$OBJ/pidfile 310 311trap fatal 3 2 312 313# create server config 314cat << EOF > $OBJ/sshd_config 315 StrictModes no 316 Port $PORT 317 Protocol 2,1 318 AddressFamily inet 319 ListenAddress 127.0.0.1 320 #ListenAddress ::1 321 PidFile $PIDFILE 322 AuthorizedKeysFile $OBJ/authorized_keys_%u 323 LogLevel DEBUG3 324 AcceptEnv _XXX_TEST_* 325 AcceptEnv _XXX_TEST 326 Subsystem sftp $SFTPSERVER 327EOF 328 329if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then 330 trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" 331 echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config 332fi 333 334# server config for proxy connects 335cp $OBJ/sshd_config $OBJ/sshd_proxy 336 337# allow group-writable directories in proxy-mode 338echo 'StrictModes no' >> $OBJ/sshd_proxy 339 340# create client config 341cat << EOF > $OBJ/ssh_config 342Host * 343 Protocol 2,1 344 Hostname 127.0.0.1 345 HostKeyAlias localhost-with-alias 346 Port $PORT 347 User $USER 348 GlobalKnownHostsFile $OBJ/known_hosts 349 UserKnownHostsFile $OBJ/known_hosts 350 RSAAuthentication yes 351 PubkeyAuthentication yes 352 ChallengeResponseAuthentication no 353 HostbasedAuthentication no 354 PasswordAuthentication no 355 RhostsRSAAuthentication no 356 BatchMode yes 357 StrictHostKeyChecking yes 358 LogLevel DEBUG3 359EOF 360 361if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then 362 trace "adding ssh_config option $TEST_SSH_SSHD_CONFOPTS" 363 echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config 364fi 365 366rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER 367 368trace "generate keys" 369for t in rsa rsa1; do 370 # generate user key 371 if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then 372 rm -f $OBJ/$t 373 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ 374 fail "ssh-keygen for $t failed" 375 fi 376 377 # known hosts file for client 378 ( 379 printf 'localhost-with-alias,127.0.0.1,::1 ' 380 cat $OBJ/$t.pub 381 ) >> $OBJ/known_hosts 382 383 # setup authorized keys 384 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER 385 echo IdentityFile $OBJ/$t >> $OBJ/ssh_config 386 387 # use key as host key, too 388 $SUDO cp $OBJ/$t $OBJ/host.$t 389 echo HostKey $OBJ/host.$t >> $OBJ/sshd_config 390 391 # don't use SUDO for proxy connect 392 echo HostKey $OBJ/$t >> $OBJ/sshd_proxy 393done 394chmod 644 $OBJ/authorized_keys_$USER 395 396# Activate Twisted Conch tests if the binary is present 397REGRESS_INTEROP_CONCH=no 398if test -x "$CONCH" ; then 399 REGRESS_INTEROP_CONCH=yes 400fi 401 402# If PuTTY is present and we are running a PuTTY test, prepare keys and 403# configuration 404REGRESS_INTEROP_PUTTY=no 405if test -x "$PUTTYGEN" -a -x "$PLINK" ; then 406 REGRESS_INTEROP_PUTTY=yes 407fi 408case "$SCRIPT" in 409*putty*) ;; 410*) REGRESS_INTEROP_PUTTY=no ;; 411esac 412 413if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then 414 mkdir -p ${OBJ}/.putty 415 416 # Add a PuTTY key to authorized_keys 417 rm -f ${OBJ}/putty.rsa2 418 puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null 419 puttygen -O public-openssh ${OBJ}/putty.rsa2 \ 420 >> $OBJ/authorized_keys_$USER 421 422 # Convert rsa2 host key to PuTTY format 423 ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/rsa > \ 424 ${OBJ}/.putty/sshhostkeys 425 ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/rsa >> \ 426 ${OBJ}/.putty/sshhostkeys 427 428 # Setup proxied session 429 mkdir -p ${OBJ}/.putty/sessions 430 rm -f ${OBJ}/.putty/sessions/localhost_proxy 431 echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy 432 echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy 433 echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy 434 echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy 435 436 REGRESS_INTEROP_PUTTY=yes 437fi 438 439# create a proxy version of the client config 440( 441 cat $OBJ/ssh_config 442 echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy 443) > $OBJ/ssh_proxy 444 445# check proxy config 446${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" 447 448start_sshd () 449{ 450 # start sshd 451 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" 452 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE 453 454 trace "wait for sshd" 455 i=0; 456 while [ ! -f $PIDFILE -a $i -lt 10 ]; do 457 i=`expr $i + 1` 458 sleep $i 459 done 460 461 test -f $PIDFILE || fatal "no sshd running on port $PORT" 462} 463 464# source test body 465. $SCRIPT 466 467# kill sshd 468cleanup 469if [ $RESULT -eq 0 ]; then 470 verbose ok $tid 471else 472 echo failed $tid 473fi 474exit $RESULT 475