1# $OpenBSD: test-exec.sh,v 1.51 2015/03/03 22:35:19 markus 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 133SSH_PROTOCOLS=`$SSH -Q protocol-version` 134if [ "x$TEST_SSH_PROTOCOLS" != "x" ]; then 135 SSH_PROTOCOLS="${TEST_SSH_PROTOCOLS}" 136fi 137 138# Path to sshd must be absolute for rexec 139case "$SSHD" in 140/*) ;; 141*) SSHD=`which $SSHD` ;; 142esac 143 144case "$SSHAGENT" in 145/*) ;; 146*) SSHAGENT=`which $SSHAGENT` ;; 147esac 148 149# Record the actual binaries used. 150SSH_BIN=${SSH} 151SSHD_BIN=${SSHD} 152SSHAGENT_BIN=${SSHAGENT} 153SSHADD_BIN=${SSHADD} 154SSHKEYGEN_BIN=${SSHKEYGEN} 155SSHKEYSCAN_BIN=${SSHKEYSCAN} 156SFTP_BIN=${SFTP} 157SFTPSERVER_BIN=${SFTPSERVER} 158SCP_BIN=${SCP} 159 160if [ "x$USE_VALGRIND" != "x" ]; then 161 mkdir -p $OBJ/valgrind-out 162 VG_TEST=`basename $SCRIPT .sh` 163 164 # Some tests are difficult to fix. 165 case "$VG_TEST" in 166 connect-privsep|reexec) 167 VG_SKIP=1 ;; 168 esac 169 170 if [ x"$VG_SKIP" = "x" ]; then 171 VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*" 172 VG_LOG="$OBJ/valgrind-out/${VG_TEST}." 173 VG_OPTS="--track-origins=yes --leak-check=full" 174 VG_OPTS="$VG_OPTS --trace-children=yes" 175 VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}" 176 VG_PATH="valgrind" 177 if [ "x$VALGRIND_PATH" != "x" ]; then 178 VG_PATH="$VALGRIND_PATH" 179 fi 180 VG="$VG_PATH $VG_OPTS" 181 SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH" 182 SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD" 183 SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT" 184 SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD" 185 SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN" 186 SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN" 187 SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}" 188 SCP="$VG --log-file=${VG_LOG}scp.%p $SCP" 189 cat > $OBJ/valgrind-sftp-server.sh << EOF 190#!/bin/sh 191exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@" 192EOF 193 chmod a+rx $OBJ/valgrind-sftp-server.sh 194 SFTPSERVER="$OBJ/valgrind-sftp-server.sh" 195 fi 196fi 197 198# Logfiles. 199# SSH_LOGFILE should be the debug output of ssh(1) only 200# SSHD_LOGFILE should be the debug output of sshd(8) only 201# REGRESS_LOGFILE is the output of the test itself stdout and stderr 202if [ "x$TEST_SSH_LOGFILE" = "x" ]; then 203 TEST_SSH_LOGFILE=$OBJ/ssh.log 204fi 205if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then 206 TEST_SSHD_LOGFILE=$OBJ/sshd.log 207fi 208if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then 209 TEST_REGRESS_LOGFILE=$OBJ/regress.log 210fi 211 212# truncate logfiles 213>$TEST_SSH_LOGFILE 214>$TEST_SSHD_LOGFILE 215>$TEST_REGRESS_LOGFILE 216 217# Create wrapper ssh with logging. We can't just specify "SSH=ssh -E..." 218# because sftp and scp don't handle spaces in arguments. 219SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh 220echo "#!/bin/sh" > $SSHLOGWRAP 221echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP 222 223chmod a+rx $OBJ/ssh-log-wrapper.sh 224SSH="$SSHLOGWRAP" 225 226# Some test data. We make a copy because some tests will overwrite it. 227# The tests may assume that $DATA exists and is writable and $COPY does 228# not exist. Tests requiring larger data files can call increase_datafile_size 229# [kbytes] to ensure the file is at least that large. 230DATANAME=data 231DATA=$OBJ/${DATANAME} 232cat ${SSHAGENT_BIN} >${DATA} 233chmod u+w ${DATA} 234COPY=$OBJ/copy 235rm -f ${COPY} 236 237increase_datafile_size() 238{ 239 while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do 240 cat ${SSHAGENT_BIN} >>${DATA} 241 done 242} 243 244# these should be used in tests 245export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP 246#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP 247 248# Portable specific functions 249have_prog() 250{ 251 saved_IFS="$IFS" 252 IFS=":" 253 for i in $PATH 254 do 255 if [ -x $i/$1 ]; then 256 IFS="$saved_IFS" 257 return 0 258 fi 259 done 260 IFS="$saved_IFS" 261 return 1 262} 263 264jot() { 265 awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }" 266} 267 268# Check whether preprocessor symbols are defined in config.h. 269config_defined () 270{ 271 str=$1 272 while test "x$2" != "x" ; do 273 str="$str|$2" 274 shift 275 done 276 egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1 277} 278 279md5 () { 280 if have_prog md5sum; then 281 md5sum 282 elif have_prog openssl; then 283 openssl md5 284 elif have_prog cksum; then 285 cksum 286 elif have_prog sum; then 287 sum 288 else 289 wc -c 290 fi 291} 292# End of portable specific functions 293 294# helper 295cleanup () 296{ 297 if [ "x$SSH_PID" != "x" ]; then 298 if [ $SSH_PID -lt 2 ]; then 299 echo bad pid for ssh: $SSH_PID 300 else 301 kill $SSH_PID 302 fi 303 fi 304 if [ -f $PIDFILE ]; then 305 pid=`$SUDO cat $PIDFILE` 306 if [ "X$pid" = "X" ]; then 307 echo no sshd running 308 else 309 if [ $pid -lt 2 ]; then 310 echo bad pid for sshd: $pid 311 else 312 $SUDO kill $pid 313 trace "wait for sshd to exit" 314 i=0; 315 while [ -f $PIDFILE -a $i -lt 5 ]; do 316 i=`expr $i + 1` 317 sleep $i 318 done 319 test -f $PIDFILE && \ 320 fatal "sshd didn't exit port $PORT pid $pid" 321 fi 322 fi 323 fi 324} 325 326start_debug_log () 327{ 328 echo "trace: $@" >$TEST_REGRESS_LOGFILE 329 echo "trace: $@" >$TEST_SSH_LOGFILE 330 echo "trace: $@" >$TEST_SSHD_LOGFILE 331} 332 333save_debug_log () 334{ 335 echo $@ >>$TEST_REGRESS_LOGFILE 336 echo $@ >>$TEST_SSH_LOGFILE 337 echo $@ >>$TEST_SSHD_LOGFILE 338 (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log 339 (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log 340 (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log 341} 342 343trace () 344{ 345 start_debug_log $@ 346 if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then 347 echo "$@" 348 fi 349} 350 351verbose () 352{ 353 start_debug_log $@ 354 if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then 355 echo "$@" 356 fi 357} 358 359warn () 360{ 361 echo "WARNING: $@" >>$TEST_SSH_LOGFILE 362 echo "WARNING: $@" 363} 364 365fail () 366{ 367 save_debug_log "FAIL: $@" 368 RESULT=1 369 echo "$@" 370 371} 372 373fatal () 374{ 375 save_debug_log "FATAL: $@" 376 printf "FATAL: " 377 fail "$@" 378 cleanup 379 exit $RESULT 380} 381 382ssh_version () 383{ 384 echo ${SSH_PROTOCOLS} | grep "$1" >/dev/null 385} 386 387RESULT=0 388PIDFILE=$OBJ/pidfile 389 390trap fatal 3 2 391 392if ssh_version 1; then 393 PROTO="2,1" 394else 395 PROTO="2" 396fi 397 398# create server config 399cat << EOF > $OBJ/sshd_config 400 StrictModes no 401 Port $PORT 402 Protocol $PROTO 403 AddressFamily inet 404 ListenAddress 127.0.0.1 405 #ListenAddress ::1 406 PidFile $PIDFILE 407 AuthorizedKeysFile $OBJ/authorized_keys_%u 408 LogLevel DEBUG3 409 AcceptEnv _XXX_TEST_* 410 AcceptEnv _XXX_TEST 411 Subsystem sftp $SFTPSERVER 412EOF 413 414if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then 415 trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" 416 echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config 417fi 418 419# server config for proxy connects 420cp $OBJ/sshd_config $OBJ/sshd_proxy 421 422# allow group-writable directories in proxy-mode 423echo 'StrictModes no' >> $OBJ/sshd_proxy 424 425# create client config 426cat << EOF > $OBJ/ssh_config 427Host * 428 Protocol $PROTO 429 Hostname 127.0.0.1 430 HostKeyAlias localhost-with-alias 431 Port $PORT 432 User $USER 433 GlobalKnownHostsFile $OBJ/known_hosts 434 UserKnownHostsFile $OBJ/known_hosts 435 RSAAuthentication yes 436 PubkeyAuthentication yes 437 ChallengeResponseAuthentication no 438 HostbasedAuthentication no 439 PasswordAuthentication no 440 RhostsRSAAuthentication no 441 BatchMode yes 442 StrictHostKeyChecking yes 443 LogLevel DEBUG3 444EOF 445 446if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then 447 trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS" 448 echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config 449fi 450 451rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER 452 453if ssh_version 1; then 454 SSH_KEYTYPES="rsa rsa1" 455else 456 SSH_KEYTYPES="rsa ed25519" 457fi 458trace "generate keys" 459for t in ${SSH_KEYTYPES}; do 460 # generate user key 461 if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then 462 rm -f $OBJ/$t 463 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ 464 fail "ssh-keygen for $t failed" 465 fi 466 467 # known hosts file for client 468 ( 469 printf 'localhost-with-alias,127.0.0.1,::1 ' 470 cat $OBJ/$t.pub 471 ) >> $OBJ/known_hosts 472 473 # setup authorized keys 474 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER 475 echo IdentityFile $OBJ/$t >> $OBJ/ssh_config 476 477 # use key as host key, too 478 $SUDO cp $OBJ/$t $OBJ/host.$t 479 echo HostKey $OBJ/host.$t >> $OBJ/sshd_config 480 481 # don't use SUDO for proxy connect 482 echo HostKey $OBJ/$t >> $OBJ/sshd_proxy 483done 484chmod 644 $OBJ/authorized_keys_$USER 485 486# Activate Twisted Conch tests if the binary is present 487REGRESS_INTEROP_CONCH=no 488if test -x "$CONCH" ; then 489 REGRESS_INTEROP_CONCH=yes 490fi 491 492# If PuTTY is present and we are running a PuTTY test, prepare keys and 493# configuration 494REGRESS_INTEROP_PUTTY=no 495if test -x "$PUTTYGEN" -a -x "$PLINK" ; then 496 REGRESS_INTEROP_PUTTY=yes 497fi 498case "$SCRIPT" in 499*putty*) ;; 500*) REGRESS_INTEROP_PUTTY=no ;; 501esac 502 503if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then 504 mkdir -p ${OBJ}/.putty 505 506 # Add a PuTTY key to authorized_keys 507 rm -f ${OBJ}/putty.rsa2 508 puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null 509 puttygen -O public-openssh ${OBJ}/putty.rsa2 \ 510 >> $OBJ/authorized_keys_$USER 511 512 # Convert rsa2 host key to PuTTY format 513 ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/rsa > \ 514 ${OBJ}/.putty/sshhostkeys 515 ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/rsa >> \ 516 ${OBJ}/.putty/sshhostkeys 517 518 # Setup proxied session 519 mkdir -p ${OBJ}/.putty/sessions 520 rm -f ${OBJ}/.putty/sessions/localhost_proxy 521 echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy 522 echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy 523 echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy 524 echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy 525 526 REGRESS_INTEROP_PUTTY=yes 527fi 528 529# create a proxy version of the client config 530( 531 cat $OBJ/ssh_config 532 echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy 533) > $OBJ/ssh_proxy 534 535# check proxy config 536${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" 537 538start_sshd () 539{ 540 # start sshd 541 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" 542 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE 543 544 trace "wait for sshd" 545 i=0; 546 while [ ! -f $PIDFILE -a $i -lt 10 ]; do 547 i=`expr $i + 1` 548 sleep $i 549 done 550 551 test -f $PIDFILE || fatal "no sshd running on port $PORT" 552} 553 554# source test body 555. $SCRIPT 556 557# kill sshd 558cleanup 559if [ $RESULT -eq 0 ]; then 560 verbose ok $tid 561else 562 echo failed $tid 563fi 564exit $RESULT 565