t_client.sh.in 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. #!@SHELL@
  2. #
  3. # run OpenVPN client against ``test reference'' server
  4. # - check that ping, http, ... via tunnel works
  5. # - check that interface config / routes are properly cleaned after test end
  6. #
  7. # prerequisites:
  8. # - openvpn binary in current directory
  9. # - writable current directory to create subdir for logs
  10. # - t_client.rc in current directory OR source dir that specifies tests
  11. # - for "ping4" checks: fping binary in $PATH
  12. # - for "ping6" checks: fping6 binary in $PATH
  13. #
  14. srcdir="${srcdir:-.}"
  15. top_builddir="${top_builddir:-..}"
  16. if [ -r "${top_builddir}"/t_client.rc ] ; then
  17. . "${top_builddir}"/t_client.rc
  18. elif [ -r "${srcdir}"/t_client.rc ] ; then
  19. . "${srcdir}"/t_client.rc
  20. else
  21. echo "$0: cannot find 't_client.rc' in build dir ('${top_builddir}')" >&2
  22. echo "$0: or source directory ('${srcdir}'). SKIPPING TEST." >&2
  23. exit 77
  24. fi
  25. # Check for external dependencies
  26. which fping > /dev/null
  27. if [ $? -ne 0 ]; then
  28. echo "$0: fping is not available in \$PATH" >&2
  29. exit 77
  30. fi
  31. which fping6 > /dev/null
  32. if [ $? -ne 0 ]; then
  33. echo "$0: fping6 is not available in \$PATH" >&2
  34. exit 77
  35. fi
  36. KILL_EXEC=`which kill`
  37. if [ $? -ne 0 ]; then
  38. echo "$0: kill not found in \$PATH" >&2
  39. exit 77
  40. fi
  41. if [ ! -x "${top_builddir}/src/openvpn/openvpn" ]
  42. then
  43. echo "no (executable) openvpn binary in current build tree. FAIL." >&2
  44. exit 1
  45. fi
  46. if [ ! -w . ]
  47. then
  48. echo "current directory is not writable (required for logging). FAIL." >&2
  49. exit 1
  50. fi
  51. if [ -z "$CA_CERT" ] ; then
  52. echo "CA_CERT not defined in 't_client.rc'. SKIP test." >&2
  53. exit 77
  54. fi
  55. if [ -z "$TEST_RUN_LIST" ] ; then
  56. echo "TEST_RUN_LIST empty, no tests defined. SKIP test." >&2
  57. exit 77
  58. fi
  59. # Ensure PREFER_KSU is in a known state
  60. PREFER_KSU="${PREFER_KSU:-0}"
  61. # make sure we have permissions to run ifconfig/route from OpenVPN
  62. # can't use "id -u" here - doesn't work on Solaris
  63. ID=`id`
  64. if expr "$ID" : "uid=0" >/dev/null
  65. then :
  66. else
  67. if [ "${PREFER_KSU}" -eq 1 ];
  68. then
  69. # Check if we have a valid kerberos ticket
  70. klist -l 1>/dev/null 2>/dev/null
  71. if [ $? -ne 0 ];
  72. then
  73. # No kerberos ticket found, skip ksu and fallback to RUN_SUDO
  74. PREFER_KSU=0
  75. echo "$0: No Kerberos ticket available. Will not use ksu."
  76. else
  77. RUN_SUDO="ksu -q -e"
  78. fi
  79. fi
  80. if [ -z "$RUN_SUDO" ]
  81. then
  82. echo "$0: this test must run be as root, or RUN_SUDO=... " >&2
  83. echo " must be set correctly in 't_client.rc'. SKIP." >&2
  84. exit 77
  85. else
  86. # We have to use sudo. Make sure that we (hopefully) do not have
  87. # to ask the users password during the test. This is done to
  88. # prevent timing issues, e.g. when the waits for openvpn to start
  89. if $RUN_SUDO $KILL_EXEC -0 $$
  90. then
  91. echo "$0: $RUN_SUDO $KILL_EXEC -0 succeeded, good."
  92. else
  93. echo "$0: $RUN_SUDO $KILL_EXEC -0 failed, cannot go on. SKIP." >&2
  94. exit 77
  95. fi
  96. fi
  97. fi
  98. LOGDIR=t_client-`hostname`-`date +%Y%m%d-%H%M%S`
  99. if mkdir $LOGDIR
  100. then :
  101. else
  102. echo "can't create log directory '$LOGDIR'. FAIL." >&2
  103. exit 1
  104. fi
  105. exit_code=0
  106. # ----------------------------------------------------------
  107. # helper functions
  108. # ----------------------------------------------------------
  109. # print failure message, increase FAIL counter
  110. fail()
  111. {
  112. echo ""
  113. echo "FAIL: $@" >&2
  114. fail_count=$(( $fail_count + 1 ))
  115. }
  116. # print "all interface IP addresses" + "all routes"
  117. # this is higly system dependent...
  118. get_ifconfig_route()
  119. {
  120. # linux / iproute2? (-> if configure got a path)
  121. if [ -n "@IPROUTE@" ]
  122. then
  123. echo "-- linux iproute2 --"
  124. @IPROUTE@ addr show | grep -v valid_lft
  125. @IPROUTE@ route show
  126. @IPROUTE@ -o -6 route show | grep -v ' cache' | sed -E -e 's/ expires [0-9]*sec//' -e 's/ (mtu|hoplimit|cwnd|ssthresh) [0-9]+//g' -e 's/ (rtt|rttvar) [0-9]+ms//g'
  127. return
  128. fi
  129. # try uname
  130. case `uname -s` in
  131. Linux)
  132. echo "-- linux / ifconfig --"
  133. LANG=C @IFCONFIG@ -a |egrep "( addr:|encap:)"
  134. LANG=C @NETSTAT@ -rn -4 -6
  135. return
  136. ;;
  137. FreeBSD|NetBSD|Darwin)
  138. echo "-- FreeBSD/NetBSD/Darwin [MacOS X] --"
  139. @IFCONFIG@ -a | egrep "(flags=|inet)"
  140. @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }'
  141. return
  142. ;;
  143. OpenBSD)
  144. echo "-- OpenBSD --"
  145. @IFCONFIG@ -a | egrep "(flags=|inet)" | \
  146. sed -e 's/pltime [0-9]*//' -e 's/vltime [0-9]*//'
  147. @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$NF }'
  148. return
  149. ;;
  150. SunOS)
  151. echo "-- Solaris --"
  152. @IFCONFIG@ -a | egrep "(flags=|inet)"
  153. @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }'
  154. return
  155. ;;
  156. AIX)
  157. echo "-- AIX --"
  158. @IFCONFIG@ -a | egrep "(flags=|inet)"
  159. @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }'
  160. return
  161. ;;
  162. esac
  163. echo "get_ifconfig_route(): no idea how to get info on your OS. FAIL." >&2
  164. exit 20
  165. }
  166. # ----------------------------------------------------------
  167. # check ifconfig
  168. # arg1: "4" or "6" -> for message
  169. # arg2: IPv4/IPv6 address that must show up in out of "get_ifconfig_route"
  170. check_ifconfig()
  171. {
  172. proto=$1 ; shift
  173. expect_list="$@"
  174. if [ -z "$expect_list" ] ; then return ; fi
  175. for expect in $expect_list
  176. do
  177. if get_ifconfig_route | fgrep "$expect" >/dev/null
  178. then :
  179. else
  180. fail "check_ifconfig(): expected IPv$proto address '$expect' not found in ifconfig output."
  181. fi
  182. done
  183. }
  184. # ----------------------------------------------------------
  185. # run pings
  186. # arg1: "4" or "6" -> fping/fing6
  187. # arg2: "want_ok" or "want_fail" (expected ping result)
  188. # arg3... -> fping arguments (host list)
  189. run_ping_tests()
  190. {
  191. proto=$1 ; want=$2 ; shift ; shift
  192. targetlist="$@"
  193. # "no targets" is fine
  194. if [ -z "$targetlist" ] ; then return ; fi
  195. case $proto in
  196. 4) cmd=fping ;;
  197. 6) cmd=fping6 ;;
  198. *) echo "internal error in run_ping_tests arg 1: '$proto'" >&2
  199. exit 1 ;;
  200. esac
  201. case $want in
  202. want_ok) sizes_list="64 1440 3000" ;;
  203. want_fail) sizes_list="64" ;;
  204. esac
  205. for bytes in $sizes_list
  206. do
  207. echo "run IPv$proto ping tests ($want), $bytes byte packets..."
  208. echo "$cmd -b $bytes -C 20 -p 250 -q $FPING_EXTRA_ARGS $targetlist" >>$LOGDIR/$SUF:fping.out
  209. $cmd -b $bytes -C 20 -p 250 -q $FPING_EXTRA_ARGS $targetlist >>$LOGDIR/$SUF:fping.out 2>&1
  210. # while OpenVPN is running, pings must succeed (want='want_ok')
  211. # before OpenVPN is up, pings must NOT succeed (want='want_fail')
  212. rc=$?
  213. if [ $rc = 0 ] # all ping OK
  214. then
  215. if [ $want = "want_fail" ] # not what we want
  216. then
  217. fail "IPv$proto ping test succeeded, but needs to *fail*."
  218. fi
  219. else # ping failed
  220. if [ $want = "want_ok" ] # not what we wanted
  221. then
  222. fail "IPv$proto ping test ($bytes bytes) failed, but should succeed."
  223. fi
  224. fi
  225. done
  226. }
  227. # ----------------------------------------------------------
  228. # main test loop
  229. # ----------------------------------------------------------
  230. SUMMARY_OK=
  231. SUMMARY_FAIL=
  232. for SUF in $TEST_RUN_LIST
  233. do
  234. # get config variables
  235. eval test_prep=\"\$PREPARE_$SUF\"
  236. eval test_postinit=\"\$POSTINIT_CMD_$SUF\"
  237. eval test_cleanup=\"\$CLEANUP_$SUF\"
  238. eval test_run_title=\"\$RUN_TITLE_$SUF\"
  239. eval openvpn_conf=\"\$OPENVPN_CONF_$SUF\"
  240. eval expect_ifconfig4=\"\$EXPECT_IFCONFIG4_$SUF\"
  241. eval expect_ifconfig6=\"\$EXPECT_IFCONFIG6_$SUF\"
  242. eval ping4_hosts=\"\$PING4_HOSTS_$SUF\"
  243. eval ping6_hosts=\"\$PING6_HOSTS_$SUF\"
  244. # If EXCEPT_IFCONFIG* variables for this test are missing, run an --up
  245. # script to generate them dynamically.
  246. if [ -z "$expect_ifconfig4" ] || [ -z "$expect_ifconfig6" ]; then
  247. up="--setenv TESTNUM $SUF --setenv TOP_BUILDDIR ${top_builddir} --script-security 2 --up ${srcdir}/update_t_client_ips.sh"
  248. else
  249. up=""
  250. fi
  251. echo -e "\n### test run $SUF: '$test_run_title' ###\n"
  252. fail_count=0
  253. if [ -n "$test_prep" ]; then
  254. echo -e "running preparation: '$test_prep'"
  255. eval $test_prep
  256. fi
  257. echo "save pre-openvpn ifconfig + route"
  258. get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_pre.txt
  259. echo -e "\nrun pre-openvpn ping tests - targets must not be reachable..."
  260. run_ping_tests 4 want_fail "$ping4_hosts"
  261. run_ping_tests 6 want_fail "$ping6_hosts"
  262. if [ "$fail_count" = 0 ] ; then
  263. echo -e "OK.\n"
  264. else
  265. echo -e "FAIL: make sure that ping hosts are ONLY reachable via VPN, SKIP test $SUF".
  266. exit_code=31
  267. continue
  268. fi
  269. pidfile="${top_builddir}/tests/$LOGDIR/openvpn-$SUF.pid"
  270. openvpn_conf="$openvpn_conf --writepid $pidfile $up"
  271. echo " run openvpn $openvpn_conf"
  272. echo "# src/openvpn/openvpn $openvpn_conf" >$LOGDIR/$SUF:openvpn.log
  273. umask 022
  274. $RUN_SUDO "${top_builddir}/src/openvpn/openvpn" $openvpn_conf >>$LOGDIR/$SUF:openvpn.log &
  275. sudopid=$!
  276. # Check if OpenVPN has initialized before continuing. It will check every 3rd second up
  277. # to $ovpn_init_check times.
  278. ovpn_init_check=10
  279. ovpn_init_success=0
  280. while [ $ovpn_init_check -gt 0 ];
  281. do
  282. sleep 3 # Wait for OpenVPN to initialize and have had time to write the pid file
  283. grep "Initialization Sequence Completed" $LOGDIR/$SUF:openvpn.log >/dev/null
  284. if [ $? -eq 0 ]; then
  285. ovpn_init_check=0
  286. ovpn_init_success=1
  287. fi
  288. ovpn_init_check=$(( $ovpn_init_check - 1 ))
  289. done
  290. opid=`cat $pidfile`
  291. if [ -n "$opid" ]; then
  292. echo " OpenVPN running with PID $opid"
  293. else
  294. echo " Could not read OpenVPN PID file" >&2
  295. fi
  296. # If OpenVPN did not start
  297. if [ $ovpn_init_success -ne 1 -o -z "$opid" ]; then
  298. echo "$0: OpenVPN did not initialize in a reasonable time" >&2
  299. if [ -n "$opid" ]; then
  300. $RUN_SUDO $KILL_EXEC $opid
  301. fi
  302. $RUN_SUDO $KILL_EXEC $sudopid
  303. echo "tail -5 $SUF:openvpn.log" >&2
  304. tail -5 $LOGDIR/$SUF:openvpn.log >&2
  305. echo -e "\nFAIL. skip rest of sub-tests for test run $SUF.\n" >&2
  306. trap - 0 1 2 3 15
  307. SUMMARY_FAIL="$SUMMARY_FAIL $SUF"
  308. exit_code=30
  309. continue
  310. fi
  311. # make sure openvpn client is terminated in case shell exits
  312. trap "$RUN_SUDO $KILL_EXEC $opid" 0
  313. trap "$RUN_SUDO $KILL_EXEC $opid ; trap - 0 ; exit 1" 1 2 3 15
  314. # compare whether anything changed in ifconfig/route setup?
  315. echo "save ifconfig+route"
  316. get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route.txt
  317. echo -n "compare pre-openvpn ifconfig+route with current values..."
  318. if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \
  319. $LOGDIR/$SUF:ifconfig_route.txt >/dev/null
  320. then
  321. fail "no differences between ifconfig/route before OpenVPN start and now."
  322. else
  323. echo -e " OK!\n"
  324. fi
  325. # post init script needed?
  326. if [ -n "$test_postinit" ]; then
  327. echo -e "running post-init cmd: '$test_postinit'"
  328. eval $test_postinit
  329. fi
  330. # expected ifconfig values in there?
  331. check_ifconfig 4 "$expect_ifconfig4"
  332. check_ifconfig 6 "$expect_ifconfig6"
  333. run_ping_tests 4 want_ok "$ping4_hosts"
  334. run_ping_tests 6 want_ok "$ping6_hosts"
  335. echo -e "ping tests done.\n"
  336. echo "stopping OpenVPN"
  337. $RUN_SUDO $KILL_EXEC $opid
  338. wait $!
  339. rc=$?
  340. if [ $rc != 0 ] ; then
  341. fail "OpenVPN return code $rc, expect 0"
  342. fi
  343. echo -e "\nsave post-openvpn ifconfig + route..."
  344. get_ifconfig_route >$LOGDIR/$SUF:ifconfig_route_post.txt
  345. echo -n "compare pre- and post-openvpn ifconfig + route..."
  346. if diff $LOGDIR/$SUF:ifconfig_route_pre.txt \
  347. $LOGDIR/$SUF:ifconfig_route_post.txt >$LOGDIR/$SUF:ifconfig_route_diff.txt
  348. then
  349. echo -e " OK.\n"
  350. else
  351. cat $LOGDIR/$SUF:ifconfig_route_diff.txt >&2
  352. fail "differences between pre- and post-ifconfig/route"
  353. fi
  354. if [ "$fail_count" = 0 ] ; then
  355. echo -e "test run $SUF: all tests OK.\n"
  356. SUMMARY_OK="$SUMMARY_OK $SUF"
  357. else
  358. echo -e "test run $SUF: $fail_count test failures. FAIL.\n";
  359. SUMMARY_FAIL="$SUMMARY_FAIL $SUF"
  360. exit_code=30
  361. fi
  362. if [ -n "$test_cleanup" ]; then
  363. echo -e "cleaning up: '$test_cleanup'"
  364. eval $test_cleanup
  365. fi
  366. done
  367. if [ -z "$SUMMARY_OK" ] ; then SUMMARY_OK=" none"; fi
  368. if [ -z "$SUMMARY_FAIL" ] ; then SUMMARY_FAIL=" none"; fi
  369. echo "Test sets succeded:$SUMMARY_OK."
  370. echo "Test sets failed:$SUMMARY_FAIL."
  371. # remove trap handler
  372. trap - 0 1 2 3 15
  373. exit $exit_code