diff --git a/scripts/crl-revoked.test b/scripts/crl-revoked.test index 5588aa5b4..821b6aac8 100755 --- a/scripts/crl-revoked.test +++ b/scripts/crl-revoked.test @@ -2,6 +2,16 @@ #crl.test +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + revocation_code="-361" exit_code=1 counter=0 diff --git a/scripts/include.am b/scripts/include.am index 50eeed9a3..2ad416b68 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -24,12 +24,17 @@ dist_noinst_SCRIPTS+= scripts/crl-revoked.test scripts/crl-revoked.log: scripts/resume.log endif +# arrange to serialize ocsp.test, ocsp-stapling.test, ocsp-stapling-with-ca-as-responder.test, ocsp-stapling2.test, and testsuite, +# to help mitigate port conflicts among them. +# note that unit.test is gated on testsuite in Makefile.am, which is also helpful for these purposes. + if BUILD_OCSP_STAPLING dist_noinst_SCRIPTS+= scripts/ocsp-stapling.test -scripts/ocsp-stapling.log: tests/unit.log +if !BUILD_OCSP_STAPLING_V2 +testsuite/testsuite.log: scripts/ocsp-stapling.log scripts/ocsp-stapling-with-ca-as-responder.log +endif scripts/ocsp-stapling.log: scripts/ocsp.log dist_noinst_SCRIPTS+= scripts/ocsp-stapling-with-ca-as-responder.test -scripts/ocsp-stapling-with-ca-as-responder.log: tests/unit.log scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp.log scripts/ocsp-stapling-with-ca-as-responder.log: scripts/ocsp-stapling.log endif @@ -38,12 +43,11 @@ if BUILD_OCSP_STAPLING_V2 dist_noinst_SCRIPTS+= scripts/ocsp-stapling2.test if BUILD_OCSP_STAPLING -scripts/ocsp-stapling2.log: tests/unit.log +testsuite/testsuite.log: scripts/ocsp-stapling2.log scripts/ocsp-stapling2.log: scripts/ocsp.log scripts/ocsp-stapling2.log: scripts/ocsp-stapling.log scripts/ocsp-stapling2.log: scripts/ocsp-stapling-with-ca-as-responder.log else -scripts/ocsp-stapling2.log: tests/unit.log scripts/ocsp-stapling2.log: scripts/ocsp.log endif diff --git a/scripts/ocsp-stapling-with-ca-as-responder.test b/scripts/ocsp-stapling-with-ca-as-responder.test index 4773ec104..fa264ef0f 100755 --- a/scripts/ocsp-stapling-with-ca-as-responder.test +++ b/scripts/ocsp-stapling-with-ca-as-responder.test @@ -1,6 +1,20 @@ #!/bin/bash -# ocsp-stapling.test +# ocsp-stapling-with-ca-as-responder.test + +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + +if [[ -z "${RETRIES_REMAINING-}" ]]; then + export RETRIES_REMAINING=2 +fi ./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' if [ $? -eq 0 ]; then @@ -9,50 +23,39 @@ if [ $? -eq 0 ]; then exit 0 fi +PARENTDIR=`pwd` -WORKSPACE=`pwd` -CERT_DIR="./certs/ocsp" -resume_port=0 -ready_file=`pwd`/wolf_ocsp_s1_readyF$$ -ready_file2=`pwd`/wolf_ocsp_s1_readyF2$$ -printf '%s\n' "ready file: $ready_file" +# create a unique workspace directory ending in PID for the script instance ($$) +# to make this instance orthogonal to any others running, even on same repo. +# TCP ports are also carefully formed below from the PID, to minimize conflicts. + +WORKSPACE="${PARENTDIR}/workspace.pid$$" + +mkdir "${WORKSPACE}" || exit $? +cp -pR certs "${WORKSPACE}"/ || exit $? +cd "$WORKSPACE" || exit $? +ln -s ../examples + +CERT_DIR="certs/ocsp" + + +ready_file="${WORKSPACE}"/wolf_ocsp_s1_readyF$$ +ready_file2="${WORKSPACE}"/wolf_ocsp_s1_readyF2$$ +printf '%s\n' "ready files: $ready_file $ready_file2" test_cnf="ocsp_s_w_ca_a_r.cnf" -copy_originals() { - cd $CERT_DIR - cp intermediate1-ca-cert.pem bak-intermediate1-ca-cert.pem - cp intermediate2-ca-cert.pem bak-intermediate2-ca-cert.pem - cp intermediate3-ca-cert.pem bak-intermediate3-ca-cert.pem - cp ocsp-responder-cert.pem bak-ocsp-responder-cert.pem - cp root-ca-cert.pem bak-root-ca-cert.pem - cp server1-cert.pem bak-server1-cert.pem - cp server2-cert.pem bak-server2-cert.pem - cp server3-cert.pem bak-server3-cert.pem - cp server4-cert.pem bak-server4-cert.pem - cp server5-cert.pem bak-server5-cert.pem - cd $WORKSPACE -} - -restore_originals() { - cd $CERT_DIR - mv bak-intermediate1-ca-cert.pem intermediate1-ca-cert.pem - mv bak-intermediate2-ca-cert.pem intermediate2-ca-cert.pem - mv bak-intermediate3-ca-cert.pem intermediate3-ca-cert.pem - mv bak-ocsp-responder-cert.pem ocsp-responder-cert.pem - mv bak-root-ca-cert.pem root-ca-cert.pem - mv bak-server1-cert.pem server1-cert.pem - mv bak-server2-cert.pem server2-cert.pem - mv bak-server3-cert.pem server3-cert.pem - mv bak-server4-cert.pem server4-cert.pem - mv bak-server5-cert.pem server5-cert.pem -} - wait_for_readyFile(){ counter=0 while [ ! -s $1 -a "$counter" -lt 20 ]; do + if [[ -n "${2-}" ]]; then + if ! kill -0 $2 2>&-; then + echo "pid $2 for port ${3-} exited before creating ready file. bailing..." + exit 1 + fi + fi echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) @@ -61,7 +64,7 @@ wait_for_readyFile(){ if test -e $1; then echo -e "found ready file, starting client..." else - echo -e "NO ready file ending test..." + echo -e "NO ready file at $1 -- ending test..." exit 1 fi @@ -76,8 +79,6 @@ remove_single_rF(){ #create a configure file for cert generation with the port 0 solution create_new_cnf() { - copy_originals - printf '%s\n' "Random Port Selected: $RPORTSELECTED" printf '%s\n' "#" > $test_cnf @@ -145,13 +146,21 @@ remove_ready_file() { cleanup() { + exit_status=$? for i in $(jobs -pr) do kill -s HUP "$i" done remove_ready_file rm $CERT_DIR/$test_cnf - restore_originals + cd "$PARENTDIR" || return 1 + rm -r "$WORKSPACE" || return 1 + + if [[ ("$exit_status" == 1) && ($RETRIES_REMAINING -gt 0) ]]; then + echo "retrying..." + RETRIES_REMAINING=$((RETRIES_REMAINING - 1)) + exec $0 "$@" + fi } trap cleanup EXIT INT TERM HUP @@ -160,9 +169,35 @@ ca=certs/external/baltimore-cybertrust-root.pem [ ! -x ./examples/client/client ] && printf '\n\n%s\n' "Client doesn't exist" && exit 1 -# create a port 0 port to use with openssl ocsp responder -./examples/server/server -R $ready_file -p $resume_port & -wait_for_readyFile $ready_file + +# choose consecutive ports based on the PID, skipping any that are +# already bound, to avoid the birthday problem in case other +# instances are sharing this host. + +get_first_free_port() { + local ret="$1" + while :; do + if [[ "$ret" -ge 65536 ]]; then + ret=1024 + fi + if ! nc -z 127.0.0.1 "$ret"; then + break + fi + ret=$((ret+1)) + done + echo "$ret" + return 0 +} + +base_port=$((((($$ + $RETRIES_REMAINING) * 5) % (65536 - 2048)) + 1024)) +port1=$(get_first_free_port $base_port) +port2=$(get_first_free_port $((port1 + 1))) + + +# create a port to use with openssl ocsp responder +./examples/server/server -R $ready_file -p $port1 & +wolf_pid=$! +wait_for_readyFile $ready_file $wolf_pid $port1 if [ ! -f $ready_file ]; then printf '%s\n' "Failed to create ready file: \"$ready_file\"" exit 1 @@ -173,7 +208,7 @@ else ./examples/client/client -p $RPORTSELECTED create_new_cnf $RPORTSELECTED fi -sleep 1 +sleep 0.1 # is our desired server there? - login.live.com doesn't answers PING #./scripts/ping.test $server 2 @@ -197,7 +232,7 @@ openssl ocsp -port $RPORTSELECTED -nmin 1 \ $@ \ & -sleep 1 +sleep 0.1 # "jobs" is not portable for posix. Must use bash interpreter! [ $(jobs -r | wc -l) -ne 1 ] && printf '\n\n%s\n' "Setup ocsp responder failed, skipping" && exit 0 @@ -205,7 +240,7 @@ printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" # client test against our own server - GOOD CERT ./examples/server/server -c certs/ocsp/server1-cert.pem \ -k certs/ocsp/server1-key.pem -R $ready_file2 \ - -p $resume_port & + -p $port2 & wait_for_readyFile $ready_file2 CLI_PORT=`cat $ready_file2` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 \ @@ -219,7 +254,7 @@ printf '%s\n\n' "------------- TEST CASE 2 SHOULD REVOKE ----------------------" remove_single_rF $ready_file2 ./examples/server/server -c certs/ocsp/server2-cert.pem \ -k certs/ocsp/server2-key.pem -R $ready_file2 \ - -p $resume_port & + -p $port2 & wait_for_readyFile $ready_file2 CLI_PORT=`cat $ready_file2` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 \ diff --git a/scripts/ocsp-stapling.test b/scripts/ocsp-stapling.test index bc0a4e56f..4df14a53e 100755 --- a/scripts/ocsp-stapling.test +++ b/scripts/ocsp-stapling.test @@ -3,6 +3,12 @@ # ocsp-stapling.test # Test requires HAVE_OCSP and HAVE_CERTIFICATE_STATUS_REQUEST +# Note, this script makes connection(s) to the public Internet. + +if [[ -z "${RETRIES_REMAINING-}" ]]; then + export RETRIES_REMAINING=2 +fi + ./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' if [ $? -eq 0 ]; then echo "TLS 1.2 or lower required" @@ -11,51 +17,37 @@ if [ $? -eq 0 ]; then fi -# create a unique ready file ending in PID for the script instance ($$) to take -# advantage of port zero solution -WORKSPACE=`pwd` +PARENTDIR=`pwd` + +# create a unique workspace directory ending in PID for the script instance ($$) +# to make this instance orthogonal to any others running, even on same repo. +# TCP ports are also carefully formed below from the PID, to minimize conflicts. + +WORKSPACE="${PARENTDIR}/workspace.pid$$" + +mkdir "${WORKSPACE}" || exit $? +cp -pR certs "${WORKSPACE}"/ || exit $? +cd "$WORKSPACE" || exit $? +ln -s ../examples + CERT_DIR="./certs/ocsp" -resume_port=0 -ready_file=`pwd`/wolf_ocsp_s1_readyF$$ -ready_file2=`pwd`/wolf_ocsp_s1_readyF2$$ +ready_file="$WORKSPACE"/wolf_ocsp_s1_readyF$$ +ready_file2="$WORKSPACE"/wolf_ocsp_s1_readyF2$$ printf '%s\n' "ready file: $ready_file" test_cnf="ocsp_s1.cnf" -copy_originals() { - cd $CERT_DIR - cp intermediate1-ca-cert.pem bak-intermediate1-ca-cert.pem - cp intermediate2-ca-cert.pem bak-intermediate2-ca-cert.pem - cp intermediate3-ca-cert.pem bak-intermediate3-ca-cert.pem - cp ocsp-responder-cert.pem bak-ocsp-responder-cert.pem - cp root-ca-cert.pem bak-root-ca-cert.pem - cp server1-cert.pem bak-server1-cert.pem - cp server2-cert.pem bak-server2-cert.pem - cp server3-cert.pem bak-server3-cert.pem - cp server4-cert.pem bak-server4-cert.pem - cp server5-cert.pem bak-server5-cert.pem - cd $WORKSPACE -} - -restore_originals() { - cd $CERT_DIR - mv bak-intermediate1-ca-cert.pem intermediate1-ca-cert.pem - mv bak-intermediate2-ca-cert.pem intermediate2-ca-cert.pem - mv bak-intermediate3-ca-cert.pem intermediate3-ca-cert.pem - mv bak-ocsp-responder-cert.pem ocsp-responder-cert.pem - mv bak-root-ca-cert.pem root-ca-cert.pem - mv bak-server1-cert.pem server1-cert.pem - mv bak-server2-cert.pem server2-cert.pem - mv bak-server3-cert.pem server3-cert.pem - mv bak-server4-cert.pem server4-cert.pem - mv bak-server5-cert.pem server5-cert.pem -} - wait_for_readyFile(){ counter=0 while [ ! -s $1 -a "$counter" -lt 20 ]; do + if [[ -n "${2-}" ]]; then + if ! kill -0 $2 2>&-; then + echo "pid $2 for port ${3-} exited before creating ready file. bailing..." + exit 1 + fi + fi echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) @@ -64,7 +56,7 @@ wait_for_readyFile(){ if test -e $1; then echo -e "found ready file, starting client..." else - echo -e "NO ready file ending test..." + echo -e "NO ready file at $1 -- ending test..." exit 1 fi @@ -79,8 +71,6 @@ remove_single_rF(){ #create a configure file for cert generation with the port 0 solution create_new_cnf() { - copy_originals - printf '%s\n' "Random Port Selected: $RPORTSELECTED" printf '%s\n' "#" > $test_cnf @@ -147,13 +137,21 @@ remove_ready_file() { cleanup() { + exit_status=$? for i in $(jobs -pr) do kill -s HUP "$i" done remove_ready_file rm $CERT_DIR/$test_cnf - restore_originals + cd "$PARENTDIR" || return 1 + rm -r "$WORKSPACE" || return 1 + + if [[ ("$exit_status" == 1) && ($RETRIES_REMAINING -gt 0) ]]; then + echo "retrying..." + RETRIES_REMAINING=$((RETRIES_REMAINING - 1)) + exec $0 "$@" + fi } trap cleanup EXIT INT TERM HUP @@ -175,13 +173,38 @@ if [ ! -z "$size" ]; then printf 'OK\n' fi +# choose consecutive ports based on the PID, skipping any that are +# already bound, to avoid the birthday problem in case other +# instances are sharing this host. + +get_first_free_port() { + local ret="$1" + while :; do + if [[ "$ret" -ge 65536 ]]; then + ret=1024 + fi + if ! nc -z 127.0.0.1 "$ret"; then + break + fi + ret=$((ret+1)) + done + echo "$ret" + return 0 +} + +base_port=$((((($$ + $RETRIES_REMAINING) * 5) % (65536 - 2048)) + 1024)) +port1=$(get_first_free_port $base_port) +port2=$(get_first_free_port $((port1 + 1))) +port3=$(get_first_free_port $((port2 + 1))) + + # test interop fail case ready_file=`pwd`/wolf_ocsp_readyF$$ printf '%s\n' "ready file: $ready_file" -# use random port and bind to any (allows use with IPv6) -./examples/server/server -b -p $resume_port -o -R $ready_file & +# bind to any (allows use with IPv6) +./examples/server/server -b -p $port1 -o -R $ready_file & wolf_pid=$! -wait_for_readyFile $ready_file +wait_for_readyFile $ready_file $wolf_pid $port1 if [ ! -f $ready_file ]; then printf '%s\n' "Failed to create ready file: \"$ready_file\"" exit 1 @@ -203,9 +226,10 @@ else fi -# create a port 0 port to use with openssl ocsp responder -./examples/server/server -b -p $resume_port -R $ready_file & -wait_for_readyFile $ready_file +# create a port to use with openssl ocsp responder +./examples/server/server -b -p $port2 -R $ready_file & +wolf_pid2=$! +wait_for_readyFile $ready_file $wolf_pid2 $port2 if [ ! -f $ready_file ]; then printf '%s\n' "Failed to create ready file: \"$ready_file\"" exit 1 @@ -257,7 +281,7 @@ sleep 0.1 printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" # client test against our own server - GOOD CERT ./examples/server/server -c certs/ocsp/server1-cert.pem -R $ready_file2 \ - -k certs/ocsp/server1-key.pem -p $resume_port & + -k certs/ocsp/server1-key.pem -p $port3 & wait_for_readyFile $ready_file2 CLI_PORT=`cat $ready_file2` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -p $CLI_PORT @@ -269,7 +293,7 @@ printf '%s\n\n' "------------- TEST CASE 2 SHOULD REVOKE ----------------------" # client test against our own server - REVOKED CERT remove_single_rF $ready_file2 ./examples/server/server -c certs/ocsp/server2-cert.pem -R $ready_file2 \ - -k certs/ocsp/server2-key.pem -p $resume_port & + -k certs/ocsp/server2-key.pem -p $port3 & wait_for_readyFile $ready_file2 sleep 0.1 CLI_PORT=`cat $ready_file2` @@ -287,7 +311,7 @@ if [ $? -ne 0 ]; then remove_single_rF $ready_file2 ./examples/server/server -c certs/ocsp/server1-cert.pem -R $ready_file2 \ -k certs/ocsp/server1-key.pem -v 4 \ - -p $resume_port & + -p $port3 & wait_for_readyFile $ready_file2 CLI_PORT=`cat $ready_file2` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 \ @@ -301,7 +325,7 @@ if [ $? -ne 0 ]; then remove_single_rF $ready_file2 ./examples/server/server -c certs/ocsp/server2-cert.pem -R $ready_file2 \ -k certs/ocsp/server2-key.pem -v 4 \ - -p $resume_port & + -p $port3 & wait_for_readyFile $ready_file2 CLI_PORT=`cat $ready_file2` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 1 -v 4 -F 1 \ diff --git a/scripts/ocsp-stapling2.test b/scripts/ocsp-stapling2.test index 58c02ce74..d166bfc9b 100755 --- a/scripts/ocsp-stapling2.test +++ b/scripts/ocsp-stapling2.test @@ -3,6 +3,20 @@ # ocsp-stapling2.test # Test requires HAVE_OCSP and HAVE_CERTIFICATE_STATUS_REQUEST_V2 +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + +if [[ -z "${RETRIES_REMAINING-}" ]]; then + export RETRIES_REMAINING=2 +fi + ./examples/client/client -v 3 2>&1 | grep -- 'Bad SSL version' if [ $? -eq 0 ]; then echo "TLS 1.2 or lower required" @@ -10,17 +24,27 @@ if [ $? -eq 0 ]; then exit 0 fi -# create a unique ready file ending in PID for the script instance ($$) to take -# advantage of port zero solution -WORKSPACE=`pwd` +PARENTDIR=`pwd` + +# create a unique workspace directory ending in PID for the script instance ($$) +# to make this instance orthogonal to any others running, even on same repo. +# TCP ports are also carefully formed below from the PID, to minimize conflicts. + +WORKSPACE="${PARENTDIR}/workspace.pid$$" + +mkdir "${WORKSPACE}" || exit $? +cp -pR certs "${WORKSPACE}"/ || exit $? +cd "$WORKSPACE" || exit $? +ln -s ../examples + CERT_DIR="certs/ocsp" -resume_port=0 -ready_file1=`pwd`/wolf_ocsp_s2_readyF1$$ -ready_file2=`pwd`/wolf_ocsp_s2_readyF2$$ -ready_file3=`pwd`/wolf_ocsp_s2_readyF3$$ -ready_file4=`pwd`/wolf_ocsp_s2_readyF4$$ -ready_file5=`pwd`/wolf_ocsp_s2_readyF5$$ + +ready_file1="$WORKSPACE"/wolf_ocsp_s2_readyF1$$ +ready_file2="$WORKSPACE"/wolf_ocsp_s2_readyF2$$ +ready_file3="$WORKSPACE"/wolf_ocsp_s2_readyF3$$ +ready_file4="$WORKSPACE"/wolf_ocsp_s2_readyF4$$ +ready_file5="$WORKSPACE"/wolf_ocsp_s2_readyF5$$ printf '%s\n' "ready file 1: $ready_file1" printf '%s\n' "ready file 2: $ready_file2" printf '%s\n' "ready file 3: $ready_file3" @@ -29,40 +53,17 @@ printf '%s\n' "ready file 5: $ready_file5" test_cnf="ocsp_s2.cnf" -copy_originals() { - cd $CERT_DIR - cp intermediate1-ca-cert.pem bak-intermediate1-ca-cert.pem - cp intermediate2-ca-cert.pem bak-intermediate2-ca-cert.pem - cp intermediate3-ca-cert.pem bak-intermediate3-ca-cert.pem - cp ocsp-responder-cert.pem bak-ocsp-responder-cert.pem - cp root-ca-cert.pem bak-root-ca-cert.pem - cp server1-cert.pem bak-server1-cert.pem - cp server2-cert.pem bak-server2-cert.pem - cp server3-cert.pem bak-server3-cert.pem - cp server4-cert.pem bak-server4-cert.pem - cp server5-cert.pem bak-server5-cert.pem - cd $WORKSPACE -} - -restore_originals() { - cd $CERT_DIR - mv bak-intermediate1-ca-cert.pem intermediate1-ca-cert.pem - mv bak-intermediate2-ca-cert.pem intermediate2-ca-cert.pem - mv bak-intermediate3-ca-cert.pem intermediate3-ca-cert.pem - mv bak-ocsp-responder-cert.pem ocsp-responder-cert.pem - mv bak-root-ca-cert.pem root-ca-cert.pem - mv bak-server1-cert.pem server1-cert.pem - mv bak-server2-cert.pem server2-cert.pem - mv bak-server3-cert.pem server3-cert.pem - mv bak-server4-cert.pem server4-cert.pem - mv bak-server5-cert.pem server5-cert.pem -} - wait_for_readyFile(){ counter=0 while [ ! -s $1 -a "$counter" -lt 20 ]; do + if [[ -n "${2-}" ]]; then + if ! kill -0 $2 2>&-; then + echo "pid $2 for port ${3-} exited before creating ready file. bailing..." + exit 1 + fi + fi echo -e "waiting for ready file..." sleep 0.1 counter=$((counter+ 1)) @@ -71,7 +72,7 @@ wait_for_readyFile(){ if test -e $1; then echo -e "found ready file, starting client..." else - echo -e "NO ready file ending test..." + echo -e "NO ready file at $1 -- ending test..." exit 1 fi @@ -86,8 +87,6 @@ remove_single_rF(){ #create a configure file for cert generation with the port 0 solution create_new_cnf() { - copy_originals - printf '%s\n' "Random Port Selected: $RPORTSELECTED" printf '%s\n' "#" > $test_cnf @@ -166,13 +165,21 @@ remove_ready_file(){ cleanup() { + exit_status=$? for i in $(jobs -pr) do kill -s HUP "$i" done remove_ready_file rm $CERT_DIR/$test_cnf - restore_originals + cd "$PARENTDIR" || return 1 + rm -r "$WORKSPACE" || return 1 + + if [[ ("$exit_status" == 1) && ($RETRIES_REMAINING -gt 0) ]]; then + echo "retrying..." + RETRIES_REMAINING=$((RETRIES_REMAINING - 1)) + exec $0 "$@" + fi } trap cleanup EXIT INT TERM HUP @@ -191,50 +198,82 @@ if [ ! -z "$size" ]; then fi #get four unique ports + +# choose consecutive ports based on the PID, skipping any that are +# already bound, to avoid the birthday problem in case other +# instances are sharing this host. + +get_first_free_port() { + local ret="$1" + while :; do + if [[ "$ret" -ge 65536 ]]; then + ret=1024 + fi + if ! nc -z 127.0.0.1 "$ret"; then + break + fi + ret=$((ret+1)) + done + echo "$ret" + return 0 +} + +base_port=$((((($$ + $RETRIES_REMAINING) * 5) % (65536 - 2048)) + 1024)) +port1=$(get_first_free_port $base_port) +port2=$(get_first_free_port $((port1 + 1))) +port3=$(get_first_free_port $((port2 + 1))) +port4=$(get_first_free_port $((port3 + 1))) +port5=$(get_first_free_port $((port4 + 1))) + # 1: -./examples/server/server -R $ready_file1 -p $resume_port & -wait_for_readyFile $ready_file1 +./examples/server/server -R $ready_file1 -p $port1 & +server_pid1=$! +wait_for_readyFile $ready_file1 $server_pid1 $port1 if [ ! -f $ready_file1 ]; then printf '%s\n' "Failed to create ready file1: \"$ready_file1\"" exit 1 fi # 2: -./examples/server/server -R $ready_file2 -p $resume_port & -wait_for_readyFile $ready_file2 +./examples/server/server -R $ready_file2 -p $port2 & +server_pid2=$! +wait_for_readyFile $ready_file2 $server_pid2 $port2 if [ ! -f $ready_file2 ]; then printf '%s\n' "Failed to create ready file2: \"$ready_file2\"" exit 1 fi # 3: -./examples/server/server -R $ready_file3 -p $resume_port & -wait_for_readyFile $ready_file3 +./examples/server/server -R $ready_file3 -p $port3 & +server_pid3=$! +wait_for_readyFile $ready_file3 $server_pid3 $port3 if [ ! -f $ready_file3 ]; then printf '%s\n' "Failed to create ready file3: \"$ready_file3\"" exit 1 fi # 4: -./examples/server/server -R $ready_file4 -p $resume_port & -wait_for_readyFile $ready_file4 +./examples/server/server -R $ready_file4 -p $port4 & +server_pid4=$! +wait_for_readyFile $ready_file4 $server_pid4 $port4 if [ ! -f $ready_file4 ]; then printf '%s\n' "Failed to create ready file4: \"$ready_file4\"" exit 1 -else - RPORTSELECTED1=`cat $ready_file1` - RPORTSELECTED2=`cat $ready_file2` - RPORTSELECTED3=`cat $ready_file3` - RPORTSELECTED4=`cat $ready_file4` - printf '%s\n' "------------- PORTS ---------------" - printf '%s' "Random ports selected: $RPORTSELECTED1 $RPORTSELECTED2" - printf '%s\n' " $RPORTSELECTED3 $RPORTSELECTED4" - printf '%s\n' "-----------------------------------" - # Use client connections to cleanly shutdown the servers - ./examples/client/client -p $RPORTSELECTED1 - ./examples/client/client -p $RPORTSELECTED2 - ./examples/client/client -p $RPORTSELECTED3 - ./examples/client/client -p $RPORTSELECTED4 - create_new_cnf $RPORTSELECTED1 $RPORTSELECTED2 $RPORTSELECTED3 \ - $RPORTSELECTED4 fi + +RPORTSELECTED1=`cat $ready_file1` +RPORTSELECTED2=`cat $ready_file2` +RPORTSELECTED3=`cat $ready_file3` +RPORTSELECTED4=`cat $ready_file4` +printf '%s\n' "------------- PORTS ---------------" +printf '%s' "Random ports selected: $RPORTSELECTED1 $RPORTSELECTED2" +printf '%s\n' " $RPORTSELECTED3 $RPORTSELECTED4" +printf '%s\n' "-----------------------------------" +# Use client connections to cleanly shutdown the servers +./examples/client/client -p $RPORTSELECTED1 +./examples/client/client -p $RPORTSELECTED2 +./examples/client/client -p $RPORTSELECTED3 +./examples/client/client -p $RPORTSELECTED4 +create_new_cnf $RPORTSELECTED1 $RPORTSELECTED2 $RPORTSELECTED3 \ + $RPORTSELECTED4 + sleep 0.1 # setup ocsp responders @@ -280,7 +319,7 @@ printf '%s\n\n' "------------- TEST CASE 1 SHOULD PASS ------------------------" # client test against our own server - GOOD CERTS ./examples/server/server -c certs/ocsp/server3-cert.pem \ -k certs/ocsp/server3-key.pem -R $ready_file5 \ - -p $resume_port & + -p $port5 & wait_for_readyFile $ready_file5 CLI_PORT=`cat $ready_file5` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 2 -v 3 \ @@ -294,7 +333,7 @@ printf '%s\n\n' "TEST CASE 2 DISABLED PENDING REVIEW" #remove_single_rF $ready_file5 #./examples/server/server -c certs/ocsp/server3-cert.pem \ # -k certs/ocsp/server3-key.pem -R $ready_file5 \ -# -p $resume_port & +# -p $port5 & #wait_for_readyFile $ready_file5 #CLI_PORT=`cat $ready_file5` #./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 3 -v 3 \ @@ -308,7 +347,7 @@ printf '%s\n\n' "------------- TEST CASE 3 SHOULD REVOKE ----------------------" remove_single_rF $ready_file5 ./examples/server/server -c certs/ocsp/server4-cert.pem \ -k certs/ocsp/server4-key.pem -R $ready_file5 \ - -p $resume_port & + -p $port5 & wait_for_readyFile $ready_file5 CLI_PORT=`cat $ready_file5` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 2 -v 3 \ @@ -321,7 +360,7 @@ printf '%s\n\n' "------------- TEST CASE 4 SHOULD REVOKE ----------------------" remove_single_rF $ready_file5 ./examples/server/server -c certs/ocsp/server4-cert.pem \ -k certs/ocsp/server4-key.pem -R $ready_file5 \ - -p $resume_port & + -p $port5 & sleep 0.1 CLI_PORT=`cat $ready_file5` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 3 -v 3 \ @@ -335,7 +374,7 @@ printf '%s\n\n' "------------- TEST CASE 5 SHOULD PASS ------------------------" remove_single_rF $ready_file5 ./examples/server/server -c certs/ocsp/server5-cert.pem \ -k certs/ocsp/server5-key.pem -R $ready_file5 \ - -p $resume_port & + -p $port5 & wait_for_readyFile $ready_file5 CLI_PORT=`cat $ready_file5` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 2 -v 3 \ @@ -348,7 +387,7 @@ printf '%s\n\n' "------------- TEST CASE 6 SHOULD REVOKE ----------------------" remove_single_rF $ready_file5 ./examples/server/server -c certs/ocsp/server5-cert.pem \ -k certs/ocsp/server5-key.pem -R $ready_file5 \ - -p $resume_port & + -p $port5 & wait_for_readyFile $ready_file5 CLI_PORT=`cat $ready_file5` ./examples/client/client -C -A certs/ocsp/root-ca-cert.pem -W 3 -v 3 \ @@ -360,7 +399,7 @@ printf '%s\n\n' "------------- TEST CASE 7 LOAD CERT IN SSL -------------------" remove_single_rF $ready_file5 ./examples/server/server -c certs/ocsp/server1-cert.pem \ -k certs/ocsp/server1-key.pem -R $ready_file5 \ - -p $resume_port -H loadSSL & + -p $port5 -H loadSSL & wolf_pid=$! wait_for_readyFile $ready_file5 CLI_PORT=`cat $ready_file5` @@ -377,7 +416,7 @@ printf '%s\n\n' "------------- TEST CASE 8 SHOULD REVOKE ----------------------" remove_single_rF $ready_file5 ./examples/server/server -c certs/ocsp/server4-cert.pem \ -k certs/ocsp/server4-key.pem -R $ready_file5 \ - -p $resume_port -H loadSSL & + -p $port5 -H loadSSL & wolf_pid=$! sleep 0.1 CLI_PORT=`cat $ready_file5` diff --git a/scripts/ocsp.test b/scripts/ocsp.test index 543705617..a939ca229 100755 --- a/scripts/ocsp.test +++ b/scripts/ocsp.test @@ -2,6 +2,8 @@ # ocsp.test +# Note, this script makes connection(s) to the public Internet. + server=www.globalsign.com ca=certs/external/ca-globalsign-root.pem diff --git a/scripts/openssl.test b/scripts/openssl.test index 4b4106551..8c12d136b 100755 --- a/scripts/openssl.test +++ b/scripts/openssl.test @@ -2,13 +2,23 @@ #openssl.test -if test -n "$WOLFSSL_OPENSSL_TEST"; then - echo "WOLFSSL_OPENSSL_TEST set, running test..." -else +if ! test -n "$WOLFSSL_OPENSSL_TEST"; then echo "WOLFSSL_OPENSSL_TEST NOT set, won't run" exit 0 fi +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + +echo "WOLFSSL_OPENSSL_TEST set, running test..." + # need a unique port since may run the same time as testsuite generate_port() { port=$(($(od -An -N2 /dev/random) % (65535-49512) + 49512)) diff --git a/scripts/pkcallbacks.test b/scripts/pkcallbacks.test index 24c9228f5..82aaef1e4 100755 --- a/scripts/pkcallbacks.test +++ b/scripts/pkcallbacks.test @@ -2,6 +2,16 @@ #pkcallbacks.test +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + exit_code=1 counter=0 # need a unique resume port since may run the same time as testsuite diff --git a/scripts/psk.test b/scripts/psk.test index d11ac59b5..cef3beba2 100755 --- a/scripts/psk.test +++ b/scripts/psk.test @@ -3,6 +3,16 @@ # psk.test # copyright wolfSSL 2016 +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + # getting unique port is modeled after resume.test script # need a unique port since may run the same time as testsuite # use server port zero hack to get one diff --git a/scripts/resume.test b/scripts/resume.test index 35d05e1f2..7d02339c6 100755 --- a/scripts/resume.test +++ b/scripts/resume.test @@ -2,6 +2,16 @@ #resume.test +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + # need a unique resume port since may run the same time as testsuite # use server port zero hack to get one resume_string="reused" diff --git a/scripts/sniffer-testsuite.test b/scripts/sniffer-testsuite.test index 9bfb39b46..69bfa50df 100755 --- a/scripts/sniffer-testsuite.test +++ b/scripts/sniffer-testsuite.test @@ -2,6 +2,16 @@ #sniffer-testsuite.test +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + # ./configure --enable-sniffer [--enable-session-ticket] # Resumption tests require "--enable-session-ticket" diff --git a/scripts/tls13.test b/scripts/tls13.test index 8bcf2c3d3..e393e68aa 100755 --- a/scripts/tls13.test +++ b/scripts/tls13.test @@ -3,6 +3,16 @@ # tls13.test # copyright wolfSSL 2016 +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + # getting unique port is modeled after resume.test script # need a unique port since may run the same time as testsuite # use server port zero hack to get one diff --git a/scripts/trusted_peer.test b/scripts/trusted_peer.test index 67ee7803e..f6e4b3e0b 100755 --- a/scripts/trusted_peer.test +++ b/scripts/trusted_peer.test @@ -3,6 +3,16 @@ # trusted_peer.test # copyright wolfSSL 2016 +# if we can, isolate the network namespace to eliminate port collisions. +if [ "${AM_BWRAPPED-}" != "yes" ]; then + bwrap_path="$(command -v bwrap)" + if [ -n "$bwrap_path" ]; then + export AM_BWRAPPED=yes + exec "$bwrap_path" --unshare-net --dev-bind / / "$0" "$@" + fi + unset AM_BWRAPPED +fi + # getting unique port is modeled after resume.test script # need a unique port since may run the same time as testsuite # use server port zero hack to get one diff --git a/wolfssl/test.h b/wolfssl/test.h index c3136894b..6904dcd6e 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -501,6 +501,34 @@ err_sys(const char* msg) } } +static WC_INLINE +#if defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) || defined(WOLFSSL_ZEPHYR) +THREAD_RETURN +#else +WC_NORETURN void +#endif +err_sys_with_errno(const char* msg) +{ +#if defined(HAVE_STRING_H) && defined(HAVE_ERRNO_H) + printf("wolfSSL error: %s: %s\n", msg, strerror(errno)); +#else + printf("wolfSSL error: %s\n", msg); +#endif + +#if !defined(__GNUC__) + /* scan-build (which pretends to be gnuc) can get confused and think the + * msg pointer can be null even when hardcoded and then it won't exit, + * making null pointer checks above the err_sys() call useless. + * We could just always exit() but some compilers will complain about no + * possible return, with gcc we know the attribute to handle that with + * WC_NORETURN. */ + if (msg) +#endif + { + XEXIT_T(EXIT_FAILURE); + } +} + extern int myoptind; extern char* myoptarg; @@ -948,7 +976,7 @@ static WC_INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_TCP); if(WOLFSSL_SOCKET_IS_INVALID(*sockfd)) { - err_sys("socket failed\n"); + err_sys_with_errno("socket failed\n"); } #ifndef USE_WINDOWS_API @@ -958,7 +986,7 @@ static WC_INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) socklen_t len = sizeof(on); int res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len); if (res < 0) - err_sys("setsockopt SO_NOSIGPIPE failed\n"); + err_sys_with_errno("setsockopt SO_NOSIGPIPE failed\n"); } #elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) ||\ defined(WOLFSSL_KEIL_TCP_NET) || defined(WOLFSSL_ZEPHYR) @@ -974,7 +1002,7 @@ static WC_INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) socklen_t len = sizeof(on); int res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len); if (res < 0) - err_sys("setsockopt TCP_NODELAY failed\n"); + err_sys_with_errno("setsockopt TCP_NODELAY failed\n"); } #endif #endif /* USE_WINDOWS_API */ @@ -992,7 +1020,7 @@ static WC_INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, if (!udp) { if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) - err_sys("tcp connect failed"); + err_sys_with_errno("tcp connect failed"); } } @@ -1000,7 +1028,7 @@ static WC_INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, static WC_INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz) { if (connect(*sockfd, (const struct sockaddr*)addr, addrSz) != 0) - err_sys("tcp connect failed"); + err_sys_with_errno("tcp connect failed"); } @@ -1098,12 +1126,21 @@ static WC_INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, socklen_t len = sizeof(on); res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); if (res < 0) - err_sys("setsockopt SO_REUSEADDR failed\n"); + err_sys_with_errno("setsockopt SO_REUSEADDR failed\n"); } +#ifdef SO_REUSEPORT + { + int res, on = 1; + socklen_t len = sizeof(on); + res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEPORT, &on, len); + if (res < 0) + err_sys_with_errno("setsockopt SO_REUSEPORT failed\n"); + } +#endif #endif if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) - err_sys("tcp bind failed"); + err_sys_with_errno("tcp bind failed"); if (!udp) { #ifdef WOLFSSL_KEIL_TCP_NET #define SOCK_LISTEN_MAX_QUEUE 1 @@ -1111,7 +1148,7 @@ static WC_INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, #define SOCK_LISTEN_MAX_QUEUE 5 #endif if (listen(*sockfd, SOCK_LISTEN_MAX_QUEUE) != 0) - err_sys("tcp listen failed"); + err_sys_with_errno("tcp listen failed"); } #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) \ && !defined(WOLFSSL_ZEPHYR) @@ -1168,12 +1205,21 @@ static WC_INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, socklen_t len = sizeof(on); res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); if (res < 0) - err_sys("setsockopt SO_REUSEADDR failed\n"); + err_sys_with_errno("setsockopt SO_REUSEADDR failed\n"); } +#ifdef SO_REUSEPORT + { + int res, on = 1; + socklen_t len = sizeof(on); + res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEPORT, &on, len); + if (res < 0) + err_sys_with_errno("setsockopt SO_REUSEPORT failed\n"); + } +#endif #endif if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) - err_sys("tcp bind failed"); + err_sys_with_errno("tcp bind failed"); #if (defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API)) && !defined(WOLFSSL_TIRTOS) if (port == 0) { @@ -1275,7 +1321,7 @@ static WC_INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, *clientfd = accept(*sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); if(WOLFSSL_SOCKET_IS_INVALID(*clientfd)) { - err_sys("tcp accept failed"); + err_sys_with_errno("tcp accept failed"); } } @@ -1286,7 +1332,7 @@ static WC_INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) unsigned long blocking = 1; int ret = ioctlsocket(*sockfd, FIONBIO, &blocking); if (ret == SOCKET_ERROR) - err_sys("ioctlsocket failed"); + err_sys_with_errno("ioctlsocket failed"); #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) \ || defined (WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS) \ || defined(WOLFSSL_ZEPHYR) @@ -1294,10 +1340,10 @@ static WC_INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) #else int flags = fcntl(*sockfd, F_GETFL, 0); if (flags < 0) - err_sys("fcntl get failed"); + err_sys_with_errno("fcntl get failed"); flags = fcntl(*sockfd, F_SETFL, flags | O_NONBLOCK); if (flags < 0) - err_sys("fcntl set failed"); + err_sys_with_errno("fcntl set failed"); #endif } @@ -1972,7 +2018,7 @@ static WC_INLINE int StackSizeCheck(func_args* args, thread_func tf) ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); if (ret != 0 || myStack == NULL) - err_sys("posix_memalign failed\n"); + err_sys_with_errno("posix_memalign failed\n"); XMEMSET(myStack, STACK_CHECK_VAL, stackSize); @@ -2029,13 +2075,11 @@ static WC_INLINE void StackTrap(void) { struct rlimit rl; if (getrlimit(RLIMIT_STACK, &rl) != 0) - err_sys("getrlimit failed"); + err_sys_with_errno("getrlimit failed"); printf("rlim_cur = %llu\n", rl.rlim_cur); rl.rlim_cur = 1024*21; /* adjust trap size here */ - if (setrlimit(RLIMIT_STACK, &rl) != 0) { - perror("setrlimit"); - err_sys("setrlimit failed"); - } + if (setrlimit(RLIMIT_STACK, &rl) != 0) + err_sys_with_errno("setrlimit failed"); } #else /* STACK_TRAP */ @@ -2398,13 +2442,13 @@ static WC_INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl) encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx)); if (encCtx == NULL) - err_sys("AtomicEncCtx malloc failed"); + err_sys_with_errno("AtomicEncCtx malloc failed"); XMEMSET(encCtx, 0, sizeof(AtomicEncCtx)); decCtx = (AtomicDecCtx*)malloc(sizeof(AtomicDecCtx)); if (decCtx == NULL) { free(encCtx); - err_sys("AtomicDecCtx malloc failed"); + err_sys_with_errno("AtomicDecCtx malloc failed"); } XMEMSET(decCtx, 0, sizeof(AtomicDecCtx));