1# $OpenBSD: test-exec.sh,v 1.105 2023/10/31 04:15:40 dtucker Exp $ 2# Placed in the Public Domain. 3 4#SUDO=sudo 5 6if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then 7 STARTTIME=`date '+%s'` 8fi 9 10if [ ! -z "$TEST_SSH_PORT" ]; then 11 PORT="$TEST_SSH_PORT" 12else 13 PORT=4242 14fi 15 16OBJ=$1 17if [ "x$OBJ" = "x" ]; then 18 echo '$OBJ not defined' 19 exit 2 20fi 21if [ ! -d $OBJ ]; then 22 echo "not a directory: $OBJ" 23 exit 2 24fi 25SCRIPT=$2 26if [ "x$SCRIPT" = "x" ]; then 27 echo '$SCRIPT not defined' 28 exit 2 29fi 30if [ ! -f $SCRIPT ]; then 31 echo "not a file: $SCRIPT" 32 exit 2 33fi 34if $TEST_SHELL -n $SCRIPT; then 35 true 36else 37 echo "syntax error in $SCRIPT" 38 exit 2 39fi 40unset SSH_AUTH_SOCK 41 42# Portable-specific settings. 43 44if [ -x /usr/ucb/whoami ]; then 45 USER=`/usr/ucb/whoami` 46elif whoami >/dev/null 2>&1; then 47 USER=`whoami` 48elif logname >/dev/null 2>&1; then 49 USER=`logname` 50else 51 USER=`id -un` 52fi 53if test -z "$LOGNAME"; then 54 LOGNAME="${USER}" 55 export LOGNAME 56fi 57 58# Unbreak GNU head(1) 59_POSIX2_VERSION=199209 60export _POSIX2_VERSION 61 62case `uname -s 2>/dev/null` in 63OSF1*) 64 BIN_SH=xpg4 65 export BIN_SH 66 ;; 67CYGWIN*) 68 os=cygwin 69 ;; 70esac 71 72# If configure tells us to use a different egrep, create a wrapper function 73# to call it. This means we don't need to change all the tests that depend 74# on a good implementation. 75if test "x${EGREP}" != "x"; then 76 egrep () 77{ 78 ${EGREP} "$@" 79} 80fi 81 82SRC=`dirname ${SCRIPT}` 83 84# defaults 85SSH=ssh 86SSHD=sshd 87SSHAGENT=ssh-agent 88SSHADD=ssh-add 89SSHKEYGEN=ssh-keygen 90SSHKEYSCAN=ssh-keyscan 91SFTP=sftp 92SFTPSERVER=/usr/libexec/openssh/sftp-server 93SCP=scp 94 95# Set by make_tmpdir() on demand (below). 96SSH_REGRESS_TMP= 97 98# Interop testing 99PLINK=/usr/local/bin/plink 100PUTTYGEN=/usr/local/bin/puttygen 101CONCH=/usr/local/bin/conch 102DROPBEAR=/usr/local/bin/dropbear 103DBCLIENT=/usr/local/bin/dbclient 104DROPBEARKEY=/usr/local/bin/dropbearkey 105DROPBEARCONVERT=/usr/local/bin/dropbearconvert 106 107# Tools used by multiple tests 108NC=$OBJ/netcat 109# Always use the one configure tells us to, even if that's empty. 110#OPENSSL_BIN="${OPENSSL_BIN:-openssl}" 111 112if [ "x$TEST_SSH_SSH" != "x" ]; then 113 SSH="${TEST_SSH_SSH}" 114fi 115if [ "x$TEST_SSH_SSHD" != "x" ]; then 116 SSHD="${TEST_SSH_SSHD}" 117fi 118if [ "x$TEST_SSH_SSHAGENT" != "x" ]; then 119 SSHAGENT="${TEST_SSH_SSHAGENT}" 120fi 121if [ "x$TEST_SSH_SSHADD" != "x" ]; then 122 SSHADD="${TEST_SSH_SSHADD}" 123fi 124if [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then 125 SSHKEYGEN="${TEST_SSH_SSHKEYGEN}" 126fi 127if [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then 128 SSHKEYSCAN="${TEST_SSH_SSHKEYSCAN}" 129fi 130if [ "x$TEST_SSH_SFTP" != "x" ]; then 131 SFTP="${TEST_SSH_SFTP}" 132fi 133if [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then 134 SFTPSERVER="${TEST_SSH_SFTPSERVER}" 135fi 136if [ "x$TEST_SSH_SCP" != "x" ]; then 137 SCP="${TEST_SSH_SCP}" 138fi 139if [ "x$TEST_SSH_PLINK" != "x" ]; then 140 PLINK="${TEST_SSH_PLINK}" 141fi 142if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then 143 PUTTYGEN="${TEST_SSH_PUTTYGEN}" 144fi 145if [ "x$TEST_SSH_CONCH" != "x" ]; then 146 CONCH="${TEST_SSH_CONCH}" 147fi 148if [ "x$TEST_SSH_DROPBEAR" != "x" ]; then 149 DROPBEAR="${TEST_SSH_DROPBEAR}" 150fi 151if [ "x$TEST_SSH_DBCLIENT" != "x" ]; then 152 DBCLIENT="${TEST_SSH_DBCLIENT}" 153fi 154if [ "x$TEST_SSH_DROPBEARKEY" != "x" ]; then 155 DROPBEARKEY="${TEST_SSH_DROPBEARKEY}" 156fi 157if [ "x$TEST_SSH_DROPBEARCONVERT" != "x" ]; then 158 DROPBEARCONVERT="${TEST_SSH_DROPBEARCONVERT}" 159fi 160if [ "x$TEST_SSH_PKCS11_HELPER" != "x" ]; then 161 SSH_PKCS11_HELPER="${TEST_SSH_PKCS11_HELPER}" 162fi 163if [ "x$TEST_SSH_SK_HELPER" != "x" ]; then 164 SSH_SK_HELPER="${TEST_SSH_SK_HELPER}" 165fi 166if [ "x$TEST_SSH_OPENSSL" != "x" ]; then 167 OPENSSL_BIN="${TEST_SSH_OPENSSL}" 168fi 169 170# Path to sshd must be absolute for rexec 171case "$SSHD" in 172/*) ;; 173*) SSHD=`which $SSHD` ;; 174esac 175 176case "$SSHAGENT" in 177/*) ;; 178*) SSHAGENT=`which $SSHAGENT` ;; 179esac 180 181# Record the actual binaries used. 182SSH_BIN=${SSH} 183SSHD_BIN=${SSHD} 184SSHAGENT_BIN=${SSHAGENT} 185SSHADD_BIN=${SSHADD} 186SSHKEYGEN_BIN=${SSHKEYGEN} 187SSHKEYSCAN_BIN=${SSHKEYSCAN} 188SFTP_BIN=${SFTP} 189SFTPSERVER_BIN=${SFTPSERVER} 190SCP_BIN=${SCP} 191 192if [ "x$USE_VALGRIND" != "x" ]; then 193 rm -rf $OBJ/valgrind-out $OBJ/valgrind-vgdb 194 mkdir -p $OBJ/valgrind-out $OBJ/valgrind-vgdb 195 # When using sudo ensure low-priv tests can write pipes and logs. 196 if [ "x$SUDO" != "x" ]; then 197 chmod 777 $OBJ/valgrind-out $OBJ/valgrind-vgdb 198 fi 199 VG_TEST=`basename $SCRIPT .sh` 200 201 # Some tests are difficult to fix. 202 case "$VG_TEST" in 203 reexec) 204 VG_SKIP=1 ;; 205 sftp-chroot) 206 if [ "x${SUDO}" != "x" ]; then 207 VG_SKIP=1 208 fi ;; 209 esac 210 211 if [ x"$VG_SKIP" = "x" ]; then 212 VG_LEAK="--leak-check=no" 213 if [ x"$VALGRIND_CHECK_LEAKS" != "x" ]; then 214 VG_LEAK="--leak-check=full" 215 fi 216 VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*" 217 VG_LOG="$OBJ/valgrind-out/${VG_TEST}." 218 VG_OPTS="--track-origins=yes $VG_LEAK" 219 VG_OPTS="$VG_OPTS --trace-children=yes" 220 VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}" 221 VG_OPTS="$VG_OPTS --vgdb-prefix=$OBJ/valgrind-vgdb/" 222 VG_PATH="valgrind" 223 if [ "x$VALGRIND_PATH" != "x" ]; then 224 VG_PATH="$VALGRIND_PATH" 225 fi 226 VG="$VG_PATH $VG_OPTS" 227 SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH" 228 SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD" 229 SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT" 230 SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD" 231 SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN" 232 SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN" 233 SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}" 234 SCP="$VG --log-file=${VG_LOG}scp.%p $SCP" 235 cat > $OBJ/valgrind-sftp-server.sh << EOF 236#!/bin/sh 237exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@" 238EOF 239 chmod a+rx $OBJ/valgrind-sftp-server.sh 240 SFTPSERVER="$OBJ/valgrind-sftp-server.sh" 241 fi 242fi 243 244# Logfiles. 245# SSH_LOGFILE should be the debug output of ssh(1) only 246# SSHD_LOGFILE should be the debug output of sshd(8) only 247# REGRESS_LOGFILE is the log of progress of the regress test itself. 248# TEST_SSH_LOGDIR will contain datestamped logs of all binaries run in 249# chronological order. 250if [ "x$TEST_SSH_LOGDIR" = "x" ]; then 251 TEST_SSH_LOGDIR=$OBJ/log 252 mkdir -p $TEST_SSH_LOGDIR 253fi 254if [ "x$TEST_SSH_LOGFILE" = "x" ]; then 255 TEST_SSH_LOGFILE=$OBJ/ssh.log 256fi 257if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then 258 TEST_SSHD_LOGFILE=$OBJ/sshd.log 259fi 260if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then 261 TEST_REGRESS_LOGFILE=$OBJ/regress.log 262fi 263 264# If set, keep track of successful tests and skip them them if we've 265# previously completed that test. 266if [ "x$TEST_REGRESS_CACHE_DIR" != "x" ]; then 267 if [ ! -d "$TEST_REGRESS_CACHE_DIR" ]; then 268 mkdir -p "$TEST_REGRESS_CACHE_DIR" 269 fi 270 TEST="`basename $SCRIPT .sh`" 271 CACHE="${TEST_REGRESS_CACHE_DIR}/${TEST}.cache" 272 for i in ${SSH} ${SSHD} ${SSHAGENT} ${SSHADD} ${SSHKEYGEN} ${SCP} \ 273 ${SFTP} ${SFTPSERVER} ${SSHKEYSCAN}; do 274 case $i in 275 /*) bin="$i" ;; 276 *) bin="`which $i`" ;; 277 esac 278 if [ "$bin" -nt "$CACHE" ]; then 279 rm -f "$CACHE" 280 fi 281 done 282 if [ -f "$CACHE" ]; then 283 echo ok cached $CACHE 284 exit 0 285 fi 286fi 287 288# truncate logfiles 289>$TEST_REGRESS_LOGFILE 290 291# Create ssh and sshd wrappers with logging. These create a datestamped 292# unique file for every invocation so that we can retain all logs from a 293# given test no matter how many times it's invoked. It also leaves a 294# symlink with the original name for tests (and people) who look for that. 295 296# For ssh, e can't just specify "SSH=ssh -E..." because sftp and scp don't 297# handle spaces in arguments. scp and sftp like to use -q so we remove those 298# to preserve our debug logging. In the rare instance where -q is desirable 299# -qq is equivalent and is not removed. 300SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh 301cat >$SSHLOGWRAP <<EOD 302#!/bin/sh 303timestamp="\`$OBJ/timestamp\`" 304logfile="${TEST_SSH_LOGDIR}/\${timestamp}.ssh.\$\$.log" 305echo "Executing: ${SSH} \$@" log \${logfile} >>$TEST_REGRESS_LOGFILE 306echo "Executing: ${SSH} \$@" >>\${logfile} 307for i in "\$@";do shift;case "\$i" in -q):;; *) set -- "\$@" "\$i";;esac;done 308rm -f $TEST_SSH_LOGFILE 309ln -f -s \${logfile} $TEST_SSH_LOGFILE 310exec ${SSH} -E\${logfile} "\$@" 311EOD 312 313chmod a+rx $OBJ/ssh-log-wrapper.sh 314REAL_SSH="$SSH" 315REAL_SSHD="$SSHD" 316SSH="$SSHLOGWRAP" 317 318SSHDLOGWRAP=$OBJ/sshd-log-wrapper.sh 319cat >$SSHDLOGWRAP <<EOD 320#!/bin/sh 321timestamp="\`$OBJ/timestamp\`" 322logfile="${TEST_SSH_LOGDIR}/\${timestamp}.sshd.\$\$.log" 323rm -f $TEST_SSHD_LOGFILE 324touch \$logfile 325test -z "$SUDO" || chown $USER \$logfile 326ln -f -s \${logfile} $TEST_SSHD_LOGFILE 327echo "Executing: ${SSHD} \$@" log \${logfile} >>$TEST_REGRESS_LOGFILE 328echo "Executing: ${SSHD} \$@" >>\${logfile} 329exec ${SSHD} -E\${logfile} "\$@" 330EOD 331chmod a+rx $OBJ/sshd-log-wrapper.sh 332 333ssh_logfile () 334{ 335 tool="$1" 336 timestamp="`$OBJ/timestamp`" 337 logfile="${TEST_SSH_LOGDIR}/${timestamp}.$tool.$$.log" 338 echo "Logging $tool to log \${logfile}" >>$TEST_REGRESS_LOGFILE 339 echo $logfile 340} 341 342# Some test data. We make a copy because some tests will overwrite it. 343# The tests may assume that $DATA exists and is writable and $COPY does 344# not exist. Tests requiring larger data files can call increase_datafile_size 345# [kbytes] to ensure the file is at least that large. 346DATANAME=data 347DATA=$OBJ/${DATANAME} 348cat ${SSHAGENT_BIN} >${DATA} 349chmod u+w ${DATA} 350COPY=$OBJ/copy 351rm -f ${COPY} 352 353increase_datafile_size() 354{ 355 while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do 356 cat ${SSHAGENT_BIN} >>${DATA} 357 done 358} 359 360# these should be used in tests 361export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP 362export SSH_PKCS11_HELPER SSH_SK_HELPER 363#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP 364 365# Portable specific functions 366which() 367{ 368 saved_IFS="$IFS" 369 IFS=":" 370 for i in $PATH 371 do 372 if [ -x $i/$1 ]; then 373 IFS="$saved_IFS" 374 echo "$i/$1" 375 return 0 376 fi 377 done 378 IFS="$saved_IFS" 379 echo "$i/$1" 380 return 1 381} 382 383have_prog() 384{ 385 which "$1" >/dev/null 2>&1 386 return $? 387} 388 389jot() { 390 awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }" 391} 392if [ ! -x "`which rev`" ]; then 393rev() 394{ 395 awk '{for (i=length; i>0; i--) printf "%s", substr($0, i, 1); print ""}' 396} 397fi 398 399# Check whether preprocessor symbols are defined in config.h. 400config_defined () 401{ 402 str=$1 403 while test "x$2" != "x" ; do 404 str="$str|$2" 405 shift 406 done 407 egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1 408} 409 410md5 () { 411 if have_prog md5sum; then 412 md5sum 413 elif have_prog openssl; then 414 openssl md5 415 elif have_prog cksum; then 416 cksum 417 elif have_prog sum; then 418 sum 419 elif [ -x ${OPENSSL_BIN} ]; then 420 ${OPENSSL_BIN} md5 421 else 422 wc -c 423 fi 424} 425 426# Some platforms don't have hostname at all, but on others uname -n doesn't 427# provide the fully qualified name we need, so in the former case we create 428# our own hostname function. 429if ! have_prog hostname; then 430 hostname() { 431 uname -n 432 } 433fi 434 435make_tmpdir () 436{ 437 SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \ 438 fatal "failed to create temporary directory" 439} 440# End of portable specific functions 441 442stop_sshd () 443{ 444 if [ -f $PIDFILE ]; then 445 pid=`$SUDO cat $PIDFILE` 446 if [ "X$pid" = "X" ]; then 447 echo no sshd running 448 else 449 if [ $pid -lt 2 ]; then 450 echo bad pid for sshd: $pid 451 else 452 $SUDO kill $pid 453 trace "wait for sshd to exit" 454 i=0; 455 while [ -f $PIDFILE -a $i -lt 5 ]; do 456 i=`expr $i + 1` 457 sleep $i 458 done 459 if test -f $PIDFILE; then 460 if $SUDO kill -0 $pid; then 461 echo "sshd didn't exit " \ 462 "port $PORT pid $pid" 463 else 464 echo "sshd died without cleanup" 465 fi 466 exit 1 467 fi 468 fi 469 fi 470 fi 471} 472 473# helper 474cleanup () 475{ 476 if [ "x$SSH_PID" != "x" ]; then 477 if [ $SSH_PID -lt 2 ]; then 478 echo bad pid for ssh: $SSH_PID 479 else 480 kill $SSH_PID 481 fi 482 fi 483 if [ "x$SSH_REGRESS_TMP" != "x" ]; then 484 rm -rf "$SSH_REGRESS_TMP" 485 fi 486 stop_sshd 487 if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then 488 now=`date '+%s'` 489 elapsed=$(($now - $STARTTIME)) 490 echo elapsed $elapsed `basename $SCRIPT .sh` 491 fi 492} 493 494start_debug_log () 495{ 496 echo "trace: $@" >>$TEST_REGRESS_LOGFILE 497 if [ -d "$TEST_SSH_LOGDIR" ]; then 498 rm -f $TEST_SSH_LOGDIR/* 499 fi 500} 501 502save_debug_log () 503{ 504 testname=`echo $tid | tr ' ' _` 505 tarname="$OBJ/failed-$testname-logs.tar" 506 507 for logfile in $TEST_SSH_LOGDIR $TEST_REGRESS_LOGFILE \ 508 $TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE; do 509 if [ ! -z "$SUDO" ] && [ -f "$logfile" ]; then 510 $SUDO chown -R $USER $logfile 511 fi 512 done 513 echo $@ >>$TEST_REGRESS_LOGFILE 514 echo $@ >>$TEST_SSH_LOGFILE 515 echo $@ >>$TEST_SSHD_LOGFILE 516 echo "Saving debug logs to $tarname" >>$TEST_REGRESS_LOGFILE 517 (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log 518 (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log 519 (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log 520 521 # Save all logfiles in a tarball. 522 (cd $OBJ && 523 logfiles="" 524 for i in $TEST_REGRESS_LOGFILE $TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE \ 525 $TEST_SSH_LOGDIR; do 526 if [ -e "`basename $i`" ]; then 527 logfiles="$logfiles `basename $i`" 528 else 529 logfiles="$logfiles $i" 530 fi 531 done 532 tar cf "$tarname" $logfiles) 533} 534 535trace () 536{ 537 start_debug_log $@ 538 if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then 539 echo "$@" 540 fi 541} 542 543verbose () 544{ 545 start_debug_log $@ 546 if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then 547 echo "$@" 548 fi 549} 550 551fail () 552{ 553 save_debug_log "FAIL: $@" 554 RESULT=1 555 echo "$@" 556 if test "x$TEST_SSH_FAIL_FATAL" != "x" ; then 557 cleanup 558 exit $RESULT 559 fi 560} 561 562fatal () 563{ 564 save_debug_log "FATAL: $@" 565 printf "FATAL: " 566 fail "$@" 567 cleanup 568 exit $RESULT 569} 570 571# Skip remaining tests in script. 572skip () 573{ 574 echo "SKIPPED: $@" 575 cleanup 576 exit $RESULT 577} 578 579maybe_add_scp_path_to_sshd () 580{ 581 # If we're testing a non-installed scp, add its directory to sshd's 582 # PATH so we can test it. We don't do this for all tests as it 583 # breaks the SetEnv tests. 584 case "$SCP" in 585 /*) PATH_WITH_SCP="`dirname $SCP`:$PATH" 586 echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_config 587 echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_proxy ;; 588 esac 589} 590 591RESULT=0 592PIDFILE=$OBJ/pidfile 593 594trap fatal 3 2 595 596# create server config 597cat << EOF > $OBJ/sshd_config 598 StrictModes no 599 Port $PORT 600 AddressFamily inet 601 ListenAddress 127.0.0.1 602 #ListenAddress ::1 603 PidFile $PIDFILE 604 AuthorizedKeysFile $OBJ/authorized_keys_%u 605 LogLevel DEBUG3 606 AcceptEnv _XXX_TEST_* 607 AcceptEnv _XXX_TEST 608 Subsystem sftp $SFTPSERVER 609EOF 610 611# This may be necessary if /usr/src and/or /usr/obj are group-writable, 612# but if you aren't careful with permissions then the unit tests could 613# be abused to locally escalate privileges. 614if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then 615 echo " StrictModes no" >> $OBJ/sshd_config 616else 617 # check and warn if excessive permissions are likely to cause failures. 618 unsafe="" 619 dir="${OBJ}" 620 while test ${dir} != "/"; do 621 if test -d "${dir}" && ! test -h "${dir}"; then 622 perms=`ls -ld ${dir}` 623 case "${perms}" in 624 ?????w????*|????????w?*) unsafe="${unsafe} ${dir}" ;; 625 esac 626 fi 627 dir=`dirname ${dir}` 628 done 629 if ! test -z "${unsafe}"; then 630 cat <<EOD 631 632WARNING: Unsafe (group or world writable) directory permissions found: 633${unsafe} 634 635These could be abused to locally escalate privileges. If you are 636sure that this is not a risk (eg there are no other users), you can 637bypass this check by setting TEST_SSH_UNSAFE_PERMISSIONS=1 638 639EOD 640 fi 641fi 642 643if [ ! -z "$TEST_SSH_MODULI_FILE" ]; then 644 trace "adding modulifile='$TEST_SSH_MODULI_FILE' to sshd_config" 645 echo " ModuliFile '$TEST_SSH_MODULI_FILE'" >> $OBJ/sshd_config 646fi 647 648if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then 649 trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" 650 echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config 651fi 652 653# server config for proxy connects 654cp $OBJ/sshd_config $OBJ/sshd_proxy 655 656# allow group-writable directories in proxy-mode 657echo 'StrictModes no' >> $OBJ/sshd_proxy 658 659# create client config 660cat << EOF > $OBJ/ssh_config 661Host * 662 Hostname 127.0.0.1 663 HostKeyAlias localhost-with-alias 664 Port $PORT 665 User $USER 666 GlobalKnownHostsFile $OBJ/known_hosts 667 UserKnownHostsFile $OBJ/known_hosts 668 PubkeyAuthentication yes 669 ChallengeResponseAuthentication no 670 PasswordAuthentication no 671 BatchMode yes 672 StrictHostKeyChecking yes 673 LogLevel DEBUG3 674EOF 675 676if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then 677 trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS" 678 echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config 679fi 680 681rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER 682 683SSH_SK_PROVIDER= 684if ! config_defined ENABLE_SK; then 685 trace skipping sk-dummy 686elif [ -f "${SRC}/misc/sk-dummy/obj/sk-dummy.so" ] ; then 687 SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/obj/sk-dummy.so" 688elif [ -f "${OBJ}/misc/sk-dummy/sk-dummy.so" ] ; then 689 SSH_SK_PROVIDER="${OBJ}/misc/sk-dummy/sk-dummy.so" 690elif [ -f "${SRC}/misc/sk-dummy/sk-dummy.so" ] ; then 691 SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/sk-dummy.so" 692fi 693export SSH_SK_PROVIDER 694 695if ! test -z "$SSH_SK_PROVIDER"; then 696 EXTRA_AGENT_ARGS='-P/*' # XXX want realpath(1)... 697 echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/ssh_config 698 echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_config 699 echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_proxy 700fi 701export EXTRA_AGENT_ARGS 702 703maybe_filter_sk() { 704 if test -z "$SSH_SK_PROVIDER" ; then 705 grep -v ^sk 706 else 707 cat 708 fi 709} 710 711SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk` 712SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk` 713 714for t in ${SSH_KEYTYPES}; do 715 # generate user key 716 if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then 717 trace "generating key type $t" 718 rm -f $OBJ/$t 719 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ 720 fail "ssh-keygen for $t failed" 721 else 722 trace "using cached key type $t" 723 fi 724 725 # setup authorized keys 726 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER 727 echo IdentityFile $OBJ/$t >> $OBJ/ssh_config 728done 729 730for t in ${SSH_HOSTKEY_TYPES}; do 731 # known hosts file for client 732 ( 733 printf 'localhost-with-alias,127.0.0.1,::1 ' 734 cat $OBJ/$t.pub 735 ) >> $OBJ/known_hosts 736 737 # use key as host key, too 738 (umask 077; $SUDO cp $OBJ/$t $OBJ/host.$t) 739 echo HostKey $OBJ/host.$t >> $OBJ/sshd_config 740 741 # don't use SUDO for proxy connect 742 echo HostKey $OBJ/$t >> $OBJ/sshd_proxy 743done 744chmod 644 $OBJ/authorized_keys_$USER 745 746# Activate Twisted Conch tests if the binary is present 747REGRESS_INTEROP_CONCH=no 748if test -x "$CONCH" ; then 749 REGRESS_INTEROP_CONCH=yes 750fi 751 752# If PuTTY is present, new enough and we are running a PuTTY test, prepare 753# keys and configuration. 754REGRESS_INTEROP_PUTTY=no 755if test -x "$PUTTYGEN" -a -x "$PLINK" && 756 "$PUTTYGEN" --help 2>&1 | grep -- --new-passphrase >/dev/null; then 757 REGRESS_INTEROP_PUTTY=yes 758fi 759case "$SCRIPT" in 760*putty*) ;; 761*) REGRESS_INTEROP_PUTTY=no ;; 762esac 763 764if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then 765 mkdir -p ${OBJ}/.putty 766 767 # Add a PuTTY key to authorized_keys 768 rm -f ${OBJ}/putty.rsa2 769 if ! "$PUTTYGEN" -t rsa -o ${OBJ}/putty.rsa2 \ 770 --random-device=/dev/urandom \ 771 --new-passphrase /dev/null < /dev/null > /dev/null; then 772 echo "Your installed version of PuTTY is too old to support --new-passphrase, skipping test" >&2 773 exit 1 774 fi 775 "$PUTTYGEN" -O public-openssh ${OBJ}/putty.rsa2 \ 776 >> $OBJ/authorized_keys_$USER 777 778 # Convert rsa2 host key to PuTTY format 779 cp $OBJ/ssh-rsa $OBJ/ssh-rsa_oldfmt 780 ${SSHKEYGEN} -p -N '' -m PEM -f $OBJ/ssh-rsa_oldfmt >/dev/null 781 ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/ssh-rsa_oldfmt > \ 782 ${OBJ}/.putty/sshhostkeys 783 ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/ssh-rsa_oldfmt >> \ 784 ${OBJ}/.putty/sshhostkeys 785 rm -f $OBJ/ssh-rsa_oldfmt 786 787 # Setup proxied session 788 mkdir -p ${OBJ}/.putty/sessions 789 rm -f ${OBJ}/.putty/sessions/localhost_proxy 790 echo "Protocol=ssh" >> ${OBJ}/.putty/sessions/localhost_proxy 791 echo "HostName=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy 792 echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy 793 echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy 794 echo "ProxyTelnetCommand=${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy 795 echo "ProxyLocalhost=1" >> ${OBJ}/.putty/sessions/localhost_proxy 796 797 PUTTYDIR=${OBJ}/.putty 798 export PUTTYDIR 799fi 800 801REGRESS_INTEROP_DROPBEAR=no 802if test -x "$DROPBEARKEY" -a -x "$DBCLIENT" -a -x "$DROPBEARCONVERT"; then 803 REGRESS_INTEROP_DROPBEAR=yes 804fi 805case "$SCRIPT" in 806*dropbear*) ;; 807*) REGRESS_INTEROP_DROPBEAR=no ;; 808esac 809 810if test "$REGRESS_INTEROP_DROPBEAR" = "yes" ; then 811 trace Create dropbear keys and add to authorized_keys 812 mkdir -p $OBJ/.dropbear 813 for i in rsa ecdsa ed25519 dss; do 814 if [ ! -f "$OBJ/.dropbear/id_$i" ]; then 815 ($DROPBEARKEY -t $i -f $OBJ/.dropbear/id_$i 816 $DROPBEARCONVERT dropbear openssh \ 817 $OBJ/.dropbear/id_$i $OBJ/.dropbear/ossh.id_$i 818 ) > /dev/null 2>&1 819 fi 820 $SSHKEYGEN -y -f $OBJ/.dropbear/ossh.id_$i \ 821 >>$OBJ/authorized_keys_$USER 822 done 823fi 824 825# create a proxy version of the client config 826( 827 cat $OBJ/ssh_config 828 echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy 829) > $OBJ/ssh_proxy 830 831# check proxy config 832${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" 833 834# extract proxycommand into separate shell script for use by Dropbear. 835echo '#!/bin/sh' >$OBJ/ssh_proxy.sh 836awk '/^proxycommand/' $OBJ/ssh_proxy | sed 's/^proxycommand//' \ 837 >>$OBJ/ssh_proxy.sh 838chmod a+x $OBJ/ssh_proxy.sh 839 840start_sshd () 841{ 842 # start sshd 843 logfile="${TEST_SSH_LOGDIR}/sshd.`$OBJ/timestamp`.$$.log" 844 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" 845 $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" \ 846 ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE 847 848 trace "wait for sshd" 849 i=0; 850 while [ ! -f $PIDFILE -a $i -lt 10 ]; do 851 i=`expr $i + 1` 852 sleep $i 853 done 854 855 test -f $PIDFILE || fatal "no sshd running on port $PORT" 856} 857 858# Find a PKCS#11 library. 859p11_find_lib() { 860 TEST_SSH_PKCS11="" 861 for _lib in "$@" ; do 862 if test -f "$_lib" ; then 863 TEST_SSH_PKCS11="$_lib" 864 return 865 fi 866 done 867} 868 869# Perform PKCS#11 setup: prepares a softhsm2 token configuration, generated 870# keys and loads them into the virtual token. 871PKCS11_OK= 872export PKCS11_OK 873p11_setup() { 874 p11_find_lib \ 875 /usr/local/lib/softhsm/libsofthsm2.so \ 876 /usr/lib64/pkcs11/libsofthsm2.so \ 877 /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so 878 test -z "$TEST_SSH_PKCS11" && return 1 879 verbose "using token library $TEST_SSH_PKCS11" 880 TEST_SSH_PIN=1234 881 TEST_SSH_SOPIN=12345678 882 if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then 883 SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}" 884 export SSH_PKCS11_HELPER 885 fi 886 887 # setup environment for softhsm2 token 888 SSH_SOFTHSM_DIR=$OBJ/SOFTHSM 889 export SSH_SOFTHSM_DIR 890 rm -rf $SSH_SOFTHSM_DIR 891 TOKEN=$SSH_SOFTHSM_DIR/tokendir 892 mkdir -p $TOKEN 893 SOFTHSM2_CONF=$SSH_SOFTHSM_DIR/softhsm2.conf 894 export SOFTHSM2_CONF 895 cat > $SOFTHSM2_CONF << EOF 896# SoftHSM v2 configuration file 897directories.tokendir = ${TOKEN} 898objectstore.backend = file 899# ERROR, WARNING, INFO, DEBUG 900log.level = DEBUG 901# If CKF_REMOVABLE_DEVICE flag should be set 902slots.removable = false 903EOF 904 out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN") 905 slot=$(echo -- $out | sed 's/.* //') 906 trace "generating keys" 907 # RSA key 908 RSA=${SSH_SOFTHSM_DIR}/RSA 909 RSAP8=${SSH_SOFTHSM_DIR}/RSAP8 910 $OPENSSL_BIN genpkey -algorithm rsa > $RSA 2>/dev/null || \ 911 fatal "genpkey RSA fail" 912 $OPENSSL_BIN pkcs8 -nocrypt -in $RSA > $RSAP8 || fatal "pkcs8 RSA fail" 913 softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" \ 914 --import $RSAP8 >/dev/null || fatal "softhsm import RSA fail" 915 chmod 600 $RSA 916 ssh-keygen -y -f $RSA > ${RSA}.pub 917 # ECDSA key 918 ECPARAM=${SSH_SOFTHSM_DIR}/ECPARAM 919 EC=${SSH_SOFTHSM_DIR}/EC 920 ECP8=${SSH_SOFTHSM_DIR}/ECP8 921 $OPENSSL_BIN genpkey -genparam -algorithm ec \ 922 -pkeyopt ec_paramgen_curve:prime256v1 > $ECPARAM || \ 923 fatal "param EC fail" 924 $OPENSSL_BIN genpkey -paramfile $ECPARAM > $EC || \ 925 fatal "genpkey EC fail" 926 $OPENSSL_BIN pkcs8 -nocrypt -in $EC > $ECP8 || fatal "pkcs8 EC fail" 927 softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" \ 928 --import $ECP8 >/dev/null || fatal "softhsm import EC fail" 929 chmod 600 $EC 930 ssh-keygen -y -f $EC > ${EC}.pub 931 # Prepare askpass script to load PIN. 932 PIN_SH=$SSH_SOFTHSM_DIR/pin.sh 933 cat > $PIN_SH << EOF 934#!/bin/sh 935echo "${TEST_SSH_PIN}" 936EOF 937 chmod 0700 "$PIN_SH" 938 PKCS11_OK=yes 939 return 0 940} 941 942# Peforms ssh-add with the right token PIN. 943p11_ssh_add() { 944 env SSH_ASKPASS="$PIN_SH" SSH_ASKPASS_REQUIRE=force ${SSHADD} "$@" 945} 946 947# source test body 948. $SCRIPT 949 950# kill sshd 951cleanup 952 953if [ "x$USE_VALGRIND" != "x" ]; then 954 # If there is an EXIT trap handler, invoke it now. 955 # Some tests set these to clean up processes such as ssh-agent. We 956 # need to wait for all valgrind processes to complete so we can check 957 # their logs, but since the EXIT traps are not invoked until 958 # test-exec.sh exits, waiting here will deadlock. 959 # This is not very portable but then neither is valgrind itself. 960 # As a bonus, dash (as used on the runners) has a "trap" that doesn't 961 # work in a pipeline (hence the temp file) or a subshell. 962 exithandler="" 963 trap >/tmp/trap.$$ && exithandler=$(cat /tmp/trap.$$ | \ 964 awk -F "'" '/EXIT$/{print $2}') 965 rm -f /tmp/trap.$$ 966 if [ "x${exithandler}" != "x" ]; then 967 verbose invoking EXIT trap handler early: ${exithandler} 968 eval "${exithandler}" 969 trap '' EXIT 970 fi 971 972 # wait for any running process to complete 973 wait; sleep 1 974 VG_RESULTS=$(find $OBJ/valgrind-out -type f -print) 975 VG_RESULT_COUNT=0 976 VG_FAIL_COUNT=0 977 for i in $VG_RESULTS; do 978 if grep "ERROR SUMMARY" $i >/dev/null; then 979 VG_RESULT_COUNT=$(($VG_RESULT_COUNT + 1)) 980 if ! grep "ERROR SUMMARY: 0 errors" $i >/dev/null; then 981 VG_FAIL_COUNT=$(($VG_FAIL_COUNT + 1)) 982 RESULT=1 983 verbose valgrind failure $i 984 cat $i 985 fi 986 fi 987 done 988 if [ x"$VG_SKIP" != "x" ]; then 989 verbose valgrind skipped 990 else 991 verbose valgrind results $VG_RESULT_COUNT failures $VG_FAIL_COUNT 992 fi 993fi 994 995if [ $RESULT -eq 0 ]; then 996 verbose ok $tid 997 if [ "x$CACHE" != "x" ]; then 998 touch "$CACHE" 999 fi 1000else 1001 echo failed $tid 1002fi 1003exit $RESULT 1004