1# $OpenBSD: test-exec.sh,v 1.47 2013/11/09 05:41:34 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 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 [ -f $PIDFILE ]; then 244 pid=`$SUDO cat $PIDFILE` 245 if [ "X$pid" = "X" ]; then 246 echo no sshd running 247 else 248 if [ $pid -lt 2 ]; then 249 echo bad pid for ssh: $pid 250 else 251 $SUDO kill $pid 252 trace "wait for sshd to exit" 253 i=0; 254 while [ -f $PIDFILE -a $i -lt 5 ]; do 255 i=`expr $i + 1` 256 sleep $i 257 done 258 test -f $PIDFILE && \ 259 fatal "sshd didn't exit port $PORT pid $pid" 260 fi 261 fi 262 fi 263} 264 265start_debug_log () 266{ 267 echo "trace: $@" >$TEST_REGRESS_LOGFILE 268 echo "trace: $@" >$TEST_SSH_LOGFILE 269 echo "trace: $@" >$TEST_SSHD_LOGFILE 270} 271 272save_debug_log () 273{ 274 echo $@ >>$TEST_REGRESS_LOGFILE 275 echo $@ >>$TEST_SSH_LOGFILE 276 echo $@ >>$TEST_SSHD_LOGFILE 277 (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log 278 (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log 279 (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log 280} 281 282trace () 283{ 284 start_debug_log $@ 285 if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then 286 echo "$@" 287 fi 288} 289 290verbose () 291{ 292 start_debug_log $@ 293 if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then 294 echo "$@" 295 fi 296} 297 298warn () 299{ 300 echo "WARNING: $@" >>$TEST_SSH_LOGFILE 301 echo "WARNING: $@" 302} 303 304fail () 305{ 306 save_debug_log "FAIL: $@" 307 RESULT=1 308 echo "$@" 309 310} 311 312fatal () 313{ 314 save_debug_log "FATAL: $@" 315 printf "FATAL: " 316 fail "$@" 317 cleanup 318 exit $RESULT 319} 320 321RESULT=0 322PIDFILE=$OBJ/pidfile 323 324trap fatal 3 2 325 326# create server config 327cat << EOF > $OBJ/sshd_config 328 StrictModes no 329 Port $PORT 330 Protocol 2,1 331 AddressFamily inet 332 ListenAddress 127.0.0.1 333 #ListenAddress ::1 334 PidFile $PIDFILE 335 AuthorizedKeysFile $OBJ/authorized_keys_%u 336 LogLevel DEBUG3 337 AcceptEnv _XXX_TEST_* 338 AcceptEnv _XXX_TEST 339 Subsystem sftp $SFTPSERVER 340EOF 341 342if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then 343 trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" 344 echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config 345fi 346 347# server config for proxy connects 348cp $OBJ/sshd_config $OBJ/sshd_proxy 349 350# allow group-writable directories in proxy-mode 351echo 'StrictModes no' >> $OBJ/sshd_proxy 352 353# create client config 354cat << EOF > $OBJ/ssh_config 355Host * 356 Protocol 2,1 357 Hostname 127.0.0.1 358 HostKeyAlias localhost-with-alias 359 Port $PORT 360 User $USER 361 GlobalKnownHostsFile $OBJ/known_hosts 362 UserKnownHostsFile $OBJ/known_hosts 363 RSAAuthentication yes 364 PubkeyAuthentication yes 365 ChallengeResponseAuthentication no 366 HostbasedAuthentication no 367 PasswordAuthentication no 368 RhostsRSAAuthentication no 369 BatchMode yes 370 StrictHostKeyChecking yes 371 LogLevel DEBUG3 372EOF 373 374if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then 375 trace "adding ssh_config option $TEST_SSH_SSHD_CONFOPTS" 376 echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config 377fi 378 379rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER 380 381trace "generate keys" 382for t in rsa rsa1; do 383 # generate user key 384 if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then 385 rm -f $OBJ/$t 386 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ 387 fail "ssh-keygen for $t failed" 388 fi 389 390 # known hosts file for client 391 ( 392 printf 'localhost-with-alias,127.0.0.1,::1 ' 393 cat $OBJ/$t.pub 394 ) >> $OBJ/known_hosts 395 396 # setup authorized keys 397 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER 398 echo IdentityFile $OBJ/$t >> $OBJ/ssh_config 399 400 # use key as host key, too 401 $SUDO cp $OBJ/$t $OBJ/host.$t 402 echo HostKey $OBJ/host.$t >> $OBJ/sshd_config 403 404 # don't use SUDO for proxy connect 405 echo HostKey $OBJ/$t >> $OBJ/sshd_proxy 406done 407chmod 644 $OBJ/authorized_keys_$USER 408 409# Activate Twisted Conch tests if the binary is present 410REGRESS_INTEROP_CONCH=no 411if test -x "$CONCH" ; then 412 REGRESS_INTEROP_CONCH=yes 413fi 414 415# If PuTTY is present and we are running a PuTTY test, prepare keys and 416# configuration 417REGRESS_INTEROP_PUTTY=no 418if test -x "$PUTTYGEN" -a -x "$PLINK" ; then 419 REGRESS_INTEROP_PUTTY=yes 420fi 421case "$SCRIPT" in 422*putty*) ;; 423*) REGRESS_INTEROP_PUTTY=no ;; 424esac 425 426if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then 427 mkdir -p ${OBJ}/.putty 428 429 # Add a PuTTY key to authorized_keys 430 rm -f ${OBJ}/putty.rsa2 431 puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null 432 puttygen -O public-openssh ${OBJ}/putty.rsa2 \ 433 >> $OBJ/authorized_keys_$USER 434 435 # Convert rsa2 host key to PuTTY format 436 ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/rsa > \ 437 ${OBJ}/.putty/sshhostkeys 438 ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/rsa >> \ 439 ${OBJ}/.putty/sshhostkeys 440 441 # Setup proxied session 442 mkdir -p ${OBJ}/.putty/sessions 443 rm -f ${OBJ}/.putty/sessions/localhost_proxy 444 echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy 445 echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy 446 echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy 447 echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy 448 449 REGRESS_INTEROP_PUTTY=yes 450fi 451 452# create a proxy version of the client config 453( 454 cat $OBJ/ssh_config 455 echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy 456) > $OBJ/ssh_proxy 457 458# check proxy config 459${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" 460 461start_sshd () 462{ 463 # start sshd 464 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" 465 $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE 466 467 trace "wait for sshd" 468 i=0; 469 while [ ! -f $PIDFILE -a $i -lt 10 ]; do 470 i=`expr $i + 1` 471 sleep $i 472 done 473 474 test -f $PIDFILE || fatal "no sshd running on port $PORT" 475} 476 477# source test body 478. $SCRIPT 479 480# kill sshd 481cleanup 482if [ $RESULT -eq 0 ]; then 483 verbose ok $tid 484else 485 echo failed $tid 486fi 487exit $RESULT 488