From 018468a67013768407c80d7651c1790bdd8ab708 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Sat, 9 Jul 2016 14:24:38 +0200 Subject: [PATCH 1/5] more user friendly... --- utils/curves.bash | 82 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/utils/curves.bash b/utils/curves.bash index 6d62ad4..4168c02 100755 --- a/utils/curves.bash +++ b/utils/curves.bash @@ -4,23 +4,91 @@ # x448 and x25519 are missing, others are not supported # License see testssl.sh +readonly RUN_DIR=$(dirname "$0") + +test_openssl_suffix() { + local naming_ext="$(uname).$(uname -m)" + local uname_arch="$(uname -m)" + local myarch_suffix="" + + [[ $uname_arch =~ 64 ]] && myarch_suffix=64 || myarch_suffix=32 + if [[ -f "$1/openssl" ]] && [[ -x "$1/openssl" ]]; then + OPENSSL="$1/openssl" + return 0 + elif [[ -f "$1/openssl.$naming_ext" ]] && [[ -x "$1/openssl.$naming_ext" ]]; then + OPENSSL="$1/openssl.$naming_ext" + return 0 + fi + return 1 +} + + +find_openssl_binary() { + # 0. check environment variable whether it's executable + if [[ -n "$OPENSSL" ]] && [[ ! -x "$OPENSSL" ]]; then + pr_warningln "\ncannot find specified (\$OPENSSL=$OPENSSL) binary." + outln " Looking some place else ..." + elif [[ -x "$OPENSSL" ]]; then + : # 1. all ok supplied $OPENSSL was found and has excutable bit set -- testrun comes below + elif test_openssl_suffix $RUN_DIR; then + : # 2. otherwise try openssl in path of testssl.sh + elif test_openssl_suffix ../$RUN_DIR; then + : # 2. otherwise try openssl in path of testssl.sh + elif test_openssl_suffix ../$RUN_DIR/bin; then + : # 3. otherwise here, this is supposed to be the standard --platform independed path in the future!!! + elif test_openssl_suffix "$(dirname "$(which openssl)")"; then + : # 5. we tried hard and failed, so now we use the system binaries + fi + + # no ERRFILE initialized yet, thus we use /dev/null for stderr directly + $OPENSSL version -a 2>/dev/null >/dev/null + if [[ $? -ne 0 ]] || [[ ! -x "$OPENSSL" ]]; then + echo "\ncannot exec or find any openssl binary" + exit 1 + fi + echo + echo "using $OPENSSL" + echo +} + + +VERBOSE=false +if [[ $1 == "-v" ]]; then + VERBOSE=true + shift +fi HN="$1" [ -z "$HN" ] && HN=testssl.sh -for curve in $(bin/openssl.Linux.x86_64 ecparam -list_curves | awk -F':' '/:/ { print $1 }'); do - printf "$curve: " +find_openssl_binary + +ERRFILE=$(mktemp /tmp/curve_tester.R.XXXXXX) || exit -6 +TMPFILE=$(mktemp /tmp/curve_tester.T.XXXXXX) || exit -6 + + +for curve in $($OPENSSL ecparam -list_curves | awk -F':' '/:/ { print $1 }'); do #if bin/openssl.Linux.x86_64 s_client -curves $curve -connect $HN:443 -servername $HN /dev/null | grep -q "BEGIN CERTIFICATE" ; then # echo 'YES' #else # echo '--' #fi - if bin/openssl.Linux.x86_64 s_client -cipher ECDH -curves $curve -connect $HN:443 -servername $HN /dev/null | grep "Server Temp Key:" ; then - : + $OPENSSL s_client -cipher ECDH -curves $curve -connect $HN:443 -servername $HN $ERRFILE | grep "Server Temp Key:" >$TMPFILE + if [[ $? -eq 0 ]]; then + printf "$curve: " + cat $TMPFILE | sed 's/^.*Server Temp Key: //' else - echo '--' + if grep -q 'Error with' $ERRFILE; then + if "$VERBOSE"; then + echo "$curve: no client support" + fi + else + echo "$curve: --" + fi fi done -# vim:ts=5:sw=5:expandtab -# $Id: curves.bash,v 1.2 2016/07/08 09:39:27 dirkw Exp $ +rm -f $ERRFILE $TMPFILE + +# vim:ts=5:sw=5:expandtab +# $Id: curves.bash,v 1.3 2016/07/09 12:22:13 dirkw Exp $ From 3c3939639189e5c86a739db98d506d4a48fc86b9 Mon Sep 17 00:00:00 2001 From: Will Elwood Date: Mon, 11 Jul 2016 13:35:55 +0100 Subject: [PATCH 2/5] Unreadable SAN list on FreeBSD On FreeBSD, sed does not support "\n" in the replacement string of a substitution. The SANs are currently output all together inside a single pair of quotes and each separated with an "n" character, needless to say this is very difficult to read. After a little digging, it seems this is a somewhat recent regression of the fix in #173. I believe `tr` would be a more cross-platform way to do this, and several sources (including the author of that PR) would seem to agree - assuming the newline is now necessary. It doesn't appear to matter what order the newline replacement happens amongst all the other replacements, so I have placed it first simply to avoid extending any already-long lines. Please correct me if this deduction is false. --- testssl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index c2dd02c..085967a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4123,9 +4123,9 @@ certificate_info() { fileout "${json_prefix}cn" "$cnok" "$cnfinding" sans=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A2 "Subject Alternative Name" | \ - egrep "DNS:|IP Address:|email:|URI:|DirName:|Registered ID:" | \ + egrep "DNS:|IP Address:|email:|URI:|DirName:|Registered ID:" | tr ',' '\n' | \ sed -e 's/ *DNS://g' -e 's/ *IP Address://g' -e 's/ *email://g' -e 's/ *URI://g' -e 's/ *DirName://g' \ - -e 's/ *Registered ID://g' -e 's/,/\n/g' \ + -e 's/ *Registered ID://g' \ -e 's/ *othername://g' -e 's/ *X400Name://g' -e 's/ *EdiPartyName://g') # ^^^ CACert out "$indent"; pr_bold " subjectAltName (SAN) " From 382d22648aa36aeb2f2c6191fc7807432aebafc5 Mon Sep 17 00:00:00 2001 From: Will Elwood Date: Mon, 11 Jul 2016 14:15:50 +0100 Subject: [PATCH 3/5] Server cipher order NPN tests should use SNI I noticed the NPN parts of this test were not returning any ECDSA ciphers where I expected them to match the results of the immediately preceding TLS 1.2 test. Found it wasn't using SNI so my test server was using the default domain (snakeoil RSA certificate) instead of the tested domain (dual ECDSA/RSA certificates). --- testssl.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index c2dd02c..90a5ad0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3499,16 +3499,16 @@ cipher_pref_check() { if ! spdy_pre " SPDY/NPN: "; then # is NPN/SPDY supported and is this no STARTTLS? outln else - npn_protos=$($OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg \"\" >$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g') + npn_protos=$($OPENSSL s_client $BUGS -nextprotoneg \"\" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g') for p in $npn_protos; do order="" - $OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg "$p" $PROXY >$ERRFILE >$TMPFILE + $OPENSSL s_client $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) printf " %-10s %s " "$p:" "$cipher" tested_cipher="-"$cipher order="$cipher" while true; do - $OPENSSL s_client -cipher "ALL:$tested_cipher" -host $NODE -port $PORT $BUGS -nextprotoneg "$p" $PROXY >$ERRFILE >$TMPFILE + $OPENSSL s_client -cipher "ALL:$tested_cipher" $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE sclient_connect_successful $? $TMPFILE || break cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) out "$cipher " From 2573a9b8b80caf841e676f3c61605c54cdc1ff6d Mon Sep 17 00:00:00 2001 From: Will Elwood Date: Mon, 11 Jul 2016 14:37:20 +0100 Subject: [PATCH 4/5] More SNI for NPN tests Found another NPN test (for the case where server doesn't specify cipher order?) that wasn't using SNI. Also found a comment saying proxies don't support NPN => removed `$PROXY` from all modified lines. --- testssl.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index 90a5ad0..a54044d 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3324,7 +3324,7 @@ run_server_preference() { [[ -n "$PROXY" ]] && arg=" SPDY/NPN is" [[ -n "$STARTTLS" ]] && arg=" " if spdy_pre " $arg" ; then # is NPN/SPDY supported and is this no STARTTLS? / no PROXY - $OPENSSL s_client -connect $NODEIP:$PORT $BUGS -nextprotoneg "$NPN_PROTOs" >$ERRFILE >$TMPFILE + $OPENSSL s_client -connect $NODEIP:$PORT $BUGS -nextprotoneg "$NPN_PROTOs" $SNI >$ERRFILE >$TMPFILE if sclient_connect_successful $? $TMPFILE; then proto[i]=$(grep -aw "Next protocol" $TMPFILE | sed -e 's/^Next protocol://' -e 's/(.)//' -e 's/ //g') if [[ -z "${proto[i]}" ]]; then @@ -3499,16 +3499,16 @@ cipher_pref_check() { if ! spdy_pre " SPDY/NPN: "; then # is NPN/SPDY supported and is this no STARTTLS? outln else - npn_protos=$($OPENSSL s_client $BUGS -nextprotoneg \"\" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g') + npn_protos=$($OPENSSL s_client $BUGS -nextprotoneg \"\" -connect $NODEIP:$PORT $SNI >$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g') for p in $npn_protos; do order="" - $OPENSSL s_client $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE + $OPENSSL s_client $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $SNI >$ERRFILE >$TMPFILE cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) printf " %-10s %s " "$p:" "$cipher" tested_cipher="-"$cipher order="$cipher" while true; do - $OPENSSL s_client -cipher "ALL:$tested_cipher" $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE + $OPENSSL s_client -cipher "ALL:$tested_cipher" $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $SNI >$ERRFILE >$TMPFILE sclient_connect_successful $? $TMPFILE || break cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) out "$cipher " From 3e8d5208dc486846d01a51e551b9f7f13f0246b3 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 11 Jul 2016 16:20:36 +0200 Subject: [PATCH 5/5] further fix, see #410 --- testssl.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 085967a..1f3f079 100755 --- a/testssl.sh +++ b/testssl.sh @@ -3811,7 +3811,7 @@ compare_server_name_to_cert() # Check whether any of the DNS names in the certificate match the servername dns_sans=$($OPENSSL x509 -in $cert -noout -text 2>>$ERRFILE | grep -A2 "Subject Alternative Name" | \ - sed -e 's/,/\n/g' | grep "DNS:" | sed -e 's/DNS://g' -e 's/ //g') + tr '.' '\n' grep "DNS:" | sed -e 's/DNS://g' -e 's/ //g') for san in $dns_sans; do [[ "$san" == "$servername" ]] && return 0 # If $san is a wildcard name, then do a wildcard match @@ -3823,7 +3823,7 @@ compare_server_name_to_cert() # Check whether any of the IP addresses in the certificate match the serername ip_sans=$($OPENSSL x509 -in $cert -noout -text 2>>$ERRFILE | grep -A2 "Subject Alternative Name" | \ - sed -e 's/,/\n/g' | grep "IP Address:" | sed -e 's/IP Address://g' -e 's/ //g') + tr ',' '\n' | grep "IP Address:" | sed -e 's/IP Address://g' -e 's/ //g') for san in $ip_sans; do [[ "$san" == "$servername" ]] && return 0 done @@ -8268,4 +8268,4 @@ fi exit $? -# $Id: testssl.sh,v 1.522 2016/07/08 09:25:39 dirkw Exp $ +# $Id: testssl.sh,v 1.523 2016/07/11 14:20:35 dirkw Exp $