xref: /openbsd-src/regress/usr.bin/ssh/test-exec.sh (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1#	$OpenBSD: test-exec.sh,v 1.54 2016/08/23 06:36:23 djm Exp $
2#	Placed in the Public Domain.
3
4USER=`id -un`
5#SUDO=sudo
6
7if [ ! -z "$TEST_SSH_PORT" ]; then
8	PORT="$TEST_SSH_PORT"
9else
10	PORT=4242
11fi
12
13OBJ=$1
14if [ "x$OBJ" = "x" ]; then
15	echo '$OBJ not defined'
16	exit 2
17fi
18if [ ! -d $OBJ ]; then
19	echo "not a directory: $OBJ"
20	exit 2
21fi
22SCRIPT=$2
23if [ "x$SCRIPT" = "x" ]; then
24	echo '$SCRIPT not defined'
25	exit 2
26fi
27if [ ! -f $SCRIPT ]; then
28	echo "not a file: $SCRIPT"
29	exit 2
30fi
31if sh -n $SCRIPT; then
32	true
33else
34	echo "syntax error in $SCRIPT"
35	exit 2
36fi
37unset SSH_AUTH_SOCK
38
39SRC=`dirname ${SCRIPT}`
40
41# defaults
42SSH=ssh
43SSHD=sshd
44SSHAGENT=ssh-agent
45SSHADD=ssh-add
46SSHKEYGEN=ssh-keygen
47SSHKEYSCAN=ssh-keyscan
48SFTP=sftp
49SFTPSERVER=/usr/libexec/sftp-server
50SCP=scp
51
52# Interop testing
53PLINK=/usr/local/bin/plink
54PUTTYGEN=/usr/local/bin/puttygen
55CONCH=/usr/local/bin/conch
56
57if [ "x$TEST_SSH_SSH" != "x" ]; then
58	SSH="${TEST_SSH_SSH}"
59fi
60if [ "x$TEST_SSH_SSHD" != "x" ]; then
61	SSHD="${TEST_SSH_SSHD}"
62fi
63if [ "x$TEST_SSH_SSHAGENT" != "x" ]; then
64	SSHAGENT="${TEST_SSH_SSHAGENT}"
65fi
66if [ "x$TEST_SSH_SSHADD" != "x" ]; then
67	SSHADD="${TEST_SSH_SSHADD}"
68fi
69if [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then
70	SSHKEYGEN="${TEST_SSH_SSHKEYGEN}"
71fi
72if [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then
73	SSHKEYSCAN="${TEST_SSH_SSHKEYSCAN}"
74fi
75if [ "x$TEST_SSH_SFTP" != "x" ]; then
76	SFTP="${TEST_SSH_SFTP}"
77fi
78if [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then
79	SFTPSERVER="${TEST_SSH_SFTPSERVER}"
80fi
81if [ "x$TEST_SSH_SCP" != "x" ]; then
82	SCP="${TEST_SSH_SCP}"
83fi
84if [ "x$TEST_SSH_PLINK" != "x" ]; then
85	PLINK="${TEST_SSH_PLINK}"
86fi
87if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then
88	PUTTYGEN="${TEST_SSH_PUTTYGEN}"
89fi
90if [ "x$TEST_SSH_CONCH" != "x" ]; then
91	CONCH="${TEST_SSH_CONCH}"
92fi
93
94SSH_PROTOCOLS=2
95#SSH_PROTOCOLS=`$SSH -Q protocol-version`
96if [ "x$TEST_SSH_PROTOCOLS" != "x" ]; then
97	SSH_PROTOCOLS="${TEST_SSH_PROTOCOLS}"
98fi
99
100# Path to sshd must be absolute for rexec
101case "$SSHD" in
102/*) ;;
103*) SSHD=`which $SSHD` ;;
104esac
105
106case "$SSHAGENT" in
107/*) ;;
108*) SSHAGENT=`which $SSHAGENT` ;;
109esac
110
111# Logfiles.
112# SSH_LOGFILE should be the debug output of ssh(1) only
113# SSHD_LOGFILE should be the debug output of sshd(8) only
114# REGRESS_LOGFILE is the output of the test itself stdout and stderr
115if [ "x$TEST_SSH_LOGFILE" = "x" ]; then
116	TEST_SSH_LOGFILE=$OBJ/ssh.log
117fi
118if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then
119	TEST_SSHD_LOGFILE=$OBJ/sshd.log
120fi
121if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then
122	TEST_REGRESS_LOGFILE=$OBJ/regress.log
123fi
124
125# truncate logfiles
126>$TEST_SSH_LOGFILE
127>$TEST_SSHD_LOGFILE
128>$TEST_REGRESS_LOGFILE
129
130# Create wrapper ssh with logging.  We can't just specify "SSH=ssh -E..."
131# because sftp and scp don't handle spaces in arguments.
132SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh
133echo "#!/bin/sh" > $SSHLOGWRAP
134echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
135
136chmod a+rx $OBJ/ssh-log-wrapper.sh
137REAL_SSH="$SSH"
138SSH="$SSHLOGWRAP"
139
140# Some test data.  We make a copy because some tests will overwrite it.
141# The tests may assume that $DATA exists and is writable and $COPY does
142# not exist.  Tests requiring larger data files can call increase_datafile_size
143# [kbytes] to ensure the file is at least that large.
144DATANAME=data
145DATA=$OBJ/${DATANAME}
146cat ${SSHAGENT} >${DATA}
147COPY=$OBJ/copy
148rm -f ${COPY}
149
150increase_datafile_size()
151{
152	while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do
153		cat ${SSHAGENT} >>${DATA}
154	done
155}
156
157# these should be used in tests
158export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP
159#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP
160
161# helper
162cleanup ()
163{
164	if [ "x$SSH_PID" != "x" ]; then
165		if [ $SSH_PID -lt 2 ]; then
166			echo bad pid for ssh: $SSH_PID
167		else
168			kill $SSH_PID
169		fi
170	fi
171	if [ -f $PIDFILE ]; then
172		pid=`$SUDO cat $PIDFILE`
173		if [ "X$pid" = "X" ]; then
174			echo no sshd running
175		else
176			if [ $pid -lt 2 ]; then
177				echo bad pid for sshd: $pid
178			else
179				$SUDO kill $pid
180				trace "wait for sshd to exit"
181				i=0;
182				while [ -f $PIDFILE -a $i -lt 5 ]; do
183					i=`expr $i + 1`
184					sleep $i
185				done
186				test -f $PIDFILE && \
187				    fatal "sshd didn't exit port $PORT pid $pid"
188			fi
189		fi
190	fi
191}
192
193start_debug_log ()
194{
195	echo "trace: $@" >$TEST_REGRESS_LOGFILE
196	echo "trace: $@" >$TEST_SSH_LOGFILE
197	echo "trace: $@" >$TEST_SSHD_LOGFILE
198}
199
200save_debug_log ()
201{
202	echo $@ >>$TEST_REGRESS_LOGFILE
203	echo $@ >>$TEST_SSH_LOGFILE
204	echo $@ >>$TEST_SSHD_LOGFILE
205	(cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log
206	(cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log
207	(cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log
208}
209
210trace ()
211{
212	start_debug_log $@
213	if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then
214		echo "$@"
215	fi
216}
217
218verbose ()
219{
220	start_debug_log $@
221	if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then
222		echo "$@"
223	fi
224}
225
226
227fail ()
228{
229	save_debug_log "FAIL: $@"
230	RESULT=1
231	echo "$@"
232
233}
234
235fatal ()
236{
237	save_debug_log "FATAL: $@"
238	printf "FATAL: "
239	fail "$@"
240	cleanup
241	exit $RESULT
242}
243
244ssh_version ()
245{
246	echo ${SSH_PROTOCOLS} | grep -q "$1"
247}
248
249RESULT=0
250PIDFILE=$OBJ/pidfile
251
252trap fatal 3 2
253
254if ssh_version 1; then
255	PROTO="2,1"
256else
257	PROTO="2"
258fi
259
260# create server config
261cat << EOF > $OBJ/sshd_config
262	Port			$PORT
263	AddressFamily		inet
264	ListenAddress		127.0.0.1
265	#ListenAddress		::1
266	PidFile			$PIDFILE
267	AuthorizedKeysFile	$OBJ/authorized_keys_%u
268	LogLevel		DEBUG3
269	AcceptEnv		_XXX_TEST_*
270	AcceptEnv		_XXX_TEST
271	Subsystem	sftp	$SFTPSERVER
272EOF
273
274# This may be necessary if /usr/src and/or /usr/obj are group-writable,
275# but if you aren't careful with permissions then the unit tests could
276# be abused to locally escalate privileges.
277if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then
278	echo "StrictModes no" >> $OBJ/sshd_config
279fi
280
281if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then
282	trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS"
283	echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config
284fi
285
286# server config for proxy connects
287cp $OBJ/sshd_config $OBJ/sshd_proxy
288
289# allow group-writable directories in proxy-mode
290echo 'StrictModes no' >> $OBJ/sshd_proxy
291
292# create client config
293cat << EOF > $OBJ/ssh_config
294Host *
295	Hostname		127.0.0.1
296	HostKeyAlias		localhost-with-alias
297	Port			$PORT
298	User			$USER
299	GlobalKnownHostsFile	$OBJ/known_hosts
300	UserKnownHostsFile	$OBJ/known_hosts
301	RSAAuthentication	yes
302	PubkeyAuthentication	yes
303	ChallengeResponseAuthentication	no
304	HostbasedAuthentication	no
305	PasswordAuthentication	no
306	RhostsRSAAuthentication	no
307	BatchMode		yes
308	StrictHostKeyChecking	yes
309	LogLevel		DEBUG3
310EOF
311
312if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then
313	trace "adding ssh_config option $TEST_SSH_SSHD_CONFOPTS"
314	echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config
315fi
316
317rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
318
319if ssh_version 1; then
320	SSH_KEYTYPES="rsa rsa1"
321else
322	SSH_KEYTYPES="rsa ed25519"
323fi
324trace "generate keys"
325for t in ${SSH_KEYTYPES}; do
326	# generate user key
327	if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then
328		rm -f $OBJ/$t
329		${SSHKEYGEN} -q -N '' -t $t  -f $OBJ/$t ||\
330			fail "ssh-keygen for $t failed"
331	fi
332
333	# known hosts file for client
334	(
335		printf 'localhost-with-alias,127.0.0.1,::1 '
336		cat $OBJ/$t.pub
337	) >> $OBJ/known_hosts
338
339	# setup authorized keys
340	cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
341	echo IdentityFile $OBJ/$t >> $OBJ/ssh_config
342
343	# use key as host key, too
344	$SUDO cp $OBJ/$t $OBJ/host.$t
345	echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
346
347	# don't use SUDO for proxy connect
348	echo HostKey $OBJ/$t >> $OBJ/sshd_proxy
349done
350chmod 644 $OBJ/authorized_keys_$USER
351
352# Activate Twisted Conch tests if the binary is present
353REGRESS_INTEROP_CONCH=no
354if test -x "$CONCH" ; then
355	REGRESS_INTEROP_CONCH=yes
356fi
357
358# If PuTTY is present and we are running a PuTTY test, prepare keys and
359# configuration
360REGRESS_INTEROP_PUTTY=no
361if test -x "$PUTTYGEN" -a -x "$PLINK" ; then
362	REGRESS_INTEROP_PUTTY=yes
363fi
364case "$SCRIPT" in
365*putty*)	;;
366*)		REGRESS_INTEROP_PUTTY=no ;;
367esac
368
369if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
370	mkdir -p ${OBJ}/.putty
371
372	# Add a PuTTY key to authorized_keys
373	rm -f ${OBJ}/putty.rsa2
374	puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null
375	puttygen -O public-openssh ${OBJ}/putty.rsa2 \
376	    >> $OBJ/authorized_keys_$USER
377
378	# Convert rsa2 host key to PuTTY format
379	${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/rsa > \
380	    ${OBJ}/.putty/sshhostkeys
381	${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/rsa >> \
382	    ${OBJ}/.putty/sshhostkeys
383
384	# Setup proxied session
385	mkdir -p ${OBJ}/.putty/sessions
386	rm -f ${OBJ}/.putty/sessions/localhost_proxy
387	echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy
388	echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy
389	echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy
390	echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy
391
392	REGRESS_INTEROP_PUTTY=yes
393fi
394
395# create a proxy version of the client config
396(
397	cat $OBJ/ssh_config
398	echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy
399) > $OBJ/ssh_proxy
400
401# check proxy config
402${SSHD} -t -f $OBJ/sshd_proxy	|| fatal "sshd_proxy broken"
403
404start_sshd ()
405{
406	# start sshd
407	$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken"
408	$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE
409
410	trace "wait for sshd"
411	i=0;
412	while [ ! -f $PIDFILE -a $i -lt 10 ]; do
413		i=`expr $i + 1`
414		sleep $i
415	done
416
417	test -f $PIDFILE || fatal "no sshd running on port $PORT"
418}
419
420# source test body
421. $SCRIPT
422
423# kill sshd
424cleanup
425if [ $RESULT -eq 0 ]; then
426	verbose ok $tid
427else
428	echo failed $tid
429fi
430exit $RESULT
431