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