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