1255670Sdes#	$OpenBSD: test-exec.sh,v 1.46 2013/06/21 02:26:26 djm Exp $
298937Sdes#	Placed in the Public Domain.
398937Sdes
498937Sdes#SUDO=sudo
598937Sdes
6146998Sdes# Unbreak GNU head(1)
7146998Sdes_POSIX2_VERSION=199209
8146998Sdesexport _POSIX2_VERSION
9146998Sdes
10146998Sdescase `uname -s 2>/dev/null` in
11146998SdesOSF1*)
12146998Sdes	BIN_SH=xpg4
13146998Sdes	export BIN_SH
14146998Sdes	;;
15239849SdesCYGWIN_NT-5.0)
16239849Sdes	os=cygwin
17239849Sdes	TEST_SSH_IPV6=no
18239849Sdes	;;
19239849SdesCYGWIN*)
20239849Sdes	os=cygwin
21239849Sdes	;;
22146998Sdesesac
23146998Sdes
24137015Sdesif [ ! -z "$TEST_SSH_PORT" ]; then
25137015Sdes	PORT="$TEST_SSH_PORT"
26137015Sdeselse
27137015Sdes	PORT=4242
28137015Sdesfi
29137015Sdes
30124208Sdesif [ -x /usr/ucb/whoami ]; then
31124208Sdes	USER=`/usr/ucb/whoami`
32124208Sdeselif whoami >/dev/null 2>&1; then
33124208Sdes	USER=`whoami`
34157016Sdeselif logname >/dev/null 2>&1; then
35157016Sdes	USER=`logname`
36124208Sdeselse
37124208Sdes	USER=`id -un`
38124208Sdesfi
39124208Sdes
4098937SdesOBJ=$1
4198937Sdesif [ "x$OBJ" = "x" ]; then
4298937Sdes	echo '$OBJ not defined'
4398937Sdes	exit 2
4498937Sdesfi
4598937Sdesif [ ! -d $OBJ ]; then
4698937Sdes	echo "not a directory: $OBJ"
4798937Sdes	exit 2
4898937Sdesfi
4998937SdesSCRIPT=$2
5098937Sdesif [ "x$SCRIPT" = "x" ]; then
5198937Sdes	echo '$SCRIPT not defined'
5298937Sdes	exit 2
5398937Sdesfi
5498937Sdesif [ ! -f $SCRIPT ]; then
5598937Sdes	echo "not a file: $SCRIPT"
5698937Sdes	exit 2
5798937Sdesfi
58126274Sdesif $TEST_SHELL -n $SCRIPT; then
5998937Sdes	true
6098937Sdeselse
6198937Sdes	echo "syntax error in $SCRIPT"
6298937Sdes	exit 2
6398937Sdesfi
6498937Sdesunset SSH_AUTH_SOCK
6598937Sdes
66146998SdesSRC=`dirname ${SCRIPT}`
67146998Sdes
6898937Sdes# defaults
6998937SdesSSH=ssh
7098937SdesSSHD=sshd
7198937SdesSSHAGENT=ssh-agent
7298937SdesSSHADD=ssh-add
7398937SdesSSHKEYGEN=ssh-keygen
7498937SdesSSHKEYSCAN=ssh-keyscan
7598937SdesSFTP=sftp
7698937SdesSFTPSERVER=/usr/libexec/openssh/sftp-server
77137015SdesSCP=scp
7898937Sdes
79180746Sdes# Interop testing
80180750SdesPLINK=plink
81180750SdesPUTTYGEN=puttygen
82180750SdesCONCH=conch
83180746Sdes
8498937Sdesif [ "x$TEST_SSH_SSH" != "x" ]; then
85128456Sdes	SSH="${TEST_SSH_SSH}"
8698937Sdesfi
8798937Sdesif [ "x$TEST_SSH_SSHD" != "x" ]; then
88128456Sdes	SSHD="${TEST_SSH_SSHD}"
8998937Sdesfi
9098937Sdesif [ "x$TEST_SSH_SSHAGENT" != "x" ]; then
91128456Sdes	SSHAGENT="${TEST_SSH_SSHAGENT}"
9298937Sdesfi
9398937Sdesif [ "x$TEST_SSH_SSHADD" != "x" ]; then
94128456Sdes	SSHADD="${TEST_SSH_SSHADD}"
9598937Sdesfi
9698937Sdesif [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then
97128456Sdes	SSHKEYGEN="${TEST_SSH_SSHKEYGEN}"
9898937Sdesfi
9998937Sdesif [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then
100128456Sdes	SSHKEYSCAN="${TEST_SSH_SSHKEYSCAN}"
10198937Sdesfi
10298937Sdesif [ "x$TEST_SSH_SFTP" != "x" ]; then
103128456Sdes	SFTP="${TEST_SSH_SFTP}"
10498937Sdesfi
10598937Sdesif [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then
106128456Sdes	SFTPSERVER="${TEST_SSH_SFTPSERVER}"
10798937Sdesfi
108137015Sdesif [ "x$TEST_SSH_SCP" != "x" ]; then
109137015Sdes	SCP="${TEST_SSH_SCP}"
110137015Sdesfi
111180746Sdesif [ "x$TEST_SSH_PLINK" != "x" ]; then
112180746Sdes	# Find real binary, if it exists
113180746Sdes	case "${TEST_SSH_PLINK}" in
114180746Sdes	/*) PLINK="${TEST_SSH_PLINK}" ;;
115180746Sdes	*) PLINK=`which ${TEST_SSH_PLINK} 2>/dev/null` ;;
116180746Sdes	esac
117180746Sdesfi
118180746Sdesif [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then
119180746Sdes	# Find real binary, if it exists
120180746Sdes	case "${TEST_SSH_PUTTYGEN}" in
121180746Sdes	/*) PUTTYGEN="${TEST_SSH_PUTTYGEN}" ;;
122180746Sdes	*) PUTTYGEN=`which ${TEST_SSH_PUTTYGEN} 2>/dev/null` ;;
123180746Sdes	esac
124180746Sdesfi
125180750Sdesif [ "x$TEST_SSH_CONCH" != "x" ]; then
126180750Sdes	# Find real binary, if it exists
127180750Sdes	case "${TEST_SSH_CONCH}" in
128180750Sdes	/*) CONCH="${TEST_SSH_CONCH}" ;;
129180750Sdes	*) CONCH=`which ${TEST_SSH_CONCH} 2>/dev/null` ;;
130180750Sdes	esac
131180750Sdesfi
13298937Sdes
133137015Sdes# Path to sshd must be absolute for rexec
134149749Sdescase "$SSHD" in
135149749Sdes/*) ;;
136149749Sdes*) SSHD=`which sshd` ;;
137149749Sdesesac
138137015Sdes
139255670Sdes# Logfiles.
140255670Sdes# SSH_LOGFILE should be the debug output of ssh(1) only
141255670Sdes# SSHD_LOGFILE should be the debug output of sshd(8) only
142255670Sdes# REGRESS_LOGFILE is the output of the test itself stdout and stderr
143146998Sdesif [ "x$TEST_SSH_LOGFILE" = "x" ]; then
144255670Sdes	TEST_SSH_LOGFILE=$OBJ/ssh.log
145146998Sdesfi
146255670Sdesif [ "x$TEST_SSHD_LOGFILE" = "x" ]; then
147255670Sdes	TEST_SSHD_LOGFILE=$OBJ/sshd.log
148255670Sdesfi
149255670Sdesif [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then
150255670Sdes	TEST_REGRESS_LOGFILE=$OBJ/regress.log
151255670Sdesfi
152146998Sdes
153255670Sdes# truncate logfiles
154255670Sdes>$TEST_SSH_LOGFILE
155255670Sdes>$TEST_SSHD_LOGFILE
156255670Sdes>$TEST_REGRESS_LOGFILE
157248613Sdes
158255670Sdes# Create wrapper ssh with logging.  We can't just specify "SSH=ssh -E..."
159255670Sdes# because sftp and scp don't handle spaces in arguments.
160255670SdesSSHLOGWRAP=$OBJ/ssh-log-wrapper.sh
161255670Sdesecho "#!/bin/sh" > $SSHLOGWRAP
162255670Sdesecho "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
163255670Sdes
164255670Sdeschmod a+rx $OBJ/ssh-log-wrapper.sh
165255670SdesSSH="$SSHLOGWRAP"
166255670Sdes
167255670Sdes# Some test data.  We make a copy because some tests will overwrite it.
168255670Sdes# The tests may assume that $DATA exists and is writable and $COPY does
169255670Sdes# not exist.
170255670SdesDATANAME=data
171255670SdesDATA=$OBJ/${DATANAME}
172255670Sdescat $SSHD $SSHD $SSHD $SSHD >${DATA}
173255670Sdeschmod u+w ${DATA}
174255670SdesCOPY=$OBJ/copy
175255670Sdesrm -f ${COPY}
176255670Sdes
17798937Sdes# these should be used in tests
178137015Sdesexport SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP
179137015Sdes#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP
18098937Sdes
181255670Sdes# Portable specific functions
182124208Sdeshave_prog()
183124208Sdes{
184124208Sdes	saved_IFS="$IFS"
185124208Sdes	IFS=":"
186124208Sdes	for i in $PATH
187124208Sdes	do
188124208Sdes		if [ -x $i/$1 ]; then
189124208Sdes			IFS="$saved_IFS"
190124208Sdes			return 0
191124208Sdes		fi
192124208Sdes	done
193124208Sdes	IFS="$saved_IFS"
194124208Sdes	return 1
195124208Sdes}
196124208Sdes
197255670Sdesjot() {
198255670Sdes	awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }"
199255670Sdes}
200255670Sdes
201255670Sdes# Check whether preprocessor symbols are defined in config.h.
202255670Sdesconfig_defined ()
203255670Sdes{
204255670Sdes	str=$1
205255670Sdes	while test "x$2" != "x" ; do
206255670Sdes		str="$str|$2"
207255670Sdes		shift
208255670Sdes	done
209255670Sdes	egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1
210255670Sdes}
211255670Sdes
212255670Sdesmd5 () {
213255670Sdes	if have_prog md5sum; then
214255670Sdes		md5sum
215255670Sdes	elif have_prog openssl; then
216255670Sdes		openssl md5
217255670Sdes	elif have_prog cksum; then
218255670Sdes		cksum
219255670Sdes	elif have_prog sum; then
220255670Sdes		sum
221255670Sdes	else
222255670Sdes		wc -c
223255670Sdes	fi
224255670Sdes}
225255670Sdes# End of portable specific functions
226255670Sdes
227255670Sdes# helper
22898937Sdescleanup ()
22998937Sdes{
23098937Sdes	if [ -f $PIDFILE ]; then
231214979Sdes		pid=`$SUDO cat $PIDFILE`
23298937Sdes		if [ "X$pid" = "X" ]; then
23398937Sdes			echo no sshd running
23498937Sdes		else
23598937Sdes			if [ $pid -lt 2 ]; then
236204861Sdes				echo bad pid for ssh: $pid
23798937Sdes			else
23898937Sdes				$SUDO kill $pid
239204861Sdes				trace "wait for sshd to exit"
240204861Sdes				i=0;
241204861Sdes				while [ -f $PIDFILE -a $i -lt 5 ]; do
242204861Sdes					i=`expr $i + 1`
243204861Sdes					sleep $i
244204861Sdes				done
245204861Sdes				test -f $PIDFILE && \
246204861Sdes				    fatal "sshd didn't exit port $PORT pid $pid"
24798937Sdes			fi
24898937Sdes		fi
24998937Sdes	fi
25098937Sdes}
25198937Sdes
252255670Sdesstart_debug_log ()
253255670Sdes{
254255670Sdes	echo "trace: $@" >$TEST_REGRESS_LOGFILE
255255670Sdes	echo "trace: $@" >$TEST_SSH_LOGFILE
256255670Sdes	echo "trace: $@" >$TEST_SSHD_LOGFILE
257255670Sdes}
258255670Sdes
259255670Sdessave_debug_log ()
260255670Sdes{
261255670Sdes	echo $@ >>$TEST_REGRESS_LOGFILE
262255670Sdes	echo $@ >>$TEST_SSH_LOGFILE
263255670Sdes	echo $@ >>$TEST_SSHD_LOGFILE
264255670Sdes	(cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log
265255670Sdes	(cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log
266255670Sdes	(cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log
267255670Sdes}
268255670Sdes
26998937Sdestrace ()
27098937Sdes{
271255670Sdes	start_debug_log $@
27298937Sdes	if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then
27398937Sdes		echo "$@"
27498937Sdes	fi
27598937Sdes}
27698937Sdes
27798937Sdesverbose ()
27898937Sdes{
279255670Sdes	start_debug_log $@
28098937Sdes	if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then
28198937Sdes		echo "$@"
28298937Sdes	fi
28398937Sdes}
28498937Sdes
285225825Sdeswarn ()
286225825Sdes{
287225825Sdes	echo "WARNING: $@" >>$TEST_SSH_LOGFILE
288225825Sdes	echo "WARNING: $@"
289225825Sdes}
29098937Sdes
29198937Sdesfail ()
29298937Sdes{
293255670Sdes	save_debug_log "FAIL: $@"
29498937Sdes	RESULT=1
29598937Sdes	echo "$@"
296255670Sdes
29798937Sdes}
29898937Sdes
29998937Sdesfatal ()
30098937Sdes{
301255670Sdes	save_debug_log "FATAL: $@"
302255670Sdes	printf "FATAL: "
30398937Sdes	fail "$@"
30498937Sdes	cleanup
30598937Sdes	exit $RESULT
30698937Sdes}
30798937Sdes
30898937SdesRESULT=0
30998937SdesPIDFILE=$OBJ/pidfile
31098937Sdes
31198937Sdestrap fatal 3 2
31298937Sdes
31398937Sdes# create server config
31498937Sdescat << EOF > $OBJ/sshd_config
315137015Sdes	StrictModes		no
31698937Sdes	Port			$PORT
317204861Sdes	Protocol		2,1
318157016Sdes	AddressFamily		inet
31998937Sdes	ListenAddress		127.0.0.1
32098937Sdes	#ListenAddress		::1
32198937Sdes	PidFile			$PIDFILE
32298937Sdes	AuthorizedKeysFile	$OBJ/authorized_keys_%u
323255670Sdes	LogLevel		DEBUG3
324137015Sdes	AcceptEnv		_XXX_TEST_*
325137015Sdes	AcceptEnv		_XXX_TEST
326137015Sdes	Subsystem	sftp	$SFTPSERVER
32798937SdesEOF
32898937Sdes
329137015Sdesif [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then
330137015Sdes	trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS"
331137015Sdes	echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config
332137015Sdesfi
333137015Sdes
33498937Sdes# server config for proxy connects
33598937Sdescp $OBJ/sshd_config $OBJ/sshd_proxy
33698937Sdes
33798937Sdes# allow group-writable directories in proxy-mode
33898937Sdesecho 'StrictModes no' >> $OBJ/sshd_proxy
33998937Sdes
34098937Sdes# create client config
34198937Sdescat << EOF > $OBJ/ssh_config
34298937SdesHost *
343204861Sdes	Protocol		2,1
34498937Sdes	Hostname		127.0.0.1
34598937Sdes	HostKeyAlias		localhost-with-alias
34698937Sdes	Port			$PORT
34798937Sdes	User			$USER
34898937Sdes	GlobalKnownHostsFile	$OBJ/known_hosts
34998937Sdes	UserKnownHostsFile	$OBJ/known_hosts
35098937Sdes	RSAAuthentication	yes
35198937Sdes	PubkeyAuthentication	yes
35298937Sdes	ChallengeResponseAuthentication	no
35398937Sdes	HostbasedAuthentication	no
35498937Sdes	PasswordAuthentication	no
355255670Sdes	RhostsRSAAuthentication	no
35698937Sdes	BatchMode		yes
35798937Sdes	StrictHostKeyChecking	yes
358255670Sdes	LogLevel		DEBUG3
35998937SdesEOF
36098937Sdes
361137015Sdesif [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then
362137015Sdes	trace "adding ssh_config option $TEST_SSH_SSHD_CONFOPTS"
363137015Sdes	echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config
364137015Sdesfi
365137015Sdes
36698937Sdesrm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
36798937Sdes
36898937Sdestrace "generate keys"
36998937Sdesfor t in rsa rsa1; do
37098937Sdes	# generate user key
371255670Sdes	if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then
372255670Sdes		rm -f $OBJ/$t
373255670Sdes		${SSHKEYGEN} -q -N '' -t $t  -f $OBJ/$t ||\
374255670Sdes			fail "ssh-keygen for $t failed"
375255670Sdes	fi
37698937Sdes
37798937Sdes	# known hosts file for client
37898937Sdes	(
379255670Sdes		printf 'localhost-with-alias,127.0.0.1,::1 '
38098937Sdes		cat $OBJ/$t.pub
38198937Sdes	) >> $OBJ/known_hosts
38298937Sdes
38398937Sdes	# setup authorized keys
38498937Sdes	cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
38598937Sdes	echo IdentityFile $OBJ/$t >> $OBJ/ssh_config
38698937Sdes
38798937Sdes	# use key as host key, too
38898937Sdes	$SUDO cp $OBJ/$t $OBJ/host.$t
38998937Sdes	echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
39098937Sdes
39198937Sdes	# don't use SUDO for proxy connect
39298937Sdes	echo HostKey $OBJ/$t >> $OBJ/sshd_proxy
39398937Sdesdone
39498937Sdeschmod 644 $OBJ/authorized_keys_$USER
39598937Sdes
396180750Sdes# Activate Twisted Conch tests if the binary is present
397180750SdesREGRESS_INTEROP_CONCH=no
398180750Sdesif test -x "$CONCH" ; then
399180750Sdes	REGRESS_INTEROP_CONCH=yes
400180750Sdesfi
401180750Sdes
402180750Sdes# If PuTTY is present and we are running a PuTTY test, prepare keys and
403180750Sdes# configuration
404180746SdesREGRESS_INTEROP_PUTTY=no
405180746Sdesif test -x "$PUTTYGEN" -a -x "$PLINK" ; then
406180750Sdes	REGRESS_INTEROP_PUTTY=yes
407180750Sdesfi
408180750Sdescase "$SCRIPT" in
409180750Sdes*putty*)	;;
410180750Sdes*)		REGRESS_INTEROP_PUTTY=no ;;
411180750Sdesesac
412180750Sdes
413180750Sdesif test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
414180746Sdes	mkdir -p ${OBJ}/.putty
415180746Sdes
416180746Sdes	# Add a PuTTY key to authorized_keys
417180746Sdes	rm -f ${OBJ}/putty.rsa2
418180746Sdes	puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null
419180746Sdes	puttygen -O public-openssh ${OBJ}/putty.rsa2 \
420180746Sdes	    >> $OBJ/authorized_keys_$USER
421180746Sdes
422180746Sdes	# Convert rsa2 host key to PuTTY format
423180746Sdes	${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/rsa > \
424180746Sdes	    ${OBJ}/.putty/sshhostkeys
425180746Sdes	${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/rsa >> \
426180746Sdes	    ${OBJ}/.putty/sshhostkeys
427180746Sdes
428180746Sdes	# Setup proxied session
429180746Sdes	mkdir -p ${OBJ}/.putty/sessions
430180746Sdes	rm -f ${OBJ}/.putty/sessions/localhost_proxy
431180746Sdes	echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy
432180746Sdes	echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy
433180746Sdes	echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy
434255670Sdes	echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy
435180746Sdes
436180746Sdes	REGRESS_INTEROP_PUTTY=yes
437180746Sdesfi
438180746Sdes
43998937Sdes# create a proxy version of the client config
44098937Sdes(
44198937Sdes	cat $OBJ/ssh_config
442255670Sdes	echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy
44398937Sdes) > $OBJ/ssh_proxy
44498937Sdes
44598937Sdes# check proxy config
44698937Sdes${SSHD} -t -f $OBJ/sshd_proxy	|| fatal "sshd_proxy broken"
44798937Sdes
44898937Sdesstart_sshd ()
44998937Sdes{
45098937Sdes	# start sshd
451180746Sdes	$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken"
452255670Sdes	$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE
45398937Sdes
45498937Sdes	trace "wait for sshd"
45598937Sdes	i=0;
456124208Sdes	while [ ! -f $PIDFILE -a $i -lt 10 ]; do
45798937Sdes		i=`expr $i + 1`
45898937Sdes		sleep $i
45998937Sdes	done
46098937Sdes
46198937Sdes	test -f $PIDFILE || fatal "no sshd running on port $PORT"
46298937Sdes}
46398937Sdes
46498937Sdes# source test body
46598937Sdes. $SCRIPT
46698937Sdes
46798937Sdes# kill sshd
46898937Sdescleanup
46998937Sdesif [ $RESULT -eq 0 ]; then
47098937Sdes	verbose ok $tid
47198937Sdeselse
47298937Sdes	echo failed $tid
47398937Sdesfi
47498937Sdesexit $RESULT
475