1#!/bin/bash
2#
3# Copyright (C) 2011-2013 Free Software Foundation, Inc.
4# Copyright 2013 Nikos Mavrogiannopoulos
5#
6# This file is part of GnuTLS.
7#
8# The launch_server() function was contributed by Cedric Arbogast.
9#
10# This file is free software; you can redistribute it and/or modify it
11# under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This file is distributed in the hope that it will be useful, but
16# WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18# General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this file; if not, write to the Free Software Foundation,
22# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
24builddir=${builddir:-.}
25
26OPENCONNECT=${OPENCONNECT:-$(which openconnect)}
27
28if test -z "${OPENCONNECT}" || ! test -x ${OPENCONNECT};then
29	echo "You need openconnect to run this test"
30	exit 1
31fi
32
33if test "${DISABLE_ASAN_BROKEN_TESTS}" = 1;then
34	echo "Disabling worker isolation to enable asan"
35	ISOLATE_WORKERS=false
36fi
37
38if test -z "${NO_NEED_ROOT}";then
39	if test "$(id -u)" != "0";then
40		echo "You need to run this script as root"
41		exit 77
42	fi
43fi
44
45# Increase verbosity as this disables the anti-debugging measures
46# of the worker processes.
47if test "${COVERAGE}" = "1" && test -z "${VERBOSE}";then
48	VERBOSE=1
49fi
50
51# NO_NEED_ROOT implies NEED_SOCKET_WRAPPER
52if test "${NEED_SOCKET_WRAPPER}" = 1 || test "${NO_NEED_ROOT}" = 1;then
53	SOCKDIR="${srcdir}/tmp/sockwrap.$$.tmp"
54	mkdir -p $SOCKDIR
55	export SOCKET_WRAPPER_DIR=$SOCKDIR
56	export SOCKET_WRAPPER_DEFAULT_IFACE=2
57	export NSS_WRAPPER_HOSTS="${srcdir}/data/vhost.hosts"
58	ADDRESS=127.0.0.$SOCKET_WRAPPER_DEFAULT_IFACE
59	RAW_OPENCONNECT="${OPENCONNECT}"
60	OPENCONNECT="eval LD_PRELOAD=libsocket_wrapper.so ${OPENCONNECT}"
61
62	if test "${DISABLE_ASAN_BROKEN_TESTS}" = 1;then
63		echo "Skipping test requiring ldpreload"
64		exit 77
65	fi
66fi
67
68update_config() {
69	file=$1
70	username=$(whoami)
71	group=$(groups|cut -f 1 -d ' ')
72
73	if test -z "${ISOLATE_WORKERS}";then
74		if test "${COVERAGE}" = "1";then
75			ISOLATE_WORKERS=false
76		else
77			ISOLATE_WORKERS=true
78		fi
79	fi
80
81	cp "${srcdir}/data/${file}" "$file.$$.tmp"
82	sed -i -e 's|@USERNAME@|'${username}'|g' "$file.$$.tmp" \
83	       -e 's|@GROUP@|'${group}'|g' "$file.$$.tmp" \
84	       -e 's|@SRCDIR@|'${srcdir}'|g' "$file.$$.tmp" \
85	       -e 's|@ISOLATE_WORKERS@|'${ISOLATE_WORKERS}'|g' "$file.$$.tmp" \
86	       -e 's|@OTP_FILE@|'${OTP_FILE}'|g' "$file.$$.tmp" \
87	       -e 's|@CRLNAME@|'${CRLNAME}'|g' "$file.$$.tmp" \
88	       -e 's|@PORT@|'${PORT}'|g' "$file.$$.tmp" \
89	       -e 's|@ADDRESS@|'${ADDRESS}'|g' "$file.$$.tmp" \
90	       -e 's|@VPNNET@|'${VPNNET}'|g' "$file.$$.tmp" \
91	       -e 's|@VPNNET6@|'${VPNNET6}'|g' "$file.$$.tmp" \
92	       -e 's|@ROUTE1@|'${ROUTE1}'|g' "$file.$$.tmp" \
93	       -e 's|@ROUTE2@|'${ROUTE2}'|g' "$file.$$.tmp" \
94	       -e 's|@MATCH_CIPHERS@|'${MATCH_CIPHERS}'|g' "$file.$$.tmp" \
95	       -e 's|@OCCTL_SOCKET@|'${OCCTL_SOCKET}'|g' "$file.$$.tmp" \
96	       -e 's|@LISTEN_NS@|'${LISTEN_NS}'|g' "$file.$$.tmp"
97	CONFIG="$file.$$.tmp"
98}
99
100fail() {
101   PID=$1
102   shift;
103   echo "Failure: $1" >&2
104   kill $PID
105   exit 1
106}
107
108launch_server() {
109	if test -n "${VERBOSE}" && test "${VERBOSE}" -ge 1;then
110	    $SERV $* -d 3 &
111	else
112	    $SERV $* >/dev/null 2>&1 &
113	fi
114	LOCALPID="$!";
115	trap "[ ! -z \"${LOCALPID}\" ] && kill ${LOCALPID};" 15
116	wait "${LOCALPID}"
117	LOCALRET="$?"
118	if [ "${LOCALRET}" != "0" ] && [ "${LOCALRET}" != "143" ] ; then
119		 # Houston, we'v got a problem...
120		 exit 1
121	fi
122}
123
124launch_sr_server() {
125	if test -n "${VERBOSE}" && test "${VERBOSE}" -ge 1;then
126		LD_PRELOAD=libsocket_wrapper.so:libuid_wrapper.so UID_WRAPPER=1 UID_WRAPPER_ROOT=1 $SERV $* -d 3 &
127	else
128		LD_PRELOAD=libsocket_wrapper.so:libuid_wrapper.so UID_WRAPPER=1 UID_WRAPPER_ROOT=1 $SERV $* >/dev/null 2>&1 &
129	fi
130	LOCALPID="$!";
131	trap "[ ! -z \"${LOCALPID}\" ] && kill ${LOCALPID};" 15
132	wait "${LOCALPID}"
133	LOCALRET="$?"
134	if [ "${LOCALRET}" != "0" ] && [ "${LOCALRET}" != "143" ] ; then
135		 # Houston, we'v got a problem...
136		 exit 1
137	fi
138}
139
140launch_pam_server() {
141	test -z "${TEST_PAMDIR}" && exit 2
142	export PAM_WRAPPER_DEBUGLEVEL=3
143	export PAM_WRAPPER_SERVICE_DIR="${builddir}/pam.$$.tmp/"
144	mkdir -p "${PAM_WRAPPER_SERVICE_DIR}"
145	test -f "${srcdir}/${TEST_PAMDIR}/users.oath.templ" && cp "${srcdir}/${TEST_PAMDIR}/users.oath.templ" "${PAM_WRAPPER_SERVICE_DIR}/users.oath"
146	test -f "${srcdir}/${TEST_PAMDIR}/passdb.templ" && cp "${srcdir}/${TEST_PAMDIR}/passdb.templ" "${PAM_WRAPPER_SERVICE_DIR}/passdb"
147	if test -f "${builddir}/${TEST_PAMDIR}/ocserv";then
148		cp "${builddir}/${TEST_PAMDIR}/ocserv" "${PAM_WRAPPER_SERVICE_DIR}/"
149	else
150		cp "${builddir}/data/pam/ocserv" "${PAM_WRAPPER_SERVICE_DIR}/"
151	fi
152	sed -i -e 's|%PAM_WRAPPER_SERVICE_DIR%|'${PAM_WRAPPER_SERVICE_DIR}'|g' "${PAM_WRAPPER_SERVICE_DIR}/ocserv"
153
154	cp "${builddir}/data/pam/nss-passwd" "${PAM_WRAPPER_SERVICE_DIR}/"
155	cp "${builddir}/data/pam/nss-group" "${PAM_WRAPPER_SERVICE_DIR}/"
156	export NSS_WRAPPER_PASSWD=${PAM_WRAPPER_SERVICE_DIR}/nss-passwd
157	export NSS_WRAPPER_GROUP=${PAM_WRAPPER_SERVICE_DIR}/nss-group
158	if test "$SOCKET_WRAPPER" != 0;then
159		SR="libsocket_wrapper.so:"
160	fi
161	if test -n "${VERBOSE}" && test "${VERBOSE}" -ge 1;then
162		LD_PRELOAD=libnss_wrapper.so:${SR}libpam_wrapper.so:libuid_wrapper.so PAM_WRAPPER=1 UID_WRAPPER=1 UID_WRAPPER_ROOT=1 $PRELOAD_CMD $SERV $* &
163	else
164		LD_PRELOAD=libnss_wrapper.so:${SR}libpam_wrapper.so:libuid_wrapper.so PAM_WRAPPER=1 UID_WRAPPER=1 UID_WRAPPER_ROOT=1 $PRELOAD_CMD $SERV $* >/dev/null 2>&1 &
165	fi
166	LOCALPID="$!";
167	unset NSS_WRAPPER_PASSWD
168	unset NSS_WRAPPER_GROUP
169	trap "[ ! -z \"${LOCALPID}\" ] && kill ${LOCALPID};" 15
170	wait "${LOCALPID}"
171	LOCALRET="$?"
172	if [ "${LOCALRET}" != "0" ] && [ "${LOCALRET}" != "143" ] ; then
173		 # Houston, we'v got a problem...
174		 exit 1
175	fi
176}
177
178launch_sr_pam_server() {
179	SOCKET_WRAPPER=1 launch_pam_server $*
180}
181
182launch_simple_sr_server() {
183	if test -n "${VERBOSE}" && test "${VERBOSE}" -ge 1;then
184		LD_PRELOAD=libsocket_wrapper.so:libuid_wrapper.so UID_WRAPPER=1 UID_WRAPPER_ROOT=1 $SERV $* -d 3 &
185	else
186		LD_PRELOAD=libsocket_wrapper.so:libuid_wrapper.so UID_WRAPPER=1 UID_WRAPPER_ROOT=1 $SERV $* >/dev/null 2>&1 &
187	fi
188}
189
190launch_simple_server() {
191	if test -n "${VERBOSE}" && test "${VERBOSE}" -ge 1;then
192		$PRELOAD_CMD $SERV $* &
193	else
194		$PRELOAD_CMD $SERV $* >/dev/null 2>&1 &
195	fi
196}
197
198launch_debug_server() {
199	valgrind --leak-check=full $SERV $* >out.txt 2>&1 &
200	LOCALPID="$!";
201	trap "[ ! -z \"${LOCALPID}\" ] && kill ${LOCALPID};" 15
202	wait "${LOCALPID}"
203	LOCALRET="$?"
204	if [ "${LOCALRET}" != "0" ] && [ "${LOCALRET}" != "143" ] ; then
205		 # Houston, we'v got a problem...
206		 exit 1
207	fi
208}
209
210wait_server() {
211	trap "kill $1" 1 15 2
212	sleep 5
213}
214
215cleanup() {
216	ret=0
217	kill $PID
218	if test $? != 0;then
219		ret=1
220	fi
221	wait
222	test -n "${PAM_WRAPPER_SERVICE_DIR}" && rm -rf ${PAM_WRAPPER_SERVICE_DIR}
223	test -n "${SOCKDIR}" && rm -rf ${SOCKDIR}
224	rm -f ${CONFIG}
225	return $ret
226}
227
228# Check for a utility to list ports.  Both ss and netstat will list
229# ports for normal users, and have similar semantics, so put the
230# command in the caller's PFCMD, or exit, indicating an unsupported
231# test.  Prefer ss from iproute2 over the older netstat.
232have_port_finder() {
233	for file in $(which ss 2> /dev/null) /*bin/ss /usr/*bin/ss /usr/local/*bin/ss;do
234		if test -x "$file";then
235			PFCMD="$file";return 0
236		fi
237	done
238
239	if test -z "$PFCMD";then
240	for file in $(which netstat 2> /dev/null) /bin/netstat /usr/bin/netstat /usr/local/bin/netstat;do
241		if test -x "$file";then
242			PFCMD="$file";return 0
243		fi
244	done
245	fi
246
247	if test -z "$PFCMD";then
248		echo "neither ss nor netstat found"
249		exit 1
250	fi
251}
252
253check_if_port_in_use() {
254	local PORT="$1"
255	local PFCMD; have_port_finder
256	$PFCMD -an|grep "[\:\.]$PORT" >/dev/null 2>&1
257}
258
259# Find a port number not currently in use.
260GETPORT='
261    rc=0
262    unset myrandom
263    while test $rc = 0; do
264        if test -n "$RANDOM"; then myrandom=$(($RANDOM + $RANDOM)); fi
265        if test -z "$myrandom"; then myrandom=$(date +%N | sed s/^0*//); fi
266        if test -z "$myrandom"; then myrandom=0; fi
267        PORT="$(((($$<<15)|$myrandom) % 63001 + 2000))"
268        check_if_port_in_use $PORT;rc=$?
269    done
270'
271
272trap "fail \"Failed to launch the server, aborting test... \"" 10
273