From dc9e3bfb585ba374e7947e4f06ef96af07c272c5 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 7 Feb 2017 14:25:41 -0500 Subject: [PATCH 01/21] Add option to create HTML This PR adds the option to generate HTML. The code was created as follows: * For each output function (`out()`, `outln()`, `pr_liteblue()`, etc.) I created two functions: one that just outputs to the terminal and one that outputs to the terminal and to the HTML file (if an HTML file is to be created). * I modified the code so that any output that should appear in the HTML file in addition to being displayed on the terminal is sent through one of the display functions: out()`, `outln()`, `pr_liteblue()`, etc. * I created a new function `retstring()` to use in place of `out()` when a function is creating a string to be "captured" by the calling function. * I modified the code so that no string returned by a function includes color-coding escape characters. --- testssl.sh | 670 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 407 insertions(+), 263 deletions(-) diff --git a/testssl.sh b/testssl.sh index 6d2462b..75987e0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -156,6 +156,7 @@ WIDE=${WIDE:-false} # whether to display for some options ju LOGFILE=${LOGFILE:-""} # logfile if used JSONFILE=${JSONFILE:-""} # jsonfile if used CSVFILE=${CSVFILE:-""} # csvfile if used +HTMLFILE=${CSVFILE:-""} # HTML if used APPEND=${APPEND:-false} # append to csv/json file instead of overwriting it GIVE_HINTS=false # give an addtional info to findings HAS_IPv6=${HAS_IPv6:-false} # if you have OpenSSL with IPv6 support AND IPv6 networking set it to yes @@ -558,81 +559,146 @@ declare TLS_CIPHER_OSSL_SUPPORTED=() ###### output functions ###### # a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%' and '--' does the rest. -out(){ +out_html() { + "$do_html" && printf -- "%b" "${1//%/%%}" >> "$HTMLFILE" +} + +out() { +# if [[ "$BASH_VERSINFO" -eq 4 ]]; then + printf -- "%b" "${1//%/%%}" + out_html "$1" +# else +# /usr/bin/printf -- "${1//%/%%}" +# fi +} +outln() { out "$1\n"; } + +out_term(){ # if [[ "$BASH_VERSINFO" -eq 4 ]]; then printf -- "%b" "${1//%/%%}" # else # /usr/bin/printf -- "${1//%/%%}" # fi } -outln() { out "$1\n"; } +outln_term() { out_term "$1\n"; } + +retstring(){ + printf -- "%b" "${1//%/%%}" +} #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 ]] && ( "$COLORBLIND" && out "\033[0;32m$1" || out "\033[0;34m$1" ) || out "$1"; pr_off; } # not yet used +pr_liteblue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;32m$1" || out_term "\033[0;34m$1" ) || out_term "$1"; pr_off; } # not yet used +pr_liteblue() { pr_liteblue_term "$1"; out_html "$1"; } +pr_liteblueln_term() { pr_liteblue_term "$1"; outln_term; } pr_liteblueln() { pr_liteblue "$1"; outln; } -pr_blue() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out "\033[1;32m$1" || out "\033[1;34m$1" ) || out "$1"; pr_off; } # used for head lines of single tests +pr_blue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;32m$1" || out_term "\033[1;34m$1" ) || out_term "$1"; pr_off; } # used for head lines of single tests +pr_blue() { pr_blue_term "$1"; out_html "$1"; } +pr_blueln_term() { pr_blue_term "$1"; outln_term; } pr_blueln() { pr_blue "$1"; outln; } -pr_warning() { [[ "$COLOR" -eq 2 ]] && out "\033[0;35m$1" || pr_underline "$1"; pr_off; } # some local problem: one test cannot be done -pr_warningln() { pr_warning "$1"; outln; } # litemagenta -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_warning_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;35m$1" || pr_underline_term "$1"; pr_off; } # some local problem: one test cannot be done +pr_warning() { pr_warning_term "$1"; out_html "$1"; } +pr_warningln_term() { pr_warning_term "$1"; outln_term; } # litemagenta +pr_warningln() { pr_warning "$1"; outln; } +pr_magenta_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;35m$1" || pr_underline_term "$1"; pr_off; } # fatal error: quitting because of this! +pr_magenta() { pr_magenta_term "$1"; out_html "$1"; } +pr_magentaln_term() { pr_magenta_term "$1"; outln_term; } +pr_magentaln() { pr_magenta "$1"; outln; } -pr_litecyan() { [[ "$COLOR" -eq 2 ]] && out "\033[0;36m$1" || out "$1"; pr_off; } # not yet used +pr_litecyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;36m$1" || out_term "$1"; pr_off; } # not yet used +pr_litecyan() { pr_litecyan_term "$1"; out_html "$1"; } +pr_litecyanln_term() { pr_litecyan_term "$1"; outln_term; } pr_litecyanln() { pr_litecyan "$1"; outln; } -pr_cyan() { [[ "$COLOR" -eq 2 ]] && out "\033[1;36m$1" || out "$1"; pr_off; } # additional hint +pr_cyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;36m$1" || out_term "$1"; pr_off; } # additional hint +pr_cyan() { pr_cyan_term "$1"; out_html "$1"; } +pr_cyanln_term() { pr_cyan_term "$1"; outln_term; } pr_cyanln() { pr_cyan "$1"; outln; } -pr_litegreyln() { pr_litegrey "$1"; outln; } # not really usable on a black background, see .. -pr_litegrey() { [[ "$COLOR" -eq 2 ]] && out "\033[0;37m$1" || out "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 -pr_grey() { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m$1" || out "$1"; pr_off; } +pr_litegreyln_term() { pr_litegrey_term "$1"; outln_term; } # not really usable on a black background, see .. +pr_litegreyln() { pr_litegrey "$1"; outln; } +pr_litegrey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 +pr_litegrey() { pr_litegrey_term "$1"; out_html "$1"; } +pr_grey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; } +pr_grey() { pr_grey_term "$1"; out_html "$1"; } +pr_greyln_term() { pr_grey_term "$1"; outln_term; } pr_greyln() { pr_grey "$1"; outln; } -pr_done_good() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out "\033[0;34m$1" || out "\033[0;32m$1" ) || out "$1"; pr_off; } # litegreen (liteblue), This is good -pr_done_goodln() { pr_done_good "$1"; outln; } -pr_done_best() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out "\033[1;34m$1" || out "\033[1;32m$1" ) || out "$1"; pr_off; } # green (blue), This is the best -pr_done_bestln() { pr_done_best "$1"; outln; } +pr_done_good_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;34m$1" || out_term "\033[0;32m$1" ) || out_term "$1"; pr_off; } # litegreen (liteblue), This is good +pr_done_good() { pr_done_good_term "$1"; out_html "$1"; } +pr_done_goodln_term() { pr_done_good_term "$1"; outln_term; } +pr_done_goodln() { pr_done_good "$1"; outln; } +pr_done_best_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;34m$1" || out_term "\033[1;32m$1" ) || out_term "$1"; pr_off; } # green (blue), This is the best +pr_done_best() { pr_done_best_term "$1"; out_html "$1"; } +pr_done_bestln_term() { pr_done_best_term "$1"; outln_term; } +pr_done_bestln() { pr_done_best "$1"; outln; } -pr_svrty_low() { [[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1" || out "$1"; pr_off; } # yellow brown | academic or minor problem +pr_svrty_low_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;33m$1" || out_term "$1"; pr_off; } # yellow brown | academic or minor problem +pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$1"; } +pr_svrty_lowln_term() { pr_svrty_low_term "$1"; outln_term; } pr_svrty_lowln() { pr_svrty_low "$1"; outln; } -pr_svrty_medium() { [[ "$COLOR" -eq 2 ]] && out "\033[0;33m$1" || out "$1"; pr_off; } # brown | it is not a bad problem but you shouldn't do this +pr_svrty_medium_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;33m$1" || out_term "$1"; pr_off; } # brown | it is not a bad problem but you shouldn't do this +pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$1"; } +pr_svrty_mediumln_term() { pr_svrty_medium_term "$1"; outln_term; } pr_svrty_mediumln() { pr_svrty_medium "$1"; outln; } -pr_svrty_high() { [[ "$COLOR" -eq 2 ]] && out "\033[0;31m$1" || pr_bold "$1"; pr_off; } # litered +pr_svrty_high_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;31m$1" || pr_bold_term "$1"; pr_off; } # litered +pr_svrty_high() { pr_svrty_high_term "$1"; out_html "$1"; } +pr_svrty_highln_term() { pr_svrty_high_term "$1"; outln_term; } pr_svrty_highln() { pr_svrty_high "$1"; outln; } -pr_svrty_critical() { [[ "$COLOR" -eq 2 ]] && out "\033[1;31m$1" || pr_bold "$1"; pr_off; } # red +pr_svrty_critical_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;31m$1" || pr_bold_term "$1"; pr_off; } # red +pr_svrty_critical() { pr_svrty_critical_term "$1"; out_html "$1"; } +pr_svrty_criticalln_term() { pr_svrty_critical_term "$1"; outln_term; } pr_svrty_criticalln(){ pr_svrty_critical "$1"; outln; } -pr_deemphasize() { out "$1"; } # hook for a weakened screen output, see #600 -pr_deemphasizeln() { outln "$1"; } +pr_deemphasize_term() { out_term "$1"; } # hook for a weakened screen output, see #600 +pr_deemphasize() { pr_deemphasize_term "$1"; out_html "$1"; } +pr_deemphasizeln_term() { pr_deemphasize_term "$1"; outln_term; } +pr_deemphasizeln() { pr_deemphasize "$1"; outln; } # color=1 functions -pr_off() { [[ "$COLOR" -ne 0 ]] && out "\033[m"; } -pr_bold() { [[ "$COLOR" -ne 0 ]] && out "\033[1m$1" || out "$1"; pr_off; } +pr_off() { [[ "$COLOR" -ne 0 ]] && out_term "\033[m"; } +pr_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m$1" || out_term "$1"; pr_off; } +pr_bold() { pr_bold_term "$1"; out_html "$1"; } +pr_boldln_term() { pr_bold_term "$1"; outln_term; } pr_boldln() { pr_bold "$1" ; outln; } -pr_italic() { [[ "$COLOR" -ne 0 ]] && out "\033[3m$1" || out "$1"; pr_off; } +pr_italic_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[3m$1" || out_term "$1"; pr_off; } +pr_italic() { pr_italic_term "$1"; out_html "$1"; } +pr_italicln_term() { pr_italic_term "$1"; outln_term; } pr_italicln() { pr_italic "$1" ; outln; } -pr_strikethru() { [[ "$COLOR" -ne 0 ]] && out "\033[9m$1" || out "$1"; pr_off; } # ugly! +pr_strikethru_term() { [[ "$COLOR" -ne 0 ]] && out "\033[9m$1" || out "$1"; pr_off; } # ugly! +pr_strikethru() { pr_strikethru_term "$1"; out_html "$1"; } +pr_strikethruln_term() { pr_strikethru_term "$1"; outln_term; } pr_strikethruln() { pr_strikethru "$1" ; outln; } -pr_underline() { [[ "$COLOR" -ne 0 ]] && out "\033[4m$1" || out "$1"; pr_off; } -pr_reverse() { [[ "$COLOR" -ne 0 ]] && out "\033[7m$1" || out "$1"; pr_off; } -pr_reverse_bold() { [[ "$COLOR" -ne 0 ]] && out "\033[7m\033[1m$1" || out "$1"; pr_off; } +pr_underline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[4m$1" || out_term "$1"; pr_off; } +pr_underline() { pr_underline_term "$1"; out_html "$1"; } +pr_reverse_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m$1" || out_term "$1"; pr_off; } +pr_reverse() { pr_reverse_term "$1"; out_html "$1"; } +pr_reverse_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m\033[1m$1" || out_term "$1"; pr_off; } +pr_reverse_bold() { pr_reverse_bold_term "$1"; out_html "$1"; } #pr_headline() { pr_blue "$1"; } #http://misc.flogisoft.com/bash/tip_colors_and_formatting #pr_headline() { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m\033[47m$1" || out "$1"; pr_off; } -pr_headline() { [[ "$COLOR" -ne 0 ]] && out "\033[1m\033[4m$1" || out "$1"; pr_off; } +pr_headline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m\033[4m$1" || out_term "$1"; pr_off; } +pr_headline() { pr_headline_term "$1"; out_html "$1"; } +pr_headlineln_term() { pr_headline_term "$1"; outln_term; } pr_headlineln() { pr_headline "$1" ; outln; } +pr_squoted_term() { out_term "'$1'"; } pr_squoted() { out "'$1'"; } +pr_dquoted_term() { out_term "\"$1\""; } pr_dquoted() { out "\"$1\""; } +local_problem_term() { pr_warning_term "Local problem: $1"; } local_problem() { pr_warning "Local problem: $1"; } +local_problem_ln_term() { pr_warningln_term "Local problem: $1"; } local_problem_ln() { pr_warningln "Local problem: $1"; } +fixme_term() { pr_warning_term "fixme: $1"; } fixme() { pr_warning "fixme: $1"; } +fixmeln_term() { pr_warningln_term "fixme: $1"; } fixmeln() { pr_warningln "fixme: $1"; } ### color switcher (see e.g. https://linuxtidbits.wordpress.com/2008/08/11/output-color-on-bash-scripts/ @@ -893,6 +959,24 @@ fileout() { # ID, SEVERITY, FINDING, CVE, CWE, HINT } ################### FILE FORMATING END ######################### +html_header() { + out_html "\n" + out_html "\n" + out_html "\n" + out_html "\n" + out_html "\n" + out_html "testssl.sh\n" + out_html "\n" + out_html "\n" + out_html "
\n"
+}
+
+html_footer() {
+     out_html "
\n" + out_html "\n" + out_html "\n" +} + ###### helper function definitions ###### if [[ $(uname) == "Linux" ]] ; then @@ -1120,7 +1204,7 @@ string_to_asciihex() { output+="$(printf "%02x," "'${string:i:1}")" done [[ -n "$string" ]] && output+="$(printf "%02x" "'${string:eos:1}")" - out "$output" + retstring "$output" return 0 } @@ -1360,7 +1444,7 @@ run_http_date() { out "Got no HTTP time, maybe try different URL?"; fileout "http_clock_skew" "INFO" "HTTP clock skew not measured. Got no HTTP time, maybe try different URL?" fi - debugme out ", epoch: $HTTP_TIME" + debugme out_term ", epoch: $HTTP_TIME" fi outln detect_ipv4 @@ -1394,7 +1478,7 @@ detect_header() { out "\n$spaces" # first awk matches the key, second extracts the from the first line the value, be careful with quotes here! HEADERVALUE=$(grep -Faiw "$key:" $HEADERFILE | sed 's/^.*://' | head -1) - [[ $DEBUG -ge 2 ]] && pr_italic "$HEADERVALUE" && out "\n$spaces" + [[ $DEBUG -ge 2 ]] && pr_italic_term "$HEADERVALUE" && out_term "\n$spaces" fileout "$2""_multiple" "WARN" "Multiple $2 headers. Using first header: $HEADERVALUE" return $nr fi @@ -1559,7 +1643,7 @@ run_hpkp() { # Get the SPKIs first spki=$(tr ';' '\n' < $TMPFILE | tr -d ' ' | tr -d '\"' | awk -F'=' '/pin.*=/ { print $2 }') - debugme outln "\n$spki" + debugme outln_term "\n$spki" # Look at the host certificate first # get the key fingerprint from the host certificate @@ -1609,7 +1693,7 @@ run_hpkp() { pr_done_good "$hpkp_spki" fileout "hpkp_$hpkp_spki" "OK" "SPKI $hpkp_spki matches the host certificate" fi - debugme out "\n $hpkp_spki | $hpkp_spki_hostcert" + debugme out_term "\n $hpkp_spki | $hpkp_spki_hostcert" # Check for intermediate match if ! "$certificate_found"; then @@ -1989,7 +2073,7 @@ normalize_ciphercode() { } prettyprint_local() { - local arg + local arg line local hexcode dash ciph sslvers kx auth enc mac export local re='^[0-9A-Fa-f]+$' @@ -2012,8 +2096,7 @@ prettyprint_local() { if [[ -z "$1" ]]; then $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 + outln "$(neat_list "$HEXC" "$ciph" "$kx" "$enc")" done else #for arg in $(echo $@ | sed 's/,/ /g'); do @@ -2022,8 +2105,9 @@ prettyprint_local() { normalize_ciphercode $hexcode # for numbers we don't do word matching: [[ $arg =~ $re ]] && \ - neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -ai "$arg" || \ - neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -wai "$arg" + line="$(neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -ai "$arg" || \ + neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -wai "$arg")" + [[ -n "$line" ]] && outln "$line" done done fi @@ -2206,13 +2290,13 @@ show_rfc_style(){ [[ "$hexcode" == "${TLS_CIPHER_HEXCODE[i]}" ]] && rfcname="${TLS_CIPHER_RFC_NAME[i]}" && break done [[ "$rfcname" == "-" ]] && rfcname="" - [[ -n "$rfcname" ]] && out "$rfcname" + [[ -n "$rfcname" ]] && retstring "$rfcname" return 0 } neat_header(){ - printf -- "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits${ADD_RFC_STR:+ Cipher Suite Name (RFC)}\n" - printf -- "%s--------------------------------------------------------------------------${ADD_RFC_STR:+---------------------------------------------------}\n" + outln "$(printf -- "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits${ADD_RFC_STR:+ Cipher Suite Name (RFC)}")" + outln "$(printf -- "%s--------------------------------------------------------------------------${ADD_RFC_STR:+---------------------------------------------------}")" } @@ -2222,11 +2306,12 @@ neat_header(){ # arg4: encryption (maybe included "export") # arg5: "true" if the cipher's "quality" should be highlighted # "false" if the line should be printed in light grey -# empty if line should be printed in black +# empty if line should be returned as a string neat_list(){ local hexcode="$1" local ossl_cipher="$2" tls_cipher="" - local kx enc strength line + local kx enc strength line what_dh bits + local -i i len kx="${3//Kx=/}" enc="${4//Enc=/}" @@ -2241,25 +2326,30 @@ neat_list(){ [[ -n "$ADD_RFC_STR" ]] && tls_cipher="$(show_rfc_style "$hexcode")" - if [[ "$5" == "false" ]]; then + if [[ -z "$5" ]]; then + retstring "$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" + return 0 + elif [[ "$5" == "false" ]]; then line="$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" pr_deemphasize "$line" return 0 fi + out "$(printf -- " %-7s %-33s " "$hexcode" "$ossl_cipher")" - #printf -- "%q" "$kx" | xxd | head -1 - # length correction for color escape codes (printf counts the escape color codes!!) - if printf -- "%q" "$kx" | egrep -aq '.;3.m|E\[1m' ; then # here's a color code which screws up the formatting with printf below - while [[ ${#kx} -lt 20 ]]; do - kx="$kx " - done - elif printf -- "%q" "$kx" | grep -aq 'E\[m' ; then # for color=1/0 we have the pr_off which screws up the formatting - while [[ ${#kx} -lt 13 ]]; do # so it'll be filled up ok - kx="$kx " - done + read what_dh bits <<< "$kx" + out "$what_dh" + if [[ -n "$bits" ]]; then + if [[ $what_dh == "DH" ]] || [[ $what_dh == "EDH" ]]; then + pr_dh_quality "$bits" " $bits" + elif [[ $what_dh == "ECDH" ]]; then + pr_ecdh_quality "$bits" " $bits" + fi fi - #echo "${#kx}" # should be always 20 / 13 - printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher" + len=${#kx} + for (( i=len; i<10; i++ )); do + out " " + done + out "$(printf -- " %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$enc" "$strength" "$tls_cipher")" } test_just_one(){ @@ -3147,7 +3237,7 @@ create_client_simulation_tls_clienthello() { done if ! $sni_extension_found; then - out "$tls_handshake_ascii" + retstring "$tls_handshake_ascii" return 0 fi @@ -3166,7 +3256,7 @@ create_client_simulation_tls_clienthello() { tls_handshake_ascii_len_hex=$(printf "%02x\n" $tls_handshake_ascii_len) len2twobytes "$tls_handshake_ascii_len_hex" tls_handshake_ascii="${tls_content_type}${tls_version_reclayer}${LEN_STR:0:2}${LEN_STR:4:2}${tls_handshake_ascii}" - out "$tls_handshake_ascii" + retstring "$tls_handshake_ascii" return 0 } @@ -3235,7 +3325,7 @@ client_simulation_sockets() { fi done - debugme outln "reading server hello..." + debugme outln_term "reading server hello..." if [[ "$DEBUG" -ge 4 ]]; then hexdump -C $SOCK_REPLY_FILE | head -6 echo @@ -3255,7 +3345,7 @@ client_simulation_sockets() { # see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)") - debugme out " (returned $lines lines) " + debugme out_term " (returned $lines lines) " # determine the return value for higher level, so that they can tell what the result is if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then @@ -3263,7 +3353,7 @@ client_simulation_sockets() { else ret=0 fi - debugme outln + debugme outln_term close_socket TMPFILE=$SOCK_REPLY_FILE @@ -4051,7 +4141,7 @@ run_client_simulation() { fi outln - debugme outln + debugme outln_term for name in "${short[@]}"; do #FIXME: printf formatting would look better, especially if we want a wide option here out " ${names[i]} " @@ -4250,7 +4340,7 @@ run_protocols() { ;; 3) # everything else lines=$(count_lines "$(hexdump -C "$TEMPDIR/$NODEIP.sslv2_sockets.dd" 2>/dev/null)") - [[ "$DEBUG" -ge 2 ]] && out " ($lines lines) " + [[ "$DEBUG" -ge 2 ]] && out_term " ($lines lines) " if [[ "$lines" -gt 1 ]]; then nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3)) add_tls_offered "ssl2" @@ -4264,7 +4354,7 @@ run_protocols() { fi fi ;; esac - debugme outln + debugme outln_term else run_prototest_openssl "-ssl2" case $? in @@ -4354,7 +4444,7 @@ run_protocols() { 2) pr_svrty_medium "not offered" if [[ "$DETECTED_TLS_VERSION" == "0300" ]]; then - [[ $DEBUG -eq 1 ]] && out " -- downgraded" + [[ $DEBUG -eq 1 ]] && out_term " -- downgraded" outln fileout "tls1" "MEDIUM" "TLSv1.0 is not offered, and downgraded to SSL" elif [[ "$DETECTED_TLS_VERSION" == 03* ]]; then @@ -4403,7 +4493,7 @@ run_protocols() { 2) out "not offered" if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then - [[ $DEBUG -eq 1 ]] && out " -- downgraded" + [[ $DEBUG -eq 1 ]] && out_term " -- downgraded" outln fileout "tls1_1" "CRITICAL" "TLSv1.1 is not offered, and downgraded to a weaker protocol" elif [[ "$DETECTED_TLS_VERSION" == "0300" ]] && [[ "$latest_supported" == "0301" ]]; then @@ -4459,7 +4549,7 @@ run_protocols() { detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))" fi if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then - [[ $DEBUG -eq 1 ]] && out " -- downgraded" + [[ $DEBUG -eq 1 ]] && out_term " -- downgraded" outln fileout "tls1_2" "MEDIUM" "TLSv1.2 is not offered and downgraded to a weaker protocol" elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -lt 0x$latest_supported ]]; then @@ -4543,6 +4633,44 @@ run_std_cipherlists() { return 0 } +pr_dh_quality() { + local bits="$1" + local string="$2" + + if [[ "$bits" -le 600 ]]; then + pr_svrty_critical "$string" + elif [[ "$bits" -le 800 ]]; then + pr_svrty_high "$string" + elif [[ "$bits" -le 1280 ]]; then + pr_svrty_medium "$string" + elif [[ "$bits" -ge 2048 ]]; then + pr_done_good "$string" + else + out "$string" + fi +} + +pr_ecdh_quality() { + local bits="$1" + local string="$2" + + if [[ "$bits" -le 80 ]]; then # has that ever existed? + pr_svrty_critical "$string" + elif [[ "$bits" -le 108 ]]; then # has that ever existed? + pr_svrty_high "$string" + elif [[ "$bits" -le 163 ]]; then + pr_svrty_medium "$string" + elif [[ "$bits" -le 193 ]]; then # hmm, according to https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography it should ok + pr_svrty_low "$string" # but openssl removed it https://github.com/drwetter/testssl.sh/issues/299#issuecomment-220905416 + elif [[ "$bits" -le 224 ]]; then + out "$string" + elif [[ "$bits" -gt 224 ]]; then + pr_done_good "$string" + else + out "$string" + fi +} + # arg1: file with input for grepping the bit length for ECDH/DHE # arg2: whether to print warning "old fart" or not (empty: no) @@ -4567,57 +4695,46 @@ read_dhbits_from_file() { what_dh="ECDH" fi - if [[ -n "$curve" ]]; then - debugme echo ">$HAS_DH_BITS|$what_dh($curve)|$bits<" - else - debugme echo ">$HAS_DH_BITS|$what_dh|$bits<" + if [[ -z "$2" ]]; then + if [[ -n "$curve" ]]; then + debugme echo ">$HAS_DH_BITS|$what_dh($curve)|$bits<" + else + debugme echo ">$HAS_DH_BITS|$what_dh|$bits<" + fi fi [[ -n "$what_dh" ]] && HAS_DH_BITS=true # FIX 190 if [[ -z "$what_dh" ]] && ! "$HAS_DH_BITS"; then - if [[ -z "$2" ]]; then + if [[ "$2" == "string" ]]; then + retstring "$old_fart" + elif [[ -z "$2" ]]; then pr_warning "$old_fart" fi return 0 fi - [[ -n "$bits" ]] && [[ -z "$2" ]] && out ", " + if [[ "$2" == "quiet" ]]; then + retstring "$bits" + return 0 + fi + + [[ -z "$2" ]] && [[ -n "$bits" ]] && out ", " if [[ $what_dh == "DH" ]] || [[ $what_dh == "EDH" ]]; then - if [[ -z "$2" ]]; then - add="bit DH" - [[ -n "$curve" ]] && add+=" ($curve)" - fi - if [[ "$bits" -le 600 ]]; then - pr_svrty_critical "$bits $add" - elif [[ "$bits" -le 800 ]]; then - pr_svrty_high "$bits $add" - elif [[ "$bits" -le 1280 ]]; then - pr_svrty_medium "$bits $add" - elif [[ "$bits" -ge 2048 ]]; then - pr_done_good "$bits $add" + add="bit DH" + [[ -n "$curve" ]] && add+=" ($curve)" + if [[ "$2" == "string" ]]; then + retstring ", $bits $add" else - out "$bits $add" + pr_dh_quality "$bits" "$bits $add" fi # https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography, http://www.keylength.com/en/compare/ elif [[ $what_dh == "ECDH" ]]; then - if [[ -z "$2" ]]; then - add="bit ECDH" - [[ -n "$curve" ]] && add+=" ($curve)" - fi - if [[ "$bits" -le 80 ]]; then # has that ever existed? - pr_svrty_critical "$bits $add" - elif [[ "$bits" -le 108 ]]; then # has that ever existed? - pr_svrty_high "$bits $add" - elif [[ "$bits" -le 163 ]]; then - pr_svrty_medium "$bits $add" - elif [[ "$bits" -le 193 ]]; then # hmm, according to https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography it should ok - pr_svrty_low "$bits $add" # but openssl removed it https://github.com/drwetter/testssl.sh/issues/299#issuecomment-220905416 - elif [[ "$bits" -le 224 ]]; then - out "$bits $add" - elif [[ "$bits" -gt 224 ]]; then - pr_done_good "$bits $add" + add="bit ECDH" + [[ -n "$curve" ]] && add+=" ($curve)" + if [[ "$2" == "string" ]]; then + retstring ", $bits $add" else - out "$bits $add" + pr_ecdh_quality "$bits" "$bits $add" fi fi @@ -4666,7 +4783,7 @@ run_server_preference() { elif [[ -n "$STARTTLS_PROTOCOL" ]]; then # now it still could be that we hit this bug: https://github.com/drwetter/testssl.sh/issues/188 # workaround is to connect with a protocol - debugme out "(workaround #188) " + debugme out_term "(workaround #188) " determine_optimal_proto $STARTTLS_PROTOCOL $OPENSSL s_client $STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_fwd $BUGS -connect $NODEIP:$PORT $PROXY $addcmd2 $ERRFILE >$TMPFILE if ! sclient_connect_successful $? $TMPFILE; then @@ -4705,7 +4822,7 @@ run_server_preference() { remark4default_cipher="" fileout "order" "OK" "Server sets a cipher order" fi - debugme out " $cipher1 | $cipher2" + debugme out_term " $cipher1 | $cipher2" outln pr_bold " Negotiated protocol " @@ -4757,23 +4874,23 @@ run_server_preference() { case "$default_cipher" in *NULL*|*EXP*) pr_svrty_critical "$default_cipher" - fileout "order_cipher" "CRITICAL" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" + fileout "order_cipher" "CRITICAL" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE" "string") $remark4default_cipher" ;; *RC4*) pr_svrty_high "$default_cipher" - fileout "order_cipher" "HIGH" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" + fileout "order_cipher" "HIGH" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE" "string") $remark4default_cipher" ;; *CBC*) pr_svrty_medium "$default_cipher" - fileout "order_cipher" "MEDIUM" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" + fileout "order_cipher" "MEDIUM" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE" "string") $remark4default_cipher" ;; # FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list *GCM*|*CHACHA20*) pr_done_best "$default_cipher" - fileout "order_cipher" "OK" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" + fileout "order_cipher" "OK" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE" "string") $remark4default_cipher" ;; # best ones ECDHE*AES*) pr_svrty_low "$default_cipher" - fileout "order_cipher" "LOW" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (cbc) $remark4default_cipher" + fileout "order_cipher" "LOW" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE" "string") (cbc) $remark4default_cipher" ;; # it's CBC. --> lucky13 "") pr_warning "default cipher empty" ; @@ -4786,7 +4903,7 @@ run_server_preference() { ;; *) out "$default_cipher" - fileout "order_cipher" "INFO" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" + fileout "order_cipher" "INFO" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE" "string") $remark4default_cipher" ;; esac read_dhbits_from_file "$TMPFILE" @@ -4817,7 +4934,7 @@ run_server_preference() { fi fi done - [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" cipher[i]="" @@ -4835,7 +4952,7 @@ run_server_preference() { cipher1=$(awk '/Cipher *:/ { print $3 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") [[ $TLS_NR_CIPHERS -ne 0 ]] && cipher[i]="$(rfc2openssl "$cipher1")" [[ -z "${cipher[i]}" ]] && cipher[i]="$cipher1" - [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" cipher[i]="" @@ -4848,7 +4965,7 @@ run_server_preference() { 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') [[ ${cipher[i]} == "0000" ]] && cipher[i]="" # Hack! - [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" cipher[i]="" @@ -4868,7 +4985,7 @@ run_server_preference() { cipher[i]="" else cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') - [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" fi fi else @@ -4879,13 +4996,13 @@ run_server_preference() { if [[ -n "${cipher[i]}" ]]; then # cipher not empty if [[ -z "${cipher[i-1]}" ]]; then # previous one empty #outln - printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both + out "$(printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}")" # print out both else # previous NOT empty if [[ "${cipher[i-1]}" == "${cipher[i]}" ]]; then # and previous protocol same cipher out ", ${proto[i]}" # same cipher --> only print out protocol behind it else outln - printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both + out "$(printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}")" # print out both fi fi fi @@ -4920,7 +5037,7 @@ check_tls12_pref() { nr_ciphers_found_r1+=1 "$FAST" && break else - debugme outln "A: $tested_cipher" + debugme outln_term "A: $tested_cipher" break fi done @@ -4935,10 +5052,10 @@ check_tls12_pref() { order+=" $cipher" batchremoved="$batchremoved:-$cipher" nr_ciphers_found_r1+=1 - debugme outln "B1: $batchremoved" + debugme outln_term "B1: $batchremoved" "$FAST" && break else - debugme outln "B2: $batchremoved" + debugme outln_term "B2: $batchremoved" break # nothing left with batchremoved ciphers, we need to put everything together fi @@ -4970,7 +5087,7 @@ check_tls12_pref() { return 1 fi fi - out "$order" + retstring "$order" tmpfile_handle $FUNCNAME.txt return 0 @@ -4993,7 +5110,7 @@ cipher_pref_check() { pr_bold " Cipher order" - outln " ssl3 00 SSLv3\n tls1 01 TLSv1\n tls1_1 02 TLSv1.1\n tls1_2 03 TLSv1.2"| while read p proto_hex proto; do + retstring " ssl3 00 SSLv3\n tls1 01 TLSv1\n tls1_1 02 TLSv1.1\n tls1_2 03 TLSv1.2\n"| while read p proto_hex proto; do order=""; ciphers_found_with_sockets=false if [[ $p == ssl3 ]] && ! "$HAS_SSL3" && ! "$using_sockets"; then out "\n SSLv3: "; local_problem "$OPENSSL doesn't support \"s_client -ssl3\""; @@ -5151,7 +5268,7 @@ cipher_pref_check() { if [[ -n "$order" ]]; then outln - printf " %-10s" "$proto: " + out "$(printf " %-10s" "$proto: ")" out "$order" fileout "order_$p" "INFO" "Default cipher order for protocol $p: $order" fi @@ -5213,17 +5330,17 @@ verify_retcode_helper() { case $retcode in # codes from ./doc/apps/verify.pod | verify(1ssl) - 26) out "(unsupported certificate purpose)" ;; # X509_V_ERR_INVALID_PURPOSE - 24) out "(certificate unreadable)" ;; # X509_V_ERR_INVALID_CA - 23) out "(certificate revoked)" ;; # X509_V_ERR_CERT_REVOKED - 21) out "(chain incomplete, only 1 cert provided)" ;; # X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE - 20) out "(chain incomplete)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY - 19) out "(self signed CA in chain)" ;; # X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN - 18) out "(self signed)" ;; # X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT - 10) out "(expired)" ;; # X509_V_ERR_CERT_HAS_EXPIRED - 9) out "(not yet valid)" ;; # X509_V_ERR_CERT_NOT_YET_VALID - 2) out "(issuer cert missing)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT - *) ret=1 ; pr_warning " (unknown, pls report) $1" ;; + 26) retstring "(unsupported certificate purpose)" ;; # X509_V_ERR_INVALID_PURPOSE + 24) retstring "(certificate unreadable)" ;; # X509_V_ERR_INVALID_CA + 23) retstring "(certificate revoked)" ;; # X509_V_ERR_CERT_REVOKED + 21) retstring "(chain incomplete, only 1 cert provided)" ;; # X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE + 20) retstring "(chain incomplete)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY + 19) retstring "(self signed CA in chain)" ;; # X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN + 18) retstring "(self signed)" ;; # X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT + 10) retstring "(expired)" ;; # X509_V_ERR_CERT_HAS_EXPIRED + 9) retstring "(not yet valid)" ;; # X509_V_ERR_CERT_NOT_YET_VALID + 2) retstring "(issuer cert missing)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT + *) ret=1 ; retstring " (unknown, pls report) $1" ;; esac return $ret } @@ -5255,7 +5372,7 @@ determine_trust() { addtl_warning="(Your openssl <= 1.0.2 might be too unreliable to determine trust)" fileout "${json_prefix}chain_of_trust_warn" "WARN" "$addtl_warning" fi - debugme outln + debugme outln_term # if you run testssl.sh from a different path /you can set either TESTSSL_INSTALL_DIR or CA_BUNDLES_PATH to find the CA BUNDLES if [[ -z $CA_BUNDLES_PATH ]]; then @@ -5282,18 +5399,18 @@ determine_trust() { if [[ ${verify_retcode[i]} -eq 0 ]]; then trust[i]=true some_ok=true - debugme pr_done_good "Ok " - debugme outln "${verify_retcode[i]}" + debugme pr_done_good_term "Ok " + debugme outln_term "${verify_retcode[i]}" else trust[i]=false all_ok=false - debugme pr_svrty_high "not trusted " - debugme outln "${verify_retcode[i]}" + debugme pr_svrty_high_term "not trusted " + debugme outln_term "${verify_retcode[i]}" fi i=$((i + 1)) done num_ca_bundles=$((i - 1)) - debugme out " " + debugme out_term " " if $all_ok; then # all stores ok pr_done_good "Ok "; pr_warning "$addtl_warning" @@ -5305,8 +5422,13 @@ determine_trust() { if ! $some_ok; then # all failed (we assume with the same issue), we're displaying the reason out " " - verify_retcode_helper "${verify_retcode[1]}" - fileout "${json_prefix}chain_of_trust" "CRITICAL" "All certificate trust checks failed: $(verify_retcode_helper "${verify_retcode[1]}"). $addtl_warning" + code="$(verify_retcode_helper "${verify_retcode[1]}")" + if [[ "$code" =~ "pls report" ]]; then + pr_warning "$code" + else + out "$code" + fi + fileout "${json_prefix}chain_of_trust" "CRITICAL" "All certificate trust checks failed: $code. $addtl_warning" else # is one ok and the others not ==> display the culprit store if $some_ok ; then @@ -5318,15 +5440,20 @@ determine_trust() { #code="$(verify_retcode_helper ${verify_retcode[i]})" #notok_was="${certificate_file[i]} $notok_was" pr_svrty_high " ${certificate_file[i]} " - verify_retcode_helper "${verify_retcode[i]}" - notok_was="${certificate_file[i]} $(verify_retcode_helper "${verify_retcode[i]}") $notok_was" + code="$(verify_retcode_helper "${verify_retcode[i]}")" + if [[ "$code" =~ "pls report" ]]; then + pr_warning "$code" + else + out "$code" + fi + notok_was="${certificate_file[i]} $code $notok_was" fi done #pr_svrty_high "$notok_was " #outln "$code" outln # lf + green ones - [[ "$DEBUG" -eq 0 ]] && out "$spaces" + [[ "$DEBUG" -eq 0 ]] && out_term "$spaces" pr_done_good "OK: $ok_was" fi fileout "${json_prefix}chain_of_trust" "CRITICAL" "Some certificate trust checks failed : OK : $ok_was NOT ok: $notok_was $addtl_warning" @@ -5360,7 +5487,7 @@ tls_time() { out "$difftime"; out " sec from localtime"; fileout "tls_time" "INFO" "Your TLS time is skewed from your localtime by $difftime seconds" fi - debugme out "$TLS_TIME" + debugme out_term "$TLS_TIME" outln else pr_warningln "SSLv3 through TLS 1.2 didn't return a timestamp" @@ -5973,9 +6100,9 @@ certificate_info() { cn_nosni="$(get_cn_from_cert "$HOSTCERT.nosni")" [[ -z "$cn_nosni" ]] && cn_nosni="no CN field in subject" fi - debugme out "\"$NODE\" | \"$cn\" | \"$cn_nosni\"" + debugme out_term "\"$NODE\" | \"$cn\" | \"$cn_nosni\"" else - debugme out "\"$NODE\" | \"$cn\"" + debugme out_term "\"$NODE\" | \"$cn\"" fi #FIXME: check for SSLv3/v2 and look whether it goes to a different CN (probably not polite) @@ -6030,7 +6157,8 @@ certificate_info() { pr_svrty_criticalln "self-signed (NOT ok)" fileout "${json_prefix}issuer" "CRITICAL" "Issuer: selfsigned" else - issuerfinding="$(pr_italic "$issuer_CN")" + issuerfinding="$issuer_CN" + pr_italic "$issuer_CN" if [[ -z "$issuer_O" ]] && [[ -n "$issuer_DC" ]]; then for san in $issuer_DC; do if [[ -z "$issuer_O" ]]; then @@ -6042,14 +6170,19 @@ certificate_info() { fi if [[ -n "$issuer_O" ]]; then issuerfinding+=" (" - issuerfinding+="$(pr_italic "$issuer_O")" + out " (" + issuerfinding+="$issuer_O" + pr_italic "$issuer_O" if [[ -n "$issuer_C" ]]; then issuerfinding+=" from " - issuerfinding+="$(pr_italic "$issuer_C")" + out " from " + issuerfinding+="$issuer_C" + pr_italic "$issuer_C" fi issuerfinding+=")" + out ")" fi - outln "$issuerfinding" + outln fileout "${json_prefix}issuer" "INFO" "Issuer: $issuerfinding" fi @@ -6749,22 +6882,14 @@ run_pfs() { fi if "$ecdhe_offered"; then for (( i=0; i < nr_curves; i++ )); do - if "${supported_curve[i]}"; then - curves_offered+="${curves_ossl[i]} " - if [[ "${bits[i]}" -le 163 ]]; then - curves_offered_text+="$(pr_svrty_medium "${curves_ossl[i]}") " - elif [[ "${bits[i]}" -le 193 ]]; then # hmm, according to https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography it should ok - curves_offered_text+="$(pr_svrty_low "${curves_ossl[i]}") " # but openssl removed it https://github.com/drwetter/testssl.sh/issues/299#issuecomment-220905416 - elif [[ "${bits[i]}" -le 224 ]]; then - curves_offered_text+="${curves_ossl[i]} " - else - curves_offered_text+="$(pr_done_good "${curves_ossl[i]}") " - fi - fi + "${supported_curve[i]}" && curves_offered+="${curves_ossl[i]} " done if [[ -n "$curves_offered" ]]; then "$WIDE" && outln - pr_bold " Elliptic curves offered: "; outln "$curves_offered_text" + pr_bold " Elliptic curves offered: " + for (( i=0; i < nr_curves; i++ )); do + "${supported_curve[i]}" && pr_ecdh_quality "${bits[i]}" "${curves_ossl[i]} " + done fileout "ecdhe_curves" "INFO" "Elliptic curves offered $curves_offered" fi fi @@ -7511,7 +7636,7 @@ get_dh_ephemeralkey() { key_bitstring="$($OPENSSL pkey -pubin -in $tmp_der_key_file -inform DER 2> $ERRFILE)" rm $tmp_der_key_file [[ -z "$key_bitstring" ]] && return 1 - out "$key_bitstring" + retstring "$key_bitstring" return 0 } @@ -7751,7 +7876,7 @@ parse_tls_serverhello() { if [[ $tls_hello_ascii_len-$i -lt 10 ]]; then if [[ "$process_full" == "all" ]]; then # The entire server response should have been retrieved. - debugme pr_warningln "Malformed message." + debugme pr_warningln_term "Malformed message." return 1 else # This could just be a result of the server's response being @@ -7767,29 +7892,29 @@ parse_tls_serverhello() { i=$i+4 if [[ $DEBUG -ge 2 ]]; then - echo " tls_protocol (reclyr): 0x$tls_protocol" - out " tls_content_type: 0x$tls_content_type" + echo " tls_protocol (reclyr): 0x$tls_protocol" + out_term " tls_content_type: 0x$tls_content_type" case $tls_content_type in - 15) outln " (alert)" ;; - 16) outln " (handshake)" ;; - 17) outln " (application data)" ;; - *) outln ;; + 15) outln_term " (alert)" ;; + 16) outln_term " (handshake)" ;; + 17) outln_term " (application data)" ;; + *) outln_term ;; esac echo " msg_len: $((msg_len/2))" - outln + outln_term fi if [[ $tls_content_type != "15" ]] && [[ $tls_content_type != "16" ]] && [[ $tls_content_type != "17" ]]; then - debugme pr_warningln "Content type other than alert, handshake, or application data detected." + debugme pr_warningln_term "Content type other than alert, handshake, or application data detected." return 1 elif [[ "${tls_protocol:0:2}" != "03" ]]; then - debugme pr_warningln "Protocol record_version.major is not 03." + debugme pr_warningln_term "Protocol record_version.major is not 03." return 1 fi DETECTED_TLS_VERSION=$tls_protocol if [[ $msg_len -gt $tls_hello_ascii_len-$i ]]; then if [[ "$process_full" == "all" ]]; then - debugme pr_warningln "Malformed message." + debugme pr_warningln_term "Malformed message." return 1 else # This could just be a result of the server's response being @@ -7809,7 +7934,7 @@ parse_tls_serverhello() { # Now check the alert messages. tls_alert_ascii_len=${#tls_alert_ascii} if [[ "$process_full" == "all" ]] && [[ $tls_alert_ascii_len%4 -ne 0 ]]; then - debugme pr_warningln "Malformed message." + debugme pr_warningln_term "Malformed message." return 1 fi if [[ $tls_alert_ascii_len -gt 0 ]]; then @@ -7820,7 +7945,7 @@ parse_tls_serverhello() { tls_err_descr=${tls_alert_ascii:j:2} # 112/0x70: Unrecognized name, 111/0x6F: certificate_unobtainable, # 113/0x71: bad_certificate_status_response, #114/0x72: bad_certificate_hash_value - debugme out " tls_err_descr: 0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})" + debugme out_term " tls_err_descr: 0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})" case $tls_err_descr in 00) tls_alert_descrip="close notify" ;; 01) tls_alert_descrip="end of early data" ;; @@ -7866,17 +7991,17 @@ parse_tls_serverhello() { echo "alert $tls_alert_descrip" >> $TMPFILE echo "===============================================================================" >> $TMPFILE if [[ $DEBUG -ge 2 ]]; then - outln " ($tls_alert_descrip)" - out " tls_err_level: ${tls_err_level}" + outln_term " ($tls_alert_descrip)" + out_term " tls_err_level: ${tls_err_level}" case $tls_err_level in - 01) outln " (warning)" ;; - 02) outln " (fatal)" ;; - *) outln ;; + 01) outln_term " (warning)" ;; + 02) outln_term " (fatal)" ;; + *) outln_term ;; esac - outln + outln_term fi if [[ "$tls_err_level" != "01" ]] && [[ "$tls_err_level" != "02" ]]; then - debugme pr_warningln "Unexpected AlertLevel (0x$tls_err_level)." + debugme pr_warningln_term "Unexpected AlertLevel (0x$tls_err_level)." return 1 elif [[ "$tls_err_level" == "02" ]]; then # Fatal alert @@ -7896,7 +8021,7 @@ parse_tls_serverhello() { if [[ $tls_handshake_ascii_len-$i -lt 8 ]]; then if [[ "$process_full" == "all" ]]; then # The entire server response should have been retrieved. - debugme pr_warningln "Malformed message." + debugme pr_warningln_term "Malformed message." return 1 else # This could just be a result of the server's response being @@ -7910,34 +8035,34 @@ parse_tls_serverhello() { i=$i+6 if [[ $DEBUG -ge 2 ]]; then - out " handshake type: 0x${tls_msg_type}" + out_term " handshake type: 0x${tls_msg_type}" case $tls_msg_type in - 00) outln " (hello_request)" ;; - 01) outln " (client_hello)" ;; - 02) outln " (server_hello)" ;; - 03) outln " (hello_verify_request)" ;; - 04) outln " (NewSessionTicket)" ;; - 06) outln " (hello_retry_request)" ;; - 08) outln " (encrypted_extensions)" ;; - 0B) outln " (certificate)" ;; - 0C) outln " (server_key_exchange)" ;; - 0D) outln " (certificate_request)" ;; - 0E) outln " (server_hello_done)" ;; - 0F) outln " (certificate_verify)" ;; - 10) outln " (client_key_exchange)" ;; - 14) outln " (finished)" ;; - 15) outln " (certificate_url)" ;; - 16) outln " (certificate_status)" ;; - 17) outln " (supplemental_data)" ;; - 18) outln " (key_update)" ;; - *) outln ;; + 00) outln_term " (hello_request)" ;; + 01) outln_term " (client_hello)" ;; + 02) outln_term " (server_hello)" ;; + 03) outln_term " (hello_verify_request)" ;; + 04) outln_term " (NewSessionTicket)" ;; + 06) outln_term " (hello_retry_request)" ;; + 08) outln_term " (encrypted_extensions)" ;; + 0B) outln_term " (certificate)" ;; + 0C) outln_term " (server_key_exchange)" ;; + 0D) outln_term " (certificate_request)" ;; + 0E) outln_term " (server_hello_done)" ;; + 0F) outln_term " (certificate_verify)" ;; + 10) outln_term " (client_key_exchange)" ;; + 14) outln_term " (finished)" ;; + 15) outln_term " (certificate_url)" ;; + 16) outln_term " (certificate_status)" ;; + 17) outln_term " (supplemental_data)" ;; + 18) outln_term " (key_update)" ;; + *) outln_term ;; esac echo " msg_len: $((msg_len/2))" - outln + outln_term fi if [[ $msg_len -gt $tls_handshake_ascii_len-$i ]]; then if [[ "$process_full" == "all" ]]; then - debugme pr_warningln "Malformed message." + debugme pr_warningln_term "Malformed message." return 1 else # This could just be a result of the server's response being @@ -7949,28 +8074,28 @@ parse_tls_serverhello() { if [[ "$tls_msg_type" == "02" ]]; then if [[ -n "$tls_serverhello_ascii" ]]; then - debugme pr_warningln "Response contained more than one ServerHello handshake message." + debugme pr_warningln_term "Response contained more than one ServerHello handshake message." return 1 fi tls_serverhello_ascii="${tls_handshake_ascii:i:msg_len}" tls_serverhello_ascii_len=$msg_len elif [[ "$process_full" == "all" ]] && [[ "$tls_msg_type" == "0B" ]]; then if [[ -n "$tls_certificate_ascii" ]]; then - debugme pr_warningln "Response contained more than one Certificate handshake message." + debugme pr_warningln_term "Response contained more than one Certificate handshake message." return 1 fi tls_certificate_ascii="${tls_handshake_ascii:i:msg_len}" tls_certificate_ascii_len=$msg_len elif ( [[ "$process_full" == "all" ]] || [[ "$process_full" == "ephemeralkey" ]] ) && [[ "$tls_msg_type" == "0C" ]]; then if [[ -n "$tls_serverkeyexchange_ascii" ]]; then - debugme pr_warningln "Response contained more than one ServerKeyExchange handshake message." + debugme pr_warningln_term "Response contained more than one ServerKeyExchange handshake message." return 1 fi tls_serverkeyexchange_ascii="${tls_handshake_ascii:i:msg_len}" tls_serverkeyexchange_ascii_len=$msg_len elif [[ "$process_full" == "all" ]] && [[ "$tls_msg_type" == "16" ]]; then if [[ -n "$tls_certificate_status_ascii" ]]; then - debugme pr_warningln "Response contained more than one certificate_status handshake message." + debugme pr_warningln_term "Response contained more than one certificate_status handshake message." return 1 fi tls_certificate_status_ascii="${tls_handshake_ascii:i:msg_len}" @@ -7987,7 +8112,7 @@ parse_tls_serverhello() { return 1 elif [[ "${tls_handshake_ascii:0:2}" != "02" ]]; then # the ServerHello MUST be the first handshake message - debugme pr_warningln "The first handshake protocol message is not a ServerHello." + debugme pr_warningln_term "The first handshake protocol message is not a ServerHello." return 1 fi @@ -8001,7 +8126,7 @@ parse_tls_serverhello() { # byte 38+39+sid-len: extension length tls_protocol2="${tls_serverhello_ascii:0:4}" if [[ "${tls_protocol2:0:2}" != "03" ]]; then - debugme pr_warningln "server_version.major in ServerHello is not 03." + debugme pr_warningln_term "server_version.major in ServerHello is not 03." return 1 fi DETECTED_TLS_VERSION="$tls_protocol2" @@ -8038,7 +8163,7 @@ parse_tls_serverhello() { fi tls_extensions_len=$(hex2dec "${tls_serverhello_ascii:extns_offset:4}")*2 if [[ $tls_extensions_len -ne $tls_serverhello_ascii_len-$extns_offset-4 ]]; then - debugme pr_warningln "Malformed message." + debugme pr_warningln_term "Malformed message." return 1 fi for (( i=0; i$ERRFILE)") - debugme out " (returned $lines lines) " + debugme out_term " (returned $lines lines) " # determine the return value for higher level, so that they can tell what the result is if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then @@ -8928,7 +9053,7 @@ tls_sockets() { ret=2 # protocol NOT available, server downgraded to $DETECTED_TLS_VERSION fi fi - debugme outln + debugme outln_term else debugme echo "stuck on sending: $ret" fi @@ -9035,16 +9160,16 @@ run_heartbleed(){ for (( n=1; n <= hb_rounds; n++)); do fd_socket 5 || return 6 - debugme out "\nsending client hello (TLS version $tls_hexcode)" - debugme outln " ($n of $hb_rounds)" + debugme out_term "\nsending client hello (TLS version $tls_hexcode)" + debugme outln_term " ($n of $hb_rounds)" socksend "$client_hello" 1 - debugme outln "\nreading server hello" + debugme outln_term "\nreading server hello" sockread_serverhello 32768 if [[ $DEBUG -ge 4 ]]; then hexdump -C "$SOCK_REPLY_FILE" | head -20 - outln "[...]" - outln "\nsending payload with TLS version $tls_hexcode:" + outln_term "[...]" + outln_term "\nsending payload with TLS version $tls_hexcode:" fi rm "$SOCK_REPLY_FILE" @@ -9054,10 +9179,10 @@ run_heartbleed(){ lines_returned=$(hexdump -ve '16/1 "%02x " " \n"' "$SOCK_REPLY_FILE" | wc -l | sed 's/ //g') if [[ $DEBUG -ge 3 ]]; then - outln "\nheartbleed reply: " + outln_term "\nheartbleed reply: " hexdump -C "$SOCK_REPLY_FILE" | head -20 - [[ $lines_returned -gt 20 ]] && outln "[...]" - outln + [[ $lines_returned -gt 20 ]] && outln_term "[...]" + outln_term fi if [[ $lines_returned -gt 1 ]]; then @@ -9066,7 +9191,7 @@ run_heartbleed(){ saved_sockreply[n]="$(hexdump -ve '1/1 "%.2x"' "$SOCK_REPLY_FILE")" [[ $n -eq 1 ]] && grep -q '500 OOPS' "$SOCK_REPLY_FILE" && found_500_oops=true rm "$SOCK_REPLY_FILE" - #debugme out "${saved_sockreply[n]}" + #debugme out_term "${saved_sockreply[n]}" #TMPFILE="${saved_sockreply[n]}" close_socket #tmpfile_handle "$FUNCNAME,$n.txt" @@ -9093,12 +9218,12 @@ run_heartbleed(){ if [[ "${saved_sockreply[1]}" == "${saved_sockreply[2]}" ]] && [[ "${saved_sockreply[2]}" == "${saved_sockreply[3]}" ]] \ && "$found_500_oops"; then pr_done_best "not vulnerable (OK)$append" - [[ $DEBUG -ge 1 ]] && out ", successful weeded out vsftpd false positive" + [[ $DEBUG -ge 1 ]] && out_term ", successful weeded out vsftpd false positive" fileout "heartbleed" "OK" "Heartbleed: not vulnerable $append" "$cve" "$cwe" else out "likely " pr_svrty_critical "VULNERABLE (NOT ok)" - [[ $DEBUG -ge 1 ]] && out " use debug >=2 to confirm" + [[ $DEBUG -ge 1 ]] && out_term " use debug >=2 to confirm" fileout "heartbleed" "CRITICAL" "Heartbleed: likely VULNERABLE $append" "$cve" "$cwe" "$hint" fi else @@ -9181,15 +9306,15 @@ run_ccs_injection(){ fd_socket 5 || return 6 # we now make a standard handshake ... - debugme out "\nsending client hello, " + debugme out_term "\nsending client hello, " socksend "$client_hello" 1 - debugme outln "\nreading server hello" + debugme outln_term "\nreading server hello" sockread_serverhello 32768 if [[ $DEBUG -ge 4 ]]; then hexdump -C "$SOCK_REPLY_FILE" | head -20 - outln "[...]" - outln "\npayload #1 with TLS version $tls_hexcode:" + outln_term "[...]" + outln_term "\npayload #1 with TLS version $tls_hexcode:" fi rm "$SOCK_REPLY_FILE" @@ -9197,13 +9322,13 @@ run_ccs_injection(){ socksend "$ccs_message" 1 || ok_ids sockread_serverhello 2048 $CCS_MAX_WAITSOCK if [[ $DEBUG -ge 3 ]]; then - outln "\n1st reply: " + outln_term "\n1st reply: " hexdump -C "$SOCK_REPLY_FILE" | head -20 # ok: 15 | 0301 | 02 | 02 | 0a # ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a) # or just timed out - outln - outln "payload #2 with TLS version $tls_hexcode:" + outln_term + outln_term "payload #2 with TLS version $tls_hexcode:" fi rm "$SOCK_REPLY_FILE" @@ -9212,12 +9337,12 @@ run_ccs_injection(){ retval=$? if [[ $DEBUG -ge 3 ]]; then - outln "\n2nd reply: " + outln_term "\n2nd reply: " printf -- "$(hexdump -C "$SOCK_REPLY_FILE")" # not ok: 15 | 0301 | 02 | 02 | 15 # ALERT | TLS 1.0 | Length=2 | Decryption failed (21) # ok: 0a or nothing: ==> RST - outln + outln_term fi sockreply=$(cat "$SOCK_REPLY_FILE" 2>/dev/null) rm "$SOCK_REPLY_FILE" @@ -9452,7 +9577,7 @@ run_crime() { # fi # fi # fi -# [[ $DEBUG -eq 2 ]] outln "$STR" +# [[ $DEBUG -eq 2 ]] outln_term "$STR" tmpfile_handle $FUNCNAME.txt return $ret } @@ -9799,9 +9924,9 @@ run_freak() { for (( i=0; i < TLS_NR_CIPHERS; i++ )); do [[ "$hexc" == "${TLS_CIPHER_HEXCODE[i]}" ]] && break done - [[ $i -eq $TLS_NR_CIPHERS ]] && out "$hexc " || out "${TLS_CIPHER_OSSL_NAME[i]} " + [[ $i -eq $TLS_NR_CIPHERS ]] && out_term "$hexc " || out_term "${TLS_CIPHER_OSSL_NAME[i]} " done - outln + outln_term else echo $(actually_supported_ciphers $exportrsa_cipher_list) fi @@ -9875,9 +10000,9 @@ run_logjam() { for (( i=0; i < TLS_NR_CIPHERS; i++ )); do [[ "$hexc" == "${TLS_CIPHER_HEXCODE[i]}" ]] && break done - [[ $i -eq $TLS_NR_CIPHERS ]] && out "$hexc " || out "${TLS_CIPHER_OSSL_NAME[i]} " + [[ $i -eq $TLS_NR_CIPHERS ]] && out_term "$hexc " || out_term "${TLS_CIPHER_OSSL_NAME[i]} " done - outln + outln_term else echo $(actually_supported_ciphers $exportdh_cipher_list) fi @@ -9918,7 +10043,7 @@ run_logjam() { dh_p="$(strip_spaces "$(colon_to_spaces "$(newline_to_spaces "$dh_p")")")" [[ "${dh_p:0:2}" == "00" ]] && dh_p="${dh_p:2}" len_dh_p="$((4*${#dh_p}))" - debugme outln "len(dh_p): $len_dh_p | dh_p: $dh_p" + debugme outln_term "len(dh_p): $len_dh_p | dh_p: $dh_p" echo "$dh_p" > $TEMPDIR/dh_p.txt if [[ ! -s "$common_primes_file" ]]; then local_problem_ln "couldn't read common primes file $common_primes_file" @@ -10044,7 +10169,7 @@ run_drown() { ;; 3) # vulnerable lines=$(count_lines "$(hexdump -C "$TEMPDIR/$NODEIP.sslv2_sockets.dd" 2>/dev/null)") - debugme out " ($lines lines) " + debugme out_term " ($lines lines) " if [[ "$lines" -gt 1 ]]; then nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3)) if [[ 0 -eq "$nr_ciphers_detected" ]]; then @@ -10992,6 +11117,7 @@ file output options (can also be preset via environment variables): --jsonfile-pretty additional pretty structured output as JSON to the specified file --csv additional output of findings to CSV file in cwd --csvfile additional output as CSV to the specified file + --htmlfile additional output as HTML to the specifed file --hints additional hints to findings --severity severities with lower level will be filtered for CSV+JSON, possible values --append if or exists rather append then overwrite @@ -11127,7 +11253,7 @@ EOF mybanner() { local idtag - local bb + local bb1 bb2 local openssl_location="$(which $OPENSSL)" local cwd="" @@ -11136,12 +11262,14 @@ mybanner() { [[ -z "$GIT_REL" ]] && \ idtag="$CVS_REL" || \ idtag="$GIT_REL -- $CVS_REL_SHORT" - [[ "$COLOR" -ne 0 ]] && idtag="\033[1;30m$idtag\033[m\033[1m" - bb=$(cat </dev/null)\" [~$OPENSSL_NR_CIPHERS ciphers]" out " on $HNAME:" @@ -11167,16 +11299,16 @@ EOF else OPENSSL_LOCATION="$openssl_location" fi - echo "$OPENSSL_LOCATION" + outln "$OPENSSL_LOCATION" outln " (built: \"$OSSL_BUILD_DATE\", platform: \"$OSSL_VER_PLATFORM\")\n" } cleanup () { if [[ "$DEBUG" -ge 1 ]]; then - outln - pr_underline "DEBUG (level $DEBUG): see files in $TEMPDIR" - outln + outln_term + pr_underline_term "DEBUG (level $DEBUG): see files in $TEMPDIR" + outln_term else [[ -d "$TEMPDIR" ]] && rm -rf "$TEMPDIR"; fi @@ -11850,7 +11982,7 @@ display_rdns_etc() { outln " A record via $CORRECT_SPACES supplied IP \"$CMDLINE_IP\"" fi if [[ -n "$rDNS" ]]; then - printf " %-23s %s" "rDNS ($nodeip):" "$rDNS" + out "$(printf " %-23s %s" "rDNS ($nodeip):" "$rDNS")" fi } @@ -11985,6 +12117,7 @@ initialize_globals() { do_json=false do_pretty_json=false do_csv=false + do_html=false do_pfs=false do_protocols=false do_rc4=false @@ -12308,7 +12441,7 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift case $DEBUG in [0-6]) ;; - *) pr_magentaln "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2 + *) pr_magentaln_term "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2 help 1 esac ;; @@ -12367,6 +12500,16 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift do_csv=true ;; + --htmlfile) + HTMLFILE=$(parse_opt_equal_sign "$1" "$2") + [[ $? -eq 0 ]] && shift + if [[ -d "$HTMLFILE" ]]; then + pr_warningln_term "$HTMLFILE exists and is a directory" + exit -6 + fi + do_html=true + html_header + ;; --append) APPEND=true ;; @@ -12609,5 +12752,6 @@ else fi fi fi +html_footer exit $? From 2af8198f27cb4a833673901998d83869c0c3068b Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 7 Feb 2017 17:06:27 -0500 Subject: [PATCH 02/21] Change HTML colors Rather than use the colors created by `aha` use colors that more closely match the colors that appear in the terminal. --- testssl.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/testssl.sh b/testssl.sh index 75987e0..f817875 100755 --- a/testssl.sh +++ b/testssl.sh @@ -589,7 +589,7 @@ retstring(){ # color print functions, see also http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html pr_liteblue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;32m$1" || out_term "\033[0;34m$1" ) || out_term "$1"; pr_off; } # not yet used -pr_liteblue() { pr_liteblue_term "$1"; out_html "$1"; } +pr_liteblue() { pr_liteblue_term "$1"; out_html "$1"; } pr_liteblueln_term() { pr_liteblue_term "$1"; outln_term; } pr_liteblueln() { pr_liteblue "$1"; outln; } pr_blue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;32m$1" || out_term "\033[1;34m$1" ) || out_term "$1"; pr_off; } # used for head lines of single tests @@ -598,27 +598,27 @@ pr_blueln_term() { pr_blue_term "$1"; outln_term; } pr_blueln() { pr_blue "$1"; outln; } pr_warning_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;35m$1" || pr_underline_term "$1"; pr_off; } # some local problem: one test cannot be done -pr_warning() { pr_warning_term "$1"; out_html "$1"; } +pr_warning() { pr_warning_term "$1"; out_html "$1"; } pr_warningln_term() { pr_warning_term "$1"; outln_term; } # litemagenta pr_warningln() { pr_warning "$1"; outln; } pr_magenta_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;35m$1" || pr_underline_term "$1"; pr_off; } # fatal error: quitting because of this! -pr_magenta() { pr_magenta_term "$1"; out_html "$1"; } +pr_magenta() { pr_magenta_term "$1"; out_html "$1"; } pr_magentaln_term() { pr_magenta_term "$1"; outln_term; } pr_magentaln() { pr_magenta "$1"; outln; } pr_litecyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;36m$1" || out_term "$1"; pr_off; } # not yet used -pr_litecyan() { pr_litecyan_term "$1"; out_html "$1"; } +pr_litecyan() { pr_litecyan_term "$1"; out_html "$1"; } pr_litecyanln_term() { pr_litecyan_term "$1"; outln_term; } pr_litecyanln() { pr_litecyan "$1"; outln; } pr_cyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;36m$1" || out_term "$1"; pr_off; } # additional hint -pr_cyan() { pr_cyan_term "$1"; out_html "$1"; } +pr_cyan() { pr_cyan_term "$1"; out_html "$1"; } pr_cyanln_term() { pr_cyan_term "$1"; outln_term; } pr_cyanln() { pr_cyan "$1"; outln; } pr_litegreyln_term() { pr_litegrey_term "$1"; outln_term; } # not really usable on a black background, see .. pr_litegreyln() { pr_litegrey "$1"; outln; } pr_litegrey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 -pr_litegrey() { pr_litegrey_term "$1"; out_html "$1"; } +pr_litegrey() { pr_litegrey_term "$1"; out_html "$1"; } pr_grey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; } pr_grey() { pr_grey_term "$1"; out_html "$1"; } pr_greyln_term() { pr_grey_term "$1"; outln_term; } @@ -634,11 +634,11 @@ pr_done_bestln_term() { pr_done_best_term "$1"; outln_term; } pr_done_bestln() { pr_done_best "$1"; outln; } pr_svrty_low_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;33m$1" || out_term "$1"; pr_off; } # yellow brown | academic or minor problem -pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$1"; } +pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$1"; } pr_svrty_lowln_term() { pr_svrty_low_term "$1"; outln_term; } pr_svrty_lowln() { pr_svrty_low "$1"; outln; } pr_svrty_medium_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;33m$1" || out_term "$1"; pr_off; } # brown | it is not a bad problem but you shouldn't do this -pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$1"; } +pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$1"; } pr_svrty_mediumln_term() { pr_svrty_medium_term "$1"; outln_term; } pr_svrty_mediumln() { pr_svrty_medium "$1"; outln; } @@ -652,7 +652,7 @@ pr_svrty_criticalln_term() { pr_svrty_critical_term "$1"; outln_term; } pr_svrty_criticalln(){ pr_svrty_critical "$1"; outln; } pr_deemphasize_term() { out_term "$1"; } # hook for a weakened screen output, see #600 -pr_deemphasize() { pr_deemphasize_term "$1"; out_html "$1"; } +pr_deemphasize() { pr_deemphasize_term "$1"; out_html "$1"; } pr_deemphasizeln_term() { pr_deemphasize_term "$1"; outln_term; } pr_deemphasizeln() { pr_deemphasize "$1"; outln; } @@ -673,9 +673,9 @@ pr_strikethruln() { pr_strikethru "$1" ; outln; } pr_underline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[4m$1" || out_term "$1"; pr_off; } pr_underline() { pr_underline_term "$1"; out_html "$1"; } pr_reverse_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m$1" || out_term "$1"; pr_off; } -pr_reverse() { pr_reverse_term "$1"; out_html "$1"; } +pr_reverse() { pr_reverse_term "$1"; out_html "$1"; } pr_reverse_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m\033[1m$1" || out_term "$1"; pr_off; } -pr_reverse_bold() { pr_reverse_bold_term "$1"; out_html "$1"; } +pr_reverse_bold() { pr_reverse_bold_term "$1"; out_html "$1"; } #pr_headline() { pr_blue "$1"; } #http://misc.flogisoft.com/bash/tip_colors_and_formatting From 1c5ef78913659e90fe911f804bc2966ccc0e5fe2 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 8 Feb 2017 15:16:51 -0500 Subject: [PATCH 03/21] Another update to HTML colors For the most part I used the RGB values for xterm from https://en.wikipedia.org/wiki/ANSI_escape_code#Colors for the HTML colors, but with a few exceptions. For example, I did not use "yellow" for `pr_svrty_low()`, since that color is very difficult to read. I also used a different color for `pr_svrty_medium()` so that `pr_svrty_medium()` would appear more red than `pr_svrty_low()`. These color choices could use more adjustment. --- testssl.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/testssl.sh b/testssl.sh index da793b1..d25730b 100755 --- a/testssl.sh +++ b/testssl.sh @@ -590,16 +590,16 @@ retstring(){ # color print functions, see also http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html pr_liteblue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;32m$1" || out_term "\033[0;34m$1" ) || out_term "$1"; pr_off; } # not yet used -pr_liteblue() { pr_liteblue_term "$1"; out_html "$1"; } +pr_liteblue() { pr_liteblue_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } pr_liteblueln_term() { pr_liteblue_term "$1"; outln_term; } pr_liteblueln() { pr_liteblue "$1"; outln; } pr_blue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;32m$1" || out_term "\033[1;34m$1" ) || out_term "$1"; pr_off; } # used for head lines of single tests -pr_blue() { pr_blue_term "$1"; out_html "$1"; } +pr_blue() { pr_blue_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } pr_blueln_term() { pr_blue_term "$1"; outln_term; } pr_blueln() { pr_blue "$1"; outln; } pr_warning_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;35m$1" || pr_underline_term "$1"; pr_off; } # some local problem: one test cannot be done -pr_warning() { pr_warning_term "$1"; out_html "$1"; } +pr_warning() { pr_warning_term "$1"; out_html "$1"; } pr_warningln_term() { pr_warning_term "$1"; outln_term; } # litemagenta pr_warningln() { pr_warning "$1"; outln; } pr_magenta_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;35m$1" || pr_underline_term "$1"; pr_off; } # fatal error: quitting because of this! @@ -608,7 +608,7 @@ pr_magentaln_term() { pr_magenta_term "$1"; outln_term; } pr_magentaln() { pr_magenta "$1"; outln; } pr_litecyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;36m$1" || out_term "$1"; pr_off; } # not yet used -pr_litecyan() { pr_litecyan_term "$1"; out_html "$1"; } +pr_litecyan() { pr_litecyan_term "$1"; out_html "$1"; } pr_litecyanln_term() { pr_litecyan_term "$1"; outln_term; } pr_litecyanln() { pr_litecyan "$1"; outln; } pr_cyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;36m$1" || out_term "$1"; pr_off; } # additional hint @@ -621,30 +621,30 @@ pr_litegreyln() { pr_litegrey "$1"; outln; } pr_litegrey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 pr_litegrey() { pr_litegrey_term "$1"; out_html "$1"; } pr_grey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; } -pr_grey() { pr_grey_term "$1"; out_html "$1"; } +pr_grey() { pr_grey_term "$1"; out_html "$1"; } pr_greyln_term() { pr_grey_term "$1"; outln_term; } pr_greyln() { pr_grey "$1"; outln; } pr_done_good_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;34m$1" || out_term "\033[0;32m$1" ) || out_term "$1"; pr_off; } # litegreen (liteblue), This is good -pr_done_good() { pr_done_good_term "$1"; out_html "$1"; } +pr_done_good() { pr_done_good_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } pr_done_goodln_term() { pr_done_good_term "$1"; outln_term; } pr_done_goodln() { pr_done_good "$1"; outln; } pr_done_best_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;34m$1" || out_term "\033[1;32m$1" ) || out_term "$1"; pr_off; } # green (blue), This is the best -pr_done_best() { pr_done_best_term "$1"; out_html "$1"; } +pr_done_best() { pr_done_best_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } pr_done_bestln_term() { pr_done_best_term "$1"; outln_term; } pr_done_bestln() { pr_done_best "$1"; outln; } pr_svrty_low_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;33m$1" || out_term "$1"; pr_off; } # yellow brown | academic or minor problem -pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$1"; } +pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$1"; } pr_svrty_lowln_term() { pr_svrty_low_term "$1"; outln_term; } pr_svrty_lowln() { pr_svrty_low "$1"; outln; } pr_svrty_medium_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;33m$1" || out_term "$1"; pr_off; } # brown | it is not a bad problem but you shouldn't do this -pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$1"; } +pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$1"; } pr_svrty_mediumln_term() { pr_svrty_medium_term "$1"; outln_term; } pr_svrty_mediumln() { pr_svrty_medium "$1"; outln; } pr_svrty_high_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;31m$1" || pr_bold_term "$1"; pr_off; } # litered -pr_svrty_high() { pr_svrty_high_term "$1"; out_html "$1"; } +pr_svrty_high() { pr_svrty_high_term "$1"; out_html "$1"; } pr_svrty_highln_term() { pr_svrty_high_term "$1"; outln_term; } pr_svrty_highln() { pr_svrty_high "$1"; outln; } pr_svrty_critical_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;31m$1" || pr_bold_term "$1"; pr_off; } # red From a50488c44f11e222cadc291a9817284391ac8cd7 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 9 Feb 2017 17:03:21 -0500 Subject: [PATCH 04/21] Handle --file option Introduced "trick" so that if the `--file` option is used, `html_header()` will only be called once before anything is printed and `html_footer()` will only be called once after all printing is complete. With this, `html_header()` now delete the output file if it exists. Also introduced the `html_reserved()`, which is called for all text to be sent to `out_html()`. `html_reserved()` converts any HTML reserved characters (", ', &, <, >) to their corresponding entity names (", ', &, <, >). --- testssl.sh | 94 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/testssl.sh b/testssl.sh index d25730b..9c93718 100755 --- a/testssl.sh +++ b/testssl.sh @@ -158,6 +158,7 @@ LOGFILE=${LOGFILE:-""} # logfile if used JSONFILE=${JSONFILE:-""} # jsonfile if used CSVFILE=${CSVFILE:-""} # csvfile if used HTMLFILE=${CSVFILE:-""} # HTML if used +HTMLHEADER=true # include HTML headers and footers in HTML file, if one is being created APPEND=${APPEND:-false} # append to csv/json file instead of overwriting it GIVE_HINTS=false # give an addtional info to findings HAS_IPv6=${HAS_IPv6:-false} # if you have OpenSSL with IPv6 support AND IPv6 networking set it to yes @@ -586,106 +587,111 @@ outln_term() { out_term "$1\n"; } retstring(){ printf -- "%b" "${1//%/%%}" } + +# For HTML output, replace any HTML reserved characters with the entity name +html_reserved(){ + echo "$1" | sed -e 's/\&/\&/g' -e 's//\>/g' -e 's/"/\"/g' -e "s/'/\"/g" +} #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_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;32m$1" || out_term "\033[0;34m$1" ) || out_term "$1"; pr_off; } # not yet used -pr_liteblue() { pr_liteblue_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } +pr_liteblue() { pr_liteblue_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_liteblueln_term() { pr_liteblue_term "$1"; outln_term; } pr_liteblueln() { pr_liteblue "$1"; outln; } pr_blue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;32m$1" || out_term "\033[1;34m$1" ) || out_term "$1"; pr_off; } # used for head lines of single tests -pr_blue() { pr_blue_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } +pr_blue() { pr_blue_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_blueln_term() { pr_blue_term "$1"; outln_term; } pr_blueln() { pr_blue "$1"; outln; } pr_warning_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;35m$1" || pr_underline_term "$1"; pr_off; } # some local problem: one test cannot be done -pr_warning() { pr_warning_term "$1"; out_html "$1"; } +pr_warning() { pr_warning_term "$1"; out_html "$(html_reserved "$1")"; } pr_warningln_term() { pr_warning_term "$1"; outln_term; } # litemagenta pr_warningln() { pr_warning "$1"; outln; } pr_magenta_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;35m$1" || pr_underline_term "$1"; pr_off; } # fatal error: quitting because of this! -pr_magenta() { pr_magenta_term "$1"; out_html "$1"; } +pr_magenta() { pr_magenta_term "$1"; out_html "$(html_reserved "$1")"; } pr_magentaln_term() { pr_magenta_term "$1"; outln_term; } pr_magentaln() { pr_magenta "$1"; outln; } pr_litecyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;36m$1" || out_term "$1"; pr_off; } # not yet used -pr_litecyan() { pr_litecyan_term "$1"; out_html "$1"; } +pr_litecyan() { pr_litecyan_term "$1"; out_html "$(html_reserved "$1")"; } pr_litecyanln_term() { pr_litecyan_term "$1"; outln_term; } pr_litecyanln() { pr_litecyan "$1"; outln; } pr_cyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;36m$1" || out_term "$1"; pr_off; } # additional hint -pr_cyan() { pr_cyan_term "$1"; out_html "$1"; } +pr_cyan() { pr_cyan_term "$1"; out_html "$(html_reserved "$1")"; } pr_cyanln_term() { pr_cyan_term "$1"; outln_term; } pr_cyanln() { pr_cyan "$1"; outln; } pr_litegreyln_term() { pr_litegrey_term "$1"; outln_term; } # not really usable on a black background, see .. pr_litegreyln() { pr_litegrey "$1"; outln; } pr_litegrey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 -pr_litegrey() { pr_litegrey_term "$1"; out_html "$1"; } +pr_litegrey() { pr_litegrey_term "$1"; out_html "$(html_reserved "$1")"; } pr_grey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; } -pr_grey() { pr_grey_term "$1"; out_html "$1"; } +pr_grey() { pr_grey_term "$1"; out_html "$(html_reserved "$1")"; } pr_greyln_term() { pr_grey_term "$1"; outln_term; } pr_greyln() { pr_grey "$1"; outln; } pr_done_good_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;34m$1" || out_term "\033[0;32m$1" ) || out_term "$1"; pr_off; } # litegreen (liteblue), This is good -pr_done_good() { pr_done_good_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } +pr_done_good() { pr_done_good_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_done_goodln_term() { pr_done_good_term "$1"; outln_term; } pr_done_goodln() { pr_done_good "$1"; outln; } pr_done_best_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;34m$1" || out_term "\033[1;32m$1" ) || out_term "$1"; pr_off; } # green (blue), This is the best -pr_done_best() { pr_done_best_term "$1"; "$COLORBLIND" && out_html "$1" || out_html "$1"; } +pr_done_best() { pr_done_best_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_done_bestln_term() { pr_done_best_term "$1"; outln_term; } pr_done_bestln() { pr_done_best "$1"; outln; } pr_svrty_low_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;33m$1" || out_term "$1"; pr_off; } # yellow brown | academic or minor problem -pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$1"; } +pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$(html_reserved "$1")"; } pr_svrty_lowln_term() { pr_svrty_low_term "$1"; outln_term; } pr_svrty_lowln() { pr_svrty_low "$1"; outln; } pr_svrty_medium_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;33m$1" || out_term "$1"; pr_off; } # brown | it is not a bad problem but you shouldn't do this -pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$1"; } +pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$(html_reserved "$1")"; } pr_svrty_mediumln_term() { pr_svrty_medium_term "$1"; outln_term; } pr_svrty_mediumln() { pr_svrty_medium "$1"; outln; } pr_svrty_high_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;31m$1" || pr_bold_term "$1"; pr_off; } # litered -pr_svrty_high() { pr_svrty_high_term "$1"; out_html "$1"; } +pr_svrty_high() { pr_svrty_high_term "$1"; out_html "$(html_reserved "$1")"; } pr_svrty_highln_term() { pr_svrty_high_term "$1"; outln_term; } pr_svrty_highln() { pr_svrty_high "$1"; outln; } pr_svrty_critical_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;31m$1" || pr_bold_term "$1"; pr_off; } # red -pr_svrty_critical() { pr_svrty_critical_term "$1"; out_html "$1"; } +pr_svrty_critical() { pr_svrty_critical_term "$1"; out_html "$(html_reserved "$1")"; } pr_svrty_criticalln_term() { pr_svrty_critical_term "$1"; outln_term; } pr_svrty_criticalln(){ pr_svrty_critical "$1"; outln; } pr_deemphasize_term() { out_term "$1"; } # hook for a weakened screen output, see #600 -pr_deemphasize() { pr_deemphasize_term "$1"; out_html "$1"; } +pr_deemphasize() { pr_deemphasize_term "$1"; out_html "$(html_reserved "$1")"; } pr_deemphasizeln_term() { pr_deemphasize_term "$1"; outln_term; } pr_deemphasizeln() { pr_deemphasize "$1"; outln; } # color=1 functions pr_off() { [[ "$COLOR" -ne 0 ]] && out_term "\033[m"; } pr_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m$1" || out_term "$1"; pr_off; } -pr_bold() { pr_bold_term "$1"; out_html "$1"; } +pr_bold() { pr_bold_term "$1"; out_html "$(html_reserved "$1")"; } pr_boldln_term() { pr_bold_term "$1"; outln_term; } pr_boldln() { pr_bold "$1" ; outln; } pr_italic_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[3m$1" || out_term "$1"; pr_off; } -pr_italic() { pr_italic_term "$1"; out_html "$1"; } +pr_italic() { pr_italic_term "$1"; out_html "$(html_reserved "$1")"; } pr_italicln_term() { pr_italic_term "$1"; outln_term; } pr_italicln() { pr_italic "$1" ; outln; } pr_strikethru_term() { [[ "$COLOR" -ne 0 ]] && out "\033[9m$1" || out "$1"; pr_off; } # ugly! -pr_strikethru() { pr_strikethru_term "$1"; out_html "$1"; } +pr_strikethru() { pr_strikethru_term "$1"; out_html "$(html_reserved "$1")"; } pr_strikethruln_term() { pr_strikethru_term "$1"; outln_term; } pr_strikethruln() { pr_strikethru "$1" ; outln; } pr_underline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[4m$1" || out_term "$1"; pr_off; } -pr_underline() { pr_underline_term "$1"; out_html "$1"; } +pr_underline() { pr_underline_term "$1"; out_html "$(html_reserved "$1")"; } pr_underlineln_term() { pr_underline_term "$1"; outln_term; } pr_underlineln() { pr_underline "$1"; outln; } pr_reverse_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m$1" || out_term "$1"; pr_off; } -pr_reverse() { pr_reverse_term "$1"; out_html "$1"; } +pr_reverse() { pr_reverse_term "$1"; out_html "$(html_reserved "$1")"; } pr_reverse_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m\033[1m$1" || out_term "$1"; pr_off; } -pr_reverse_bold() { pr_reverse_bold_term "$1"; out_html "$1"; } +pr_reverse_bold() { pr_reverse_bold_term "$1"; out_html "$(html_reserved "$1")"; } #pr_headline() { pr_blue "$1"; } #http://misc.flogisoft.com/bash/tip_colors_and_formatting #pr_headline() { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m\033[47m$1" || out "$1"; pr_off; } pr_headline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m\033[4m$1" || out_term "$1"; pr_off; } -pr_headline() { pr_headline_term "$1"; out_html "$1"; } +pr_headline() { pr_headline_term "$1"; out_html "$(html_reserved "$1")"; } pr_headlineln_term() { pr_headline_term "$1"; outln_term; } pr_headlineln() { pr_headline "$1" ; outln; } @@ -963,21 +969,28 @@ fileout() { # ID, SEVERITY, FINDING, CVE, CWE, HINT ################### FILE FORMATING END ######################### html_header() { - out_html "\n" - out_html "\n" - out_html "\n" - out_html "\n" - out_html "\n" - out_html "testssl.sh\n" - out_html "\n" - out_html "\n" - out_html "
\n"
+     if "$HTMLHEADER"; then
+          rm -f "$HTMLFILE"
+          out_html "\n"
+          out_html "\n"
+          out_html "\n"
+          out_html "\n"
+          out_html "\n"
+          out_html "testssl.sh\n"
+          out_html "\n"
+          out_html "\n"
+          out_html "
\n"
+     fi
+     return 0
 }
 
 html_footer() {
-     out_html "
\n" - out_html "\n" - out_html "\n" + if "$HTMLHEADER"; then + out_html "
\n" + out_html "\n" + out_html "\n" + fi + return 0 } ###### helper function definitions ###### @@ -11322,6 +11335,7 @@ cleanup () { fi outln "$APPEND" || fileout_footer + html_footer } fatal() { @@ -11386,7 +11400,7 @@ ignore_no_or_lame() { [[ "$WARNINGS" == off ]] && return 0 [[ "$WARNINGS" == false ]] && return 0 [[ "$WARNINGS" == batch ]] && return 1 - pr_warning "$1 --> " + pr_warning_term "$1 --> " read a if [[ "$a" == "$(tolower "$2")" ]]; then $ok_arg return 0 @@ -12002,7 +12016,7 @@ datebanner() { # one line with char $1 over screen width $2 draw_line() { - printf -- "$1"'%.s' $(eval "echo {1.."$(($2))"}") + out "$(printf -- "$1"'%.s' $(eval "echo {1.."$(($2))"}"))" } @@ -12092,7 +12106,7 @@ run_mass_testing() { cmdline=$(filter_input "$cmdline") [[ -z "$cmdline" ]] && continue [[ "$cmdline" == "EOF" ]] && break - cmdline="$0 $global_cmdline --warnings=batch -q --append $cmdline" + cmdline="$0 $global_cmdline --warnings=batch -q --no-html-header --append $cmdline" draw_line "=" $((TERM_WIDTH / 2)); outln; outln "$cmdline" $cmdline @@ -12516,7 +12530,9 @@ parse_cmd_line() { exit -6 fi do_html=true - html_header + ;; + --no-html-header) + HTMLHEADER=false ;; --append) APPEND=true @@ -12700,6 +12716,7 @@ lets_roll() { initialize_globals parse_cmd_line "$@" +html_header get_install_dir set_color_functions maketempf @@ -12760,6 +12777,5 @@ else fi fi fi -html_footer exit $? From 2b5324b8efcec4d295bb7a0a8b7a9e1cf028484d Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 10 Feb 2017 10:59:20 -0500 Subject: [PATCH 05/21] Fix emphasize_stuff_in_headers() Changed `emphasize_stuff_in_headers()` so that the appropriate coloring would appear both in the terminal and in the HTML. It's slow, but it works. --- testssl.sh | 139 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 104 insertions(+), 35 deletions(-) diff --git a/testssl.sh b/testssl.sh index 9c93718..9f92e34 100755 --- a/testssl.sh +++ b/testssl.sh @@ -560,6 +560,12 @@ declare TLS_CIPHER_EXPORT=() declare TLS_CIPHER_OSSL_SUPPORTED=() ###### output functions ###### + +# For HTML output, replace any HTML reserved characters with the entity name +html_reserved(){ + echo "$1" | sed -e 's/\&/\&/g' -e 's//\>/g' -e 's/"/\"/g' -e "s/'/\'/g" +} + # a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%' and '--' does the rest. out_html() { "$do_html" && printf -- "%b" "${1//%/%%}" >> "$HTMLFILE" @@ -588,10 +594,6 @@ retstring(){ printf -- "%b" "${1//%/%%}" } -# For HTML output, replace any HTML reserved characters with the entity name -html_reserved(){ - echo "$1" | sed -e 's/\&/\&/g' -e 's//\>/g' -e 's/"/\"/g' -e "s/'/\"/g" -} #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 @@ -973,6 +975,7 @@ html_header() { rm -f "$HTMLFILE" out_html "\n" out_html "\n" + out_html "\n" out_html "\n" out_html "\n" out_html "\n" @@ -1369,7 +1372,7 @@ run_http_header() { "Testing HTTP header response @ \"$URL_PATH\", $HTTP_STATUS_CODE$msg_thereafter (Hint: better try another URL)" ;; 401) - grep -aq "^WWW-Authenticate" $HEADERFILE && out " "; strip_lf "$(grep -a "^WWW-Authenticate" $HEADERFILE)" + grep -aq "^WWW-Authenticate" $HEADERFILE && out " "; out "$(strip_lf "$(grep -a "^WWW-Authenticate" $HEADERFILE)")" fileout "HTTP_STATUS_CODE" "INFO" \ "Testing HTTP header response @ \"$URL_PATH\", $HTTP_STATUS_CODE$msg_thereafter $(grep -a "^WWW-Authenticate" $HEADERFILE)" ;; @@ -1817,36 +1820,102 @@ run_hpkp() { } emphasize_stuff_in_headers(){ -# see http://www.grymoire.com/Unix/Sed.html#uh-3 -# outln "$1" | sed "s/[0-9]*/$brown&$off/g" - outln "$1" | sed -e "s/\([0-9]\)/$brown\1$off/g" \ - -e "s/Debian/"$yellow"\Debian$off/g" \ - -e "s/Win32/"$yellow"\Win32$off/g" \ - -e "s/Win64/"$yellow"\Win64$off/g" \ - -e "s/Ubuntu/"$yellow"Ubuntu$off/g" \ - -e "s/ubuntu/"$yellow"ubuntu$off/g" \ - -e "s/jessie/"$yellow"jessie$off/g" \ - -e "s/squeeze/"$yellow"squeeze$off/g" \ - -e "s/wheezy/"$yellow"wheezy$off/g" \ - -e "s/lenny/"$yellow"lenny$off/g" \ - -e "s/SUSE/"$yellow"SUSE$off/g" \ - -e "s/Red Hat Enterprise Linux/"$yellow"Red Hat Enterprise Linux$off/g" \ - -e "s/Red Hat/"$yellow"Red Hat$off/g" \ - -e "s/CentOS/"$yellow"CentOS$off/g" \ - -e "s/Via/"$yellow"Via$off/g" \ - -e "s/X-Forwarded/"$yellow"X-Forwarded$off/g" \ - -e "s/Liferay-Portal/"$yellow"Liferay-Portal$off/g" \ - -e "s/X-Cache-Lookup/"$yellow"X-Cache-Lookup$off/g" \ - -e "s/X-Cache/"$yellow"X-Cache$off/g" \ - -e "s/X-Squid/"$yellow"X-Squid$off/g" \ - -e "s/X-Server/"$yellow"X-Server$off/g" \ - -e "s/X-Varnish/"$yellow"X-Varnish$off/g" \ - -e "s/X-OWA-Version/"$yellow"X-OWA-Version$off/g" \ - -e "s/MicrosoftSharePointTeamServices/"$yellow"MicrosoftSharePointTeamServices$off/g" \ - -e "s/X-Version/"$yellow"X-Version$off/g" \ - -e "s/X-Powered-By/"$yellow"X-Powered-By$off/g" \ - -e "s/X-UA-Compatible/"$yellow"X-UA-Compatible$off/g" \ - -e "s/X-AspNet-Version/"$yellow"X-AspNet-Version$off/g" + local text="$1" + local -i len + + len=${#text} + while [[ $len -gt 0 ]]; do + if [[ -z "$(tr -d '0-9' <<< "${text:0:1}")" ]]; then + out_term "$brown${text:0:1}$off" + out_html "${text:0:1}" + text="${text:1}" + len=$len-1 + elif [[ $len -ge 31 ]] && [[ "${text:0:31}" == "MicrosoftSharePointTeamServices" ]]; then + out_term "$yellow${text:0:31}$off" + out_html "${text:0:31}" + text="${text:31}" + len=$len-31 + elif [[ $len -ge 24 ]] && [[ "${text:0:24}" == "Red Hat Enterprise Linux" ]]; then + out_term "$yellow${text:0:24}$off" + out_html "${text:0:24}" + text="${text:24}" + len=$len-24 + elif [[ $len -ge 16 ]] && [[ "${text:0:16}" == "X-AspNet-Version" ]]; then + out_term "$yellow${text:0:16}$off" + out_html "${text:0:16}" + text="${text:16}" + len=$len-16 + elif [[ $len -ge 15 ]] && [[ "${text:0:15}" == "X-UA-Compatible" ]]; then + out_term "$yellow${text:0:15}$off" + out_html "${text:0:15}" + text="${text:15}" + len=$len-15 + elif [[ $len -ge 14 ]] && ( [[ "${text:0:14}" == "Liferay-Portal" ]] || [[ "${text:0:14}" == "X-Cache-Lookup" ]] || \ + [[ "${text:0:14}" == "X-Cache-Status" ]] ) ; then + out_term "$yellow${text:0:14}$off" + out_html "${text:0:14}" + text="${text:14}" + len=$len-14 + elif [[ $len -ge 13 ]] && [[ "${text:0:13}" == "X-OWA-Version" ]]; then + out_term "$yellow${text:0:13}$off" + out_html "${text:0:13}" + text="${text:13}" + len=$len-13 + elif [[ $len -ge 12 ]] && [[ "${text:0:12}" == "X-Powered-By" ]]; then + out_term "$yellow${text:0:12}$off" + out_html "${text:0:12}" + text="${text:12}" + len=$len-12 + elif [[ $len -ge 11 ]] && [[ "${text:0:11}" == "X-Forwarded" ]]; then + out_term "$yellow${text:0:11}$off" + out_html "${text:0:11}" + text="${text:11}" + len=$len-11 + elif [[ $len -ge 9 ]] && ( [[ "${text:0:9}" == "X-Varnish" ]] || [[ "${text:0:9}" == "X-Version" ]] ); then + out_term "$yellow${text:0:9}$off" + out_html "${text:0:9}" + text="${text:9}" + len=$len-9 + elif [[ $len -ge 8 ]] && [[ "${text:0:8}" == "X-Server" ]]; then + out_term "$yellow${text:0:8}$off" + out_html "${text:0:8}" + text="${text:8}" + len=$len-8 + elif [[ $len -ge 7 ]] && ( [[ "${text:0:7}" == "squeeze" ]] || [[ "${text:0:7}" == "Red Hat" ]] || \ + [[ "${text:0:7}" == "X-Cache" ]] || [[ "${text:0:7}" == "X-Squid" ]] ) ; then + out_term "$yellow${text:0:7}$off" + out_html "${text:0:7}" + text="${text:7}" + len=$len-7 + elif [[ $len -ge 6 ]] && ( [[ "${text:0:6}" == "Debian" ]] || [[ "${text:0:6}" == "Ubuntu" ]] || \ + [[ "${text:0:6}" == "ubuntu" ]] || [[ "${text:0:6}" == "jessie" ]] || \ + [[ "${text:0:6}" == "wheezy" ]] || [[ "${text:0:6}" == "CentOS" ]] ) ; then + out_term "$yellow${text:0:6}$off" + out_html "${text:0:6}" + text="${text:6}" + len=$len-6 + elif [[ $len -ge 5 ]] && ( [[ "${text:0:5}" == "Win32" ]] || [[ "${text:0:5}" == "Win64" ]] || [[ "${text:0:5}" == "lenny" ]] ); then + out_term "$yellow${text:0:5}$off" + out_html "${text:0:5}" + text="${text:5}" + len=$len-5 + elif [[ $len -ge 4 ]] && [[ "${text:0:4}" == "SUSE" ]]; then + out_term "$yellow${text:0:4}$off" + out_html "${text:0:4}" + text="${text:4}" + len=$len-4 + elif [[ $len -ge 3 ]] && [[ "${text:0:3}" == "Via" ]]; then + out_term "$yellow${text:0:3}$off" + out_html "${text:0:3}" + text="${text:3}" + len=$len-3 + else + out "${text:0:1}" + text="${text:1}" + len=$len-1 + fi + done + outln } run_server_banner() { From 2652362ce0fa5d2c77cf9303612327eff7426cb9 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 10 Feb 2017 14:47:49 -0500 Subject: [PATCH 06/21] Final fixes Found more places where output should only go to terminal, or where it was only going to the terminal (e.g., printf) but should also be in the HTML. Also added the ability to include active URLs in the HTML output. To Do: Handle automatic generation of HTML file name and support for parallel testing. --- testssl.sh | 92 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/testssl.sh b/testssl.sh index 9f92e34..8633084 100755 --- a/testssl.sh +++ b/testssl.sh @@ -712,6 +712,9 @@ fixme() { pr_warning "fixme: $1"; } fixmeln_term() { pr_warningln_term "fixme: $1"; } fixmeln() { pr_warningln "fixme: $1"; } +pr_url() { out_term "$1"; out_html "$1"; } +pr_boldurl() { pr_bold_term "$1"; out_html "$1"; } + ### color switcher (see e.g. https://linuxtidbits.wordpress.com/2008/08/11/output-color-on-bash-scripts/ ### http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html set_color_functions() { @@ -2343,7 +2346,7 @@ openssl2rfc() { [[ "$1" == "${TLS_CIPHER_OSSL_NAME[i]}" ]] && rfcname="${TLS_CIPHER_RFC_NAME[i]}" && break done [[ "$rfcname" == "-" ]] && rfcname="" - [[ -n "$rfcname" ]] && out "$rfcname" + [[ -n "$rfcname" ]] && retstring "$rfcname" return 0 } @@ -2355,7 +2358,7 @@ rfc2openssl() { [[ "$1" == "${TLS_CIPHER_RFC_NAME[i]}" ]] && ossl_name="${TLS_CIPHER_OSSL_NAME[i]}" && break done [[ "$ossl_name" == "-" ]] && ossl_name="" - [[ -n "$ossl_name" ]] && out "$ossl_name" + [[ -n "$ossl_name" ]] && retstring "$ossl_name" return 0 } @@ -2990,7 +2993,7 @@ run_cipher_per_proto() { fi outln neat_header - outln " -ssl2 22 SSLv2\n -ssl3 00 SSLv3\n -tls1 01 TLS 1\n -tls1_1 02 TLS 1.1\n -tls1_2 03 TLS 1.2"| while read proto proto_hex proto_text; do + retstring " -ssl2 22 SSLv2\n -ssl3 00 SSLv3\n -tls1 01 TLS 1\n -tls1_1 02 TLS 1.1\n -tls1_2 03 TLS 1.2\n" | while read proto proto_hex proto_text; do "$using_sockets" || locally_supported "$proto" "$proto_text" || continue "$using_sockets" && out "$proto_text " outln @@ -3289,7 +3292,7 @@ create_client_simulation_tls_clienthello() { if [[ $offset -ge $tls_handshake_ascii_len ]]; then # No extensions - out "$tls_handshake_ascii" + retstring "$tls_handshake_ascii" return 0 fi @@ -4363,7 +4366,7 @@ run_prototest_openssl() { # idempotent function to add SSL/TLS protocols. It should ease testing # PROTOS_OFFERED's content is in openssl terminology add_tls_offered() { - grep -w "$1" <<< "$PROTOS_OFFERED" || PROTOS_OFFERED+="$1 " + grep -qw "$1" <<< "$PROTOS_OFFERED" || PROTOS_OFFERED+="$1 " } # function which checks whether SSLv2 - TLS 1.2 is being offereed @@ -5190,7 +5193,7 @@ cipher_pref_check() { pr_bold " Cipher order" - retstring " ssl3 00 SSLv3\n tls1 01 TLSv1\n tls1_1 02 TLSv1.1\n tls1_2 03 TLSv1.2\n"| while read p proto_hex proto; do + retstring " ssl3 00 SSLv3\n tls1 01 TLSv1\n tls1_1 02 TLSv1.1\n tls1_2 03 TLSv1.2\n" | while read p proto_hex proto; do order=""; ciphers_found_with_sockets=false if [[ $p == ssl3 ]] && ! "$HAS_SSL3" && ! "$using_sockets"; then out "\n SSLv3: "; local_problem "$OPENSSL doesn't support \"s_client -ssl3\""; @@ -5363,7 +5366,7 @@ cipher_pref_check() { order="" $OPENSSL s_client $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $SNI >$ERRFILE >$TMPFILE cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) - printf " %-10s %s " "$p:" "$cipher" + out "$(printf " %-10s %s " "$p:" "$cipher")" tested_cipher="-"$cipher order="$cipher" if ! "$FAST"; then @@ -6583,7 +6586,7 @@ run_server_defaults() { i=1 newhostcert=$(cat $HOSTCERT) while [[ $i -le $certs_found ]]; do - if [ "$newhostcert" == "${previous_hostcert[i]}" ]; then + if [[ "$newhostcert" == "${previous_hostcert[i]}" ]]; then match_found=true break; fi @@ -9304,12 +9307,12 @@ run_heartbleed(){ if [[ "${saved_sockreply[1]}" == "${saved_sockreply[2]}" ]] && [[ "${saved_sockreply[2]}" == "${saved_sockreply[3]}" ]] \ && "$found_500_oops"; then pr_done_best "not vulnerable (OK)$append" - [[ $DEBUG -ge 1 ]] && out_term ", successful weeded out vsftpd false positive" + [[ $DEBUG -ge 1 ]] && out ", successful weeded out vsftpd false positive" fileout "heartbleed" "OK" "Heartbleed: not vulnerable $append" "$cve" "$cwe" else out "likely " pr_svrty_critical "VULNERABLE (NOT ok)" - [[ $DEBUG -ge 1 ]] && out_term " use debug >=2 to confirm" + [[ $DEBUG -ge 1 ]] && out " use debug >=2 to confirm" fileout "heartbleed" "CRITICAL" "Heartbleed: likely VULNERABLE $append" "$cve" "$cwe" "$hint" fi else @@ -9850,7 +9853,7 @@ run_tls_poodle() { pr_bold " POODLE, TLS"; out " ($cve), experimental " #FIXME - echo "#FIXME" + pr_warningln "#FIXME" fileout "poodle_tls" "WARN" "POODLE, TLS: Not tested. Not yet implemented #FIXME" "$cve" "$cwe" return 7 } @@ -10285,7 +10288,9 @@ run_drown() { if [[ "$DEBUG" -ge 1 ]] || "$SHOW_CENSYS_LINK"; then # not advertising it as it after 5 tries and account is needed cert_fingerprint_sha2=${cert_fingerprint_sha2/SHA256 /} - outln "$spaces https://censys.io/ipv4?q=$cert_fingerprint_sha2 could help you to find out" + out "$spaces " + pr_url "https://censys.io/ipv4?q=$cert_fingerprint_sha2" + outln " could help you to find out" fileout "drown" "INFO" "make sure you don't use this certificate elsewhere with SSLv2 enabled services, see https://censys.io/ipv4?q=$cert_fingerprint_sha2" fi else @@ -10889,9 +10894,11 @@ run_youknowwho() { old_fart() { - outln "Get precompiled bins or compile https://github.com/PeterMosmans/openssl ." + out "Get precompiled bins or compile " + pr_url "https://github.com/PeterMosmans/openssl" + outln "." fileout "old_fart" "WARN" "Your $OPENSSL $OSSL_VER version is an old fart... . It doesn\'t make much sense to proceed. Get precompiled bins or compile https://github.com/PeterMosmans/openssl ." - fatal "Your $OPENSSL $OSSL_VER version is an old fart... . It doesn\'t make much sense to proceed." -5 + fatal "Your $OPENSSL $OSSL_VER version is an old fart... . It doesn't make much sense to proceed." -5 } # try very hard to determine the install path to get ahold of the mapping file and the CA bundles @@ -10977,7 +10984,7 @@ 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 ..." + outln_term " Looking some place else ..." elif [[ -x "$OPENSSL" ]]; then : # 1. all ok supplied $OPENSSL was found and has excutable bit set -- testrun comes below elif [[ -e "/mnt/c/Windows/System32/bash.exe" ]] && test_openssl_suffix "$(dirname "$(which openssl)")"; then @@ -11087,10 +11094,12 @@ check4openssl_oldfarts() { pr_warningln " Your \"$OPENSSL\" is way too old (/dev/null)\" [~$OPENSSL_NR_CIPHERS ciphers]" out " on $HNAME:" @@ -11536,10 +11546,10 @@ prepare_logging() { : # just for clarity: a log file was specified, no need to do anything else fi >$LOGFILE - outln "## Scan started as: \"$PROG_NAME $CMDLINE\"" >>${LOGFILE} - outln "## at $HNAME:$OPENSSL_LOCATION" >>${LOGFILE} - outln "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE" >>${LOGFILE} - outln "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n" >>${LOGFILE} + outln_term "## Scan started as: \"$PROG_NAME $CMDLINE\"" >>${LOGFILE} + outln_term "## at $HNAME:$OPENSSL_LOCATION" >>${LOGFILE} + outln_term "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE" >>${LOGFILE} + outln_term "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n" >>${LOGFILE} exec > >(tee -a ${LOGFILE}) # not decided yet. Maybe good to have a separate file or none at all #exec 2> >(tee -a ${LOGFILE} >&2) @@ -12031,8 +12041,8 @@ determine_service() { grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190 out " Service set:$CORRECT_SPACES STARTTLS via " fileout "service" "INFO" "$protocol" - toupper "$protocol" - [[ -n "$XMPP_HOST" ]] && echo -n " (XMPP domain=\'$XMPP_HOST\')" + out "$(toupper "$protocol")" + [[ -n "$XMPP_HOST" ]] && out " (XMPP domain=\'$XMPP_HOST\')" outln ;; *) outln @@ -12355,7 +12365,7 @@ parse_cmd_line() { case $STARTTLS_PROTOCOL in ftp|smtp|pop3|imap|xmpp|telnet|ldap|nntp|postgres) ;; ftps|smtps|pop3s|imaps|xmpps|telnets|ldaps|nntps|postgress) ;; - *) pr_magentaln "\nunrecognized STARTTLS protocol \"$1\", see help" 1>&2 + *) pr_magentaln_term "\nunrecognized STARTTLS protocol \"$1\", see help" 1>&2 help 1 ;; esac ;; @@ -12514,7 +12524,7 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift case "$WARNINGS" in batch|off|false) ;; - *) pr_magentaln "\nwarnings can be either \"batch\", \"off\" or \"false\"" + *) pr_magentaln_term "\nwarnings can be either \"batch\", \"off\" or \"false\"" help 1 esac ;; @@ -12532,7 +12542,7 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift case $DEBUG in [0-6]) ;; - *) pr_magentaln_term "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2 + *) pr_magentaln_term_term "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2 help 1 esac ;; @@ -12542,7 +12552,7 @@ parse_cmd_line() { case $COLOR in [0-2]) ;; *) COLOR=2 - pr_magentaln "\nunrecognized color: \"$1\", must be between 0..2" 1>&2 + pr_magentaln_term "\nunrecognized color: \"$1\", must be between 0..2" 1>&2 help 1 esac ;; @@ -12595,7 +12605,7 @@ parse_cmd_line() { HTMLFILE=$(parse_opt_equal_sign "$1" "$2") [[ $? -eq 0 ]] && shift if [[ -d "$HTMLFILE" ]]; then - pr_warningln_term "$HTMLFILE exists and is a directory" + pr_warningln_term_term "$HTMLFILE exists and is a directory" exit -6 fi do_html=true @@ -12620,7 +12630,7 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift case "$cipher_mapping" in no-rfc) unset ADD_RFC_STR;; - *) pr_magentaln "\nmapping can only be \"no-rfc\"" + *) pr_magentaln_term "\nmapping can only be \"no-rfc\"" help 1 ;; esac ;; @@ -12640,7 +12650,7 @@ parse_cmd_line() { (--) shift break ;; - (-*) pr_magentaln "0: unrecognized option \"$1\"" 1>&2; + (-*) pr_magentaln_term "0: unrecognized option \"$1\"" 1>&2; help 1 ;; (*) break @@ -12672,7 +12682,7 @@ nodeip_to_proper_ip6() { if is_ipv6addr $NODEIP; then ${UNBRACKTD_IPV6} || NODEIP="[$NODEIP]" len_nodeip=${#NODEIP} - CORRECT_SPACES="$(draw_line " " "$((len_nodeip - 17))" )" + CORRECT_SPACES="$(printf -- " "'%.s' $(eval "echo {1.."$((len_nodeip - 17))"}"))" # IPv6 addresses are longer, this varaible takes care that "further IP" and "Service" is properly aligned fi } From f633ce67d6ed46b775e830360e201d2eca26ccae Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 10 Feb 2017 15:05:43 -0500 Subject: [PATCH 07/21] Color change Change `emphasize_stuff_in_headers()` to use olive and bold olive rather than brown and yellow. This matches what `aha` creates and appears similar to what is displayed in the terminal on a Mac. Also, yellow text is very difficult to read. --- testssl.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/testssl.sh b/testssl.sh index 8633084..5d7e6c4 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1830,86 +1830,86 @@ emphasize_stuff_in_headers(){ while [[ $len -gt 0 ]]; do if [[ -z "$(tr -d '0-9' <<< "${text:0:1}")" ]]; then out_term "$brown${text:0:1}$off" - out_html "${text:0:1}" + out_html "${text:0:1}" text="${text:1}" len=$len-1 elif [[ $len -ge 31 ]] && [[ "${text:0:31}" == "MicrosoftSharePointTeamServices" ]]; then out_term "$yellow${text:0:31}$off" - out_html "${text:0:31}" + out_html "${text:0:31}" text="${text:31}" len=$len-31 elif [[ $len -ge 24 ]] && [[ "${text:0:24}" == "Red Hat Enterprise Linux" ]]; then out_term "$yellow${text:0:24}$off" - out_html "${text:0:24}" + out_html "${text:0:24}" text="${text:24}" len=$len-24 elif [[ $len -ge 16 ]] && [[ "${text:0:16}" == "X-AspNet-Version" ]]; then out_term "$yellow${text:0:16}$off" - out_html "${text:0:16}" + out_html "${text:0:16}" text="${text:16}" len=$len-16 elif [[ $len -ge 15 ]] && [[ "${text:0:15}" == "X-UA-Compatible" ]]; then out_term "$yellow${text:0:15}$off" - out_html "${text:0:15}" + out_html "${text:0:15}" text="${text:15}" len=$len-15 elif [[ $len -ge 14 ]] && ( [[ "${text:0:14}" == "Liferay-Portal" ]] || [[ "${text:0:14}" == "X-Cache-Lookup" ]] || \ [[ "${text:0:14}" == "X-Cache-Status" ]] ) ; then out_term "$yellow${text:0:14}$off" - out_html "${text:0:14}" + out_html "${text:0:14}" text="${text:14}" len=$len-14 elif [[ $len -ge 13 ]] && [[ "${text:0:13}" == "X-OWA-Version" ]]; then out_term "$yellow${text:0:13}$off" - out_html "${text:0:13}" + out_html "${text:0:13}" text="${text:13}" len=$len-13 elif [[ $len -ge 12 ]] && [[ "${text:0:12}" == "X-Powered-By" ]]; then out_term "$yellow${text:0:12}$off" - out_html "${text:0:12}" + out_html "${text:0:12}" text="${text:12}" len=$len-12 elif [[ $len -ge 11 ]] && [[ "${text:0:11}" == "X-Forwarded" ]]; then out_term "$yellow${text:0:11}$off" - out_html "${text:0:11}" + out_html "${text:0:11}" text="${text:11}" len=$len-11 elif [[ $len -ge 9 ]] && ( [[ "${text:0:9}" == "X-Varnish" ]] || [[ "${text:0:9}" == "X-Version" ]] ); then out_term "$yellow${text:0:9}$off" - out_html "${text:0:9}" + out_html "${text:0:9}" text="${text:9}" len=$len-9 elif [[ $len -ge 8 ]] && [[ "${text:0:8}" == "X-Server" ]]; then out_term "$yellow${text:0:8}$off" - out_html "${text:0:8}" + out_html "${text:0:8}" text="${text:8}" len=$len-8 elif [[ $len -ge 7 ]] && ( [[ "${text:0:7}" == "squeeze" ]] || [[ "${text:0:7}" == "Red Hat" ]] || \ [[ "${text:0:7}" == "X-Cache" ]] || [[ "${text:0:7}" == "X-Squid" ]] ) ; then out_term "$yellow${text:0:7}$off" - out_html "${text:0:7}" + out_html "${text:0:7}" text="${text:7}" len=$len-7 elif [[ $len -ge 6 ]] && ( [[ "${text:0:6}" == "Debian" ]] || [[ "${text:0:6}" == "Ubuntu" ]] || \ [[ "${text:0:6}" == "ubuntu" ]] || [[ "${text:0:6}" == "jessie" ]] || \ [[ "${text:0:6}" == "wheezy" ]] || [[ "${text:0:6}" == "CentOS" ]] ) ; then out_term "$yellow${text:0:6}$off" - out_html "${text:0:6}" + out_html "${text:0:6}" text="${text:6}" len=$len-6 elif [[ $len -ge 5 ]] && ( [[ "${text:0:5}" == "Win32" ]] || [[ "${text:0:5}" == "Win64" ]] || [[ "${text:0:5}" == "lenny" ]] ); then out_term "$yellow${text:0:5}$off" - out_html "${text:0:5}" + out_html "${text:0:5}" text="${text:5}" len=$len-5 elif [[ $len -ge 4 ]] && [[ "${text:0:4}" == "SUSE" ]]; then out_term "$yellow${text:0:4}$off" - out_html "${text:0:4}" + out_html "${text:0:4}" text="${text:4}" len=$len-4 elif [[ $len -ge 3 ]] && [[ "${text:0:3}" == "Via" ]]; then out_term "$yellow${text:0:3}$off" - out_html "${text:0:3}" + out_html "${text:0:3}" text="${text:3}" len=$len-3 else From fea2558b20a8a8c919c4d501db8013ca5546629e Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 10 Feb 2017 16:30:14 -0500 Subject: [PATCH 08/21] Show gray for COLOR=1 Gray should appear for COLOR=1 or COLOR=2. Since `pr_grey()` is basically the same as `out()` for COLOR=0, `mybanner()` should just call `pr_grey()` without checking the value of `$COLOR`. --- testssl.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 5d7e6c4..6d6e05b 100755 --- a/testssl.sh +++ b/testssl.sh @@ -626,9 +626,9 @@ pr_cyanln() { pr_cyan "$1"; outln; } pr_litegreyln_term() { pr_litegrey_term "$1"; outln_term; } # not really usable on a black background, see .. pr_litegreyln() { pr_litegrey "$1"; outln; } -pr_litegrey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 +pr_litegrey_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 pr_litegrey() { pr_litegrey_term "$1"; out_html "$(html_reserved "$1")"; } -pr_grey_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; } +pr_grey_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; } pr_grey() { pr_grey_term "$1"; out_html "$(html_reserved "$1")"; } pr_greyln_term() { pr_grey_term "$1"; outln_term; } pr_greyln() { pr_grey "$1"; outln; } @@ -11380,7 +11380,7 @@ EOF pr_bold "$bb1" pr_boldurl "$SWURL"; outln pr_bold " (" - [[ "$COLOR" -ne 0 ]] && pr_grey "$idtag" || out "$idtag" + pr_grey "$idtag" pr_boldln ")" pr_bold "$bb2" pr_boldurl "https://testssl.sh/bugs/"; outln From 376fb95d04ec2e5a1f644d77366644e997173e4c Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 10 Feb 2017 17:08:49 -0500 Subject: [PATCH 09/21] Follow $COLOR value in HTML output Use the value of `$COLOR` to affect the HTML output in addition to the output to the terminal. --- testssl.sh | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/testssl.sh b/testssl.sh index 6d6e05b..46b26e2 100755 --- a/testssl.sh +++ b/testssl.sh @@ -598,65 +598,65 @@ retstring(){ # color print functions, see also http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html pr_liteblue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;32m$1" || out_term "\033[0;34m$1" ) || out_term "$1"; pr_off; } # not yet used -pr_liteblue() { pr_liteblue_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } +pr_liteblue() { pr_liteblue_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; } pr_liteblueln_term() { pr_liteblue_term "$1"; outln_term; } pr_liteblueln() { pr_liteblue "$1"; outln; } pr_blue_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;32m$1" || out_term "\033[1;34m$1" ) || out_term "$1"; pr_off; } # used for head lines of single tests -pr_blue() { pr_blue_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } +pr_blue() { pr_blue_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; } pr_blueln_term() { pr_blue_term "$1"; outln_term; } pr_blueln() { pr_blue "$1"; outln; } pr_warning_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;35m$1" || pr_underline_term "$1"; pr_off; } # some local problem: one test cannot be done -pr_warning() { pr_warning_term "$1"; out_html "$(html_reserved "$1")"; } +pr_warning() { pr_warning_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); } pr_warningln_term() { pr_warning_term "$1"; outln_term; } # litemagenta pr_warningln() { pr_warning "$1"; outln; } pr_magenta_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;35m$1" || pr_underline_term "$1"; pr_off; } # fatal error: quitting because of this! -pr_magenta() { pr_magenta_term "$1"; out_html "$(html_reserved "$1")"; } +pr_magenta() { pr_magenta_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); } pr_magentaln_term() { pr_magenta_term "$1"; outln_term; } pr_magentaln() { pr_magenta "$1"; outln; } pr_litecyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;36m$1" || out_term "$1"; pr_off; } # not yet used -pr_litecyan() { pr_litecyan_term "$1"; out_html "$(html_reserved "$1")"; } +pr_litecyan() { pr_litecyan_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_litecyanln_term() { pr_litecyan_term "$1"; outln_term; } pr_litecyanln() { pr_litecyan "$1"; outln; } pr_cyan_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;36m$1" || out_term "$1"; pr_off; } # additional hint -pr_cyan() { pr_cyan_term "$1"; out_html "$(html_reserved "$1")"; } +pr_cyan() { pr_cyan_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_cyanln_term() { pr_cyan_term "$1"; outln_term; } pr_cyanln() { pr_cyan "$1"; outln; } pr_litegreyln_term() { pr_litegrey_term "$1"; outln_term; } # not really usable on a black background, see .. pr_litegreyln() { pr_litegrey "$1"; outln; } pr_litegrey_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; } # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876 -pr_litegrey() { pr_litegrey_term "$1"; out_html "$(html_reserved "$1")"; } +pr_litegrey() { pr_litegrey_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_grey_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; } -pr_grey() { pr_grey_term "$1"; out_html "$(html_reserved "$1")"; } +pr_grey() { pr_grey_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_greyln_term() { pr_grey_term "$1"; outln_term; } pr_greyln() { pr_grey "$1"; outln; } pr_done_good_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;34m$1" || out_term "\033[0;32m$1" ) || out_term "$1"; pr_off; } # litegreen (liteblue), This is good -pr_done_good() { pr_done_good_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } +pr_done_good() { pr_done_good_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; } pr_done_goodln_term() { pr_done_good_term "$1"; outln_term; } pr_done_goodln() { pr_done_good "$1"; outln; } pr_done_best_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;34m$1" || out_term "\033[1;32m$1" ) || out_term "$1"; pr_off; } # green (blue), This is the best -pr_done_best() { pr_done_best_term "$1"; "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } +pr_done_best() { pr_done_best_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; } pr_done_bestln_term() { pr_done_best_term "$1"; outln_term; } pr_done_bestln() { pr_done_best "$1"; outln; } pr_svrty_low_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;33m$1" || out_term "$1"; pr_off; } # yellow brown | academic or minor problem -pr_svrty_low() { pr_svrty_low_term "$1"; out_html "$(html_reserved "$1")"; } +pr_svrty_low() { pr_svrty_low_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_svrty_lowln_term() { pr_svrty_low_term "$1"; outln_term; } pr_svrty_lowln() { pr_svrty_low "$1"; outln; } pr_svrty_medium_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;33m$1" || out_term "$1"; pr_off; } # brown | it is not a bad problem but you shouldn't do this -pr_svrty_medium() { pr_svrty_medium_term "$1"; out_html "$(html_reserved "$1")"; } +pr_svrty_medium() { pr_svrty_medium_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_svrty_mediumln_term() { pr_svrty_medium_term "$1"; outln_term; } pr_svrty_mediumln() { pr_svrty_medium "$1"; outln; } pr_svrty_high_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;31m$1" || pr_bold_term "$1"; pr_off; } # litered -pr_svrty_high() { pr_svrty_high_term "$1"; out_html "$(html_reserved "$1")"; } +pr_svrty_high() { pr_svrty_high_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); } pr_svrty_highln_term() { pr_svrty_high_term "$1"; outln_term; } pr_svrty_highln() { pr_svrty_high "$1"; outln; } pr_svrty_critical_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;31m$1" || pr_bold_term "$1"; pr_off; } # red -pr_svrty_critical() { pr_svrty_critical_term "$1"; out_html "$(html_reserved "$1")"; } +pr_svrty_critical() { pr_svrty_critical_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); } pr_svrty_criticalln_term() { pr_svrty_critical_term "$1"; outln_term; } pr_svrty_criticalln(){ pr_svrty_critical "$1"; outln; } @@ -668,32 +668,32 @@ pr_deemphasizeln() { pr_deemphasize "$1"; outln; } # color=1 functions pr_off() { [[ "$COLOR" -ne 0 ]] && out_term "\033[m"; } pr_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m$1" || out_term "$1"; pr_off; } -pr_bold() { pr_bold_term "$1"; out_html "$(html_reserved "$1")"; } +pr_bold() { pr_bold_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_boldln_term() { pr_bold_term "$1"; outln_term; } pr_boldln() { pr_bold "$1" ; outln; } pr_italic_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[3m$1" || out_term "$1"; pr_off; } -pr_italic() { pr_italic_term "$1"; out_html "$(html_reserved "$1")"; } +pr_italic() { pr_italic_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_italicln_term() { pr_italic_term "$1"; outln_term; } pr_italicln() { pr_italic "$1" ; outln; } -pr_strikethru_term() { [[ "$COLOR" -ne 0 ]] && out "\033[9m$1" || out "$1"; pr_off; } # ugly! -pr_strikethru() { pr_strikethru_term "$1"; out_html "$(html_reserved "$1")"; } +pr_strikethru_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[9m$1" || out_term "$1"; pr_off; } # ugly! +pr_strikethru() { pr_strikethru_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_strikethruln_term() { pr_strikethru_term "$1"; outln_term; } pr_strikethruln() { pr_strikethru "$1" ; outln; } pr_underline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[4m$1" || out_term "$1"; pr_off; } -pr_underline() { pr_underline_term "$1"; out_html "$(html_reserved "$1")"; } +pr_underline() { pr_underline_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_underlineln_term() { pr_underline_term "$1"; outln_term; } pr_underlineln() { pr_underline "$1"; outln; } pr_reverse_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m$1" || out_term "$1"; pr_off; } -pr_reverse() { pr_reverse_term "$1"; out_html "$(html_reserved "$1")"; } +pr_reverse() { pr_reverse_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_reverse_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m\033[1m$1" || out_term "$1"; pr_off; } -pr_reverse_bold() { pr_reverse_bold_term "$1"; out_html "$(html_reserved "$1")"; } +pr_reverse_bold() { pr_reverse_bold_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } #pr_headline() { pr_blue "$1"; } #http://misc.flogisoft.com/bash/tip_colors_and_formatting #pr_headline() { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m\033[47m$1" || out "$1"; pr_off; } pr_headline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m\033[4m$1" || out_term "$1"; pr_off; } -pr_headline() { pr_headline_term "$1"; out_html "$(html_reserved "$1")"; } +pr_headline() { pr_headline_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; } pr_headlineln_term() { pr_headline_term "$1"; outln_term; } pr_headlineln() { pr_headline "$1" ; outln; } @@ -1826,6 +1826,10 @@ emphasize_stuff_in_headers(){ local text="$1" local -i len + if [[ $COLOR -ne 2 ]]; then + out "$text" + text="" + fi len=${#text} while [[ $len -gt 0 ]]; do if [[ -z "$(tr -d '0-9' <<< "${text:0:1}")" ]]; then From 308b24cbe98b77e30d2f5ede49bac80fa69a9428 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 14 Feb 2017 13:19:12 -0500 Subject: [PATCH 10/21] Let testssl.sh create HTML file name Add option for testssl.sh to create the HTML file name. If testssl.sh creates the file name, then, in the case of mass testing, a separate HTML file is created for each test (i.e., for each line in the file provided to `--file`). --- testssl.sh | 50 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/testssl.sh b/testssl.sh index fe05661..20ef416 100755 --- a/testssl.sh +++ b/testssl.sh @@ -569,7 +569,7 @@ html_reserved(){ # a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%' and '--' does the rest. out_html() { - "$do_html" && printf -- "%b" "${1//%/%%}" >> "$HTMLFILE" + "$do_html" && [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] && printf -- "%b" "${1//%/%%}" >> "$HTMLFILE" } out() { @@ -975,8 +975,17 @@ fileout() { # ID, SEVERITY, FINDING, CVE, CWE, HINT ################### FILE FORMATING END ######################### html_header() { + local fname_prefix="$1" + if "$HTMLHEADER"; then - rm -f "$HTMLFILE" + [[ -z "$fname_prefix" ]] && fname_prefix="$NODE"_"$PORT" + if [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]]; then + rm -f "$HTMLFILE" + elif [[ -z "$HTMLFILE" ]]; then + HTMLFILE=$fname_prefix-$(date +"%Y%m%d-%H%M".html) + else + HTMLFILE=$HTMLFILE/$fname_prefix-$(date +"%Y%m%d-%H%M".html) + fi out_html "\n" out_html "\n" out_html "\n" @@ -991,6 +1000,15 @@ html_header() { return 0 } +html_banner() { + if "$QUIET" && "$HTMLHEADER"; then + out_html "## Scan started as: \"$PROG_NAME $CMDLINE\"\n" + out_html "## at $HNAME:$OPENSSL_LOCATION\n" + out_html "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE\n" + out_html "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n\n" + fi +} + html_footer() { if "$HTMLHEADER"; then out_html "\n" @@ -11374,6 +11392,7 @@ file output options (can also be preset via environment variables): --jsonfile-pretty additional pretty structured output as JSON to the specified file --csv additional output of findings to CSV file in cwd --csvfile additional output as CSV to the specified file + --html additional output as HTML to file --htmlfile additional output as HTML to the specifed file --hints additional hints to findings --severity severities with lower level will be filtered for CSV+JSON, possible values @@ -12356,10 +12375,12 @@ run_mass_testing_parallel() { run_mass_testing() { local cmdline="" local global_cmdline=${CMDLINE%%--file*} + local html_header="" if [[ ! -r "$FNAME" ]] && "$IKNOW_FNAME"; then fatal "Can't read file \"$FNAME\"" "2" fi + [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] && html_header="--no-html-header" pr_reverse "====== Running in file batch mode with file=\"$FNAME\" ======"; outln "\n" APPEND=false # Make sure we close out our files @@ -12367,7 +12388,7 @@ run_mass_testing() { cmdline=$(filter_input "$cmdline") [[ -z "$cmdline" ]] && continue [[ "$cmdline" == "EOF" ]] && break - cmdline="$0 $global_cmdline --warnings=batch -q --no-html-header --append $cmdline" + cmdline="$0 $global_cmdline --warnings=batch -q $html_header --append $cmdline" draw_line "=" $((TERM_WIDTH / 2)); outln; outln "$cmdline" $cmdline @@ -12783,13 +12804,13 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift do_csv=true ;; + --html) + do_html=true + ;; # DEFINITION of HTMLFILE is not arg specified: automagically in parse_hn_port() + # following does the same but we can specify a file location additionally --htmlfile) HTMLFILE=$(parse_opt_equal_sign "$1" "$2") [[ $? -eq 0 ]] && shift - if [[ -d "$HTMLFILE" ]]; then - pr_warningln_term_term "$HTMLFILE exists and is a directory" - exit -6 - fi do_html=true ;; --no-html-header) @@ -12978,7 +12999,18 @@ lets_roll() { initialize_globals parse_cmd_line "$@" -html_header +if ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ); then + if "$do_display_only"; then + html_header "local-ciphers" + elif "$do_mass_testing"; then + html_header + elif "$do_mx_all_ips"; then + html_header "mx-$URI" + else + parse_hn_port "${URI}" # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now + html_header + fi +fi get_install_dir set_color_functions maketempf @@ -13003,6 +13035,7 @@ if $do_mass_testing; then exit $? fi +html_banner #TODO: there shouldn't be the need for a special case for --mx, only the ip adresses we would need upfront and the do-parser if $do_mx_all_ips; then query_globals # if we have just 1x "do_*" --> we do a standard run -- otherwise just the one specified @@ -13010,7 +13043,6 @@ if $do_mx_all_ips; then run_mx_all_ips "${URI}" $PORT # we should reduce run_mx_all_ips to the stuff neccessary as ~15 lines later we have sililar code ret=$? else - parse_hn_port "${URI}" # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now prepare_logging if ! determine_ip_addresses; then fatal "No IP address could be determined" 2 From 48088bbceb0caab4e420246c7fceb3c6aafc5769 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 14 Feb 2017 13:44:03 -0500 Subject: [PATCH 11/21] Cleanup Rearrange code so that in the case of just a single test, `parse_hn_port()` is not called earlier than it was previously unless it needs to be called in order to create the HTML file name. Doing this ensures that the banner is displayed even if the `$URI` cannot be parsed (except in the case that the `$URI` needs to be parsed in order to create a file name) and that any error messages created by `parse_hn_port()` will be included in the HTML, if possible. --- testssl.sh | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/testssl.sh b/testssl.sh index 20ef416..880e049 100755 --- a/testssl.sh +++ b/testssl.sh @@ -977,26 +977,24 @@ fileout() { # ID, SEVERITY, FINDING, CVE, CWE, HINT html_header() { local fname_prefix="$1" - if "$HTMLHEADER"; then - [[ -z "$fname_prefix" ]] && fname_prefix="$NODE"_"$PORT" - if [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]]; then - rm -f "$HTMLFILE" - elif [[ -z "$HTMLFILE" ]]; then - HTMLFILE=$fname_prefix-$(date +"%Y%m%d-%H%M".html) - else - HTMLFILE=$HTMLFILE/$fname_prefix-$(date +"%Y%m%d-%H%M".html) - fi - out_html "\n" - out_html "\n" - out_html "\n" - out_html "\n" - out_html "\n" - out_html "\n" - out_html "testssl.sh\n" - out_html "\n" - out_html "\n" - out_html "
\n"
+     [[ -z "$fname_prefix" ]] && fname_prefix="$NODE"_"$PORT"
+     if [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]]; then
+          rm -f "$HTMLFILE"
+     elif [[ -z "$HTMLFILE" ]]; then
+          HTMLFILE=$fname_prefix-$(date +"%Y%m%d-%H%M".html)
+     else
+          HTMLFILE=$HTMLFILE/$fname_prefix-$(date +"%Y%m%d-%H%M".html)
      fi
+     out_html "\n"
+     out_html "\n"
+     out_html "\n"
+     out_html "\n"
+     out_html "\n"
+     out_html "\n"
+     out_html "testssl.sh\n"
+     out_html "\n"
+     out_html "\n"
+     out_html "
\n"
      return 0
 }
 
@@ -12999,7 +12997,8 @@ lets_roll() {
 
 initialize_globals
 parse_cmd_line "$@"
-if ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ); then
+! "$do_html" && HTMLHEADER=false
+if "$HTMLHEADER" && ( ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ) ); then
      if "$do_display_only"; then
           html_header "local-ciphers"
      elif "$do_mass_testing"; then
@@ -13007,7 +13006,7 @@ if ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ); t
      elif "$do_mx_all_ips"; then
           html_header "mx-$URI"
      else
-          parse_hn_port "${URI}"    # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now
+          ( [[ -z "$HTMLFILE" ]] || [[ -d "$HTMLFILE" ]] ) && parse_hn_port "${URI}"    # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now
           html_header
      fi
 fi
@@ -13043,6 +13042,7 @@ if $do_mx_all_ips; then
      run_mx_all_ips "${URI}" $PORT # we should reduce run_mx_all_ips to the stuff neccessary as ~15 lines later we have sililar code
      ret=$?
 else
+     [[ -z "$NODE" ]] && parse_hn_port "${URI}"                                 # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now
      prepare_logging
      if ! determine_ip_addresses; then
           fatal "No IP address could be determined" 2

From 4b1435f958654d5ebdcac67a566058fac2d31fee Mon Sep 17 00:00:00 2001
From: David Cooper 
Date: Fri, 17 Feb 2017 16:40:50 -0500
Subject: [PATCH 12/21] Make link from redirect URL

If the HTTP Status Code includes a redirect URL, then make the URL a hyper link in the HTTP output.
---
 testssl.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/testssl.sh b/testssl.sh
index 88cdb95..2283d2c 100755
--- a/testssl.sh
+++ b/testssl.sh
@@ -1423,7 +1423,7 @@ run_http_header() {
      case $HTTP_STATUS_CODE in
           301|302|307|308)
                redirect=$(grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n')
-               out ", redirecting to \"$redirect\""
+               out ", redirecting to \""; pr_url "$redirect"; out "\""
                if [[ $redirect == "http://"* ]]; then
                     pr_svrty_high " -- Redirect to insecure URL (NOT ok)"
                     fileout "HTTP_STATUS_CODE" "HIGH" \, "Redirect to insecure URL. Url: \"$redirect\""

From 8d66786e42cc296937ba6b9bbdfe73d9be8209e2 Mon Sep 17 00:00:00 2001
From: Dirk 
Date: Sat, 25 Feb 2017 16:31:30 +0100
Subject: [PATCH 13/21] Just saving my workJust saving my work  ...

This branch is for getting the HTML patch from @dcooper16 into 2.9dev

Change to David's PR:
* removed HTMLHEADER. We always want that (in fact for flat JSON this is missing and needs to be added)
* not sure what this change does to --file
* changing of names  They were redundant sometimes (pr_*_term )
* some formatting for readbility

Open points:
* there's a loop and a segfault --> tm_done_best
* HTMLHEADER: --file
* the former sed statement aroung L1900 for the header was way more readable. The combined
  html+terminal version is just too much. Maybe a switch whether HTML is requested
  is better so that this can be separated.
  * Then e.g. "/\>/g' -e 's/"/\"/g' -e "s/'/\'/g"
+    sed  -e 's/\&/\&/g' -e 's//\>/g' -e 's/"/\"/g' -e "s/'/\'/g" <<< "$1"
 }
 
-# a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%' and '--' does the rest.
-out_html() {
-     "$do_html" && [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] && printf -- "%b" "${1//%/%%}" >> "$HTMLFILE"
+html_out() {
+     "$do_html" || return
+     [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] && printf -- "%b" "${1//%/%%}" >> "$HTMLFILE"
+     # here and other printf's: a little bit of sanitzing with bash internal search&replace -- otherwise printf will hiccup at '%'. '--' and %b do the rest.
 }
 
 out() {
-#     if [[ "$BASH_VERSINFO" -eq 4 ]]; then
-          printf -- "%b" "${1//%/%%}"
-          out_html "$1"
-#     else
-#          /usr/bin/printf -- "${1//%/%%}"
-#     fi
+     printf -- "%b" "${1//%/%%}"
+     html_out "$1"
 }
 outln() { out "$1\n"; }
 
-out_term(){
-#     if [[ "$BASH_VERSINFO" -eq 4 ]]; then
-          printf -- "%b" "${1//%/%%}"
-#     else
-#          /usr/bin/printf -- "${1//%/%%}"
-#     fi
-}
-outln_term() { out_term "$1\n"; }
-
-retstring(){
-          printf -- "%b" "${1//%/%%}"
+tm_out(){
+     printf -- "%b" "${1//%/%%}"
 }
+tmln_out() { tm_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_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;32m$1" || out_term "\033[0;34m$1" ) || out_term "$1"; pr_off; }    # not yet used
-pr_liteblue()      { pr_liteblue_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; }
-pr_liteblueln_term() { pr_liteblue_term "$1"; outln_term; }
-pr_liteblueln() { pr_liteblue "$1"; outln; }
-pr_blue_term()  { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;32m$1" || out_term "\033[1;34m$1" ) || out_term "$1"; pr_off; }    # used for head lines of single tests
-pr_blue()       { pr_blue_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; }
-pr_blueln_term() { pr_blue_term "$1"; outln_term; }
-pr_blueln()     { pr_blue "$1"; outln; }
+tm_liteblue()   { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && tm_out "\033[0;32m$1" || tm_out "\033[0;34m$1" ) || tm_out "$1"; tm_off; }    # not yet used
+pr_liteblue()   { tm_liteblue "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ) || html_out "$(html_reserved "$1")"; }
+tmln_liteblue() { tm_liteblue "$1"; tmln_out; }
+prln_liteblue() { pr_liteblue "$1"; outln; }
 
-pr_warning_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;35m$1" || pr_underline_term "$1"; pr_off; }                     # some local problem: one test cannot be done
-pr_warning()      { pr_warning_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); }
-pr_warningln_term() { pr_warning_term "$1"; outln_term; }                                                                    # litemagenta
-pr_warningln()      { pr_warning "$1"; outln; }
-pr_magenta_term()   { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;35m$1" || pr_underline_term "$1"; pr_off; }                   # fatal error: quitting because of this!
-pr_magenta()        { pr_magenta_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); }
-pr_magentaln_term() { pr_magenta_term "$1"; outln_term; }
-pr_magentaln()      { pr_magenta "$1"; outln; }
+tm_blue()       { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && tm_out "\033[1;32m$1" || tm_out "\033[1;34m$1" ) || tm_out "$1"; tm_off; }    # used for head lines of single tests
+pr_blue()       { tm_blue "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ) || html_out "$(html_reserved "$1")"; }
+tmln_blue()     { tm_blue "$1"; tmln_out; }
+prln_blue()     { pr_blue "$1"; outln; }
 
-pr_litecyan_term()   { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;36m$1" || out_term "$1"; pr_off; }                           # not yet used
-pr_litecyan()   { pr_litecyan_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_litecyanln_term() { pr_litecyan_term "$1"; outln_term; }
-pr_litecyanln() { pr_litecyan "$1"; outln; }
-pr_cyan_term()  { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;36m$1" || out_term "$1"; pr_off; }                                # additional hint
-pr_cyan()       { pr_cyan_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_cyanln_term() { pr_cyan_term "$1"; outln_term; }
-pr_cyanln()     { pr_cyan "$1"; outln; }
+# we should be able to use aliases here
+tm_warning()    { [[ "$COLOR" -eq 2 ]] && tm_out "\033[0;35m$1" || tm_underline "$1"; tm_off; }                   # some local problem: one test cannot be done
+tmln_warning()  { tm_warning "$1"; tmln_out; }                                                                    # litemagenta
+pr_warning()    { tm_warning "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ); }
+prln_warning()  { pr_warning "$1"; outln; }
 
-pr_litegreyln_term() { pr_litegrey_term "$1"; outln_term; }                                                                  # not really usable on a black background, see ..
-pr_litegreyln() { pr_litegrey "$1"; outln; }
-pr_litegrey_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[0;37m$1" || out_term "$1"; pr_off; }                             # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876
-pr_litegrey()   { pr_litegrey_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_grey_term()  { [[ "$COLOR" -ne 0 ]] && out_term "\033[1;30m$1" || out_term "$1"; pr_off; }
-pr_grey()       { pr_grey_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_greyln_term() { pr_grey_term "$1"; outln_term; }
-pr_greyln()     { pr_grey "$1"; outln; }
+tm_magenta()    { [[ "$COLOR" -eq 2 ]] && tm_out "\033[1;35m$1" || tm_underline "$1"; tm_off; }                   # fatal error: quitting because of this!
+tmln_magenta()  { tm_magenta "$1"; tmln_out; }
+# different as warning above?
+pr_magenta()    { tm_magenta "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ); }
+prln_magenta()  { pr_magenta "$1"; outln; }
 
-pr_done_good_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[0;34m$1" || out_term "\033[0;32m$1" ) || out_term "$1"; pr_off; }   # litegreen (liteblue), This is good
-pr_done_good()      { pr_done_good_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; }
-pr_done_goodln_term() { pr_done_good_term "$1"; outln_term; }
-pr_done_goodln()    { pr_done_good "$1"; outln; }
-pr_done_best_term() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_term "\033[1;34m$1" || out_term "\033[1;32m$1" ) ||  out_term "$1"; pr_off; }  # green (blue), This is the best
-pr_done_best()      { pr_done_best_term "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ) || out_html "$(html_reserved "$1")"; }
-pr_done_bestln_term() { pr_done_best_term "$1"; outln_term; }
-pr_done_bestln()    { pr_done_best "$1"; outln; }
+tm_litecyan()   { [[ "$COLOR" -eq 2 ]] && tm_out "\033[0;36m$1" || tm_out "$1"; tm_off; }                         # not yet used
+tmln_litecyan() { tm_litecyan "$1"; tmln_out; }
+pr_litecyan()   { tm_litecyan "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+prln_litecyan() { pr_litecyan "$1"; outln; }
 
-pr_svrty_low_term()  { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;33m$1" || out_term "$1"; pr_off; }         # yellow brown | academic or minor problem
-pr_svrty_low()       { pr_svrty_low_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_svrty_lowln_term() { pr_svrty_low_term "$1"; outln_term; }
-pr_svrty_lowln()     { pr_svrty_low "$1"; outln; }
-pr_svrty_medium_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;33m$1" || out_term "$1"; pr_off; }       # brown | it is not a bad problem but you shouldn't do this
-pr_svrty_medium()    { pr_svrty_medium_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_svrty_mediumln_term() { pr_svrty_medium_term "$1"; outln_term; }
-pr_svrty_mediumln()  { pr_svrty_medium "$1"; outln; }
+tm_cyan()       { [[ "$COLOR" -eq 2 ]] && tm_out "\033[1;36m$1" || tm_out "$1"; tm_off; }                         # additional hint
+tmln_cyan()     { tm_cyan "$1"; tmln_out; }
+pr_cyan()       { tm_cyan "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+prln_cyan()     { pr_cyan "$1"; outln; }
 
-pr_svrty_high_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[0;31m$1" || pr_bold_term "$1"; pr_off; }               # litered
-pr_svrty_high()      { pr_svrty_high_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); }
-pr_svrty_highln_term() { pr_svrty_high_term "$1"; outln_term; }
-pr_svrty_highln()    { pr_svrty_high "$1"; outln; }
-pr_svrty_critical_term() { [[ "$COLOR" -eq 2 ]] && out_term "\033[1;31m$1" || pr_bold_term "$1"; pr_off; }           # red
-pr_svrty_critical()  { pr_svrty_critical_term "$1"; [[ "$COLOR" -eq 2 ]] && out_html "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")" ); }
-pr_svrty_criticalln_term() { pr_svrty_critical_term "$1"; outln_term; }
-pr_svrty_criticalln(){ pr_svrty_critical "$1"; outln; }
+tm_litegrey()   { [[ "$COLOR" -ne 0 ]] && tm_out "\033[0;37m$1" || tm_out "$1"; tm_off; }                        # ... https://github.com/drwetter/testssl.sh/pull/600#issuecomment-276129876
+tmln_litegrey() { tm_litegrey "$1"; tmln_out; }                                                                  # not really usable on a black background, see ..
+prln_litegrey() { pr_litegrey "$1"; outln; }
+pr_litegrey()   { tm_litegrey "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
 
-pr_deemphasize_term() { out_term "$1"; }                                                                   # hook for a weakened screen output, see #600
-pr_deemphasize()      { pr_deemphasize_term "$1"; out_html "$(html_reserved "$1")"; }
-pr_deemphasizeln_term() { pr_deemphasize_term "$1"; outln_term; }
-pr_deemphasizeln()    { pr_deemphasize "$1"; outln; }
+tm_grey()       { [[ "$COLOR" -ne 0 ]] && tm_out "\033[1;30m$1" || tm_out "$1"; tm_off; }
+pr_grey()       { tm_grey "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+tmln_grey()     { tm_grey "$1"; tmln_out; }
+prln_grey()     { pr_grey "$1"; outln; }
+
+tm_done_good()   { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && tm_out "\033[0;34m$1" || tm_out "\033[0;32m$1" ) || tm_out "$1"; tm_off; }   # litegreen (liteblue), This is good
+tmln_done_good() { tm_done_good "$1"; tmln_out; }
+pr_done_good()   { tm_done_good "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ) || html_out "$(html_reserved "$1")"; }
+prln_done_good() { pr_done_good "$1"; outln; }
+
+tm_done_best()   { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && tm_out "\033[1;34m$1" || tm_out "\033[1;32m$1" ) ||  tm_out "$1"; tm_off; }  # green (blue), This is the best
+pr_done_best()   { tm_done_best "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ) || html_out "$(html_reserved "$1")"; }
+tm_done_best()   { tm_done_best "$1"; tmln_out; }
+prln_done_best() { pr_done_best "$1"; outln; } 
+
+tm_svrty_low()     { [[ "$COLOR" -eq 2 ]] && tm_out "\033[1;33m$1" || tm_out "$1"; tm_off; }         # yellow brown | academic or minor problem
+tmln_svrty_low()   { tm_svrty_low "$1"; tmln_out; }
+pr_svrty_low()     { tm_svrty_low "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+prln_svrty_low()   { pr_svrty_low "$1"; outln; }
+
+tm_svrty_medium()  { [[ "$COLOR" -eq 2 ]] && tm_out "\033[0;33m$1" || tm_out "$1"; tm_off; }       # brown | it is not a bad problem but you shouldn't do this
+pr_svrty_medium()  { tm_svrty_medium "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+tmln_svrty_medium(){ tm_svrty_medium "$1"; tmln_out; }
+prln_svrty_medium(){ pr_svrty_medium "$1"; outln; }
+
+tm_svrty_high()    { [[ "$COLOR" -eq 2 ]] && tm_out "\033[0;31m$1" || tm_bold "$1"; tm_off; }               # litered
+pr_svrty_high()    { tm_svrty_high "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ); }
+tmln_svrty_high()  { tm_svrty_high "$1"; tmln_out; }
+prln_svrty_high()  { pr_svrty_high "$1"; outln; }
+
+tm_svrty_critical()   { [[ "$COLOR" -eq 2 ]] && tm_out "\033[1;31m$1" || tm_bold "$1"; tm_off; }           # red
+pr_svrty_critical()   { tm_svrty_critical "$1"; [[ "$COLOR" -eq 2 ]] && html_out "$(html_reserved "$1")" || ( [[ "$COLOR" -eq 1 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ); }
+tmln_svrty_critical() { tm_svrty_critical "$1"; tmln_out; }
+prln_svrty_critical() { pr_svrty_critical "$1"; outln; }
+
+tm_deemphasize()      { tm_out "$1"; }                                                                   # hook for a weakened screen output, see #600
+pr_deemphasize()      { tm_deemphasize "$1"; html_out "$(html_reserved "$1")"; }
+tmln_deemphasize()    { tm_deemphasize "$1"; tmln_out; }
+prln_deemphasize()    { pr_deemphasize "$1"; outln; }
 
 # color=1 functions
-pr_off()          { [[ "$COLOR" -ne 0 ]] && out_term "\033[m"; }
-pr_bold_term()    { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m$1" || out_term "$1"; pr_off; }
-pr_bold()         { pr_bold_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_boldln_term()  { pr_bold_term "$1"; outln_term; }
-pr_boldln()       { pr_bold "$1" ; outln; }
-pr_italic_term()  { [[ "$COLOR" -ne 0 ]] && out_term "\033[3m$1" || out_term "$1"; pr_off; }
-pr_italic()       { pr_italic_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_italicln_term() { pr_italic_term "$1"; outln_term; }
-pr_italicln()     { pr_italic "$1" ; outln; }
-pr_strikethru_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[9m$1" || out_term "$1"; pr_off; }                          # ugly!
-pr_strikethru()   { pr_strikethru_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_strikethruln_term() { pr_strikethru_term "$1"; outln_term; }
-pr_strikethruln() { pr_strikethru "$1" ; outln; }
-pr_underline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[4m$1" || out_term "$1"; pr_off; }
-pr_underline()    { pr_underline_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_underlineln_term() { pr_underline_term "$1"; outln_term; }
-pr_underlineln()  { pr_underline "$1"; outln; }
-pr_reverse_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m$1" || out_term "$1"; pr_off; }
-pr_reverse()      { pr_reverse_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_reverse_bold_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[7m\033[1m$1" || out_term "$1"; pr_off; }
-pr_reverse_bold() { pr_reverse_bold_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
+tm_off()        { [[ "$COLOR" -ne 0 ]] && tm_out "\033[m"; }
+
+tm_bold()       { [[ "$COLOR" -ne 0 ]] && tm_out "\033[1m$1" || tm_out "$1"; tm_off; }
+tmln_bold()     { tm_bold "$1"; tmln_out; }
+pr_bold()       { tm_bold "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+prln_bold()     { pr_bold "$1" ; outln; }
+
+tm_italic()     { [[ "$COLOR" -ne 0 ]] && tm_out "\033[3m$1" || tm_out "$1"; tm_off; }
+tm_italic()     { pr_italic "$1" ; outln; }
+pr_italic()     { tm_italic "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+tmln_italic()   { tm_italic "$1"; tmln_out; }
+
+tm_strikethru()   { [[ "$COLOR" -ne 0 ]] && tm_out "\033[9m$1" || tm_out "$1"; tm_off; }                          # ugly!
+tmln_strikethru() { tm_strikethru "$1"; tmln_out; }
+pr_strikethru()   { tm_strikethru "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+prln_strikethru() { pr_strikethru "$1" ; outln; }
+
+tm_underline()    { [[ "$COLOR" -ne 0 ]] && tm_out "\033[4m$1" || tm_out "$1"; tm_off; }
+tmln_underline()  { tm_underline "$1"; tmln_out; }
+pr_underline()    { tm_underline "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+prln_underline()  { pr_underline "$1"; outln; }
+
+tm_reverse()      { [[ "$COLOR" -ne 0 ]] && tm_out "\033[7m$1" || tm_out "$1"; tm_off; }
+tm_reverse_bold() { [[ "$COLOR" -ne 0 ]] && tm_out "\033[7m\033[1m$1" || tm_out "$1"; tm_off; }
+pr_reverse()      { tm_reverse "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
+pr_reverse_bold() { tm_reverse_bold "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
 
 #pr_headline() { pr_blue "$1"; }
 #http://misc.flogisoft.com/bash/tip_colors_and_formatting
 
-#pr_headline() { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m\033[47m$1" || out "$1"; pr_off; }
-pr_headline_term() { [[ "$COLOR" -ne 0 ]] && out_term "\033[1m\033[4m$1" || out_term "$1"; pr_off; }
-pr_headline() { pr_headline_term "$1"; [[ "$COLOR" -ne 0 ]] && out_html "$(html_reserved "$1")" || out_html "$(html_reserved "$1")"; }
-pr_headlineln_term() { pr_headline_term "$1"; outln_term; }
+#pr_headline() { [[ "$COLOR" -eq 2 ]] && out "\033[1;30m\033[47m$1" || out "$1"; tm_off; }
+tm_headline()   { [[ "$COLOR" -ne 0 ]] && tm_out "\033[1m\033[4m$1" || tm_out "$1"; tm_off; }
+tmln_headline() { tm_headline "$1"; tmln_out; }
+pr_headline()   { tm_headline "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; }
 pr_headlineln() { pr_headline "$1" ; outln; }
 
-pr_squoted_term() { out_term "'$1'"; }
+tm_squoted() { tm_out "'$1'"; }
 pr_squoted() { out "'$1'"; }
-pr_dquoted_term() { out_term "\"$1\""; }
+tm_dquoted() { tm_out "\"$1\""; }
 pr_dquoted() { out "\"$1\""; }
 
-local_problem_term() { pr_warning_term "Local problem: $1"; }
-local_problem() { pr_warning "Local problem: $1"; }
-local_problem_ln_term() { pr_warningln_term "Local problem: $1"; }
-local_problem_ln() { pr_warningln "Local problem: $1"; }
+tm_local_problem()   { tm_warning "Local problem: $1"; }
+tmln_local_problem() { tmln_warning "Local problem: $1"; }
+pr_local_problem()   { pr_warning "Local problem: $1"; }
+prln_local_problem() { prln_warning "Local problem: $1"; }
 
-fixme_term() { pr_warning_term "fixme: $1"; }
-fixme() { pr_warning "fixme: $1"; }
-fixmeln_term() { pr_warningln_term "fixme: $1"; }
-fixmeln() { pr_warningln "fixme: $1"; }
+tm_fixme()   { tm_warning "pr_fixme: $1"; }
+tmln_fixme() { tmln_warning "pr_fixme: $1"; }
+pr_fixme()   { pr_warning "pr_fixme: $1"; }
+prln_fixme() { prln_warning "pr_fixme: $1"; }
 
-pr_url() { out_term "$1"; out_html "$1"; }
-pr_boldurl() { pr_bold_term "$1"; out_html "$1"; }
+pr_url()     { tm_out "$1"; html_out "$1"; }
+pr_boldurl() { tm_bold "$1"; html_out "$1"; }
 
 ### color switcher (see e.g. https://linuxtidbits.wordpress.com/2008/08/11/output-color-on-bash-scripts/
 ###                         http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
@@ -979,34 +981,30 @@ html_header() {
      else
           HTMLFILE=$HTMLFILE/$fname_prefix-$(date +"%Y%m%d-%H%M".html)
      fi
-     out_html "\n"
-     out_html "\n"
-     out_html "\n"
-     out_html "\n"
-     out_html "\n"
-     out_html "\n"
-     out_html "testssl.sh\n"
-     out_html "\n"
-     out_html "\n"
-     out_html "
\n"
+     html_out "\n"
+     html_out "\n"
+     html_out "\n"
+     html_out "\n"
+     html_out "\n"
+     html_out "\n"
+     html_out "testssl.sh\n"
+     html_out "\n"
+     html_out "\n"
+     html_out "
\n"
      return 0
 }
 
 html_banner() {
-     if "$QUIET" && "$HTMLHEADER"; then
-          out_html "## Scan started as: \"$PROG_NAME $CMDLINE\"\n"
-          out_html "## at $HNAME:$OPENSSL_LOCATION\n"
-          out_html "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE\n"
-          out_html "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n\n"
-     fi
+     html_out "## Scan started as: \"$PROG_NAME $CMDLINE\"\n"
+     html_out "## at $HNAME:$OPENSSL_LOCATION\n"
+     html_out "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE\n"
+     html_out "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n\n"
 }
 
 html_footer() {
-     if "$HTMLHEADER"; then
-          out_html "
\n" - out_html "\n" - out_html "\n" - fi + html_out "
\n" + html_out "\n" + html_out "\n" return 0 } @@ -1296,7 +1294,7 @@ string_to_asciihex() { output+="$(printf "%02x," "'${string:i:1}")" done [[ -n "$string" ]] && output+="$(printf "%02x" "'${string:eos:1}")" - retstring "$output" + tm_out "$output" return 0 } @@ -1536,7 +1534,7 @@ run_http_date() { out "Got no HTTP time, maybe try different URL?"; fileout "http_clock_skew" "INFO" "HTTP clock skew not measured. Got no HTTP time, maybe try different URL?" fi - debugme out_term ", epoch: $HTTP_TIME" + debugme tm_out ", epoch: $HTTP_TIME" fi outln detect_ipv4 @@ -1570,7 +1568,7 @@ detect_header() { out "\n$spaces" # first awk matches the key, second extracts the from the first line the value, be careful with quotes here! HEADERVALUE=$(grep -Faiw "$key:" $HEADERFILE | sed 's/^.*://' | head -1) - [[ $DEBUG -ge 2 ]] && pr_italic_term "$HEADERVALUE" && out_term "\n$spaces" + [[ $DEBUG -ge 2 ]] && tm_italic "$HEADERVALUE" && tm_out "\n$spaces" fileout "$2""_multiple" "WARN" "Multiple $2 headers. Using first header: $HEADERVALUE" return $nr fi @@ -1735,7 +1733,7 @@ run_hpkp() { # Get the SPKIs first spki=$(tr ';' '\n' < $TMPFILE | tr -d ' ' | tr -d '\"' | awk -F'=' '/pin.*=/ { print $2 }') - debugme outln_term "\n$spki" + debugme tmln_out "\n$spki" # Look at the host certificate first # get the key fingerprint from the host certificate @@ -1785,7 +1783,7 @@ run_hpkp() { pr_done_good "$hpkp_spki" fileout "hpkp_$hpkp_spki" "OK" "SPKI $hpkp_spki matches the host certificate" fi - debugme out_term "\n $hpkp_spki | $hpkp_spki_hostcert" + debugme tm_out "\n $hpkp_spki | $hpkp_spki_hostcert" # Check for intermediate match if ! "$certificate_found"; then @@ -1851,7 +1849,7 @@ run_hpkp() { if [[ -n "${backup_spki_str[0]}" ]]; then pr_done_good "${backup_spki[0]}" #out " Root CA: " - pr_italicln " ${backup_spki_str[0]}" + tm_italic " ${backup_spki_str[0]}" else outln "${backup_spki[0]}" fi @@ -1861,26 +1859,26 @@ run_hpkp() { # it's a Root CA outside the chain pr_done_good "$spaces_indented ${backup_spki[i]}" #out " Root CA: " - pr_italicln " ${backup_spki_str[i]}" + tm_italic " ${backup_spki_str[i]}" else outln "$spaces_indented ${backup_spki[i]}" fi done if [[ ! -f "$ca_hashes" ]] && "$spki_match"; then out "$spaces " - pr_warningln "Attribution of further hashes couldn't be done as $ca_hashes could not be found" + prln_warning "Attribution of further hashes couldn't be done as $ca_hashes could not be found" fileout "hpkp_spkimatch" "WARN" "Attribution of further hashes couldn't be done as $ca_hashes could not be found" fi # If all else fails... if ! "$spki_match"; then "$has_backup_spki" && out "$spaces" # we had a few lines with backup SPKIs already - pr_svrty_highln " No matching key for SPKI found " + prln_svrty_high " No matching key for SPKI found " fileout "hpkp_spkimatch" "HIGH" "None of the SPKI match your host certificate, intermediate CA or known root CAs. You may have bricked this site" fi if ! "$has_backup_spki"; then - pr_svrty_highln " No backup keys found. Loss/compromise of the currently pinned key(s) will lead to bricked site. " + prln_svrty_high " No backup keys found. Loss/compromise of the currently pinned key(s) will lead to bricked site. " fileout "hpkp_backup" "HIGH" "No backup keys found. Loss/compromise of the currently pinned key(s) will lead to bricked site." fi else @@ -1903,87 +1901,87 @@ emphasize_stuff_in_headers(){ len=${#text} while [[ $len -gt 0 ]]; do if [[ -z "$(tr -d '0-9' <<< "${text:0:1}")" ]]; then - out_term "${brown}${text:0:1}${off}" - out_html "${text:0:1}" + tm_out "${brown}${text:0:1}${off}" + html_out "${text:0:1}" text="${text:1}" len=$len-1 elif [[ $len -ge 31 ]] && [[ "${text:0:31}" == "MicrosoftSharePointTeamServices" ]]; then - out_term "${yellow}${text:0:31}${off}" - out_html "${text:0:31}" + tm_out "${yellow}${text:0:31}${off}" + html_out "${text:0:31}" text="${text:31}" len=$len-31 elif [[ $len -ge 24 ]] && [[ "${text:0:24}" == "Red Hat Enterprise Linux" ]]; then - out_term "${yellow}${text:0:24}${off}" - out_html "${text:0:24}" + tm_out "${yellow}${text:0:24}${off}" + html_out "${text:0:24}" text="${text:24}" len=$len-24 elif [[ $len -ge 16 ]] && [[ "${text:0:16}" == "X-AspNet-Version" ]]; then - out_term "${yellow}${text:0:16}${off}" - out_html "${text:0:16}" + tm_out "${yellow}${text:0:16}${off}" + html_out "${text:0:16}" text="${text:16}" len=$len-16 elif [[ $len -ge 15 ]] && [[ "${text:0:15}" == "X-UA-Compatible" ]]; then - out_term "${yellow}${text:0:15}${off}" - out_html "${text:0:15}" + tm_out "${yellow}${text:0:15}${off}" + html_out "${text:0:15}" text="${text:15}" len=$len-15 elif [[ $len -ge 14 ]] && ( [[ "${text:0:14}" == "Liferay-Portal" ]] || [[ "${text:0:14}" == "X-Cache-Lookup" ]] || \ [[ "${text:0:14}" == "X-Cache-Status" ]] ) ; then - out_term "${yellow}${text:0:14}${off}" - out_html "${text:0:14}" + tm_out "${yellow}${text:0:14}${off}" + html_out "${text:0:14}" text="${text:14}" len=$len-14 elif [[ $len -ge 13 ]] && [[ "${text:0:13}" == "X-OWA-Version" ]]; then - out_term "${yellow}${text:0:13}${off}" - out_html "${text:0:13}" + tm_out "${yellow}${text:0:13}${off}" + html_out "${text:0:13}" text="${text:13}" len=$len-13 elif [[ $len -ge 12 ]] && [[ "${text:0:12}" == "X-Powered-By" ]]; then - out_term "${yellow}${text:0:12}${off}" - out_html "${text:0:12}" + tm_out "${yellow}${text:0:12}${off}" + html_out "${text:0:12}" text="${text:12}" len=$len-12 elif [[ $len -ge 11 ]] && [[ "${text:0:11}" == "X-Forwarded" ]]; then - out_term "${yellow}${text:0:11}${off}" - out_html "${text:0:11}" + tm_out "${yellow}${text:0:11}${off}" + html_out "${text:0:11}" text="${text:11}" len=$len-11 elif [[ $len -ge 9 ]] && ( [[ "${text:0:9}" == "X-Varnish" ]] || [[ "${text:0:9}" == "X-Version" ]] ); then - out_term "${yellow}${text:0:9}${off}" - out_html "${text:0:9}" + tm_out "${yellow}${text:0:9}${off}" + html_out "${text:0:9}" text="${text:9}" len=$len-9 elif [[ $len -ge 8 ]] && [[ "${text:0:8}" == "X-Server" ]]; then - out_term "${yellow}${text:0:8}${off}" - out_html "${text:0:8}" + tm_out "${yellow}${text:0:8}${off}" + html_out "${text:0:8}" text="${text:8}" len=$len-8 elif [[ $len -ge 7 ]] && ( [[ "${text:0:7}" == "squeeze" ]] || [[ "${text:0:7}" == "Red Hat" ]] || \ [[ "${text:0:7}" == "X-Cache" ]] || [[ "${text:0:7}" == "X-Squid" ]] ) ; then - out_term "${yellow}${text:0:7}${off}" - out_html "${text:0:7}" + tm_out "${yellow}${text:0:7}${off}" + html_out "${text:0:7}" text="${text:7}" len=$len-7 elif [[ $len -ge 6 ]] && ( [[ "${text:0:6}" == "Debian" ]] || [[ "${text:0:6}" == "Ubuntu" ]] || \ [[ "${text:0:6}" == "ubuntu" ]] || [[ "${text:0:6}" == "jessie" ]] || \ [[ "${text:0:6}" == "wheezy" ]] || [[ "${text:0:6}" == "CentOS" ]] ) ; then - out_term "${yellow}${text:0:6}${off}" - out_html "${text:0:6}" + tm_out "${yellow}${text:0:6}${off}" + html_out "${text:0:6}" text="${text:6}" len=$len-6 elif [[ $len -ge 5 ]] && ( [[ "${text:0:5}" == "Win32" ]] || [[ "${text:0:5}" == "Win64" ]] || [[ "${text:0:5}" == "lenny" ]] ); then - out_term "${yellow}${text:0:5}${off}" - out_html "${text:0:5}" + tm_out "${yellow}${text:0:5}${off}" + html_out "${text:0:5}" text="${text:5}" len=$len-5 elif [[ $len -ge 4 ]] && [[ "${text:0:4}" == "SUSE" ]]; then - out_term "${yellow}${text:0:4}${off}" - out_html "${text:0:4}" + tm_out "${yellow}${text:0:4}${off}" + html_out "${text:0:4}" text="${text:4}" len=$len-4 elif [[ $len -ge 3 ]] && [[ "${text:0:3}" == "Via" ]]; then - out_term "${yellow}${text:0:3}${off}" - out_html "${text:0:3}" + tm_out "${yellow}${text:0:3}${off}" + html_out "${text:0:3}" text="${text:3}" len=$len-3 else @@ -2012,7 +2010,7 @@ run_server_banner() { emphasize_stuff_in_headers "$serverbanner" fileout "serverbanner" "INFO" "Server banner identified: $serverbanner" if [[ "$serverbanner" = *Microsoft-IIS/6.* ]] && [[ $OSSL_VER == 1.0.2* ]]; then - pr_warningln " It's recommended to run another test w/ OpenSSL 1.0.1 !" + prln_warning " It's recommended to run another test w/ OpenSSL 1.0.1 !" # see https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892 fileout "IIS6_openssl_mismatch" "WARN" "It is recommended to rerun this test w/ OpenSSL 1.0.1. See https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892" fi @@ -2200,7 +2198,7 @@ run_more_flags() { #TODO: I am not testing for the correctness or anything stupid yet, e.g. "X-Frame-Options: allowall" or Access-Control-Allow-Origin: * if "$first"; then - pr_svrty_mediumln "--" + prln_svrty_medium "--" fileout "sec_headers" "MEDIUM" "No security (or other interesting) headers detected" ret=1 else @@ -2384,9 +2382,9 @@ std_cipherlists() { else singlespaces=$(echo "$2" | sed -e 's/ \+/ /g' -e 's/^ //' -e 's/ $//g' -e 's/ //g') if [[ "$OPTIMAL_PROTO" == "-ssl2" ]]; then - local_problem_ln "No $singlespaces for SSLv2 configured in $OPENSSL" + prln_local_problem "No $singlespaces for SSLv2 configured in $OPENSSL" else - local_problem_ln "No $singlespaces configured in $OPENSSL" + prln_local_problem "No $singlespaces configured in $OPENSSL" fi fileout "std_$4" "WARN" "Cipher $2 ($1) not supported by local OpenSSL ($OPENSSL)" fi @@ -2419,7 +2417,7 @@ openssl2rfc() { [[ "$1" == "${TLS_CIPHER_OSSL_NAME[i]}" ]] && rfcname="${TLS_CIPHER_RFC_NAME[i]}" && break done [[ "$rfcname" == "-" ]] && rfcname="" - [[ -n "$rfcname" ]] && retstring "$rfcname" + [[ -n "$rfcname" ]] && tm_out "$rfcname" return 0 } @@ -2431,7 +2429,7 @@ rfc2openssl() { [[ "$1" == "${TLS_CIPHER_RFC_NAME[i]}" ]] && ossl_name="${TLS_CIPHER_OSSL_NAME[i]}" && break done [[ "$ossl_name" == "-" ]] && ossl_name="" - [[ -n "$ossl_name" ]] && retstring "$ossl_name" + [[ -n "$ossl_name" ]] && tm_out "$ossl_name" return 0 } @@ -2451,7 +2449,7 @@ show_rfc_style(){ [[ "$hexcode" == "${TLS_CIPHER_HEXCODE[i]}" ]] && rfcname="${TLS_CIPHER_RFC_NAME[i]}" && break done [[ "$rfcname" == "-" ]] && rfcname="" - [[ -n "$rfcname" ]] && retstring "$rfcname" + [[ -n "$rfcname" ]] && tm_out "$rfcname" return 0 } @@ -2488,7 +2486,7 @@ neat_list(){ [[ -n "$ADD_RFC_STR" ]] && tls_cipher="$(show_rfc_style "$hexcode")" if [[ -z "$5" ]]; then - retstring "$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" + tm_out "$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" return 0 elif [[ "$5" == "false" ]]; then line="$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" @@ -2542,7 +2540,7 @@ test_just_one(){ [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && pr_warning " Cipher mapping not available, doing a fallback to openssl" if ! "$HAS_DH_BITS"; then [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && out "." - pr_warningln " (Your $OPENSSL cannot show DH/ECDH bits)" + prln_warning " (Your $OPENSSL cannot show DH/ECDH bits)" fi fi outln @@ -2884,7 +2882,7 @@ run_allciphers() { outln if ! "$HAS_DH_BITS"; then [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && out "." - pr_warningln " Your $OPENSSL cannot show DH/ECDH bits" + prln_warning " Your $OPENSSL cannot show DH/ECDH bits" fi fi outln @@ -3061,12 +3059,12 @@ run_cipher_per_proto() { outln if ! "$HAS_DH_BITS"; then [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && out "." - pr_warningln " (Your $OPENSSL cannot show DH/ECDH bits)" + prln_warning " (Your $OPENSSL cannot show DH/ECDH bits)" fi fi outln neat_header - retstring " -ssl2 22 SSLv2\n -ssl3 00 SSLv3\n -tls1 01 TLS 1\n -tls1_1 02 TLS 1.1\n -tls1_2 03 TLS 1.2\n" | while read proto proto_hex proto_text; do + tm_out " -ssl2 22 SSLv2\n -ssl3 00 SSLv3\n -tls1 01 TLS 1\n -tls1_1 02 TLS 1.1\n -tls1_2 03 TLS 1.2\n" | while read proto proto_hex proto_text; do "$using_sockets" || locally_supported "$proto" "$proto_text" || continue "$using_sockets" && out "$proto_text " outln @@ -3365,7 +3363,7 @@ create_client_simulation_tls_clienthello() { if [[ $offset -ge $tls_handshake_ascii_len ]]; then # No extensions - retstring "$tls_handshake_ascii" + tm_out "$tls_handshake_ascii" return 0 fi @@ -3398,7 +3396,7 @@ create_client_simulation_tls_clienthello() { done if ! $sni_extension_found; then - retstring "$tls_handshake_ascii" + tm_out "$tls_handshake_ascii" return 0 fi @@ -3417,7 +3415,7 @@ create_client_simulation_tls_clienthello() { tls_handshake_ascii_len_hex=$(printf "%02x\n" $tls_handshake_ascii_len) len2twobytes "$tls_handshake_ascii_len_hex" tls_handshake_ascii="${tls_content_type}${tls_version_reclayer}${LEN_STR:0:2}${LEN_STR:4:2}${tls_handshake_ascii}" - retstring "$tls_handshake_ascii" + tm_out "$tls_handshake_ascii" return 0 } @@ -3486,7 +3484,7 @@ client_simulation_sockets() { fi done - debugme outln_term "reading server hello..." + debugme tmln_out "reading server hello..." if [[ "$DEBUG" -ge 4 ]]; then hexdump -C $SOCK_REPLY_FILE | head -6 echo @@ -3506,7 +3504,7 @@ client_simulation_sockets() { # see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)") - debugme out_term " (returned $lines lines) " + debugme tm_out " (returned $lines lines) " # determine the return value for higher level, so that they can tell what the result is if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then @@ -3514,7 +3512,7 @@ client_simulation_sockets() { else ret=0 fi - debugme outln_term + debugme tmln_out close_socket TMPFILE=$SOCK_REPLY_FILE @@ -4302,7 +4300,7 @@ run_client_simulation() { fi outln - debugme outln_term + debugme tmln_out for name in "${short[@]}"; do #FIXME: printf formatting would look better, especially if we want a wide option here out " ${names[i]} " @@ -4399,7 +4397,7 @@ run_client_simulation() { locally_supported() { [[ -n "$2" ]] && out "$2 " if $OPENSSL s_client "$1" -connect x 2>&1 | grep -aq "unknown option"; then - local_problem_ln "$OPENSSL doesn't support \"s_client $1\"" + prln_local_problem "$OPENSSL doesn't support \"s_client $1\"" return 7 fi return 0 @@ -4471,13 +4469,13 @@ run_protocols() { if "$SSL_NATIVE"; then using_sockets=false - pr_underlineln "via native openssl" + prln_underline "via native openssl" else using_sockets=true if [[ -n "$STARTTLS" ]]; then - pr_underlineln "via sockets " + prln_underline "via sockets " else - pr_underlineln "via sockets except SPDY+HTTP2 " + prln_underline "via sockets except SPDY+HTTP2 " fi fi outln @@ -4493,21 +4491,21 @@ run_protocols() { fileout "sslv2" "WARN" "SSLv2: received a strange SSLv2 reply (rerun with DEBUG>=2)" ;; 1) # no sslv2 server hello returned, like in openlitespeed which returns HTTP! - pr_done_bestln "not offered (OK)" + prln_done_best "not offered (OK)" fileout "sslv2" "OK" "SSLv2 is not offered" ;; 0) # reset - pr_done_bestln "not offered (OK)" + prln_done_best "not offered (OK)" fileout "sslv2" "OK" "SSLv2 is not offered" ;; 3) # everything else lines=$(count_lines "$(hexdump -C "$TEMPDIR/$NODEIP.sslv2_sockets.dd" 2>/dev/null)") - [[ "$DEBUG" -ge 2 ]] && out_term " ($lines lines) " + [[ "$DEBUG" -ge 2 ]] && tm_out " ($lines lines) " if [[ "$lines" -gt 1 ]]; then nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3)) add_tls_offered "ssl2" if [[ 0 -eq "$nr_ciphers_detected" ]]; then - pr_svrty_highln "supported but couldn't detect a cipher and vulnerable to CVE-2015-3197 "; + prln_svrty_high "supported but couldn't detect a cipher and vulnerable to CVE-2015-3197 "; fileout "sslv2" "HIGH" "SSLv2 is offered, vulnerable to CVE-2015-3197" else pr_svrty_critical "offered (NOT ok), also VULNERABLE to DROWN attack"; @@ -4516,17 +4514,17 @@ run_protocols() { fi fi ;; esac - debugme outln_term + debugme tmln_out else run_prototest_openssl "-ssl2" case $? in 0) - pr_svrty_criticalln "offered (NOT ok)" + prln_svrty_critical "offered (NOT ok)" fileout "sslv2" "CRITICAL" "SSLv2 is offered" add_tls_offered "ssl2" ;; 1) - pr_done_bestln "not offered (OK)" + prln_done_best "not offered (OK)" fileout "sslv2" "OK" "SSLv2 is not offered" ;; 5) @@ -4548,23 +4546,23 @@ run_protocols() { fi case $? in 0) - pr_svrty_highln "offered (NOT ok)" + prln_svrty_high "offered (NOT ok)" fileout "sslv3" "HIGH" "SSLv3 is offered" latest_supported="0300" latest_supported_string="SSLv3" add_tls_offered "ssl3" ;; 1) - pr_done_bestln "not offered (OK)" + prln_done_best "not offered (OK)" fileout "sslv3" "OK" "SSLv3 is not offered" ;; 2) if [[ "$DETECTED_TLS_VERSION" == 03* ]]; then detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))" - pr_svrty_criticalln "server responded with higher version number ($detected_version_string) than requested by client (NOT ok)" + prln_svrty_critical "server responded with higher version number ($detected_version_string) than requested by client (NOT ok)" fileout "sslv3" "CRITICAL" "SSLv3: server responded with higher version number ($detected_version_string) than requested by client" else - pr_svrty_criticalln "server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)" + prln_svrty_critical "server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)" fileout "sslv3" "CRITICAL" "SSLv3: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fi ;; @@ -4599,22 +4597,22 @@ run_protocols() { outln fileout "tls1" "INFO" "TLSv1.0 is not offered" # neither good or bad else - pr_svrty_criticalln " -- connection failed rather than downgrading to $latest_supported_string (NOT ok)" + prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string (NOT ok)" fileout "tls1" "CRITICAL" "TLSv1.0: connection failed rather than downgrading to $latest_supported_string" fi ;; 2) pr_svrty_medium "not offered" if [[ "$DETECTED_TLS_VERSION" == "0300" ]]; then - [[ $DEBUG -eq 1 ]] && out_term " -- downgraded" + [[ $DEBUG -eq 1 ]] && tm_out " -- downgraded" outln fileout "tls1" "MEDIUM" "TLSv1.0 is not offered, and downgraded to SSL" elif [[ "$DETECTED_TLS_VERSION" == 03* ]]; then detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))" - pr_svrty_criticalln " -- server responded with higher version number ($detected_version_string) than requested by client" + prln_svrty_critical " -- server responded with higher version number ($detected_version_string) than requested by client" fileout "tls1" "CRITICAL" "TLSv1.0: server responded with higher version number ($detected_version_string) than requested by client" else - pr_svrty_criticalln " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" + prln_svrty_critical " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fileout "tls1" "CRITICAL" "TLSv1.0: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fi ;; @@ -4648,25 +4646,25 @@ run_protocols() { outln fileout "tls1_1" "INFO" "TLSv1.1 is not offered" # neither good or bad else - pr_svrty_criticalln " -- connection failed rather than downgrading to $latest_supported_string" + prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string" fileout "tls1_1" "CRITICAL" "TLSv1.1: connection failed rather than downgrading to $latest_supported_string" fi ;; 2) out "not offered" if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then - [[ $DEBUG -eq 1 ]] && out_term " -- downgraded" + [[ $DEBUG -eq 1 ]] && tm_out " -- downgraded" outln fileout "tls1_1" "CRITICAL" "TLSv1.1 is not offered, and downgraded to a weaker protocol" elif [[ "$DETECTED_TLS_VERSION" == "0300" ]] && [[ "$latest_supported" == "0301" ]]; then - pr_svrty_criticalln " -- server supports TLSv1.0, but downgraded to SSLv3 (NOT ok)" + prln_svrty_critical " -- server supports TLSv1.0, but downgraded to SSLv3 (NOT ok)" fileout "tls1_1" "CRITICAL" "TLSv1.1 is not offered, and downgraded to SSLv3 rather than TLSv1.0" elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -gt 0x0302 ]]; then detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))" - pr_svrty_criticalln " -- server responded with higher version number ($detected_version_string) than requested by client (NOT ok)" + prln_svrty_critical " -- server responded with higher version number ($detected_version_string) than requested by client (NOT ok)" fileout "tls1_1" "CRITICAL" "TLSv1.1 is not offered, server responded with higher version number ($detected_version_string) than requested by client" else - pr_svrty_criticalln " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)" + prln_svrty_critical " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2} (NOT ok)" fileout "tls1_1" "CRITICAL" "TLSv1.1: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fi ;; @@ -4688,7 +4686,7 @@ run_protocols() { fi case $? in 0) - pr_done_bestln "offered (OK)" + prln_done_best "offered (OK)" fileout "tls1_2" "OK" "TLSv1.2 is offered" latest_supported="0303" latest_supported_string="TLSv1.2" @@ -4700,7 +4698,7 @@ run_protocols() { outln fileout "tls1_2" "MEDIUM" "TLSv1.2 is not offered" # no GCM, penalty else - pr_svrty_criticalln " -- connection failed rather than downgrading to $latest_supported_string" + prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string" fileout "tls1_2" "CRITICAL" "TLSv1.2: connection failed rather than downgrading to $latest_supported_string" fi ;; @@ -4712,17 +4710,17 @@ run_protocols() { detected_version_string="TLSv1.$((0x$DETECTED_TLS_VERSION-0x0301))" fi if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then - [[ $DEBUG -eq 1 ]] && out_term " -- downgraded" + [[ $DEBUG -eq 1 ]] && tm_out " -- downgraded" outln fileout "tls1_2" "MEDIUM" "TLSv1.2 is not offered and downgraded to a weaker protocol" elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -lt 0x$latest_supported ]]; then - pr_svrty_criticalln " -- server supports $latest_supported_string, but downgraded to $detected_version_string" + prln_svrty_critical " -- server supports $latest_supported_string, but downgraded to $detected_version_string" fileout "tls1_2" "CRITICAL" "TLSv1.2 is not offered, and downgraded to $detected_version_string rather than $latest_supported_string" elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -gt 0x0303 ]]; then - pr_svrty_criticalln " -- server responded with higher version number ($detected_version_string) than requested by client" + prln_svrty_critical " -- server responded with higher version number ($detected_version_string) than requested by client" fileout "tls1_2" "CRITICAL" "TLSv1.2 is not offered, server responded with higher version number ($detected_version_string) than requested by client" else - pr_svrty_criticalln " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" + prln_svrty_critical " -- server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fileout "tls1_2" "CRITICAL" "TLSv1.2: server responded with version number ${DETECTED_TLS_VERSION:0:2}.${DETECTED_TLS_VERSION:2:2}" fi ;; @@ -4877,14 +4875,14 @@ pr_ecdh_curve_quality() { # The return value is an indicator of the quality of the cipher in $1: # 0 = $1 is empty # 1 = pr_svrty_critical, 2 = pr_svrty_high, 3 = pr_svrty_medium, 4 = pr_svrty_low -# 5 = neither good nor bad, 6 = pr_done_good, 7 = pr_done_best +# 5 = neither good nor bad, 6 = pr_done_good, 7 = pr_done_best pr_cipher_quality() { local cipher="$1" local text="$2" [[ -z "$1" ]] && return 0 [[ -z "$text" ]] && text="$cipher" - + if [[ "$cipher" != TLS_* ]] && [[ "$cipher" != SSL_* ]]; then # This must be the OpenSSL name for a cipher if [[ $TLS_NR_CIPHERS -eq 0 ]]; then @@ -4981,7 +4979,7 @@ read_dhbits_from_file() { [[ -n "$what_dh" ]] && HAS_DH_BITS=true # FIX 190 if [[ -z "$what_dh" ]] && ! "$HAS_DH_BITS"; then if [[ "$2" == "string" ]]; then - retstring "$old_fart" + tm_out "$old_fart" elif [[ -z "$2" ]]; then pr_warning "$old_fart" fi @@ -4989,7 +4987,7 @@ read_dhbits_from_file() { fi if [[ "$2" == "quiet" ]]; then - retstring "$bits" + tm_out "$bits" return 0 fi @@ -4998,7 +4996,7 @@ read_dhbits_from_file() { add="bit DH" [[ -n "$curve" ]] && add+=" ($curve)" if [[ "$2" == "string" ]]; then - retstring ", $bits $add" + tm_out ", $bits $add" else pr_dh_quality "$bits" "$bits $add" fi @@ -5007,7 +5005,7 @@ read_dhbits_from_file() { add="bit ECDH" [[ -n "$curve" ]] && add+=" ($curve)" if [[ "$2" == "string" ]]; then - retstring ", $bits $add" + tm_out ", $bits $add" else pr_ecdh_quality "$bits" "$bits $add" fi @@ -5058,7 +5056,7 @@ run_server_preference() { elif [[ -n "$STARTTLS_PROTOCOL" ]]; then # now it still could be that we hit this bug: https://github.com/drwetter/testssl.sh/issues/188 # workaround is to connect with a protocol - debugme out_term "(workaround #188) " + debugme tm_out "(workaround #188) " determine_optimal_proto $STARTTLS_PROTOCOL $OPENSSL s_client $STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_fwd $BUGS -connect $NODEIP:$PORT $PROXY $addcmd2 $ERRFILE >$TMPFILE if ! sclient_connect_successful $? $TMPFILE; then @@ -5097,7 +5095,7 @@ run_server_preference() { remark4default_cipher="" fileout "order" "OK" "Server sets a cipher order" fi - debugme out_term " $cipher1 | $cipher2" + debugme tm_out " $cipher1 | $cipher2" outln pr_bold " Negotiated protocol " @@ -5110,11 +5108,11 @@ run_server_preference() { default_proto=$(grep -aw "Protocol" $TMPFILE | sed -e 's/^.*Protocol.*://' -e 's/ //g') case "$default_proto" in *TLSv1.2) - pr_done_bestln $default_proto + prln_done_best $default_proto fileout "order_proto" "OK" "Default protocol TLS1.2" ;; *TLSv1.1) - pr_done_goodln $default_proto + prln_done_good $default_proto fileout "order_proto" "OK" "Default protocol TLS1.1" ;; *TLSv1) @@ -5122,11 +5120,11 @@ run_server_preference() { fileout "order_proto" "INFO" "Default protocol TLS1.0" ;; *SSLv2) - pr_svrty_criticalln $default_proto + prln_svrty_critical $default_proto fileout "order_proto" "CRITICAL" "Default protocol SSLv2" ;; *SSLv3) - pr_svrty_criticalln $default_proto + prln_svrty_critical $default_proto fileout "order_proto" "CRITICAL" "Default protocol SSLv3" ;; "") @@ -5192,7 +5190,7 @@ run_server_preference() { for p in ssl2 ssl3 tls1 tls1_1 tls1_2; do if [[ $p == ssl2 ]] && ! "$HAS_SSL2"; then if ! "$using_sockets" || [[ $TLS_NR_CIPHERS -eq 0 ]]; then - out " (SSLv2: "; local_problem "$OPENSSL doesn't support \"s_client -ssl2\""; outln ")"; + out " (SSLv2: "; pr_local_problem "$OPENSSL doesn't support \"s_client -ssl2\""; outln ")"; continue else sslv2_sockets "" "true" @@ -5214,7 +5212,7 @@ run_server_preference() { fi fi done - [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && tmln_out "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" cipher[i]="" @@ -5222,7 +5220,7 @@ run_server_preference() { fi elif [[ $p == ssl3 ]] && ! "$HAS_SSL3"; then if ! "$using_sockets"; then - out " (SSLv3: "; local_problem "$OPENSSL doesn't support \"s_client -ssl3\"" ; outln ")"; + out " (SSLv3: "; pr_local_problem "$OPENSSL doesn't support \"s_client -ssl3\"" ; outln ")"; continue else tls_sockets "00" "$TLS_CIPHER" @@ -5234,7 +5232,7 @@ run_server_preference() { cipher[i]="$(rfc2openssl "$cipher1")" [[ -z "${cipher[i]}" ]] && cipher[i]="$cipher1" fi - [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && tmln_out "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" cipher[i]="" @@ -5251,7 +5249,7 @@ run_server_preference() { cipher[i]="$(openssl2rfc "${cipher[i]}")" [[ -z "${cipher[i]}" ]] && cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') fi - [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && tmln_out "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" cipher[i]="" @@ -5275,7 +5273,7 @@ run_server_preference() { cipher[i]="$(openssl2rfc "${cipher[i]}")" [[ -z "${cipher[i]}" ]] && cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') fi - [[ $DEBUG -ge 2 ]] && outln_term "Default cipher for ${proto[i]}: ${cipher[i]}" + [[ $DEBUG -ge 2 ]] && tmln_out "Default cipher for ${proto[i]}: ${cipher[i]}" fi fi else @@ -5335,7 +5333,7 @@ check_tls12_pref() { nr_ciphers_found_r1+=1 "$FAST" && break else - debugme outln_term "A: $tested_cipher" + debugme tmln_out "A: $tested_cipher" break fi done @@ -5350,10 +5348,10 @@ check_tls12_pref() { order+=" $cipher" batchremoved="$batchremoved:-$cipher" nr_ciphers_found_r1+=1 - debugme outln_term "B1: $batchremoved" + debugme tmln_out "B1: $batchremoved" "$FAST" && break else - debugme outln_term "B2: $batchremoved" + debugme tmln_out "B2: $batchremoved" break # nothing left with batchremoved ciphers, we need to put everything together fi @@ -5378,14 +5376,14 @@ check_tls12_pref() { fi done if "$FAST" && [[ $nr_ciphers_found_r2 -ne 1 ]]; then - fixmeln "something weird happened around line $((LINENO - 14))" + prln_fixme "something weird happened around line $((LINENO - 14))" return 1 elif ! "$FAST" && [[ $nr_ciphers_found_r2 -ne $nr_ciphers_found_r1 ]]; then - fixmeln "something weird happened around line $((LINENO - 16))" + prln_fixme "something weird happened around line $((LINENO - 16))" return 1 fi fi - retstring "$order" + tm_out "$order" tmpfile_handle $FUNCNAME.txt return 0 @@ -5408,10 +5406,10 @@ cipher_pref_check() { pr_bold " Cipher order" - retstring " ssl3 00 SSLv3\n tls1 01 TLSv1\n tls1_1 02 TLSv1.1\n tls1_2 03 TLSv1.2\n" | while read p proto_hex proto; do + tm_out " ssl3 00 SSLv3\n tls1 01 TLSv1\n tls1_1 02 TLSv1.1\n tls1_2 03 TLSv1.2\n" | while read p proto_hex proto; do order=""; ciphers_found_with_sockets=false if [[ $p == ssl3 ]] && ! "$HAS_SSL3" && ! "$using_sockets"; then - out "\n SSLv3: "; local_problem "$OPENSSL doesn't support \"s_client -ssl3\""; + out "\n SSLv3: "; pr_local_problem "$OPENSSL doesn't support \"s_client -ssl3\""; continue fi has_server_protocol "$p" || continue @@ -5639,7 +5637,7 @@ get_host_cert() { awk '/-----BEGIN/,/-----END/ { print $0 }' $tmpvar >$HOSTCERT return 0 else - [[ -z "$1" ]] && pr_warningln "could not retrieve host certificate!" + [[ -z "$1" ]] && prln_warning "could not retrieve host certificate!" #fileout "host_certificate" "WARN" "Could not retrieve host certificate!" return 1 fi @@ -5653,17 +5651,17 @@ verify_retcode_helper() { case $retcode in # codes from ./doc/apps/verify.pod | verify(1ssl) - 26) retstring "(unsupported certificate purpose)" ;; # X509_V_ERR_INVALID_PURPOSE - 24) retstring "(certificate unreadable)" ;; # X509_V_ERR_INVALID_CA - 23) retstring "(certificate revoked)" ;; # X509_V_ERR_CERT_REVOKED - 21) retstring "(chain incomplete, only 1 cert provided)" ;; # X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE - 20) retstring "(chain incomplete)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY - 19) retstring "(self signed CA in chain)" ;; # X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN - 18) retstring "(self signed)" ;; # X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT - 10) retstring "(expired)" ;; # X509_V_ERR_CERT_HAS_EXPIRED - 9) retstring "(not yet valid)" ;; # X509_V_ERR_CERT_NOT_YET_VALID - 2) retstring "(issuer cert missing)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT - *) ret=1 ; retstring " (unknown, pls report) $1" ;; + 26) tm_out "(unsupported certificate purpose)" ;; # X509_V_ERR_INVALID_PURPOSE + 24) tm_out "(certificate unreadable)" ;; # X509_V_ERR_INVALID_CA + 23) tm_out "(certificate revoked)" ;; # X509_V_ERR_CERT_REVOKED + 21) tm_out "(chain incomplete, only 1 cert provided)" ;; # X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE + 20) tm_out "(chain incomplete)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY + 19) tm_out "(self signed CA in chain)" ;; # X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN + 18) tm_out "(self signed)" ;; # X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT + 10) tm_out "(expired)" ;; # X509_V_ERR_CERT_HAS_EXPIRED + 9) tm_out "(not yet valid)" ;; # X509_V_ERR_CERT_NOT_YET_VALID + 2) tm_out "(issuer cert missing)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT + *) ret=1 ; tm_out " (unknown, pls report) $1" ;; esac return $ret } @@ -5695,7 +5693,7 @@ determine_trust() { addtl_warning="(Your $OPENSSL <= 1.0.2 might be too unreliable to determine trust)" fileout "${json_prefix}chain_of_trust_warn" "WARN" "$addtl_warning" fi - debugme outln_term + debugme tmln_out # if you run testssl.sh from a different path /you can set either TESTSSL_INSTALL_DIR or CA_BUNDLES_PATH to find the CA BUNDLES if [[ -z $CA_BUNDLES_PATH ]]; then @@ -5706,7 +5704,7 @@ determine_trust() { for bundle_fname in $ca_bundles; do certificate_file[i]=$(basename ${bundle_fname//.pem}) if [[ ! -r $bundle_fname ]]; then - pr_warningln "\"$bundle_fname\" cannot be found / not readable" + prln_warning "\"$bundle_fname\" cannot be found / not readable" return 7 fi debugme printf -- " %-12s" "${certificate_file[i]}" @@ -5722,18 +5720,18 @@ determine_trust() { if [[ ${verify_retcode[i]} -eq 0 ]]; then trust[i]=true some_ok=true - debugme pr_done_good_term "Ok " - debugme outln_term "${verify_retcode[i]}" + debugme tm_done_good "Ok " + debugme tmln_out "${verify_retcode[i]}" else trust[i]=false all_ok=false - debugme pr_svrty_high_term "not trusted " - debugme outln_term "${verify_retcode[i]}" + debugme tm_svrty_high "not trusted " + debugme tmln_out "${verify_retcode[i]}" fi i=$((i + 1)) done num_ca_bundles=$((i - 1)) - debugme out_term " " + debugme tm_out " " if $all_ok; then # all stores ok pr_done_good "Ok "; pr_warning "$addtl_warning" @@ -5776,7 +5774,7 @@ determine_trust() { #outln "$code" outln # lf + green ones - [[ "$DEBUG" -eq 0 ]] && out_term "$spaces" + [[ "$DEBUG" -eq 0 ]] && tm_out "$spaces" pr_done_good "OK: $ok_was" fi fileout "${json_prefix}chain_of_trust" "CRITICAL" "Some certificate trust checks failed : OK : $ok_was NOT ok: $notok_was $addtl_warning" @@ -5810,10 +5808,10 @@ tls_time() { out "$difftime"; out " sec from localtime"; fileout "tls_time" "INFO" "Your TLS time is skewed from your localtime by $difftime seconds" fi - debugme out_term "$TLS_TIME" + debugme tm_out "$TLS_TIME" outln else - pr_warningln "SSLv3 through TLS 1.2 didn't return a timestamp" + prln_warning "SSLv3 through TLS 1.2 didn't return a timestamp" fileout "tls_time" "INFO" "No TLS timestamp returned by SSLv3 through TLSv1.2" fi return 0 @@ -5991,7 +5989,7 @@ get_server_certificate() { $OPENSSL s_client $STARTTLS $BUGS $1 -showcerts -connect $NODEIP:$PORT $PROXY $addcmd -$proto -tlsextdebug >$ERRFILE >$TMPFILE if ! sclient_connect_successful $? $TMPFILE; then if [ -z "$1" ]; then - pr_warningln "Strange, no SSL/TLS protocol seems to be supported (error around line $((LINENO - 6)))" + prln_warning "Strange, no SSL/TLS protocol seems to be supported (error around line $((LINENO - 6)))" fi tmpfile_handle $FUNCNAME.txt return 7 # this is ugly, I know @@ -6191,11 +6189,11 @@ must_staple() { local cert extn local -i extn_len local supported=false - + # Note this function is only looking for status_request (5) and not # status_request_v2 (17), since OpenSSL seems to only include status_request (5) # in its ClientHello when the "-status" option is used. - + # OpenSSL 1.1.0 supports pretty-printing the "TLS Feature extension." For any # previous versions of OpenSSL, OpenSSL can only show if the extension OID is present. if $OPENSSL x509 -in "$HOSTCERT" -noout -text 2>>$ERRFILE | grep -A 1 "TLS Feature:" | grep -q "status_request"; then @@ -6220,7 +6218,7 @@ must_staple() { fi if "$supported"; then - pr_done_bestln "Supported" + prln_done_best "Supported" fileout "${json_prefix}ocsp_must_staple" "OK" "OCSP must staple : supported" return 0 else @@ -6287,19 +6285,19 @@ certificate_info() { fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: SHA224 with RSA" ;; sha256WithRSAEncryption) - pr_done_goodln "SHA256 with RSA" + prln_done_good "SHA256 with RSA" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA256 with RSA" ;; sha384WithRSAEncryption) - pr_done_goodln "SHA384 with RSA" + prln_done_good "SHA384 with RSA" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA384 with RSA" ;; sha512WithRSAEncryption) - pr_done_goodln "SHA512 with RSA" + prln_done_good "SHA512 with RSA" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA512 with RSA" ;; ecdsa-with-SHA1) - pr_svrty_mediumln "ECDSA with SHA1" + prln_svrty_medium "ECDSA with SHA1" fileout "${json_prefix}algorithm" "MEDIUM" "Signature Algorithm: ECDSA with SHA1" ;; ecdsa-with-SHA224) @@ -6307,19 +6305,19 @@ certificate_info() { fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: ECDSA with SHA224" ;; ecdsa-with-SHA256) - pr_done_goodln "ECDSA with SHA256" + prln_done_good "ECDSA with SHA256" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA256" ;; ecdsa-with-SHA384) - pr_done_goodln "ECDSA with SHA384" + prln_done_good "ECDSA with SHA384" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA384" ;; ecdsa-with-SHA512) - pr_done_goodln "ECDSA with SHA512" + prln_done_good "ECDSA with SHA512" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA512" ;; dsaWithSHA1) - pr_svrty_mediumln "DSA with SHA1" + prln_svrty_medium "DSA with SHA1" fileout "${json_prefix}algorithm" "MEDIUM" "Signature Algorithm: DSA with SHA1" ;; dsa_with_SHA224) @@ -6327,14 +6325,14 @@ certificate_info() { fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: DSA with SHA224" ;; dsa_with_SHA256) - pr_done_goodln "DSA with SHA256" + prln_done_good "DSA with SHA256" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: DSA with SHA256" ;; rsassaPss) cert_sig_hash_algo="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 1 "Signature Algorithm" | head -2 | tail -1 | sed 's/^.*Hash Algorithm: //')" case $cert_sig_hash_algo in sha1) - pr_svrty_mediumln "RSASSA-PSS with SHA1" + prln_svrty_medium "RSASSA-PSS with SHA1" fileout "${json_prefix}algorithm" "MEDIUM" "Signature Algorithm: RSASSA-PSS with SHA1" ;; sha224) @@ -6342,33 +6340,33 @@ certificate_info() { fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: RSASSA-PSS with SHA224" ;; sha256) - pr_done_goodln "RSASSA-PSS with SHA256" + prln_done_good "RSASSA-PSS with SHA256" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: RSASSA-PSS with SHA256" ;; sha384) - pr_done_goodln "RSASSA-PSS with SHA384" + prln_done_good "RSASSA-PSS with SHA384" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: RSASSA-PSS with SHA384" ;; sha512) - pr_done_goodln "RSASSA-PSS with SHA512" + prln_done_good "RSASSA-PSS with SHA512" fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: RSASSA-PSS with SHA512" ;; *) out "RSASSA-PSS with $cert_sig_hash_algo" - pr_warningln " (Unknown hash algorithm)" + prln_warning " (Unknown hash algorithm)" fileout "${json_prefix}algorithm" "DEBUG" "Signature Algorithm: RSASSA-PSS with $cert_sig_hash_algo" esac ;; md2*) - pr_svrty_criticalln "MD2" + prln_svrty_critical "MD2" fileout "${json_prefix}algorithm" "CRITICAL" "Signature Algorithm: MD2" ;; md4*) - pr_svrty_criticalln "MD4" + prln_svrty_critical "MD4" fileout "${json_prefix}algorithm" "CRITICAL" "Signature Algorithm: MD4" ;; md5*) - pr_svrty_criticalln "MD5" + prln_svrty_critical "MD5" fileout "${json_prefix}algorithm" "CRITICAL" "Signature Algorithm: MD5" ;; *) @@ -6391,7 +6389,7 @@ certificate_info() { *ecdsa*|*ecPublicKey) out "ECDSA ";; *GOST*|*gost*) out "GOST ";; *dh*|*DH*) out "DH " ;; - *) pr_warning "fixme: $cert_key_algo " ;; + *) pr_warning "pr_fixme: $cert_key_algo " ;; esac # https://tools.ietf.org/html/rfc4492, http://www.keylength.com/en/compare/ # http://infoscience.epfl.ch/record/164526/files/NPDF-22.pdf @@ -6485,9 +6483,9 @@ certificate_info() { cn_nosni="$(get_cn_from_cert "$HOSTCERT.nosni")" [[ -z "$cn_nosni" ]] && cn_nosni="no CN field in subject" fi - debugme out_term "\"$NODE\" | \"$cn\" | \"$cn_nosni\"" + debugme tm_out "\"$NODE\" | \"$cn\" | \"$cn_nosni\"" else - debugme out_term "\"$NODE\" | \"$cn\"" + debugme tm_out "\"$NODE\" | \"$cn\"" fi #FIXME: check for SSLv3/v2 and look whether it goes to a different CN (probably not polite) @@ -6539,7 +6537,7 @@ certificate_info() { issuer_DC="$(awk -F'=' '/DC=/ { print $2 }' <<< "$issuer")" if [[ "$issuer_O" == "issuer=" ]] || [[ "$issuer_O" == "issuer= " ]] || [[ "$issuer_CN" == "$cn" ]]; then - pr_svrty_criticalln "self-signed (NOT ok)" + prln_svrty_critical "self-signed (NOT ok)" fileout "${json_prefix}issuer" "CRITICAL" "Issuer: selfsigned" else issuerfinding="$issuer_CN" @@ -6645,7 +6643,7 @@ certificate_info() { trustfinding_nosni="" fi if "$has_dns_sans" && ( [[ $trust_nosni -eq 4 ]] || [[ $trust_nosni -eq 8 ]] ); then - pr_svrty_mediumln "$trustfinding_nosni" + prln_svrty_medium "$trustfinding_nosni" else outln "$trustfinding_nosni" fi @@ -6978,7 +6976,7 @@ run_server_defaults() { lifetime=$(echo $sessticket_str | grep -a lifetime | sed 's/[A-Za-z:() ]//g') unit=$(echo $sessticket_str | grep -a lifetime | sed -e 's/^.*'"$lifetime"'//' -e 's/[ ()]//g') out "$lifetime $unit " - pr_svrty_lowln "(PFS requires session ticket keys to be rotated <= daily)" + prln_svrty_low "(PFS requires session ticket keys to be rotated <= daily)" fileout "session_ticket" "LOW" "TLS session tickes RFC 5077 valid for $lifetime $unit (PFS requires session ticket keys to be rotated at least daily)" fi @@ -7028,7 +7026,7 @@ run_pfs() { [[ $TLS_NR_CIPHERS == 0 ]] && using_sockets=false outln - pr_headline " Testing robust (perfect) forward secrecy"; pr_underlineln ", (P)FS -- omitting Null Authentication/Encryption, 3DES, RC4 " + pr_headline " Testing robust (perfect) forward secrecy"; prln_underline ", (P)FS -- omitting Null Authentication/Encryption, 3DES, RC4 " if ! "$using_sockets"; then [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && pr_warning " Cipher mapping not available, doing a fallback to openssl" if ! "$HAS_DH_BITS" && "$WIDE"; then @@ -7087,7 +7085,7 @@ run_pfs() { debugme echo $(actually_supported_ciphers $pfs_cipher_list) if [[ "$nr_supported_ciphers" -le "$CLIENT_MIN_PFS" ]]; then outln - local_problem_ln "You only have $nr_supported_ciphers PFS ciphers on the client side " + prln_local_problem "You only have $nr_supported_ciphers PFS ciphers on the client side " fileout "pfs" "WARN" "(Perfect) Forward Secrecy tests: Skipped. You only have $nr_supported_ciphers PFS ciphers on the client site. ($CLIENT_MIN_PFS are required)" return 1 fi @@ -7099,7 +7097,7 @@ run_pfs() { if [[ $sclient_success -ne 0 ]]; then outln - pr_svrty_mediumln " No ciphers supporting Forward Secrecy offered" + prln_svrty_medium " No ciphers supporting Forward Secrecy offered" fileout "pfs" "MEDIUM" "(Perfect) Forward Secrecy : No ciphers supporting Forward Secrecy offered" else outln @@ -7352,7 +7350,7 @@ spdy_pre(){ return 1 fi if ! "$HAS_SPDY"; then - local_problem "$OPENSSL doesn't support SPDY/NPN"; + pr_local_problem "$OPENSSL doesn't support SPDY/NPN"; fileout "spdy_npn" "WARN" "SPDY/NPN : not tested $OPENSSL doesn't support SPDY/NPN" return 7 fi @@ -7373,7 +7371,7 @@ http2_pre(){ return 1 fi if ! "$HAS_ALPN" && "$SSL_NATIVE"; then - local_problem_ln "$OPENSSL doesn't support HTTP2/ALPN"; + prln_local_problem "$OPENSSL doesn't support HTTP2/ALPN"; fileout "https_alpn" "WARN" "HTTP2/ALPN : HTTP/2 was not tested as $OPENSSL does not support it" return 7 fi @@ -7403,7 +7401,7 @@ run_spdy() { fileout "spdy_npn" "INFO" "SPDY/NPN : $tmpstr (advertised)" ret=0 else - pr_cyanln "please check manually, server response was ambiguous ..." + prln_cyan "please check manually, server response was ambiguous ..." fileout "spdy_npn" "INFO" "SPDY/NPN : please check manually, server response was ambiguous ..." ret=10 fi @@ -7661,7 +7659,7 @@ fd_socket() { proyxline=${proyxline#* } if [[ "${proyxline%% *}" != "200" ]]; then pr_magenta "Unable to CONNECT via proxy. " - [[ "$PORT" != 443 ]] && pr_magentaln "Check whether your proxy supports port $PORT and the underlying protocol." + [[ "$PORT" != 443 ]] && prln_magenta "Check whether your proxy supports port $PORT and the underlying protocol." return 6 fi fi @@ -8022,7 +8020,7 @@ get_dh_ephemeralkey() { key_bitstring="$($OPENSSL pkey -pubin -in $tmp_der_key_file -inform DER 2> $ERRFILE)" rm $tmp_der_key_file [[ -z "$key_bitstring" ]] && return 1 - retstring "$key_bitstring" + tm_out "$key_bitstring" return 0 } @@ -8262,7 +8260,7 @@ parse_tls_serverhello() { if [[ $tls_hello_ascii_len-$i -lt 10 ]]; then if [[ "$process_full" == "all" ]]; then # The entire server response should have been retrieved. - debugme pr_warningln_term "Malformed message." + debugme tmln_warning "Malformed message." return 1 else # This could just be a result of the server's response being @@ -8279,28 +8277,28 @@ parse_tls_serverhello() { if [[ $DEBUG -ge 2 ]]; then echo " tls_protocol (reclyr): 0x$tls_protocol" - out_term " tls_content_type: 0x$tls_content_type" + tm_out " tls_content_type: 0x$tls_content_type" case $tls_content_type in - 15) outln_term " (alert)" ;; - 16) outln_term " (handshake)" ;; - 17) outln_term " (application data)" ;; - *) outln_term ;; + 15) tmln_out " (alert)" ;; + 16) tmln_out " (handshake)" ;; + 17) tmln_out " (application data)" ;; + *) tmln_out ;; esac echo " msg_len: $((msg_len/2))" - outln_term + tmln_out fi if [[ $tls_content_type != "15" ]] && [[ $tls_content_type != "16" ]] && [[ $tls_content_type != "17" ]]; then - debugme pr_warningln_term "Content type other than alert, handshake, or application data detected." + debugme tmln_warning "Content type other than alert, handshake, or application data detected." return 1 elif [[ "${tls_protocol:0:2}" != "03" ]]; then - debugme pr_warningln_term "Protocol record_version.major is not 03." + debugme tmln_warning "Protocol record_version.major is not 03." return 1 fi DETECTED_TLS_VERSION=$tls_protocol if [[ $msg_len -gt $tls_hello_ascii_len-$i ]]; then if [[ "$process_full" == "all" ]]; then - debugme pr_warningln_term "Malformed message." + debugme tmln_warning "Malformed message." return 1 else # This could just be a result of the server's response being @@ -8320,7 +8318,7 @@ parse_tls_serverhello() { # Now check the alert messages. tls_alert_ascii_len=${#tls_alert_ascii} if [[ "$process_full" == "all" ]] && [[ $tls_alert_ascii_len%4 -ne 0 ]]; then - debugme pr_warningln_term "Malformed message." + debugme tmln_warning "Malformed message." return 1 fi if [[ $tls_alert_ascii_len -gt 0 ]]; then @@ -8331,7 +8329,7 @@ parse_tls_serverhello() { tls_err_descr=${tls_alert_ascii:j:2} # 112/0x70: Unrecognized name, 111/0x6F: certificate_unobtainable, # 113/0x71: bad_certificate_status_response, #114/0x72: bad_certificate_hash_value - debugme out_term " tls_err_descr: 0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})" + debugme tm_out " tls_err_descr: 0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})" case $tls_err_descr in 00) tls_alert_descrip="close notify" ;; 01) tls_alert_descrip="end of early data" ;; @@ -8377,17 +8375,17 @@ parse_tls_serverhello() { echo "alert $tls_alert_descrip" >> $TMPFILE echo "===============================================================================" >> $TMPFILE if [[ $DEBUG -ge 2 ]]; then - outln_term " ($tls_alert_descrip)" - out_term " tls_err_level: ${tls_err_level}" + tmln_out " ($tls_alert_descrip)" + tm_out " tls_err_level: ${tls_err_level}" case $tls_err_level in - 01) outln_term " (warning)" ;; - 02) outln_term " (fatal)" ;; - *) outln_term ;; + 01) tmln_out " (warning)" ;; + 02) tmln_out " (fatal)" ;; + *) tmln_out ;; esac - outln_term + tmln_out fi if [[ "$tls_err_level" != "01" ]] && [[ "$tls_err_level" != "02" ]]; then - debugme pr_warningln_term "Unexpected AlertLevel (0x$tls_err_level)." + debugme tmln_warning "Unexpected AlertLevel (0x$tls_err_level)." return 1 elif [[ "$tls_err_level" == "02" ]]; then # Fatal alert @@ -8407,7 +8405,7 @@ parse_tls_serverhello() { if [[ $tls_handshake_ascii_len-$i -lt 8 ]]; then if [[ "$process_full" == "all" ]]; then # The entire server response should have been retrieved. - debugme pr_warningln_term "Malformed message." + debugme tmln_warning "Malformed message." return 1 else # This could just be a result of the server's response being @@ -8421,34 +8419,34 @@ parse_tls_serverhello() { i=$i+6 if [[ $DEBUG -ge 2 ]]; then - out_term " handshake type: 0x${tls_msg_type}" + tm_out " handshake type: 0x${tls_msg_type}" case $tls_msg_type in - 00) outln_term " (hello_request)" ;; - 01) outln_term " (client_hello)" ;; - 02) outln_term " (server_hello)" ;; - 03) outln_term " (hello_verify_request)" ;; - 04) outln_term " (NewSessionTicket)" ;; - 06) outln_term " (hello_retry_request)" ;; - 08) outln_term " (encrypted_extensions)" ;; - 0B) outln_term " (certificate)" ;; - 0C) outln_term " (server_key_exchange)" ;; - 0D) outln_term " (certificate_request)" ;; - 0E) outln_term " (server_hello_done)" ;; - 0F) outln_term " (certificate_verify)" ;; - 10) outln_term " (client_key_exchange)" ;; - 14) outln_term " (finished)" ;; - 15) outln_term " (certificate_url)" ;; - 16) outln_term " (certificate_status)" ;; - 17) outln_term " (supplemental_data)" ;; - 18) outln_term " (key_update)" ;; - *) outln_term ;; + 00) tmln_out " (hello_request)" ;; + 01) tmln_out " (client_hello)" ;; + 02) tmln_out " (server_hello)" ;; + 03) tmln_out " (hello_verify_request)" ;; + 04) tmln_out " (NewSessionTicket)" ;; + 06) tmln_out " (hello_retry_request)" ;; + 08) tmln_out " (encrypted_extensions)" ;; + 0B) tmln_out " (certificate)" ;; + 0C) tmln_out " (server_key_exchange)" ;; + 0D) tmln_out " (certificate_request)" ;; + 0E) tmln_out " (server_hello_done)" ;; + 0F) tmln_out " (certificate_verify)" ;; + 10) tmln_out " (client_key_exchange)" ;; + 14) tmln_out " (finished)" ;; + 15) tmln_out " (certificate_url)" ;; + 16) tmln_out " (certificate_status)" ;; + 17) tmln_out " (supplemental_data)" ;; + 18) tmln_out " (key_update)" ;; + *) tmln_out ;; esac echo " msg_len: $((msg_len/2))" - outln_term + tmln_out fi if [[ $msg_len -gt $tls_handshake_ascii_len-$i ]]; then if [[ "$process_full" == "all" ]]; then - debugme pr_warningln_term "Malformed message." + debugme tmln_warning "Malformed message." return 1 else # This could just be a result of the server's response being @@ -8460,28 +8458,28 @@ parse_tls_serverhello() { if [[ "$tls_msg_type" == "02" ]]; then if [[ -n "$tls_serverhello_ascii" ]]; then - debugme pr_warningln_term "Response contained more than one ServerHello handshake message." + debugme tmln_warning "Response contained more than one ServerHello handshake message." return 1 fi tls_serverhello_ascii="${tls_handshake_ascii:i:msg_len}" tls_serverhello_ascii_len=$msg_len elif [[ "$process_full" == "all" ]] && [[ "$tls_msg_type" == "0B" ]]; then if [[ -n "$tls_certificate_ascii" ]]; then - debugme pr_warningln_term "Response contained more than one Certificate handshake message." + debugme tmln_warning "Response contained more than one Certificate handshake message." return 1 fi tls_certificate_ascii="${tls_handshake_ascii:i:msg_len}" tls_certificate_ascii_len=$msg_len elif ( [[ "$process_full" == "all" ]] || [[ "$process_full" == "ephemeralkey" ]] ) && [[ "$tls_msg_type" == "0C" ]]; then if [[ -n "$tls_serverkeyexchange_ascii" ]]; then - debugme pr_warningln_term "Response contained more than one ServerKeyExchange handshake message." + debugme tmln_warning "Response contained more than one ServerKeyExchange handshake message." return 1 fi tls_serverkeyexchange_ascii="${tls_handshake_ascii:i:msg_len}" tls_serverkeyexchange_ascii_len=$msg_len elif [[ "$process_full" == "all" ]] && [[ "$tls_msg_type" == "16" ]]; then if [[ -n "$tls_certificate_status_ascii" ]]; then - debugme pr_warningln_term "Response contained more than one certificate_status handshake message." + debugme tmln_warning "Response contained more than one certificate_status handshake message." return 1 fi tls_certificate_status_ascii="${tls_handshake_ascii:i:msg_len}" @@ -8498,7 +8496,7 @@ parse_tls_serverhello() { return 1 elif [[ "${tls_handshake_ascii:0:2}" != "02" ]]; then # the ServerHello MUST be the first handshake message - debugme pr_warningln_term "The first handshake protocol message is not a ServerHello." + debugme tmln_warning "The first handshake protocol message is not a ServerHello." return 1 fi @@ -8512,7 +8510,7 @@ parse_tls_serverhello() { # byte 38+39+sid-len: extension length tls_protocol2="${tls_serverhello_ascii:0:4}" if [[ "${tls_protocol2:0:2}" != "03" ]]; then - debugme pr_warningln_term "server_version.major in ServerHello is not 03." + debugme tmln_warning "server_version.major in ServerHello is not 03." return 1 fi DETECTED_TLS_VERSION="$tls_protocol2" @@ -8549,7 +8547,7 @@ parse_tls_serverhello() { fi tls_extensions_len=$(hex2dec "${tls_serverhello_ascii:extns_offset:4}")*2 if [[ $tls_extensions_len -ne $tls_serverhello_ascii_len-$extns_offset-4 ]]; then - debugme pr_warningln_term "Malformed message." + debugme tmln_warning "Malformed message." return 1 fi for (( i=0; i$ERRFILE)") - debugme out_term " (returned $lines lines) " + debugme tm_out " (returned $lines lines) " # determine the return value for higher level, so that they can tell what the result is if [[ $save -eq 1 ]] || [[ $lines -eq 1 ]]; then @@ -9441,7 +9439,7 @@ tls_sockets() { ret=2 # protocol NOT available, server downgraded to $DETECTED_TLS_VERSION fi fi - debugme outln_term + debugme tmln_out else debugme echo "stuck on sending: $ret" fi @@ -9547,16 +9545,16 @@ run_heartbleed(){ x00, x0f, x00, x01, x01" fd_socket 5 || return 6 - debugme out_term "\nsending client hello (TLS version $tls_hexcode)" - debugme outln_term " ($n of $hb_rounds)" + debugme tm_out "\nsending client hello (TLS version $tls_hexcode)" + debugme tmln_out " ($n of $hb_rounds)" socksend "$client_hello" 1 - debugme outln_term "\nreading server hello" + debugme tmln_out "\nreading server hello" sockread_serverhello 32768 if [[ $DEBUG -ge 4 ]]; then hexdump -C "$SOCK_REPLY_FILE" | head -20 - outln_term "[...]" - outln_term "\nsending payload with TLS version $tls_hexcode:" + tmln_out "[...]" + tmln_out "\nsending payload with TLS version $tls_hexcode:" fi rm "$SOCK_REPLY_FILE" @@ -9578,10 +9576,10 @@ run_heartbleed(){ debugme echo "lines HB reply: $lines_returned" if [[ $DEBUG -ge 3 ]]; then - outln_term "\nheartbleed reply: " + tmln_out "\nheartbleed reply: " hexdump -C "$SOCK_REPLY_FILE" | head -20 - [[ $lines_returned -gt 20 ]] && outln_term "[...]" - outln_term + [[ $lines_returned -gt 20 ]] && tmln_out "[...]" + tmln_out fi if [[ $lines_returned -gt 1 ]] && [[ "${tls_hello_ascii:0:4}" == "1803" ]]; then @@ -9620,7 +9618,7 @@ run_heartbleed(){ # helper function ok_ids(){ - pr_done_bestln "\n ok -- something resetted our ccs packets" + prln_done_best "\n ok -- something resetted our ccs packets" return 0 } @@ -9688,25 +9686,25 @@ run_ccs_injection(){ fd_socket 5 || return 6 # we now make a standard handshake ... - debugme out_term "\nsending client hello, " + debugme tm_out "\nsending client hello, " socksend "$client_hello" 1 - debugme outln_term "\nreading server hello" + debugme tmln_out "\nreading server hello" sockread_serverhello 32768 if [[ $DEBUG -ge 4 ]]; then hexdump -C "$SOCK_REPLY_FILE" | head -20 - outln_term "[...]" - out_term "\nsending payload #1 with TLS version $tls_hexcode: " + tmln_out "[...]" + tm_out "\nsending payload #1 with TLS version $tls_hexcode: " fi rm "$SOCK_REPLY_FILE" # ... and then send the a change cipher spec message socksend "$ccs_message" 1 || ok_ids sockread_serverhello 4096 $CCS_MAX_WAITSOCK if [[ $DEBUG -ge 3 ]]; then - outln_term "\n1st reply: " + tmln_out "\n1st reply: " hexdump -C "$SOCK_REPLY_FILE" | head -20 - outln_term - out_term "sending payload #2 with TLS version $tls_hexcode: " + tmln_out + tm_out "sending payload #2 with TLS version $tls_hexcode: " fi rm "$SOCK_REPLY_FILE" @@ -9719,9 +9717,9 @@ run_ccs_injection(){ debugme echo "tls_content_type: ${tls_hello_ascii:0:2} | tls_protocol: ${tls_hello_ascii:2:4} | byte6: $byte6" if [[ $DEBUG -ge 3 ]]; then - outln_term "\n2nd reply: " + tmln_out "\n2nd reply: " hexdump -C "$SOCK_REPLY_FILE" - outln_term + tmln_out fi # in general, see https://en.wikipedia.org/wiki/Transport_Layer_Security#Alert_protocol @@ -9796,20 +9794,20 @@ run_renego() { #FIXME: didn't occur to me yet but why not also to check on "Secure Renegotiation IS supported" case $sec_renego in 0) - pr_svrty_criticalln "VULNERABLE (NOT ok)" + prln_svrty_critical "VULNERABLE (NOT ok)" fileout "secure_renego" "CRITICAL" "Secure Renegotiation: VULNERABLE" "$cve" "$cwe" "$hint" ;; 1) - pr_done_bestln "not vulnerable (OK)" + prln_done_best "not vulnerable (OK)" fileout "secure_renego" "OK" "Secure Renegotiation: not vulnerable" "$cve" "$cwe" ;; *) - pr_warningln "FIXME (bug): $sec_renego" + prln_warning "FIXME (bug): $sec_renego" fileout "secure_renego" "WARN" "Secure Renegotiation: FIXME (bug) $sec_renego" "$cve" "$cwe" ;; esac else - pr_warningln "handshake didn't succeed" + prln_warning "handshake didn't succeed" fileout "secure_renego" "WARN" "Secure Renegotiation: handshake didn't succeed" "$cve" "$cwe" fi @@ -9820,7 +9818,7 @@ run_renego() { 0.9.8*) # we need this for Mac OSX unfortunately case "$OSSL_VER_APPENDIX" in [a-l]) - local_problem_ln "$OPENSSL cannot test this secure renegotiation vulnerability" + prln_local_problem "$OPENSSL cannot test this secure renegotiation vulnerability" fileout "sec_client_renego" "WARN" "Secure Client-Initiated Renegotiation : $OPENSSL cannot test this secure renegotiation vulnerability" "$cve" "$cwe" return 3 ;; @@ -9836,7 +9834,7 @@ run_renego() { esac if "$CLIENT_AUTH"; then - pr_warningln "client authentication prevents this from being tested" + prln_warning "client authentication prevents this from being tested" fileout "sec_client_renego" "WARN" "Secure Client-Initiated Renegotiation : client authentication prevents this from being tested" sec_client_renego=1 else @@ -9862,11 +9860,11 @@ run_renego() { fi ;; 1) - pr_done_goodln "not vulnerable (OK)" + prln_done_good "not vulnerable (OK)" fileout "sec_client_renego" "OK" "Secure Client-Initiated Renegotiation : not vulnerable" "$cve" "$cwe" ;; *) - pr_warningln "FIXME (bug): $sec_client_renego" + prln_warning "FIXME (bug): $sec_client_renego" fileout "sec_client_renego" "DEBUG" "Secure Client-Initiated Renegotiation : FIXME (bug) $sec_client_renego - Please report" "$cve" "$cwe" ;; esac @@ -9900,7 +9898,7 @@ run_crime() { $OPENSSL zlib -e -a -in /dev/stdin &>/dev/stdout $TEMPDIR/dh_p.txt if [[ ! -s "$common_primes_file" ]]; then - local_problem_ln "couldn't read common primes file $common_primes_file" + prln_local_problem "couldn't read common primes file $common_primes_file" out "${spaces}" fileout "LOGJAM_common primes" "WARN" "couldn't read common primes file $common_primes_file" ret=7 @@ -10561,7 +10559,7 @@ run_drown() { case $? in 7) # strange reply, couldn't convert the cipher spec length to a hex number - fixme "strange v2 reply " + pr_fixme "strange v2 reply " outln " (rerun with DEBUG >=2)" [[ $DEBUG -ge 3 ]] && hexdump -C "$TEMPDIR/$NODEIP.sslv2_sockets.dd" | head -1 ret=7 @@ -10569,20 +10567,20 @@ run_drown() { ;; 3) # vulnerable lines=$(count_lines "$(hexdump -C "$TEMPDIR/$NODEIP.sslv2_sockets.dd" 2>/dev/null)") - debugme out_term " ($lines lines) " + debugme tm_out " ($lines lines) " if [[ "$lines" -gt 1 ]]; then nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3)) if [[ 0 -eq "$nr_ciphers_detected" ]]; then - pr_svrty_highln "SSLv2 is supported but couldn't detect a cipher (NOT ok)"; + prln_svrty_high "SSLv2 is supported but couldn't detect a cipher (NOT ok)"; fileout "drown" "HIGH" "SSLv2 is offered, but could not detect a cipher" "$cve" "$cwe" "$hint" else - pr_svrty_criticalln "VULNERABLE (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers"; + prln_svrty_critical "VULNERABLE (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers"; fileout "drown" "CRITICAL" "VULNERABLE, SSLv2 offered with $nr_ciphers_detected ciphers" "$cve" "$cwe" "$hint" fi fi ret=1 ;; - *) pr_done_bestln "not vulnerable on this port (OK)" + *) prln_done_best "not vulnerable on this port (OK)" fileout "drown" "OK" "not vulnerable to DROWN" "$cve" "$cwe" # Any fingerprint that is placed in $RSA_CERT_FINGERPRINT_SHA2 is # also added to $CERT_FINGERPRINT_SHA2, so if $CERT_FINGERPRINT_SHA2 @@ -10713,10 +10711,10 @@ run_beast(){ if [[ $? -ne 0 ]]; then # protocol supported? if "$continued"; then # second round: we hit TLS1 if "$HAS_SSL3" || "$using_sockets"; then - pr_done_goodln "no SSL3 or TLS1 (OK)" + prln_done_good "no SSL3 or TLS1 (OK)" fileout "beast" "OK" "BEAST: not vulnerable, no SSL3 or TLS1" "$cve" "$cwe" else - pr_done_goodln "no TLS1 (OK)" + prln_done_good "no TLS1 (OK)" fileout "beast" "OK" "BEAST: not vulnerable, no TLS1" "$cve" "$cwe" fi return 0 @@ -10843,12 +10841,12 @@ run_beast(){ first=false else [[ $proto == "tls1" ]] && ! $first && echo -n "$spaces " - pr_done_goodln "no CBC ciphers for $(toupper $proto) (OK)" + prln_done_good "no CBC ciphers for $(toupper $proto) (OK)" first=false fi else if ! "$vuln_beast" ; then - pr_done_goodln " no CBC ciphers for $(toupper $proto) (OK)" + prln_done_good " no CBC ciphers for $(toupper $proto) (OK)" fileout "cbc_$proto" "OK" "BEAST: No CBC ciphers for $(toupper $proto)" "$cve" "$cwe" fi fi @@ -10878,7 +10876,7 @@ run_beast(){ fileout "beast" "MEDIUM" "BEAST: VULNERABLE -- and no higher protocols as mitigation supported" "$cve" "$cwe" "$hint" fi fi - "$first" && ! "$vuln_beast" && pr_done_goodln "no CBC ciphers found for any protocol (OK)" + "$first" && ! "$vuln_beast" && prln_done_good "no CBC ciphers found for any protocol (OK)" "$using_sockets" && HAS_DH_BITS="$has_dh_bits" tmpfile_handle $FUNCNAME.txt @@ -11179,10 +11177,10 @@ run_rc4() { "$WIDE" && pr_svrty_high "VULNERABLE (NOT ok)" fileout "rc4" "HIGH" "RC4: VULNERABLE, Detected ciphers: $rc4_detected" "$cve" "$cwe" "$hint" elif [[ $nr_ciphers -eq 0 ]]; then - local_problem_ln "No RC4 Ciphers configured in $OPENSSL" + prln_local_problem "No RC4 Ciphers configured in $OPENSSL" fileout "rc4" "WARN" "RC4 ciphers not supported by local OpenSSL ($OPENSSL)" else - pr_done_goodln "no RC4 ciphers detected (OK)" + prln_done_good "no RC4 ciphers detected (OK)" fileout "rc4" "OK" "RC4: not vulnerable" "$cve" "$cwe" fi outln @@ -11228,7 +11226,7 @@ get_install_dir() { CIPHERS_BY_STRENGTH_FILE="$RUN_DIR/etc/cipher-mapping.txt" [[ -z "$TESTSSL_INSTALL_DIR" ]] && TESTSSL_INSTALL_DIR="$RUN_DIR" # probably TESTSSL_INSTALL_DIR fi - + [[ -r "$TESTSSL_INSTALL_DIR/etc/cipher-mapping.txt" ]] && CIPHERS_BY_STRENGTH_FILE="$TESTSSL_INSTALL_DIR/etc/cipher-mapping.txt" if [[ ! -r "$CIPHERS_BY_STRENGTH_FILE" ]]; then [[ -r "$RUN_DIR/cipher-mapping.txt" ]] && CIPHERS_BY_STRENGTH_FILE="$RUN_DIR/cipher-mapping.txt" @@ -11267,7 +11265,7 @@ get_install_dir() { unset ADD_RFC_STR unset SHOW_RFC debugme echo "$CIPHERS_BY_STRENGTH_FILE" - pr_warningln "\nATTENTION: No cipher mapping file found!" + prln_warning "\nATTENTION: No cipher mapping file found!" outln "Please note from 2.9dev on $PROG_NAME needs files in \"\$TESTSSL_INSTALL_DIR/etc/\" to function correctly." outln ignore_no_or_lame "Type \"yes\" to ignore this warning and proceed at your own risk" "yes" @@ -11305,8 +11303,8 @@ 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_term " Looking some place else ..." + prln_warning "\ncannot find specified (\$OPENSSL=$OPENSSL) binary." + tmln_out " Looking some place else ..." elif [[ -x "$OPENSSL" ]]; then : # 1. all ok supplied $OPENSSL was found and has excutable bit set -- testrun comes below elif [[ -e "/mnt/c/Windows/System32/bash.exe" ]] && test_openssl_suffix "$(dirname "$(which openssl)")"; then @@ -11413,7 +11411,7 @@ check4openssl_oldfarts() { ;; esac if [[ $OSSL_VER_MAJOR -lt 1 ]]; then ## mm: Patch for libressl - pr_warningln " Your \"$OPENSSL\" is way too old (&2 + prln_magenta "Fatal error: $1" >&2 exit $2 # 1: cmd line error # 2: secondary/other cmd line error @@ -11769,7 +11767,7 @@ initialize_engine(){ return 1 else # we have engine support if [[ -n "$OPENSSL_CONF" ]]; then - pr_warningln "For now I am providing the config file to have GOST support" + prln_warning "For now I am providing the config file to have GOST support" else OPENSSL_CONF=$TEMPDIR/gost.conf || exit -6 # see https://www.mail-archive.com/openssl-users@openssl.org/msg65395.html @@ -11804,7 +11802,7 @@ ignore_no_or_lame() { [[ "$WARNINGS" == off ]] && return 0 [[ "$WARNINGS" == false ]] && return 0 [[ "$WARNINGS" == batch ]] && return 1 - pr_warning_term "$1 --> " + tm_warning "$1 --> " read a if [[ "$a" == "$(tolower "$2")" ]]; then return 0 @@ -11875,10 +11873,10 @@ prepare_logging() { : # just for clarity: a log file was specified, no need to do anything else fi >$LOGFILE - outln_term "## Scan started as: \"$PROG_NAME $CMDLINE\"" >>${LOGFILE} - outln_term "## at $HNAME:$OPENSSL_LOCATION" >>${LOGFILE} - outln_term "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE" >>${LOGFILE} - outln_term "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n" >>${LOGFILE} + tmln_out "## Scan started as: \"$PROG_NAME $CMDLINE\"" >>${LOGFILE} + tmln_out "## at $HNAME:$OPENSSL_LOCATION" >>${LOGFILE} + tmln_out "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE" >>${LOGFILE} + tmln_out "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n" >>${LOGFILE} exec > >(tee -a ${LOGFILE}) # not decided yet. Maybe good to have a separate file or none at all #exec 2> >(tee -a ${LOGFILE} >&2) @@ -12226,7 +12224,7 @@ check_proxy() { fatal "Your $OPENSSL is too old to support the \"-proxy\" option" -5 fi if [[ "$PROXY" == "auto" ]]; then - # get $ENV + # get $ENV PROXY=${https_proxy#*\/\/} [[ -z "$PROXY" ]] && PROXY=${http_proxy#*\/\/} [[ -z "$PROXY" ]] && fatal "you specified \"--proxy=auto\" but \"\$http(s)_proxy\" is empty" 2 @@ -12310,7 +12308,7 @@ determine_optimal_proto() { [[ $all_failed -eq 0 ]] && OPTIMAL_PROTO="" debugme echo "OPTIMAL_PROTO: $OPTIMAL_PROTO" if [[ "$OPTIMAL_PROTO" == "-ssl2" ]]; then - pr_magentaln "$NODEIP:$PORT appears to only support SSLv2." + prln_magenta "$NODEIP:$PORT appears to only support SSLv2." ignore_no_or_lame " Type \"yes\" to proceed and accept false negatives or positives" "yes" [[ $? -ne 0 ]] && exit -2 fi @@ -12325,7 +12323,7 @@ determine_optimal_proto() { pr_bold " $NODEIP:$PORT " fi tmpfile_handle $FUNCNAME.txt - pr_boldln "doesn't seem to be a TLS/SSL enabled server"; + prln_bold "doesn't seem to be a TLS/SSL enabled server"; ignore_no_or_lame " The results might look ok but they could be nonsense. Really proceed ? (\"yes\" to continue)" "yes" [[ $? -ne 0 ]] && exit -2 fi @@ -12497,7 +12495,7 @@ run_mx_all_ips() { outln pr_bold "Done testing now all MX records (on port $mxport): "; outln "$mxs" else - pr_boldln " $1 has no MX records(s)" + prln_bold " $1 has no MX records(s)" fi return $ret } @@ -12726,7 +12724,7 @@ parse_cmd_line() { case $STARTTLS_PROTOCOL in ftp|smtp|pop3|imap|xmpp|telnet|ldap|nntp|postgres) ;; ftps|smtps|pop3s|imaps|xmpps|telnets|ldaps|nntps|postgress) ;; - *) pr_magentaln_term "\nunrecognized STARTTLS protocol \"$1\", see help" 1>&2 + *) tmln_magenta "\nunrecognized STARTTLS protocol \"$1\", see help" 1>&2 help 1 ;; esac ;; @@ -12885,7 +12883,7 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift case "$WARNINGS" in batch|off|false) ;; - *) pr_magentaln_term "\nwarnings can be either \"batch\", \"off\" or \"false\"" + *) tmln_magenta "\nwarnings can be either \"batch\", \"off\" or \"false\"" help 1 esac ;; @@ -12903,7 +12901,7 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift case $DEBUG in [0-6]) ;; - *) pr_magentaln_term_term "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2 + *) tmln_magenta_term "\nunrecognized debug value \"$1\", must be between 0..6" 1>&2 help 1 esac ;; @@ -12913,7 +12911,7 @@ parse_cmd_line() { case $COLOR in [0-2]) ;; *) COLOR=2 - pr_magentaln_term "\nunrecognized color: \"$1\", must be between 0..2" 1>&2 + tmln_magenta "\nunrecognized color: \"$1\", must be between 0..2" 1>&2 help 1 esac ;; @@ -12971,9 +12969,6 @@ parse_cmd_line() { [[ $? -eq 0 ]] && shift do_html=true ;; - --no-html-header) - HTMLHEADER=false - ;; --append) APPEND=true ;; @@ -12992,7 +12987,7 @@ parse_cmd_line() { case "$cipher_mapping" in no-rfc) unset ADD_RFC_STR; unset SHOW_RFC;; rfc) SHOW_RFC="rfc" ;; - *) pr_magentaln_term "\nmapping can only be \"rfc\" or \"no-rfc\"" + *) tmln_magenta "\nmapping can only be \"rfc\" or \"no-rfc\"" help 1 ;; esac ;; @@ -13012,7 +13007,7 @@ parse_cmd_line() { (--) shift break ;; - (-*) pr_warningln_term "0: unrecognized option \"$1\"" 1>&2; + (-*) tmln_warning "0: unrecognized option \"$1\"" 1>&2; help 1 ;; (*) break @@ -13157,8 +13152,8 @@ lets_roll() { initialize_globals parse_cmd_line "$@" -! "$do_html" && HTMLHEADER=false -if "$HTMLHEADER" && ( ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ) ); then + +if ( ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ) ); then if "$do_display_only"; then html_header "local-ciphers" elif "$do_mass_testing"; then @@ -13170,6 +13165,7 @@ if "$HTMLHEADER" && ( ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d html_header fi fi + get_install_dir set_color_functions maketempf From 4727a69a62933d97a88da1da9a697ce2b69b95ec Mon Sep 17 00:00:00 2001 From: Dirk Date: Sat, 25 Feb 2017 17:15:18 +0100 Subject: [PATCH 14/21] fixed segfaults --- testssl.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 5470458..3a0ba2f 100755 --- a/testssl.sh +++ b/testssl.sh @@ -628,8 +628,8 @@ pr_done_good() { tm_done_good "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && prln_done_good() { pr_done_good "$1"; outln; } tm_done_best() { [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && tm_out "\033[1;34m$1" || tm_out "\033[1;32m$1" ) || tm_out "$1"; tm_off; } # green (blue), This is the best +tmln_done_best() { tm_done_best "$1"; tmln_out; } pr_done_best() { tm_done_best "$1"; [[ "$COLOR" -eq 2 ]] && ( "$COLORBLIND" && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")" ) || html_out "$(html_reserved "$1")"; } -tm_done_best() { tm_done_best "$1"; tmln_out; } prln_done_best() { pr_done_best "$1"; outln; } tm_svrty_low() { [[ "$COLOR" -eq 2 ]] && tm_out "\033[1;33m$1" || tm_out "$1"; tm_off; } # yellow brown | academic or minor problem @@ -666,9 +666,9 @@ pr_bold() { tm_bold "$1"; [[ "$COLOR" -ne 0 ]] && html_out "$(html_reserved "$1")" || html_out "$(html_reserved "$1")"; } -tmln_italic() { tm_italic "$1"; tmln_out; } +prln_italic() { pr_italic "$1"; tmln_out; } tm_strikethru() { [[ "$COLOR" -ne 0 ]] && tm_out "\033[9m$1" || tm_out "$1"; tm_off; } # ugly! tmln_strikethru() { tm_strikethru "$1"; tmln_out; } From 915cadd20da05e8325d63ea65c1d444dcf04b681 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Mon, 27 Feb 2017 10:34:04 -0500 Subject: [PATCH 15/21] Merge PR #646 into 2.9dev_html This PR just brings 2.9dev_html up to date with 2.9dev. --- testssl.sh | 110 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 40 deletions(-) diff --git a/testssl.sh b/testssl.sh index 3a0ba2f..568d18f 100755 --- a/testssl.sh +++ b/testssl.sh @@ -228,8 +228,7 @@ HAS_FALLBACK_SCSV=false HAS_PROXY=false HAS_XMPP=false HAS_POSTGRES=false -ADD_RFC_STR="rfc" # display RFC ciphernames -SHOW_RFC="" # display RFC ciphernames instead of OpenSSL ciphernames +DISPLAY_CIPHERNAMES="openssl" # display OpenSSL ciphername (but both OpenSSL and RFC ciphernames in wide mode) PORT=443 # unless otherwise auto-determined, see below NODE="" NODEIP="" @@ -2454,8 +2453,21 @@ show_rfc_style(){ } neat_header(){ - outln "$(printf -- "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits${ADD_RFC_STR:+ Cipher Suite Name (RFC)}")" - outln "$(printf -- "%s--------------------------------------------------------------------------${ADD_RFC_STR:+---------------------------------------------------}")" + if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then + out "$(printf -- "Hexcode Cipher Suite Name (RFC) KeyExch. Encryption Bits")" + [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && out "$(printf -- " Cipher Suite Name (OpenSSL)")" + outln + out "$(printf -- "%s------------------------------------------------------------------------------------------")" + [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && out "$(printf -- "---------------------------------------")" + outln + else + out "$(printf -- "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits")" + [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && out "$(printf -- " Cipher Suite Name (RFC)")" + outln + out "$(printf -- "%s--------------------------------------------------------------------------")" + [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && out "$(printf -- "---------------------------------------------------")" + outln + fi } @@ -2481,21 +2493,32 @@ neat_list(){ enc="${enc//POLY1305/}" # remove POLY1305 enc="${enc//\//}" # remove "/" - echo "$export" | grep -iq export && strength="$strength,exp" + grep -iq export <<< "$export" && strength="$strength,exp" - [[ -n "$ADD_RFC_STR" ]] && tls_cipher="$(show_rfc_style "$hexcode")" + [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && tls_cipher="$(show_rfc_style "$hexcode")" - if [[ -z "$5" ]]; then - tm_out "$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" - return 0 - elif [[ "$5" == "false" ]]; then - line="$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" - pr_deemphasize "$line" + if [[ "$5" != "true" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then + line="$(printf -- " %-7s %-49s %-10s %-12s%-8s" "$hexcode" "$tls_cipher" "$kx" "$enc" "$strength")" + [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && line+="$(printf -- " %-33s${SHOW_EACH_C:+ %-0s}" "$ossl_cipher")" + else + line="$(printf -- " %-7s %-33s %-10s %-12s%-8s" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength")" + [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && line+="$(printf -- " %-49s${SHOW_EACH_C:+ %-0s}" "$tls_cipher")" + fi + if [[ -z "$5" ]]; then + tm_out "$line" + else + pr_deemphasize "$line" + fi return 0 fi - out "$(printf -- " %-7s %-33s " "$hexcode" "$ossl_cipher")" - read what_dh bits <<< "$kx" + len=${#kx} + if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then + out "$(printf -- " %-7s %-49s " "$hexcode" "$tls_cipher")" + else + out "$(printf -- " %-7s %-33s " "$hexcode" "$ossl_cipher")" + fi out "$what_dh" if [[ -n "$bits" ]]; then if [[ $what_dh == "DH" ]] || [[ $what_dh == "EDH" ]]; then @@ -2504,11 +2527,15 @@ neat_list(){ pr_ecdh_quality "$bits" " $bits" fi fi - len=${#kx} for (( i=len; i<10; i++ )); do out " " done - out "$(printf -- " %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$enc" "$strength" "$tls_cipher")" + out "$(printf -- " %-12s%-8s" "$enc" "$strength")" + if [[ "$DISPLAY_CIPHERNAMES" == rfc ]]; then + out "$(printf -- " %-33s${SHOW_EACH_C:+ %-0s}" "$ossl_cipher")" + elif [[ "$DISPLAY_CIPHERNAMES" == openssl ]]; then + out "$(printf -- " %-49s${SHOW_EACH_C:+ %-0s}" "$tls_cipher")" + fi } test_just_one(){ @@ -4366,10 +4393,10 @@ run_client_simulation() { fi #FiXME: awk cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://') - if [[ -z "$SHOW_RFC" ]] && ( [[ "$cipher" == TLS_* ]] || [[ "$cipher" == SSL_* ]] ); then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && ( [[ "$cipher" == TLS_* ]] || [[ "$cipher" == SSL_* ]] ); then cipher="$(rfc2openssl "$cipher")" [[ -z "$cipher" ]] && cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://') - elif [[ -n "$SHOW_RFC" ]] && [[ "$cipher" != TLS_* ]] && [[ "$cipher" != SSL_* ]]; then + elif [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]] && [[ "$cipher" != TLS_* ]] && [[ "$cipher" != SSL_* ]]; then cipher="$(openssl2rfc "$cipher")" [[ -z "$cipher" ]] && cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://') fi @@ -4882,7 +4909,7 @@ pr_cipher_quality() { [[ -z "$1" ]] && return 0 [[ -z "$text" ]] && text="$cipher" - + if [[ "$cipher" != TLS_* ]] && [[ "$cipher" != SSL_* ]]; then # This must be the OpenSSL name for a cipher if [[ $TLS_NR_CIPHERS -eq 0 ]]; then @@ -5144,7 +5171,7 @@ run_server_preference() { pr_bold " Negotiated cipher " default_cipher_ossl=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') - if [[ -z "$SHOW_RFC" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then default_cipher="$default_cipher_ossl" else default_cipher="$(openssl2rfc "$default_cipher_ossl")" @@ -5203,7 +5230,7 @@ run_server_preference() { cipher1="${TLS_CIPHER_HEXCODE[j]}" cipher1="$(tolower "x${cipher1:2:2}${cipher1:7:2}${cipher1:12:2}")" if [[ "$supported_sslv2_ciphers" =~ "$cipher1" ]]; then - if ( [[ -z "$SHOW_RFC" ]] && [[ "${TLS_CIPHER_OSSL_NAME[j]}" != "-" ]] ) || [[ "${TLS_CIPHER_RFC_NAME[j]}" == "-" ]]; then + if ( [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && [[ "${TLS_CIPHER_OSSL_NAME[j]}" != "-" ]] ) || [[ "${TLS_CIPHER_RFC_NAME[j]}" == "-" ]]; then cipher[i]="${TLS_CIPHER_OSSL_NAME[j]}" else cipher[i]="${TLS_CIPHER_RFC_NAME[j]}" @@ -5228,7 +5255,7 @@ run_server_preference() { proto[i]="SSLv3" cipher[i]="" cipher1=$(awk '/Cipher *:/ { print $3 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") - if [[ -z "$SHOW_RFC" ]] && [[ $TLS_NR_CIPHERS -ne 0 ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && [[ $TLS_NR_CIPHERS -ne 0 ]]; then cipher[i]="$(rfc2openssl "$cipher1")" [[ -z "${cipher[i]}" ]] && cipher[i]="$cipher1" fi @@ -5245,7 +5272,7 @@ run_server_preference() { 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') [[ ${cipher[i]} == "0000" ]] && cipher[i]="" # Hack! - if [[ -n "$SHOW_RFC" ]] && [[ -n "${cipher[i]}" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]] && [[ -n "${cipher[i]}" ]]; then cipher[i]="$(openssl2rfc "${cipher[i]}")" [[ -z "${cipher[i]}" ]] && cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') fi @@ -5269,7 +5296,7 @@ run_server_preference() { cipher[i]="" else cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') - if [[ -n "$SHOW_RFC" ]] && [[ -n "${cipher[i]}" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]] && [[ -n "${cipher[i]}" ]]; then cipher[i]="$(openssl2rfc "${cipher[i]}")" [[ -z "${cipher[i]}" ]] && cipher[i]=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') fi @@ -5284,7 +5311,7 @@ run_server_preference() { if [[ -n "${cipher[i]}" ]]; then # cipher not empty if [[ -z "${cipher[i-1]}" ]]; then # previous one empty #outln - if [[ -z "$SHOW_RFC" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then out "$(printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}")" # print out both else out "$(printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}")" # print out both @@ -5294,7 +5321,7 @@ run_server_preference() { out ", ${proto[i]}" # same cipher --> only print out protocol behind it else outln - if [[ -z "$SHOW_RFC" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then out "$(printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}")" # print out both else out "$(printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}")" # print out both @@ -5555,14 +5582,14 @@ cipher_pref_check() { for (( i=0; i < nr_ciphers; i++ )); do [[ "$cipher" == "${rfc_ciph[i]}" ]] && ciphers_found2[i]=true && break done - if [[ -z "$SHOW_RFC" ]] && [[ $TLS_NR_CIPHERS -ne 0 ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && [[ $TLS_NR_CIPHERS -ne 0 ]]; then cipher="$(rfc2openssl "$cipher")" # If there is no OpenSSL name for the cipher, then use the RFC name [[ -z "$cipher" ]] && cipher=$(awk '/Cipher *:/ { print $3 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") fi order+="$cipher " done - elif [[ -n "$order" ]] && [[ -n "$SHOW_RFC" ]]; then + elif [[ -n "$order" ]] && [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then rfc_order="" while read -d " " cipher; do rfc_ciph="$(openssl2rfc "$cipher")" @@ -5604,7 +5631,7 @@ cipher_pref_check() { order+="$cipher " done fi - if [[ -n "$order" ]] && [[ -n "$SHOW_RFC" ]]; then + if [[ -n "$order" ]] && [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then rfc_order="" while read -d " " cipher; do rfc_ciph="$(openssl2rfc "$cipher")" @@ -7162,7 +7189,7 @@ run_pfs() { for (( i=0; i < nr_supported_ciphers; i++ )); do ! "${ciphers_found[i]}" && ! "$SHOW_EACH_C" && continue if "${ciphers_found[i]}"; then - if ( [[ -z "$SHOW_RFC" ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then + if ( [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then pfs_cipher="${ciph[i]}" else pfs_cipher="${rfc_ciph[i]}" @@ -10756,7 +10783,7 @@ run_beast(){ [[ "$cbc_cipher" == "${ciph[i]}" ]] && break done ciphers_found[i]=true - if [[ -z "$SHOW_RFC" ]] || [[ "${rfc_ciph[i]}" == "-" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] || [[ "${rfc_ciph[i]}" == "-" ]]; then detected_cbc_ciphers+="${ciph[i]} " else detected_cbc_ciphers+="${rfc_ciph[i]} " @@ -10787,7 +10814,7 @@ run_beast(){ [[ "$cbc_cipher" == "${rfc_ciph[i]}" ]] && break done ciphers_found[i]=true - if ( [[ -z "$SHOW_RFC" ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then + if ( [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then detected_cbc_ciphers+=" ${ciph[i]}" else detected_cbc_ciphers+=" ${rfc_ciph[i]}" @@ -11165,7 +11192,7 @@ run_rc4() { outln "${sigalg[i]}" fi if "${ciphers_found[i]}"; then - if ( [[ -z "$SHOW_RFC" ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then + if ( [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then rc4_detected+="${ciph[i]} " else rc4_detected+="${rfc_ciph[i]} " @@ -11262,8 +11289,7 @@ get_install_dir() { fi if [[ ! -r "$CIPHERS_BY_STRENGTH_FILE" ]]; then - unset ADD_RFC_STR - unset SHOW_RFC + DISPLAY_CIPHERNAMES="no-rfc" debugme echo "$CIPHERS_BY_STRENGTH_FILE" prln_warning "\nATTENTION: No cipher mapping file found!" outln "Please note from 2.9dev on $PROG_NAME needs files in \"\$TESTSSL_INSTALL_DIR/etc/\" to function correctly." @@ -11521,8 +11547,10 @@ output options (can also be preset via environment variables): --quiet don't output the banner. By doing this you acknowledge usage terms normally appearing in the banner --wide wide output for tests like RC4, BEAST. PFS also with hexcode, kx, strength, RFC name --show-each for wide outputs: display all ciphers tested -- not only succeeded ones - --mapping (rfc: display the RFC Cipher Suite name instead of the OpenSSL name; - no-rfc: don't display the RFC Cipher Suite Name) + --mapping no-rfc: don't display the RFC Cipher Suite Name, display OpenSSL names only --color <0|1|2> 0: no escape or other codes, 1: b/w escape codes, 2: color (default) --colorblind swap green and blue in the output --debug <0-6> 1: screen output normal but keeps debug output in /tmp/. 2-6: see "grep -A 5 '^DEBUG=' testssl.sh" @@ -12985,9 +13013,11 @@ parse_cmd_line() { cipher_mapping=$(parse_opt_equal_sign "$1" "$2") [[ $? -eq 0 ]] && shift case "$cipher_mapping" in - no-rfc) unset ADD_RFC_STR; unset SHOW_RFC;; - rfc) SHOW_RFC="rfc" ;; - *) tmln_magenta "\nmapping can only be \"rfc\" or \"no-rfc\"" + no-openssl) DISPLAY_CIPHERNAMES="rfc-only" ;; + no-rfc) DISPLAY_CIPHERNAMES="openssl-only" ;; + openssl) DISPLAY_CIPHERNAMES="openssl" ;; + rfc) DISPLAY_CIPHERNAMES="rfc" ;; + *) tmln_warning "\nmapping can only be \"no-openssl\", \"no-rfc\", \"openssl\" or \"rfc\"" help 1 ;; esac ;; From f53afdc14919a3afbfefeb4a8ca2970743fe08a3 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Mon, 27 Feb 2017 11:17:19 -0500 Subject: [PATCH 16/21] Redo emphasize_stuff_in_headers() This PR re-implements `emphasize_stuff_in_headers()` in the HTML branch to more closely match the version in 2.9dev. --- testssl.sh | 162 +++++++++++++++++++++-------------------------------- 1 file changed, 64 insertions(+), 98 deletions(-) diff --git a/testssl.sh b/testssl.sh index 568d18f..48fd55c 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1890,106 +1890,72 @@ run_hpkp() { } emphasize_stuff_in_headers(){ - local text="$1" - local -i len + local html_brown="" + local html_yellow="" + local html_off="<\\/span>" - if [[ $COLOR -ne 2 ]]; then - out "$text" - text="" +# see http://www.grymoire.com/Unix/Sed.html#uh-3 +# outln "$1" | sed "s/[0-9]*/$brown&${off}/g" + tmln_out "$1" | sed -e "s/\([0-9]\)/${brown}\1${off}/g" \ + -e "s/Debian/${yellow}\Debian${off}/g" \ + -e "s/Win32/${yellow}\Win32${off}/g" \ + -e "s/Win64/${yellow}\Win64${off}/g" \ + -e "s/Ubuntu/${yellow}Ubuntu${off}/g" \ + -e "s/ubuntu/${yellow}ubuntu${off}/g" \ + -e "s/jessie/${yellow}jessie${off}/g" \ + -e "s/squeeze/${yellow}squeeze${off}/g" \ + -e "s/wheezy/${yellow}wheezy${off}/g" \ + -e "s/lenny/${yellow}lenny${off}/g" \ + -e "s/SUSE/${yellow}SUSE${off}/g" \ + -e "s/Red Hat Enterprise Linux/${yellow}Red Hat Enterprise Linux${off}/g" \ + -e "s/Red Hat/${yellow}Red Hat${off}/g" \ + -e "s/CentOS/${yellow}CentOS${off}/g" \ + -e "s/Via/${yellow}Via${off}/g" \ + -e "s/X-Forwarded/${yellow}X-Forwarded${off}/g" \ + -e "s/Liferay-Portal/${yellow}Liferay-Portal${off}/g" \ + -e "s/X-Cache-Lookup/${yellow}X-Cache-Lookup${off}/g" \ + -e "s/X-Cache/${yellow}X-Cache${off}/g" \ + -e "s/X-Squid/${yellow}X-Squid${off}/g" \ + -e "s/X-Server/${yellow}X-Server${off}/g" \ + -e "s/X-Varnish/${yellow}X-Varnish${off}/g" \ + -e "s/X-OWA-Version/${yellow}X-OWA-Version${off}/g" \ + -e "s/MicrosoftSharePointTeamServices/${yellow}MicrosoftSharePointTeamServices${off}/g" \ + -e "s/X-Version/${yellow}X-Version${off}/g" \ + -e "s/X-Powered-By/${yellow}X-Powered-By${off}/g" \ + -e "s/X-UA-Compatible/${yellow}X-UA-Compatible${off}/g" \ + -e "s/X-AspNet-Version/${yellow}X-AspNet-Version${off}/g" + + if "$do_html"; then + html_out "$(tm_out "$1" | sed -e "s/\([0-9]\)/${html_brown}\1${html_off}/g" \ + -e "s/Debian/${html_yellow}\Debian${html_off}/g" \ + -e "s/Win32/${html_yellow}\Win32${html_off}/g" \ + -e "s/Win64/${html_yellow}\Win64${html_off}/g" \ + -e "s/Ubuntu/${html_yellow}Ubuntu${html_off}/g" \ + -e "s/ubuntu/${html_yellow}ubuntu${html_off}/g" \ + -e "s/jessie/${html_yellow}jessie${html_off}/g" \ + -e "s/squeeze/${html_yellow}squeeze${html_off}/g" \ + -e "s/wheezy/${html_yellow}wheezy${html_off}/g" \ + -e "s/lenny/${html_yellow}lenny${html_off}/g" \ + -e "s/SUSE/${html_yellow}SUSE${html_off}/g" \ + -e "s/Red Hat Enterprise Linux/${html_yellow}Red Hat Enterprise Linux${html_off}/g" \ + -e "s/Red Hat/${html_yellow}Red Hat${html_off}/g" \ + -e "s/CentOS/${html_yellow}CentOS${html_off}/g" \ + -e "s/Via/${html_yellow}Via${html_off}/g" \ + -e "s/X-Forwarded/${html_yellow}X-Forwarded${html_off}/g" \ + -e "s/Liferay-Portal/${html_yellow}Liferay-Portal${html_off}/g" \ + -e "s/X-Cache-Lookup/${html_yellow}X-Cache-Lookup${html_off}/g" \ + -e "s/X-Cache/${html_yellow}X-Cache${html_off}/g" \ + -e "s/X-Squid/${html_yellow}X-Squid${html_off}/g" \ + -e "s/X-Server/${html_yellow}X-Server${html_off}/g" \ + -e "s/X-Varnish/${html_yellow}X-Varnish${html_off}/g" \ + -e "s/X-OWA-Version/${html_yellow}X-OWA-Version${html_off}/g" \ + -e "s/MicrosoftSharePointTeamServices/${html_yellow}MicrosoftSharePointTeamServices${html_off}/g" \ + -e "s/X-Version/${html_yellow}X-Version${html_off}/g" \ + -e "s/X-Powered-By/${html_yellow}X-Powered-By${html_off}/g" \ + -e "s/X-UA-Compatible/${html_yellow}X-UA-Compatible${html_off}/g" \ + -e "s/X-AspNet-Version/${html_yellow}X-AspNet-Version${html_off}/g")" + html_out "\n" fi - len=${#text} - while [[ $len -gt 0 ]]; do - if [[ -z "$(tr -d '0-9' <<< "${text:0:1}")" ]]; then - tm_out "${brown}${text:0:1}${off}" - html_out "${text:0:1}" - text="${text:1}" - len=$len-1 - elif [[ $len -ge 31 ]] && [[ "${text:0:31}" == "MicrosoftSharePointTeamServices" ]]; then - tm_out "${yellow}${text:0:31}${off}" - html_out "${text:0:31}" - text="${text:31}" - len=$len-31 - elif [[ $len -ge 24 ]] && [[ "${text:0:24}" == "Red Hat Enterprise Linux" ]]; then - tm_out "${yellow}${text:0:24}${off}" - html_out "${text:0:24}" - text="${text:24}" - len=$len-24 - elif [[ $len -ge 16 ]] && [[ "${text:0:16}" == "X-AspNet-Version" ]]; then - tm_out "${yellow}${text:0:16}${off}" - html_out "${text:0:16}" - text="${text:16}" - len=$len-16 - elif [[ $len -ge 15 ]] && [[ "${text:0:15}" == "X-UA-Compatible" ]]; then - tm_out "${yellow}${text:0:15}${off}" - html_out "${text:0:15}" - text="${text:15}" - len=$len-15 - elif [[ $len -ge 14 ]] && ( [[ "${text:0:14}" == "Liferay-Portal" ]] || [[ "${text:0:14}" == "X-Cache-Lookup" ]] || \ - [[ "${text:0:14}" == "X-Cache-Status" ]] ) ; then - tm_out "${yellow}${text:0:14}${off}" - html_out "${text:0:14}" - text="${text:14}" - len=$len-14 - elif [[ $len -ge 13 ]] && [[ "${text:0:13}" == "X-OWA-Version" ]]; then - tm_out "${yellow}${text:0:13}${off}" - html_out "${text:0:13}" - text="${text:13}" - len=$len-13 - elif [[ $len -ge 12 ]] && [[ "${text:0:12}" == "X-Powered-By" ]]; then - tm_out "${yellow}${text:0:12}${off}" - html_out "${text:0:12}" - text="${text:12}" - len=$len-12 - elif [[ $len -ge 11 ]] && [[ "${text:0:11}" == "X-Forwarded" ]]; then - tm_out "${yellow}${text:0:11}${off}" - html_out "${text:0:11}" - text="${text:11}" - len=$len-11 - elif [[ $len -ge 9 ]] && ( [[ "${text:0:9}" == "X-Varnish" ]] || [[ "${text:0:9}" == "X-Version" ]] ); then - tm_out "${yellow}${text:0:9}${off}" - html_out "${text:0:9}" - text="${text:9}" - len=$len-9 - elif [[ $len -ge 8 ]] && [[ "${text:0:8}" == "X-Server" ]]; then - tm_out "${yellow}${text:0:8}${off}" - html_out "${text:0:8}" - text="${text:8}" - len=$len-8 - elif [[ $len -ge 7 ]] && ( [[ "${text:0:7}" == "squeeze" ]] || [[ "${text:0:7}" == "Red Hat" ]] || \ - [[ "${text:0:7}" == "X-Cache" ]] || [[ "${text:0:7}" == "X-Squid" ]] ) ; then - tm_out "${yellow}${text:0:7}${off}" - html_out "${text:0:7}" - text="${text:7}" - len=$len-7 - elif [[ $len -ge 6 ]] && ( [[ "${text:0:6}" == "Debian" ]] || [[ "${text:0:6}" == "Ubuntu" ]] || \ - [[ "${text:0:6}" == "ubuntu" ]] || [[ "${text:0:6}" == "jessie" ]] || \ - [[ "${text:0:6}" == "wheezy" ]] || [[ "${text:0:6}" == "CentOS" ]] ) ; then - tm_out "${yellow}${text:0:6}${off}" - html_out "${text:0:6}" - text="${text:6}" - len=$len-6 - elif [[ $len -ge 5 ]] && ( [[ "${text:0:5}" == "Win32" ]] || [[ "${text:0:5}" == "Win64" ]] || [[ "${text:0:5}" == "lenny" ]] ); then - tm_out "${yellow}${text:0:5}${off}" - html_out "${text:0:5}" - text="${text:5}" - len=$len-5 - elif [[ $len -ge 4 ]] && [[ "${text:0:4}" == "SUSE" ]]; then - tm_out "${yellow}${text:0:4}${off}" - html_out "${text:0:4}" - text="${text:4}" - len=$len-4 - elif [[ $len -ge 3 ]] && [[ "${text:0:3}" == "Via" ]]; then - tm_out "${yellow}${text:0:3}${off}" - html_out "${text:0:3}" - text="${text:3}" - len=$len-3 - else - out "${text:0:1}" - text="${text:1}" - len=$len-1 - fi - done - outln } run_server_banner() { From 0ada7b100c773900375d4df5fb81a69e9d968d72 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Mon, 27 Feb 2017 11:49:51 -0500 Subject: [PATCH 17/21] Handle HTML reserved characters in headers So far I haven't seen any HTML reserved characters (&, <, >, ", ') in the strings processed by `emphasize_stuff_in_headers()`, so this PR may be unnecessary. However, this PR will ensure that any such characters will be properly escaped in the HTML output. --- testssl.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 48fd55c..85aa370 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1926,7 +1926,9 @@ emphasize_stuff_in_headers(){ -e "s/X-AspNet-Version/${yellow}X-AspNet-Version${off}/g" if "$do_html"; then - html_out "$(tm_out "$1" | sed -e "s/\([0-9]\)/${html_brown}\1${html_off}/g" \ + html_out "$(tm_out "$1" | sed -e 's/\&/\&/g' \ + -e 's//\>/g' -e 's/"/\"/g' -e "s/'/\'/g" \ + -e "s/\([0-9]\)/${html_brown}\1${html_off}/g" \ -e "s/Debian/${html_yellow}\Debian${html_off}/g" \ -e "s/Win32/${html_yellow}\Win32${html_off}/g" \ -e "s/Win64/${html_yellow}\Win64${html_off}/g" \ From 79a8a02328d479cbb42b991c68827565a8a29421 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 27 Feb 2017 19:16:29 +0100 Subject: [PATCH 18/21] adding spring boot header detection --- testssl.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testssl.sh b/testssl.sh index 48fd55c..90e1521 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1920,6 +1920,7 @@ emphasize_stuff_in_headers(){ -e "s/X-Varnish/${yellow}X-Varnish${off}/g" \ -e "s/X-OWA-Version/${yellow}X-OWA-Version${off}/g" \ -e "s/MicrosoftSharePointTeamServices/${yellow}MicrosoftSharePointTeamServices${off}/g" \ + -e "s/X-Application-Context/${yellow}X-Application-Context${off}/g" \ -e "s/X-Version/${yellow}X-Version${off}/g" \ -e "s/X-Powered-By/${yellow}X-Powered-By${off}/g" \ -e "s/X-UA-Compatible/${yellow}X-UA-Compatible${off}/g" \ @@ -1950,6 +1951,7 @@ emphasize_stuff_in_headers(){ -e "s/X-Varnish/${html_yellow}X-Varnish${html_off}/g" \ -e "s/X-OWA-Version/${html_yellow}X-OWA-Version${html_off}/g" \ -e "s/MicrosoftSharePointTeamServices/${html_yellow}MicrosoftSharePointTeamServices${html_off}/g" \ + -e "s/X-Application-Context/${html_yellow}X-Application-Context${html_off}/g" \ -e "s/X-Version/${html_yellow}X-Version${html_off}/g" \ -e "s/X-Powered-By/${html_yellow}X-Powered-By${html_off}/g" \ -e "s/X-UA-Compatible/${html_yellow}X-UA-Compatible${html_off}/g" \ From ca6cb0bf8101976093b7efc834f4ce7118c9f3df Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 28 Feb 2017 18:33:17 +0100 Subject: [PATCH 19/21] updated from #632 from dcooper16/negotiated_cipher --- testssl.sh | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/testssl.sh b/testssl.sh index 90e1521..a0d6925 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5011,7 +5011,7 @@ read_dhbits_from_file() { run_server_preference() { - local cipher1 cipher2 + local cipher1 cipher2 prev_cipher="" local default_cipher default_cipher_ossl default_proto local remark4default_cipher supported_sslv2_ciphers local -a cipher proto @@ -5277,25 +5277,17 @@ run_server_preference() { for i in 1 2 3 4 5 6; do if [[ -n "${cipher[i]}" ]]; then # cipher not empty - if [[ -z "${cipher[i-1]}" ]]; then # previous one empty - #outln + if [[ -z "$prev_cipher" ]] || [[ "$prev_cipher" != "${cipher[i]}" ]]; then + [[ -n "$prev_cipher" ]] && outln if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then out "$(printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}")" # print out both else out "$(printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}")" # print out both fi - else # previous NOT empty - if [[ "${cipher[i-1]}" == "${cipher[i]}" ]]; then # and previous protocol same cipher - out ", ${proto[i]}" # same cipher --> only print out protocol behind it - else - outln - if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then - out "$(printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}")" # print out both - else - out "$(printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}")" # print out both - fi - fi - fi + else + out ", ${proto[i]}" # same cipher --> only print out protocol behind it + fi + prev_cipher="${cipher[i]}" fi fileout "order_${proto[i]}_cipher" "INFO" "Default cipher on ${proto[i]}: ${cipher[i]} $remark4default_cipher" done From 3c22511806def691168e252b0d777f6cbfcbcb11 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 28 Feb 2017 13:31:06 -0500 Subject: [PATCH 20/21] Fix HTML headers and footers This PR ensures that each HTML file produced by testssl.sh only includes a single header, at the top, and a single footer, at the end. It also tries to ensure that the short-version banner is only placed at the top of the HTML file if (1) mass testing is being performed and (2) the results of each test is being placed in a separate file. It also moves some of the logic out of main and into `html_header()`. --- testssl.sh | 65 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/testssl.sh b/testssl.sh index a0d6925..ed390bc 100755 --- a/testssl.sh +++ b/testssl.sh @@ -160,6 +160,7 @@ LOGFILE=${LOGFILE:-""} # logfile if used JSONFILE=${JSONFILE:-""} # jsonfile if used CSVFILE=${CSVFILE:-""} # csvfile if used HTMLFILE=${HTMLFILE:-""} # HTML if used +HTMLHEADER=true # include HTML headers and footers in HTML file, if one is being created APPEND=${APPEND:-false} # append to csv/json file instead of overwriting it GIVE_HINTS=false # give an addtional info to findings HAS_IPv6=${HAS_IPv6:-false} # if you have OpenSSL with IPv6 support AND IPv6 networking set it to yes @@ -970,9 +971,30 @@ fileout() { # ID, SEVERITY, FINDING, CVE, CWE, HINT ################### FILE FORMATING END ######################### html_header() { - local fname_prefix="$1" + local fname_prefix + + # Don't create HTML headers and footers in the following scenarios: + # * HTML output is not being created. + # * mass testing is being performed and each test will have its own HTML file. + # * this is an individual test within a mass test and all HTML output is being placed in a single file. + if ! "$do_html" || \ + ( "$do_mass_testing" && ( [[ -z "$HTMLFILE" ]] || [[ -d "$HTMLFILE" ]] ) ) || \ + ( "$APPEND" && [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ); then + HTMLHEADER=false + return 0 + fi + + if "$do_display_only"; then + fname_prefix="local-ciphers" + elif "$do_mass_testing"; then + : + elif "$do_mx_all_ips"; then + fname_prefix="mx-$URI" + else + ( [[ -z "$HTMLFILE" ]] || [[ -d "$HTMLFILE" ]] ) && parse_hn_port "${URI}" # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now + fname_prefix="$NODE"_"$PORT" + fi - [[ -z "$fname_prefix" ]] && fname_prefix="$NODE"_"$PORT" if [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]]; then rm -f "$HTMLFILE" elif [[ -z "$HTMLFILE" ]]; then @@ -994,16 +1016,20 @@ html_header() { } html_banner() { - html_out "## Scan started as: \"$PROG_NAME $CMDLINE\"\n" - html_out "## at $HNAME:$OPENSSL_LOCATION\n" - html_out "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE\n" - html_out "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n\n" + if "$APPEND" && "$HTMLHEADER"; then + html_out "## Scan started as: \"$PROG_NAME $CMDLINE\"\n" + html_out "## at $HNAME:$OPENSSL_LOCATION\n" + html_out "## version testssl: $VERSION ${GIT_REL_SHORT:-$CVS_REL_SHORT} from $REL_DATE\n" + html_out "## version openssl: \"$OSSL_VER\" from \"$OSSL_BUILD_DATE\")\n\n" + fi } html_footer() { - html_out "
\n" - html_out "\n" - html_out "\n" + if "$HTMLHEADER"; then + html_out "
\n" + html_out "\n" + html_out "\n" + fi return 0 } @@ -12212,7 +12238,7 @@ check_proxy() { fatal "Your $OPENSSL is too old to support the \"-proxy\" option" -5 fi if [[ "$PROXY" == "auto" ]]; then - # get $ENV + # get $ENV PROXY=${https_proxy#*\/\/} [[ -z "$PROXY" ]] && PROXY=${http_proxy#*\/\/} [[ -z "$PROXY" ]] && fatal "you specified \"--proxy=auto\" but \"\$http(s)_proxy\" is empty" 2 @@ -12517,12 +12543,10 @@ run_mass_testing_parallel() { run_mass_testing() { local cmdline="" local global_cmdline=${CMDLINE%%--file*} - local html_header="" if [[ ! -r "$FNAME" ]] && "$IKNOW_FNAME"; then fatal "Can't read file \"$FNAME\"" "2" fi - [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] && html_header="--no-html-header" pr_reverse "====== Running in file batch mode with file=\"$FNAME\" ======"; outln "\n" APPEND=false # Make sure we close out our files @@ -12530,7 +12554,7 @@ run_mass_testing() { cmdline=$(filter_input "$cmdline") [[ -z "$cmdline" ]] && continue [[ "$cmdline" == "EOF" ]] && break - cmdline="$0 $global_cmdline --warnings=batch -q $html_header --append $cmdline" + cmdline="$0 $global_cmdline --warnings=batch -q --append $cmdline" draw_line "=" $((TERM_WIDTH / 2)); outln; outln "$cmdline" $cmdline @@ -13142,20 +13166,7 @@ lets_roll() { initialize_globals parse_cmd_line "$@" - -if ( ! "$do_mass_testing" || ( [[ -n "$HTMLFILE" ]] && [[ ! -d "$HTMLFILE" ]] ) ); then - if "$do_display_only"; then - html_header "local-ciphers" - elif "$do_mass_testing"; then - html_header - elif "$do_mx_all_ips"; then - html_header "mx-$URI" - else - ( [[ -z "$HTMLFILE" ]] || [[ -d "$HTMLFILE" ]] ) && parse_hn_port "${URI}" # NODE, URL_PATH, PORT, IPADDR and IP46ADDR is set now - html_header - fi -fi - +html_header get_install_dir set_color_functions maketempf From c791e5cc0e737573c45cf0ec424fb65eddc4fb71 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 15 Mar 2017 10:32:29 -0400 Subject: [PATCH 21/21] Speedup normalize_ciphercode() This PR is the same as #661, except that it applies to the 2.9dev_html branch. It also fixes a bug in `prettyprint_local()` when a pattern to match is provided as input. --- testssl.sh | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/testssl.sh b/testssl.sh index 2d2bcae..6173c48 100755 --- a/testssl.sh +++ b/testssl.sh @@ -211,7 +211,6 @@ GOST_STATUS_PROBLEM=false DETECTED_TLS_VERSION="" PATTERN2SHOW="" SOCK_REPLY_FILE="" -HEXC="" NW_STR="" LEN_STR="" SNI="" @@ -2205,30 +2204,19 @@ run_more_flags() { } -# #1: string with 2 opensssl codes, HEXC= same in NSS/ssllabs terminology +# #1: string with 2 opensssl codes, output is same in NSS/ssllabs terminology normalize_ciphercode() { - part1=$(echo "$1" | awk -F',' '{ print $1 }') - part2=$(echo "$1" | awk -F',' '{ print $2 }') - part3=$(echo "$1" | awk -F',' '{ print $3 }') - if [[ "$part1" == "0x00" ]]; then # leading 0x00 - HEXC=$part2 + if [[ "${1:2:2}" == "00" ]]; then + tm_out "$(tolower "x${1:7:2}")" else - #part2=$(echo $part2 | sed 's/0x//g') - part2=${part2//0x/} - if [[ -n "$part3" ]]; then # a SSLv2 cipher has three parts - #part3=$(echo $part3 | sed 's/0x//g') - part3=${part3//0x/} - fi - HEXC="$part1$part2$part3" + tm_out "$(tolower "x${1:2:2}${1:7:2}${1:12:2}")" fi -#TODO: we should just echo this and avoid the global var HEXC - HEXC=$(tolower "$HEXC"| sed 's/0x/x/') # strip leading 0 return 0 } prettyprint_local() { local arg line - local hexcode dash ciph sslvers kx auth enc mac export + local hexc hexcode dash ciph sslvers kx auth enc mac export local re='^[0-9A-Fa-f]+$' if [[ "$1" == 0x* ]] || [[ "$1" == 0X* ]]; then @@ -2249,19 +2237,19 @@ prettyprint_local() { if [[ -z "$1" ]]; then $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 - outln "$(neat_list "$HEXC" "$ciph" "$kx" "$enc")" + hexc="$(normalize_ciphercode $hexcode)" + outln "$(neat_list "$hexc" "$ciph" "$kx" "$enc")" done else #for arg in $(echo $@ | sed 's/,/ /g'); do for arg in ${*//,/ /}; do $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 + hexc="$(normalize_ciphercode $hexcode)" # for numbers we don't do word matching: [[ $arg =~ $re ]] && \ - line="$(neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -ai "$arg" || \ - neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -wai "$arg")" - [[ -n "$line" ]] && outln "$line" + line="$(neat_list "$hexc" "$ciph" "$kx" "$enc" | grep -ai "$arg")" || \ + line="$(neat_list "$hexc" "$ciph" "$kx" "$enc" | grep -wai "$arg")" + [[ -n "$line" ]] && outln "$line" done done fi @@ -2610,16 +2598,16 @@ test_just_one(){ done else while read hexc n ciph[nr_ciphers] sslvers[nr_ciphers] kx[nr_ciphers] auth enc[nr_ciphers] mac export2[nr_ciphers]; do - normalize_ciphercode $hexc + hexc="$(normalize_ciphercode $hexc)" # is argument a number? if [[ $arg =~ $re ]]; then - neat_list "$HEXC" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qai "$arg" + neat_list "$hexc" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qai "$arg" else - neat_list "$HEXC" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qwai "$arg" + neat_list "$hexc" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qwai "$arg" fi if [[ $? -eq 0 ]]; then # string matches, so we can ssl to it: ciphers_found[nr_ciphers]=false - normalized_hexcode[nr_ciphers]="$HEXC" + normalized_hexcode[nr_ciphers]="$hexc" sigalg[nr_ciphers]="" ossl_supported[nr_ciphers]=true nr_ciphers+=1