From 838112e6d20cd059abc0436518bbfcb7adbd2fea Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Mon, 24 Aug 2015 23:50:03 +0200 Subject: [PATCH] - LibreSSL compatibility: recent pull spits out an error if cnf file isn't found (oh well) ==> introduction of #ERRFILE, good idea anyway - commented what I wanted to achieve with the colors - code cleanups --- testssl.sh | 346 +++++++++++++++++++++++++++++------------------------ 1 file changed, 188 insertions(+), 158 deletions(-) diff --git a/testssl.sh b/testssl.sh index a6a8248..2c7a315 100755 --- a/testssl.sh +++ b/testssl.sh @@ -74,7 +74,7 @@ echo $VERSION | egrep -q "dev|rc" && \ readonly PROG_NAME=$(basename "$0") readonly RUN_DIR=$(dirname $0) INSTALL_DIR="" -MAP_RFC_FNAME="" +MAPPING_FILE_RFC="" which git &>/dev/null && readonly GIT_REL=$(git log --format='%h %ci' -1 2>/dev/null | awk '{ print $1" "$2" "$3 }') readonly CVS_REL=$(tail -5 $0 | awk '/dirkw Exp/ { print $4" "$5" "$6}') @@ -93,8 +93,6 @@ TERM_CURRPOS=0 # ^^^ we also need to find out the length or current pos in # following variables make use of $ENV, e.g. OPENSSL= ./testssl.sh # 0 means (normally) true here. Some of the variables are also accessible with a command line switch -# we have tab indentation with 5 virtual chars! - declare -x OPENSSL COLOR=${COLOR:-2} # 2: Full color, 1: b/w+positioning, 0: no ESC at all SHOW_EACH_C=${SHOW_EACH_C:-0} # where individual ciphers are tested show just the positively ones tested #FIXME: upside down value @@ -128,10 +126,11 @@ readonly CLIENT_MIN_PFS=5 # number of ciphers needed to run a test for PFS DAYS2WARN1=${DAYS2WARN1:-60} # days to warn before cert expires, threshold 1 DAYS2WARN2=${DAYS2WARN2:-30} # days to warn before cert expires, threshold 2 -# furher vars needed to follow +# further vars needed to follow readonly NPN_PROTOs="spdy/4a2,spdy/3,spdy/3.1,spdy/2,spdy/1,http/1.1" TEMPDIR="" TMPFILE="" +ERRFILE="" HOSTCERT="" HEADERFILE="" HEADERFILE_BREACH="" @@ -252,24 +251,24 @@ outln() { out "$1\n"; } #TODO: Still no shell injection safe but if just run it from the cmd line: that's fine # color print functions, see also http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html -pr_liteblue() { [[ "$COLOR" -eq 2 ]] && out "\033[0;34m$1" || out "$1"; pr_off; } +pr_liteblue() { [[ "$COLOR" -eq 2 ]] && out "\033[0;34m$1" || out "$1"; pr_off; } # not yet used pr_liteblueln() { pr_liteblue "$1"; outln; } -pr_blue() { [[ "$COLOR" -eq 2 ]] && out "\033[1;34m$1" || out "$1"; pr_off; } +pr_blue() { [[ "$COLOR" -eq 2 ]] && out "\033[1;34m$1" || out "$1"; pr_off; } # used for head lines of single tests pr_blueln() { pr_blue "$1"; outln; } -pr_litered() { [[ "$COLOR" -eq 2 ]] && out "\033[0;31m$1" || pr_bold "$1"; pr_off; } +pr_litered() { [[ "$COLOR" -eq 2 ]] && out "\033[0;31m$1" || pr_bold "$1"; pr_off; } # this is bad pr_literedln() { pr_litered "$1"; outln; } -pr_red() { [[ "$COLOR" -eq 2 ]] && out "\033[1;31m$1" || pr_bold "$1"; pr_off; } +pr_red() { [[ "$COLOR" -eq 2 ]] && out "\033[1;31m$1" || pr_bold "$1"; pr_off; } # oh, this is really bad pr_redln() { pr_red "$1"; outln; } -pr_litemagenta() { [[ "$COLOR" -eq 2 ]] && out "\033[0;35m$1" || pr_underline "$1"; pr_off; } +pr_litemagenta() { [[ "$COLOR" -eq 2 ]] && out "\033[0;35m$1" || pr_underline "$1"; pr_off; } # local problem: one test acconot be done pr_litemagentaln() { pr_litemagenta "$1"; outln; } -pr_magenta() { [[ "$COLOR" -eq 2 ]] && out "\033[1;35m$1" || pr_underline "$1"; pr_off; } +pr_magenta() { [[ "$COLOR" -eq 2 ]] && out "\033[1;35m$1" || pr_underline "$1"; pr_off; } # Fatal error: quitting because of this pr_magentaln() { pr_magenta "$1"; outln; } -pr_litecyan() { [[ "$COLOR" -eq 2 ]] && out "\033[0;36m$1" || out "$1"; pr_off; } +pr_litecyan() { [[ "$COLOR" -eq 2 ]] && out "\033[0;36m$1" || out "$1"; pr_off; } # not yet used pr_litecyanln() { pr_litecyan "$1"; outln; } -pr_cyan() { [[ "$COLOR" -eq 2 ]] && out "\033[1;36m$1" || out "$1"; pr_off; } +pr_cyan() { [[ "$COLOR" -eq 2 ]] && out "\033[1;36m$1" || out "$1"; pr_off; } # additional hint pr_cyanln() { pr_cyan "$1"; outln; } pr_litegreyln() { pr_litegrey "$1"; outln; } @@ -277,14 +276,14 @@ pr_litegrey() { [[ "$COLOR" -eq 2 ]] && out "\033[0;37m$1" || out "$1"; pr_off pr_grey() { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m$1" || out "$1"; pr_off; } pr_greyln() { pr_grey "$1"; outln; } -pr_litegreen() { [[ "$COLOR" -eq 2 ]] && out "\033[0;32m$1" || out "$1"; pr_off; } +pr_litegreen() { [[ "$COLOR" -eq 2 ]] && out "\033[0;32m$1" || out "$1"; pr_off; } # This is good pr_litegreenln() { pr_litegreen "$1"; outln; } -pr_green() { [[ "$COLOR" -eq 2 ]] && out "\033[1;32m$1" || out "$1"; pr_off; } +pr_green() { [[ "$COLOR" -eq 2 ]] && out "\033[1;32m$1" || out "$1"; pr_off; } # This is the best pr_greenln() { pr_green "$1"; outln; } -pr_yellow() { [[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1" || out "$1"; pr_off; } +pr_yellow() { [[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1" || out "$1"; pr_off; } # academic or minor problem pr_yellowln() { pr_yellow "$1"; outln; } -pr_brown() { [[ "$COLOR" -eq 2 ]] && out "\033[0;33m$1" || out "$1"; pr_off; } +pr_brown() { [[ "$COLOR" -eq 2 ]] && out "\033[0;33m$1" || out "$1"; pr_off; } # it is not a bad problem but you shouldn't do this pr_brownln() { pr_brown "$1"; outln; } @@ -376,6 +375,15 @@ count_words() { echo "$1" | wc -w | sed 's/ //g' } +count_ciphers() { + printf "$1" | sed 's/:/ /g' | wc -w | sed 's/ //g' +} + +actually_supported_ciphers() { + $OPENSSL ciphers "$1" 2>/dev/null || echo "" +} + + newline_to_spaces() { echo "$1" | tr '\n' ' ' | sed 's/ $//' } @@ -405,9 +413,11 @@ out_row_aligned() { tmpfile_handle() { if [[ "$DEBUG" -eq 0 ]] ; then - rm $TMPFILE + rm $TMPFILE 2>/dev/null + [[ $ERRFILE =~ "dev/null" ]] || rm $ERRFILE else - mv $TMPFILE "$TEMPDIR/$NODEIP.$1" + mv $TMPFILE "$TEMPDIR/$NODEIP.$1" 2>/dev/null + mv $ERRFILE "$TEMPDIR/$NODEIP.$(sed 's/\.txt//g' <<<$1).errorlog" 2>/dev/null fi } @@ -465,7 +475,7 @@ runs_HTTP() { out " -- ASSUMING_HTTP set though" ret=0 else - out ", assuming no HTTP service, skipping HTTP checks" + out ", assuming no HTTP service => skipping HTTP checks" ret=1 fi ;; @@ -519,15 +529,15 @@ EOF ret=0 else #TODO: attention: if this runs into a timeout, we're dead. Try again differently: - printf "$GET_REQ11" | $OPENSSL s_client $OPTIMAL_PROTO -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI 1>$HEADERFILE 2>/dev/null + printf "$GET_REQ11" | $OPENSSL s_client $OPTIMAL_PROTO -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI 1>$HEADERFILE 2>$ERRFILE if [ $? -ne 0 ]; then pr_litemagentaln " failed (1st request stalled, 2nd erroneous)" return 3 #ret=3 fi fi - status_code=$(awk '/^HTTP\// { print $2 }' $HEADERFILE 2>/dev/null) - msg_thereafter=$(awk -F"$status_code" '/^HTTP\// { print $2 }' $HEADERFILE 2>/dev/null) # dirty trick to use the status code as a + status_code=$(awk '/^HTTP\// { print $2 }' $HEADERFILE 2>>$ERRFILE) + msg_thereafter=$(awk -F"$status_code" '/^HTTP\// { print $2 }' $HEADERFILE 2>>$ERRFILE) # dirty trick to use the status code as a msg_thereafter=$(strip_lf "$msg_thereafter") # field separator, otherwise we need a loop with awk debugme echo "Status/MSG: $status_code $msg_thereafter" @@ -571,7 +581,7 @@ run_http_date() { if $HAS_GNUDATE ; then HTTP_TIME=$(date --date="$HTTP_TIME" "+%s") else - HTTP_TIME=$(date -j -f "%a, %d %b %Y %T %Z" "$HTTP_TIME" "+%s" 2>/dev/null) # the trailing \r confuses BSD flavors otherwise + HTTP_TIME=$(date -j -f "%a, %d %b %Y %T %Z" "$HTTP_TIME" "+%s" 2>>$ERRFILE) # the trailing \r confuses BSD flavors otherwise fi difftime=$(($HTTP_TIME - $now)) @@ -824,6 +834,8 @@ run_rp_banner() { emphasize_stuff_in_headers "$line" done fi + outln + tmpfile_handle $FUNCNAME.txt return 0 @@ -991,14 +1003,14 @@ prettyprint_local() { neat_header if [[ -z "$1" ]]; then - $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode dash ciph sslvers kx auth enc mac export ; do # -V doesn't work with openssl < 1.0 + $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do # -V doesn't work with openssl < 1.0 normalize_ciphercode $hexcode neat_list $HEXC $ciph $kx $enc outln done else for arg in $(echo $@ | sed 's/,/ /g'); do - $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode dash ciph sslvers kx auth enc mac export ; do # -V doesn't work with openssl < 1.0 + $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do # -V doesn't work with openssl < 1.0 normalize_ciphercode $hexcode # for numbers we don't do word matching: [[ $arg =~ $re ]] && \ @@ -1015,7 +1027,7 @@ prettyprint_local() { # list ciphers (and makes sure you have them locally configured) # arg[1]: cipher list (or anything else) listciphers() { - local ret + local -i ret local debugname="$(sed -e s'/\!/not/g' -e 's/\:/_/g' <<< $1)" $OPENSSL ciphers "$1" &>$TMPFILE @@ -1031,15 +1043,15 @@ listciphers() { # argv[2]: string on console # argv[3]: ok to offer? 0: yes, 1: no std_cipherlists() { - local ret + local -i ret local singlespaces local debugname="$(sed -e s'/\!/not/g' -e 's/\:/_/g' <<< $1)" pr_bold "$2 " # indent in order to be in the same row as server preferences if listciphers "$1"; then # is that locally available?? - $OPENSSL s_client -cipher "$1" $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI 2>$TMPFILE.2 >$TMPFILE $ERRFILE >$TMPFILE >$TMPFILE tmpfile_handle $FUNCNAME.$debugname.txt else singlespaces=$(echo "$2" | sed -e 's/ \+/ /g' -e 's/^ //' -e 's/ $//g' -e 's/ //g') - pr_magentaln "Local problem: No $singlespaces configured in $OPENSSL" + local_problem "No $singlespaces configured in $OPENSSL" fi # we need lf in those cases: [[ $DEBUG -ge 2 ]] && echo @@ -1089,8 +1100,10 @@ socksend() { #FIXME: This is only for HB and CCS, others use still sockread_serverhello() sockread() { + local -i ret=0 + local ddreply + [[ "x$2" == "x" ]] && maxsleep=$MAX_WAITSOCK || maxsleep=$2 - ret=0 ddreply=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7 dd bs=$1 of=$ddreply count=1 <&5 2>/dev/null & @@ -1098,21 +1111,22 @@ sockread() { ret=$? SOCKREPLY=$(cat $ddreply) rm $ddreply - return $ret } show_rfc_style(){ - [ ! -r "$MAP_RFC_FNAME" ] && return 1 - RFCname=$(grep -iw "$1" "$MAP_RFC_FNAME" | sed -e 's/^.*TLS/TLS/' -e 's/^.*SSL/SSL/') - [[ -n "$RFCname" ]] && out "$RFCname" + local rfcname + + [[ -z "$MAPPING_FILE_RFC" ]] && return 1 + rfcname=$(grep -iw "$1" "$MAPPING_FILE_RFC" | sed -e 's/^.*TLS/TLS/' -e 's/^.*SSL/SSL/') + [[ -n "$rfcname" ]] && out "$rfcname" return 0 } neat_header(){ - outln "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits${MAP_RFC_FNAME:+ Cipher Suite Name (RFC)}" - outln "%s-------------------------------------------------------------------------${MAP_RFC_FNAME:+----------------------------------------------}" + printf -- "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits${MAPPING_FILE_RFC:+ Cipher Suite Name (RFC)}\n" + printf -- "%s-------------------------------------------------------------------------${MAPPING_FILE_RFC:+----------------------------------------------}\n" } @@ -1121,11 +1135,15 @@ neat_header(){ # arg3: keyexchange # arg4: encryption (maybe included "export") neat_list(){ - kx=$(echo "$3" | sed 's/Kx=//g') - enc=$(echo "$4" | sed 's/Enc=//g') - strength=$(echo $enc | sed -e 's/.*(//' -e 's/)//') # strength = encryption bits - strength=$(echo $strength | sed -e 's/ChaCha20-Poly1305/ly1305/g') # workaround for empty bits ChaCha20-Poly1305 - enc=$(echo $enc | sed -e 's/(.*)//g' -e 's/ChaCha20-Poly1305/ChaCha20-Po/g') # workaround for empty bits ChaCha20-Poly1305 + local hexcode="$1" + local ossl_cipher="$2" + local kx enc strength + + kx=$(sed 's/Kx=//g' <<< "$3") + enc=$(sed 's/Enc=//g' <<< "$4") + strength=$(sed -e 's/.*(//' -e 's/)//' <<< "$enc") # strength = encryption bits + strength=$(sed -e 's/ChaCha20-Poly1305/ly1305/g' <<< "$strength") # workaround for empty bits ChaCha20-Poly1305 + enc=$(sed -e 's/(.*)//g' -e 's/ChaCha20-Poly1305/ChaCha20-Po/g' <<< "$enc") # workaround for empty bits ChaCha20-Poly1305 echo "$export" | grep -iq export && strength="$strength,export" # workaround for color escape codes: if printf -- "$kx" | "${HEXDUMPVIEW[@]}" | grep -q 33 ; then # here's a color code @@ -1134,11 +1152,11 @@ neat_list(){ [[ "${#kx}" -eq 19 ]] && kx="$kx " # 19 means DH, colored >=1000. Add another space #echo ${#kx} # should be always 20 fi - if [[ -r "$MAP_RFC_FNAME" ]]; then - printf -- " %-7s %-30s %-10s %-11s%-11s${MAP_RFC_FNAME:+ %-48s}${SHOW_EACH_C:+ }" "$1" "$2" "$kx" "$enc" "$strength" "$(show_rfc_style $HEXC)" - else - printf -- " %-7s %-30s %-10s %-11s%-11s${SHOW_EACH_C:+ }" "$1" "$2" "$kx" "$enc" "$strength" - fi + #if [[ -r "$MAPPING_FILE_RFC" ]]; then + printf -- " %-7s %-30s %-10s %-11s%-11s${MAPPING_FILE_RFC:+ %-48s}${SHOW_EACH_C:+ }" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$(show_rfc_style $HEXC)" + #else + # printf -- " %-7s %-30s %-10s %-11s%-11s${SHOW_EACH_C:+ }" "$1" "$2" "$kx" "$enc" "$strength" + #fi } test_just_one(){ @@ -1157,7 +1175,7 @@ test_just_one(){ neat_header for arg in $(echo $@ | sed 's/,/ /g'); do # 1st check whether openssl has cipher or not - $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode dash ciph sslvers kx auth enc mac export ; do + $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do # FIXME: e.g. OpenSSL < 1.0 doesn't understand "-V" --> we can't do anything about it! normalize_ciphercode $hexcode # is argument a number? @@ -1202,13 +1220,13 @@ run_allciphers(){ local hexcode n ciph sslvers kx auth enc mac export local dhlen - nr_ciphers=$($OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' | sed 's/:/ /g' | wc -w) + nr_ciphers=$(count_ciphers "$($OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE)") pr_blue "--> Testing all locally available $nr_ciphers ciphers against the server"; outln ", ordered by encryption strength" ! $HAS_DH_BITS && pr_litemagentaln " (Your $OPENSSL cannot show DH/ECDH bits)" outln neat_header - $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' | while read hexcode n ciph sslvers kx auth enc mac export; do + $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>>$ERRFILE | while read hexcode n ciph sslvers kx auth enc mac export; do # FIXME: e.g. OpenSSL < 1.0 doesn't understand "-V" --> we can't do anything about it! $OPENSSL s_client -cipher $ciph $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE $ERRFILE | while read hexcode n ciph sslvers kx auth enc mac export; do # -V doesn't work with openssl < 1.0 $OPENSSL s_client -cipher $ciph $proto $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE &1 | grep -aq "unknown option" if [[ $? -eq 0 ]]; then - pr_magentaln "Local problem: $OPENSSL doesn't support \"s_client $1\"" + local_problem "$OPENSSL doesn't support \"s_client $1\"" ret=7 - else - ret=0 fi return $ret } @@ -1292,7 +1308,7 @@ locally_supported() { run_prototest_openssl() { local sni="$SNI" - local ret + local -i ret=0 $OPENSSL s_client -state $1 $STARTTLS -connect $NODEIP:$PORT $PROXY $sni &>$TMPFILE Testing server preferences"; outln "\n" pr_bold " Has server cipher order? " - $OPENSSL s_client $STARTTLS -cipher $list_fwd -connect $NODEIP:$PORT $PROXY $SNI /dev/null >$TMPFILE + $OPENSSL s_client $STARTTLS -cipher $list_fwd -connect $NODEIP:$PORT $PROXY $SNI $ERRFILE >$TMPFILE if [ $? -ne 0 ]; then pr_magenta "no matching cipher in this list found (pls report this): " outln "$list_fwd . " ret=6 else cipher1=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g') - $OPENSSL s_client $STARTTLS -cipher $list_reverse -connect $NODEIP:$PORT $PROXY $SNI /dev/null >$TMPFILE + $OPENSSL s_client $STARTTLS -cipher $list_reverse -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE cipher2=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/^ \+Cipher \+://' -e 's/ //g') if [[ "$cipher1" != "$cipher2" ]]; then @@ -1522,7 +1544,7 @@ run_server_preference() { [[ $DEBUG -ge 2 ]] && out " $cipher1 | $cipher2" outln - $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI /dev/null >$TMPFILE + $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE pr_bold " Negotiated protocol " default_proto=$(grep -aw "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g') case "$default_proto" in @@ -1556,7 +1578,7 @@ run_server_preference() { for p in ssl2 ssl3 tls1 tls1_1 tls1_2; do #locally_supported -"$p" " " || continue locally_supported -"$p" || continue - $OPENSSL s_client $STARTTLS -"$p" -connect $NODEIP:$PORT $PROXY $SNI /dev/null >$TMPFILE + $OPENSSL s_client $STARTTLS -"$p" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE if [[ $? -eq 0 ]]; then proto[i]=$(grep -aw "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g') cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') @@ -1572,7 +1594,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 -host $NODE -port $PORT -nextprotoneg "$NPN_PROTOs" /dev/null >$TMPFILE + $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg "$NPN_PROTOs" >$ERRFILE >$TMPFILE if [[ $? -eq 0 ]]; then proto[i]=$(grep -aw "Next protocol" $TMPFILE | sed -e 's/^Next protocol://' -e 's/(.)//' -e 's/ //g') if [[ -z "${proto[i]}" ]]; then @@ -1621,7 +1643,7 @@ cipher_pref_check() { pr_bold " Cipher order" for p in ssl2 ssl3 tls1 tls1_1 tls1_2; do - $OPENSSL s_client $STARTTLS -"$p" -connect $NODEIP:$PORT $PROXY $SNI /dev/null >$TMPFILE + $OPENSSL s_client $STARTTLS -"$p" -connect $NODEIP:$PORT $PROXY $SNI $ERRFILE >$TMPFILE if [[ $? -eq 0 ]]; then tested_cipher="" proto=$(grep -aw "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g') @@ -1631,7 +1653,7 @@ cipher_pref_check() { printf " %-10s %s " "$proto:" "$cipher" tested_cipher="-"$cipher while true; do - $OPENSSL s_client $STARTTLS -"$p" -cipher "ALL:$tested_cipher" -connect $NODEIP:$PORT $PROXY $SNI /dev/null >$TMPFILE + $OPENSSL s_client $STARTTLS -"$p" -cipher "ALL:$tested_cipher" -connect $NODEIP:$PORT $PROXY $SNI >$ERRFILE >$TMPFILE [[ $? -ne 0 ]] && break cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') out "$cipher " @@ -1644,14 +1666,14 @@ cipher_pref_check() { if ! spdy_pre " SPDY/NPN: " ; then # is NPN/SPDY supported and is this no STARTTLS? outln else - protos=$($OPENSSL s_client -host $NODE -port $PORT -nextprotoneg \"\" /dev/null | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g') + protos=$($OPENSSL s_client -host $NODE -port $PORT -nextprotoneg \"\" >$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g') for p in $protos; do - $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg "$p" $PROXY /dev/null >$TMPFILE + $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg "$p" $PROXY >$$ERRFILE >$TMPFILE cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') printf " %-10s %s " "$p:" "$cipher" tested_cipher="-"$cipher while true; do - $OPENSSL s_client -cipher "ALL:$tested_cipher" -host $NODE -port $PORT -nextprotoneg "$p" $PROXY /dev/null >$TMPFILE + $OPENSSL s_client -cipher "ALL:$tested_cipher" -host $NODE -port $PORT -nextprotoneg "$p" $PROXY >$ERRFILE >$TMPFILE [[ $? -ne 0 ]] && break cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') out "$cipher " @@ -1670,15 +1692,15 @@ get_host_cert() { # arg1 is proto or empty $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI $1 2>/dev/null $HOSTCERT - return $? + return $((${PIPESTATUS[0]} + ${PIPESTATUS[1]})) } get_all_certs() { local savedir local nrsaved - local ret + local -i ret - $OPENSSL s_client -showcerts $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI 2>/dev/null $TEMPDIR/allcerts.txt + $OPENSSL s_client -showcerts $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI 2>$ERRFILE $TEMPDIR/allcerts.txt ret=$? savedir=$(pwd); cd $TEMPDIR # http://backreference.org/2010/05/09/ocsp-verification-with-openssl/ @@ -1732,7 +1754,7 @@ run_server_defaults() { #TLS extensions follow now # throwing 1st every cipher/protocol at the server to know what works for proto in tls1_2 tls1_1 tls1 ssl3; do - $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug -status /dev/null >$TMPFILE + $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug -status $ERRFILE >$TMPFILE ret=$? get_host_cert "-$proto" [ $? -eq 0 ] && [ $ret -eq 0 ] && break @@ -1740,7 +1762,7 @@ run_server_defaults() { done # this loop is needed for IIS/6 if [ $ret -eq 7 ]; then # "-status" kills GOST only servers, so we do another test without it and see whether that works then: - if ! $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug /dev/null >$TMPFILE; then + if ! $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug >$ERRFILE >$TMPFILE; then pr_magentaln "$OPENSSL returned an error around line $LINENO". tmpfile_handle tlsextdebug+status.txt return 7 # this is ugly, I know @@ -1748,7 +1770,7 @@ run_server_defaults() { gost_status_problem=true fi fi - $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY -$proto 2>/dev/null $HOSTCERT.nosni + $OPENSSL s_client $STARTTLS -connect $NODEIP:$PORT $PROXY -$proto 2>>$ERRFILE $HOSTCERT.nosni pr_bold " TLS server extensions " extensions=$(grep -aw "^TLS server extension" $TMPFILE | sed -e 's/^TLS server extension \"//' -e 's/\".*$/,/g') if [ -z "$extensions" ]; then @@ -1769,8 +1791,8 @@ run_server_defaults() { pr_bold " Server key size " keysize=$(grep -aw "^Server public key is" $TMPFILE | sed -e 's/^Server public key is //' -e 's/bit//' -e 's/ //') - sig_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text | grep "Signature Algorithm" | sed 's/^.*Signature Algorithm: //' | sort -u ) - key_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text | awk -F':' '/Public Key Algorithm:/ { print $2 }' | sort -u ) + sig_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep "Signature Algorithm" | sed 's/^.*Signature Algorithm: //' | sort -u ) + key_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | awk -F':' '/Public Key Algorithm:/ { print $2 }' | sort -u ) if [ -z "$keysize" ]; then outln "(couldn't determine)" @@ -1805,12 +1827,12 @@ run_server_defaults() { # old, but interesting: https://blog.hboeck.de/archives/754-Playing-with-the-EFF-SSL-Observatory.html pr_bold " Fingerprint / Serial " - outln "$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha1 | sed 's/Fingerprint=//' | sed 's/://g' ) / $($OPENSSL x509 -noout -in $HOSTCERT -serial | sed 's/serial=//')" - outln "$spaces$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 | sed 's/Fingerprint=//' | sed 's/://g' )" + outln "$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha1 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g' ) / $($OPENSSL x509 -noout -in $HOSTCERT -serial 2>>$ERRFILE | sed 's/serial=//')" + outln "$spaces$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g' )" pr_bold " Common Name (CN) " - if $OPENSSL x509 -in $HOSTCERT -noout -subject | grep -wq CN; then - cn=$($OPENSSL x509 -in $HOSTCERT -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//') + if $OPENSSL x509 -in $HOSTCERT -noout -subject 2>>$ERRFILE | grep -wq CN; then + cn=$($OPENSSL x509 -in $HOSTCERT -noout -subject 2>>$ERRFILE | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//') pr_underline "$cn" else cn="(no CN field in subject)" @@ -1819,8 +1841,8 @@ run_server_defaults() { cn_nosni="" if [[ -s $HOSTCERT.nosni ]] ; then - if $OPENSSL x509 -in $HOSTCERT.nosni -noout -subject | grep -wq CN; then - cn_nosni=$($OPENSSL x509 -in $HOSTCERT.nosni -noout -subject | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//') + if $OPENSSL x509 -in $HOSTCERT.nosni -noout -subject 2>>$ERRFILE | grep -wq CN; then + cn_nosni=$($OPENSSL x509 -in $HOSTCERT.nosni -noout -subject 2>>$ERRFILE | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//') else cn_nosni="no CN field in subject" fi @@ -1846,7 +1868,7 @@ run_server_defaults() { fi fi - sans=$($OPENSSL x509 -in $HOSTCERT -noout -text | grep -A3 "Subject Alternative Name" | grep "DNS:" | \ + sans=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A3 "Subject Alternative Name" | grep "DNS:" | \ sed -e 's/DNS://g' -e 's/ //g' -e 's/,/ /g' -e 's/othername://g') # ^^^ CACert @@ -1860,10 +1882,10 @@ run_server_defaults() { fi outln pr_bold " Issuer " - issuer=$($OPENSSL x509 -in $HOSTCERT -noout -issuer | sed -e 's/^.*CN=//g' -e 's/\/.*$//g') - issuer_o=$($OPENSSL x509 -in $HOSTCERT -noout -issuer | sed 's/^.*O=//g' | sed 's/\/.*$//g') - if $OPENSSL x509 -in $HOSTCERT -noout -issuer | grep -q 'C=' ; then - issuer_c=$($OPENSSL x509 -in $HOSTCERT -noout -issuer | sed 's/^.*C=//g' | sed 's/\/.*$//g') + issuer=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE| sed -e 's/^.*CN=//g' -e 's/\/.*$//g') + issuer_o=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | sed 's/^.*O=//g' | sed 's/\/.*$//g') + if $OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | grep -q 'C=' ; then + issuer_c=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | sed 's/^.*C=//g' | sed 's/\/.*$//g') else issuer_c="" # CACert would have 'issuer= ' here otherwise fi @@ -1877,7 +1899,7 @@ run_server_defaults() { # http://events.ccc.de/congress/2010/Fahrplan/attachments/1777_is-the-SSLiverse-a-safe-place.pdf, see page 40pp pr_bold " EV cert"; out " (experimental) " - policy_oid=$($OPENSSL x509 -in $HOSTCERT -text | awk '/ .Policy: / { print $2 }') + policy_oid=$($OPENSSL x509 -in $HOSTCERT -text 2>>$ERRFILE | awk '/ .Policy: / { print $2 }') if echo $issuer | egrep -q 'Extended Validation|Extended Validated|EV SSL|EV CA' || \ [[ "2.16.840.1.114028.10.1.2" == "$policy_oid" ]] || \ [[ "1.3.6.1.4.1.17326.10.14.2.1.2" == "$policy_oid" ]] || \ @@ -1896,15 +1918,15 @@ run_server_defaults() { # https://certs.opera.com/03/ev-oids.xml pr_bold " Certificate Expiration " - expire=$($OPENSSL x509 -in $HOSTCERT -checkend 0) + expire=$($OPENSSL x509 -in $HOSTCERT -checkend 0 2>>$ERRFILE) if ! echo $expire | grep -qw not; then pr_red "expired!" else secs2warn=$((24 * 60 * 60 * $DAYS2WARN2)) # low threshold first - expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn) + expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn 2>>$ERRFILE) if echo "$expire" | grep -qw not; then secs2warn=$((24 * 60 * 60 * $DAYS2WARN1)) - expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn) + expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn 2>>$ERRFILE) if echo "$expire" | grep -qw not; then pr_litegreen ">= $DAYS2WARN1 days" else @@ -1916,11 +1938,11 @@ run_server_defaults() { fi if $HAS_GNUDATE ; then - enddate=$(date --date="$($OPENSSL x509 -in $HOSTCERT -noout -enddate | cut -d= -f 2)" +"%F %H:%M %z") - startdate=$(date --date="$($OPENSSL x509 -in $HOSTCERT -noout -startdate | cut -d= -f 2)" +"%F %H:%M") + enddate=$(date --date="$($OPENSSL x509 -in $HOSTCERT -noout -enddate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M %z") + startdate=$(date --date="$($OPENSSL x509 -in $HOSTCERT -noout -startdate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M") else - enddate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -enddate | cut -d= -f 2)" +"%F %H:%M %z") - startdate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -startdate | cut -d= -f 2)" +"%F %H:%M") + enddate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -enddate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M %z") + startdate=$(date -j -f "%b %d %T %Y %Z" "$($OPENSSL x509 -in $HOSTCERT -noout -startdate 2>>$ERRFILE | cut -d= -f 2)" +"%F %H:%M") fi outln " ($startdate --> $enddate)" @@ -1929,7 +1951,7 @@ run_server_defaults() { pr_bold " # of certificates provided"; outln " $(get_all_certs)" pr_bold " Certificate Revocation List " - crl="$($OPENSSL x509 -in $HOSTCERT -noout -text | grep -A 4 "CRL Distribution" | grep URI | sed 's/^.*URI://')" + crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 4 "CRL Distribution" | grep URI | sed 's/^.*URI://')" case $(count_lines "$crl") in 0) pr_literedln "--" ;; 1) outln "$crl" ;; @@ -1937,7 +1959,7 @@ run_server_defaults() { esac pr_bold " OCSP URI " - ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri) + ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE) [ x"$ocsp_uri" == "x" ] && pr_literedln "--" || echo "$ocsp_uri" pr_bold " OCSP stapling " @@ -1963,7 +1985,7 @@ run_server_defaults() { # already -- and that was a different one -- means that would get overwritten anyway tmpfile_handle tlsextdebug+status.txt - tls_time + tls_time return $ret } @@ -1994,7 +2016,7 @@ run_pfs() { no_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $pfs_cipher_list)) if [ "$no_supported_ciphers" -le "$CLIENT_MIN_PFS" ] ; then outln - pr_magentaln " Local problem: you only have $number_pfs PFS ciphers on the client side " + local_problem "You only have $number_pfs PFS ciphers on the client side " return 1 fi @@ -2005,12 +2027,12 @@ run_pfs() { pr_brownln "Not OK: No ciphers supporting Forward Secrecy offered" else pfs_offered=0 + pr_litegreen " PFS is offered (OK)" if $WIDE; then - pr_litegreen " PFS ciphers (OK): " - outln ", cipher follow (client/browser support is here specially important) \n" + outln ", ciphers follow (client/browser support is here specially important) \n" neat_header else - pr_litegreen " PFS is offered (OK) " + out " " fi while read hexcode dash pfs_cipher sslvers kx auth enc mac; do tmpfile=$TMPFILE.$hexcode @@ -2038,7 +2060,7 @@ run_pfs() { else out "$pfs_cipher " fi - done < <($OPENSSL ciphers -V "$pfs_cipher_list") # -V doesn't work with openssl < 1.0 + done < <($OPENSSL ciphers -V "$pfs_cipher_list" 2>$ERRFILE) # -V doesn't work with openssl < 1.0 # ^^^^^ posix redirect as shopt will either segfault or doesn't work with old bash versions debugme echo $pfs_offered @@ -2075,19 +2097,22 @@ spdy_pre(){ # first, does the current openssl support it? $OPENSSL s_client help 2>&1 | grep -qw nextprotoneg if [ $? -ne 0 ]; then - pr_magentaln "Local problem: $OPENSSL doesn't support SPDY/NPN"; + local_problem "$OPENSSL doesn't support SPDY/NPN"; return 7 fi return 0 } run_spdy() { + local tmpstr + local -i ret=0 + pr_bold " SPDY/NPN " if ! spdy_pre ; then echo return 0 fi - $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs /dev/null >$TMPFILE + $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs $ERRFILE >$TMPFILE tmpstr=$(grep -a '^Protocols' $TMPFILE | sed 's/Protocols.*: //') if [ -z "$tmpstr" -o "$tmpstr" == " " ] ; then out "not offered" @@ -2657,7 +2682,7 @@ tls_sockets() { save=$? # see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL - lines=$(hexdump -C "$SOCK_REPLY_FILE" 2>/dev/null | wc -l | sed 's/ //g') + lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)") [[ "$DEBUG" -ge 2 ]] && out " (returned $lines lines) " # determine the return value for higher level, so that they can tell what the result is @@ -2922,6 +2947,10 @@ run_ccs_injection(){ return $ret } +local_problem() { + pr_litemagentaln "Local problem: $1" +} + run_renego() { # no SNI here. Not needed as there won't be two different SSL stacks for one IP local legacycmd="" @@ -2951,7 +2980,7 @@ run_renego() { case "$OSSL_VER" in 0.9.8*) # we need this for Mac OSX unfortunately case "$OSSL_VER_APPENDIX" in - [a-l]) pr_magentaln "Local Problem: $OPENSSL cannot test this secure renegotiation vulnerability" + [a-l]) local_problem "$OPENSSL cannot test this secure renegotiation vulnerability" return 3 ;; [m-z]) ;; # all ok esac ;; @@ -2998,7 +3027,7 @@ run_crime() { # first we need to test whether OpenSSL binary has zlib support $OPENSSL zlib -e -a -in /dev/stdin &>/dev/stdout /dev/null || echo "" -} - # Padding Oracle On Downgraded Legacy Encryption, in a nutshell: don't use CBC Ciphers in SSLv3 run_ssl_poodle() { local -i ret=0 @@ -3135,7 +3155,7 @@ run_ssl_poodle() { [ $VULN_COUNT -le $VULN_THRESHLD ] && outln && pr_blue "--> Testing for SSLv3 POODLE (Padding Oracle On Downgraded Legacy Encryption)" && outln "\n" pr_bold " POODLE, SSL"; out " (CVE-2014-3566) " - cbc_ciphers=$($OPENSSL ciphers -v 'ALL:eNULL' | awk '/CBC/ { print $1 }' | tr '\n' ':') + cbc_ciphers=$($OPENSSL ciphers -v 'ALL:eNULL' 2>$ERRFILE | awk '/CBC/ { print $1 }' | tr '\n' ':') #FIXME: even with worst openssl client (FreeBSD9) we have 17 reasonable ciphers but is that enough to check?? debugme echo $cbc_ciphers $OPENSSL s_client -ssl3 $STARTTLS -cipher $cbc_ciphers -connect $NODEIP:$PORT $PROXY $SNI &>$TMPFILE &1 | grep -q "\-fallback_scsv" if [ $? -gt 0 ]; then - pr_magentaln "Local Problem: Your $OPENSSL lacks TLS_FALLBACK_SCSV support" + local_problem "$OPENSSL lacks TLS_FALLBACK_SCSV support" return 4 fi @@ -3220,7 +3240,7 @@ run_freak() { #echo "========= ${PIPESTATUS[*]} case $no_supported_ciphers in - 0) pr_magentaln "Local problem: your $OPENSSL doesn't have any EXPORT RSA ciphers configured" + 0) local_problem "$OPENSSL doesn't have any EXPORT RSA ciphers configured" return 7 ;; 1|2|3) addtl_warning=" ($magenta""tested only with $no_supported_ciphers out of 9 ciphers only!$off)" ;; @@ -3260,7 +3280,7 @@ run_logjam() { no_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $exportdhe_cipher_list)) case $no_supported_ciphers in - 0) pr_magentaln "Local problem: your $OPENSSL doesn't have any DHE EXPORT ciphers configured" + 0) local_problem "$OPENSSL doesn't have any DHE EXPORT ciphers configured" return 3 ;; 1|2) addtl_warning=" ($magenta""tested w/ $no_supported_ciphers/4 ciphers only!$off)" ;; 3) addtl_warning=" (tested w/ $no_supported_ciphers/4 ciphers)" ;; @@ -3309,9 +3329,10 @@ run_beast(){ pr_bold " BEAST"; out " (CVE-2011-3389) " $WIDE && outln + >$ERRFILE # 2) test handfull of common CBC ciphers for proto in ssl3 tls1; do - $OPENSSL s_client -"$proto" $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI >$TMPFILE 2>/dev/null $TMPFILE 2>>$ERRFILE $TMPFILE 2>/dev/null $TMPFILE 2>>$ERRFILE >$ERRFILE | grep -a CBC) # -V doesn't work with openssl < 1.0 # ^^^^^ process substitution as shopt will either segfault or doesn't work with old bash versions if ! $WIDE; then @@ -3371,7 +3392,7 @@ run_beast(){ # 2) support for TLS 1.1+1.2? for proto in tls1_1 tls1_2; do - $OPENSSL s_client -state -"$proto" $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI 2>/dev/null >$TMPFILE >$ERRFILE >$TMPFILE $TMPFILE # -V doesn't work with openssl < 1.0, feeding this into the while loop below + $OPENSSL ciphers -V 'RC4:@STRENGTH' >$TMPFILE 2>$ERRFILE # -V doesn't work with openssl < 1.0, feeding this into the while loop below $OPENSSL s_client -cipher $rc4_ciphers_list $STARTTLS -connect $NODEIP:$PORT $PROXY $SNI &>/dev/null =39 won't connect to them unless it's in this white list: http://mxr.mozilla.org/mozilla-central/source/security/manager/ssl/IntolerantFallbackList.inc @@ -3487,27 +3508,27 @@ get_install_dir() { #INSTALL_DIR=$(cd "$(dirname "$0")" && pwd)/$(basename "$0") INSTALL_DIR=$(dirname ${BASH_SOURCE[0]}) - [ -r "$RUN_DIR/mapping-rfc.txt" ] && MAP_RFC_FNAME="$RUN_DIR/mapping-rfc.txt" - [ -r "$INSTALL_DIR/mapping-rfc.txt" ] && MAP_RFC_FNAME="$INSTALL_DIR/mapping-rfc.txt" + [ -r "$RUN_DIR/mapping-rfc.txt" ] && MAPPING_FILE_RFC="$RUN_DIR/mapping-rfc.txt" + [ -r "$INSTALL_DIR/mapping-rfc.txt" ] && MAPPING_FILE_RFC="$INSTALL_DIR/mapping-rfc.txt" # we haven't found the mapping file yet... - if [ ! -r "$MAP_RFC_FNAME" ] && which readlink &>/dev/null ; then + if [ ! -r "$MAPPING_FILE_RFC" ] && which readlink &>/dev/null ; then readlink -f ls &>/dev/null && \ INSTALL_DIR=$(readlink -f $(basename ${BASH_SOURCE[0]})) || \ INSTALL_DIR=$(readlink $(basename ${BASH_SOURCE[0]})) # not sure whether Darwin has -f INSTALL_DIR=$(dirname $INSTALL_DIR 2>/dev/null) - [ -r "$INSTALL_DIR/mapping-rfc.txt" ] && MAP_RFC_FNAME="$INSTALL_DIR/mapping-rfc.txt" + [ -r "$INSTALL_DIR/mapping-rfc.txt" ] && MAPPING_FILE_RFC="$INSTALL_DIR/mapping-rfc.txt" fi # still no mapping file: - if [ ! -r "$MAP_RFC_FNAME" ] && which realpath &>/dev/null ; then + if [ ! -r "$MAPPING_FILE_RFC" ] && which realpath &>/dev/null ; then INSTALL_DIR=$(dirname $(realpath ${BASH_SOURCE[0]})) - MAP_RFC_FNAME="$INSTALL_DIR/mapping-rfc.txt" + MAPPING_FILE_RFC="$INSTALL_DIR/mapping-rfc.txt" fi - [ ! -r "$MAP_RFC_FNAME" ] && pr_litemagentaln "\nNo mapping file found" - debugme echo "$MAP_RFC_FNAME" + [ ! -r "$MAPPING_FILE_RFC" ] && unset MAPPING_FILE_RFC && pr_litemagentaln "\nNo mapping file found" + debugme echo "$MAPPING_FILE_RFC" } @@ -3555,13 +3576,14 @@ find_openssl_binary() { : # 5. we tried hard and failed, so now we use the system binaries fi + # no ERRFILE initialized yet $OPENSSL version -a 2>/dev/null >/dev/null if [ $? -ne 0 ] || [ ! -x "$OPENSSL" ]; then fatal "cannot exec or find any openssl binary" -1 fi # http://www.openssl.org/news/openssl-notes.html - OSSL_VER=$($OPENSSL version 2>/dev/null| awk -F' ' '{ print $2 }') + OSSL_VER=$($OPENSSL version 2>/dev/null | awk -F' ' '{ print $2 }') OSSL_VER_MAJOR=$(echo "$OSSL_VER" | sed 's/\..*$//') OSSL_VER_MINOR=$(echo "$OSSL_VER" | sed -e 's/^.\.//' | tr -d '[a-zA-Z]-') OSSL_VER_APPENDIX=$(echo "$OSSL_VER" | tr -d '[0-9.]') @@ -3700,7 +3722,7 @@ mybanner() { local cwd="" $QUIET && return - nr_ciphers=$(count_ciphers $($OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH')) + nr_ciphers=$(count_ciphers $($OPENSSL ciphers 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>/dev/null)) [ -z "$GIT_REL" ] && \ idtag="$CVS_REL" || \ idtag="$GIT_REL -- $CVS_REL_SHORT" @@ -3742,6 +3764,12 @@ EOF maketempf() { TEMPDIR=$(mktemp -d /tmp/ssltester.XXXXXX) || exit -6 TMPFILE=$TEMPDIR/tempfile.txt || exit -6 + if [[ "$DEBUG" -eq 0 ]]; then + ERRFILE="/dev/null" + else + ERRFILE=$TEMPDIR/errorfile.txt || exit -6 + >$ERRFILE + fi HOSTCERT=$TEMPDIR/host_certificate.txt HEADERFILE=$TEMPDIR/http_header.txt HEADERFILE_BREACH=$TEMPDIR/http_header_breach.txt @@ -3774,7 +3802,7 @@ PATH: $PATH PROG_NAME: $PROG_NAME INSTALL_DIR: $INSTALL_DIR RUN_DIR: $RUN_DIR -MAP_RFC_FNAME: $MAP_RFC_FNAME +MAPPING_FILE_RFC: $MAPPING_FILE_RFC CAPATH: $CAPATH @@ -3825,11 +3853,17 @@ cleanup () { outln } +fatal() { + pr_magentaln "Fatal error: $1" + exit $2 +} + + # for now only GOST engine initialize_engine(){ grep -q '^# testssl config file' "$OPENSSL_CONF" 2>/dev/null && return 0 # have been here already - if ! $OPENSSL engine gost -vvvv -t -c >/dev/null 2>&1; then + if ! $OPENSSL engine gost -vvvv -t -c 2>/dev/null >/dev/null; then outln pr_litemagenta "No engine or GOST support via engine with your $OPENSSL"; outln return 1 @@ -3837,7 +3871,7 @@ initialize_engine(){ outln pr_litemagenta "No engine or GOST support via engine with your $OPENSSL"; outln return 1 - else # we have engine support + else # we have engine support if [[ -n "$OPENSSL_CONF" ]]; then pr_litemagentaln "For now I am providing the config file in to have GOST support" else @@ -3863,12 +3897,13 @@ EOF export OPENSSL_CONF fi fi - return 0 } ignore_no_or_lame() { + local a + [[ "$WARNINGS" == "off" ]] && return 0 [[ "$WARNINGS" == "false" ]] && return 0 [[ "$WARNINGS" == "batch" ]] && return 1 @@ -3884,8 +3919,9 @@ ignore_no_or_lame() { # arg1: URI # arg2: protocol parse_hn_port() { - NODE="$1" + local tmp_port + NODE="$1" # strip "https" and trailing urlpath supposed it was supplied additionally echo "$NODE" | grep -q 'https://' && NODE=$(echo "$NODE" | sed -e 's/^https\:\/\///') @@ -3913,10 +3949,10 @@ parse_hn_port() { URL_PATH=$(echo $URL_PATH | sed 's/\/\//\//g') # we rather want // -> / [[ -z "$URL_PATH" ]] && URL_PATH="/" debugme echo $URL_PATH - return 0 # NODE, URL_PATH, PORT is set now } + is_ipv4addr() { local octet="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])" local ipv4address="$octet\\.$octet\\.$octet\\.$octet" @@ -3936,8 +3972,8 @@ is_ipv6addr() { # less than 2x ":" [[ $(count_lines "$(echo -n "$1" | tr ':' '\n')") -le 1 ]] && \ return 1 - #check on char we allow: - [[ -n "$(echo -n | tr -d '0-9:a-fA-F ' | sed -e '/^$/d')" ]] && \ + #check on chars allowed: + [[ -n "$(tr -d '0-9:a-fA-F ' <<< "$1" | sed -e '/^$/d')" ]] && \ return 1 return 0 } @@ -4087,7 +4123,7 @@ determine_rdns() { elif which host &> /dev/null; then rDNS=$(host -t PTR $NODEIP 2>/dev/null | awk '/pointer/ { print $NF }') elif which nslookup &> /dev/null; then - rDNS=$(nslookup -type=PTR $NODEIP 2> /dev/null | grep -v 'canonical name =' | grep 'name = ' | awk '{ print $NF }' | sed 's/\.$//') + rDNS=$(nslookup -type=PTR $NODEIP 2>/dev/null | grep -v 'canonical name =' | grep 'name = ' | awk '{ print $NF }' | sed 's/\.$//') fi OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 rDNS=$(echo $rDNS) @@ -4101,25 +4137,18 @@ get_mx_record() { OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 if which host &> /dev/null; then - mxs=$(host -t MX "$1" 2>/dev/null| grep 'handled by' | sed -e 's/^.*by //g' -e 's/\.$//') + mxs=$(host -t MX "$1" 2>/dev/null | grep 'handled by' | sed -e 's/^.*by //g' -e 's/\.$//') elif which dig &> /dev/null; then mxs=$(dig +short -t MX "$1" 2>/dev/null) elif which nslookup &> /dev/null; then mxs=$(nslookup -type=MX "$1" 2>/dev/null | grep 'mail exchanger = ' | sed 's/^.*mail exchanger = //g') else - pr_magentaln 'No dig, host or nslookup' - exit -3 + fatal "No dig, host or nslookup" -3 fi OPENSSL_CONF="$saved_openssl_conf" echo "$mxs" } -fatal() { - pr_magentaln "Fatal error: $1" - exit $2 -} - - # We need to get the IP address of the proxy so we can use it in fd_socket check_proxy(){ local save_LOCAL_A=$LOCAL_A @@ -4196,7 +4225,7 @@ determine_service() { # see http://xmpp.org/rfcs/rfc3920.html fi fi - $OPENSSL s_client -connect $NODEIP:$PORT $PROXY $STARTTLS 2>/dev/null >$TMPFILE $ERRFILE >$TMPFILE $NODEIP:$PORT ($NODE) <---"; outln "\n" if [[ "$1" == "Testing" ]]; then @@ -4764,4 +4794,4 @@ fi exit $ret -# $Id: testssl.sh,v 1.357 2015/08/24 12:09:44 dirkw Exp $ +# $Id: testssl.sh,v 1.358 2015/08/24 21:50:01 dirkw Exp $