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