xref: /aosp_15_r20/external/ltp/testcases/network/stress/ssh/ssh-stress.sh (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0-or-later
3# Copyright (c) 2021 Joerg Vehlow <[email protected]>
4# Copyright (c) 2015 Oracle and/or its affiliates. All Rights Reserved.
5# Copyright (c) International Business Machines Corp., 2005
6# Author: Mitsuru Chinen <[email protected]>
7
8TST_CLEANUP="cleanup"
9TST_SETUP="setup"
10TST_TESTFUNC="test"
11TST_CNT=3
12TST_NEEDS_ROOT=1
13TST_NEEDS_TMPDIR=1
14TST_NEEDS_CMDS="sshd ssh ssh-keygen od pkill pgrep"
15
16
17# SSH config file on the remote host
18RHOST_SSH_CONF=
19# SSH command to connect from the remote host to the test host
20RHOST_SSH=
21# Processes started on the remote host, killed at cleanup
22RHOST_PIDS=
23# Netstress process started on the test host, killed at cleanup
24NETSTRESS_PID=
25
26cleanup()
27{
28	local pids
29
30	# Stop the ssh daemon
31	[ -s sshd.pid ] && kill $(cat sshd.pid)
32	[ -n "$NETSTRESS_PID" ] && kill -INT $NETSTRESS_PID >/dev/null 2>&1
33
34	[ -n "$RHOST_PIDS" ] && tst_rhost_run -c "kill $RHOST_PIDS" >/dev/null 2>&1
35
36	# Kill all remaining ssh processes
37	[ -n "$RHOST_SSH_CONF" ] && tst_rhost_run -c "pkill -f '^ssh $RHOST_SSH_CONF'"
38}
39
40setup()
41{
42	local port rc
43
44
45	port=$(tst_rhost_run -c "tst_get_unused_port ipv${TST_IPVER} stream")
46
47	cat << EOF > sshd_config
48Port $port
49ListenAddress $(tst_ipaddr)
50PermitRootLogin yes
51AuthorizedKeysFile $TST_TMPDIR/authorized_keys
52PasswordAuthentication no
53AllowTcpForwarding yes
54TCPKeepAlive yes
55UseDNS no
56StrictModes no
57PidFile $TST_TMPDIR/sshd.pid
58HostKey $TST_TMPDIR/ssh_host_rsa_key
59HostKey $TST_TMPDIR/ssh_host_ecdsa_key
60HostKey $TST_TMPDIR/ssh_host_ed25519_key
61EOF
62
63	ssh-keygen -q -N "" -t rsa -b 4096 -f $TST_TMPDIR/ssh_host_rsa_key
64	ssh-keygen -q -N "" -t ecdsa -f $TST_TMPDIR/ssh_host_ecdsa_key
65	ssh-keygen -q -N "" -t ed25519 -f $TST_TMPDIR/ssh_host_ed25519_key
66
67	tst_res TINFO "Generate configuration file and key at the remote host"
68	tst_rhost_run -s -c "ssh-keygen -t rsa -N \"\" -f $TST_TMPDIR/id_rsa \
69		>/dev/null"
70
71	RHOST_SSH_CONF=$TST_TMPDIR/ssh_config
72
73	tst_rhost_run -s -c "printf \"\
74Port $port\n\
75StrictHostKeyChecking no\n\
76PasswordAuthentication no\n\
77ExitOnForwardFailure yes\n\
78UserKnownHostsFile $TST_TMPDIR/known_hosts\n\
79IdentityFile $TST_TMPDIR/id_rsa\n\" > $RHOST_SSH_CONF"
80
81	tst_res TINFO "Generate authorized_keys"
82	tst_rhost_run -c "cat ${TST_TMPDIR}/id_rsa.pub" > authorized_keys
83
84	tst_res TINFO "restore context of authorized_keys"
85	rc=$(command -v restorecon)
86	[ -n "$rc" ] && $rc authorized_keys
87
88	$(command -v sshd) -f $TST_TMPDIR/sshd_config || \
89		tst_brk TBROK "Failed to run sshd daemon"
90
91	RHOST_SSH="ssh -$TST_IPVER -F $RHOST_SSH_CONF $(tst_ipaddr)"
92}
93
94test_ssh_connectivity()
95{
96	if ! tst_rhost_run -c "$RHOST_SSH 'true >/dev/null 2>&1' >/dev/null"; then
97		tst_res TFAIL "SSH not reachable"
98		return
99	fi
100}
101
102test1()
103{
104	local num all_conn pid
105
106	tst_res TINFO "Verify SSH connectivity over IPv$TST_IPVER is not broken after creating many SSH sessions"
107
108	test_ssh_connectivity
109
110	RHOST_PIDS=
111	num=0
112	while [ $num -lt $CONNECTION_TOTAL ]; do
113		pid=$(tst_rhost_run -c "$RHOST_SSH -N </dev/null 1>/dev/null 2>&1 \
114			& echo \$!")
115		RHOST_PIDS="$RHOST_PIDS $pid"
116		num=$(($num + 1))
117	done
118
119	tst_res TINFO "Killing all ssh sessions"
120	num=0
121	for pid in $RHOST_PIDS; do
122		tst_rhost_run -c "kill $pid" >/dev/null
123		[ $? -ne 0 ] && num=$((num + 1))
124	done
125
126	if [ $num -ne 0 ]; then
127		tst_res TFAIL "$num ssh processes died unexpectedly during execution"
128		return
129	fi
130
131	test_ssh_connectivity
132
133	tst_res TPASS "Test finished successfully"
134}
135
136test2()
137{
138	local start_epoc pids total_connections elapse_epoc new_pids
139	local ssh_num wait_sec login_sec
140
141	tst_res TINFO "Verify SSH connectivity over IPv$TST_IPVER is not broken after logging in/out by many clients asynchronously"
142
143	test_ssh_connectivity
144
145	start_epoc=$(date +%s)
146	RHOST_PIDS=
147	total_connections=0
148	while true; do
149		# Exit after the specified time has elapsed.
150		elapse_epoc=$(( $(date +%s) - $start_epoc))
151		[ $elapse_epoc -ge $NS_DURATION ] && break
152
153		new_pids=
154		for pid in $RHOST_PIDS; do
155			if tst_rhost_run -c "kill -0 $pid" >/dev/null; then
156				new_pids="$new_pids $pid"
157			fi
158		done
159		RHOST_PIDS="$new_pids"
160
161		# Do not make ssh connection over the specified quantity
162		ssh_num=$(echo "$pids" | wc -w)
163		if [ $ssh_num -ge $CONNECTION_TOTAL ]; then
164			tst_res TINFO "Max connections reached"
165			tst_sleep 1
166			continue
167		fi
168
169		# specified wait time and login time
170		wait_sec=$(( $(od -A n -d -N 1 /dev/urandom) * 3 / 255 ))
171		login_sec=$(( $(od -A n -d -N 1 /dev/urandom) * 10 / 255 ))
172
173		# Login to the server
174		pid=$(tst_rhost_run -c "( \
175			  sleep $wait_sec && $RHOST_SSH -l root \"sleep $login_sec\" \
176			) </dev/null 1>/dev/null 2>&1 & echo \$!"
177		)
178		RHOST_PIDS="$RHOST_PIDS $pid"
179		total_connections=$(( total_connections + 1 ))
180	done
181
182	tst_res TINFO "Waiting for all connections to terminate"
183	while [ -n "$RHOST_PIDS" ]; do
184		tst_sleep 1
185		new_pids=
186		for pid in $RHOST_PIDS; do
187			if tst_rhost_run -c "kill -0 $pid" >/dev/null 2>&1; then
188				new_pids="$new_pids $pid"
189			fi
190		done
191		RHOST_PIDS="$new_pids"
192	done
193
194	test_ssh_connectivity
195
196	tst_res TPASS "Test finished successfully ($total_connections connections)"
197}
198
199test3()
200{
201	local port lport localhost rhost ret
202	tst_res TINFO "Verify SSH connectivity over IPv$TST_IPVER is not broken after forwarding TCP traffic"
203
204	localhost="127.0.0.1"
205	rhost="$(tst_ipaddr)"
206	if [ "$TST_IPVER" = "6" ]; then
207		localhost="::1"
208		rhost="[$(tst_ipaddr)]"
209	fi
210
211	test_ssh_connectivity
212
213	# Get an ssh forwarding port
214	lport=$(tst_rhost_run -c "tst_get_unused_port ipv${TST_IPVER} stream")
215
216	# Start a tcp server
217	netstress -R 3 -B $TST_TMPDIR >/dev/null 2>&1
218	[ $? -ne 0 ] && tst_brk TBROK "Unable to start netstress server"
219	NETSTRESS_PID=$(pgrep -f "^netstress .*$TST_TMPDIR")
220	port=$(cat netstress_port)
221
222	# Setup an ssh tunnel from the remote host to testhost
223	tst_rhost_run -c "$RHOST_SSH -f -N -L $lport:$rhost:$port </dev/null >/dev/null 2>&1"
224	if [ "$?" -ne 0 ]; then
225		tst_res TFAIL "Failed to create an SSH session with port forwarding"
226		return
227	fi
228	RHOST_PIDS=$(tst_rhost_run -c "pgrep -f '^ssh .*$lport:$rhost:$port'")
229
230	# Start the TCP traffic clients
231	tst_rhost_run -s -c "netstress -r $NS_TIMES -l -H $localhost -g $lport > /dev/null"
232
233	tst_rhost_run -c "kill $RHOST_PIDS >/dev/null 2>&1"
234
235	test_ssh_connectivity
236
237	tst_res TPASS "Test finished successfully"
238}
239
240. tst_net.sh
241tst_run
242