From c09a77006ec30e6abdfb827d624473050972bdeb Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 24 Jan 2017 10:49:59 -0500 Subject: [PATCH 01/52] Rename cipher lists for run_logjam() This PR renames the cipher lists for `run_logjam()` in generate_static_cipher_lists.sh to align with their names in testssl.sh, as requested in #590. I think these names are still open for misinterpretation, however, since its not clear whether "dh_cipher" refers to ciphers that use static DH keys, ephemeral DH keys, or both. --- utils/generate_static_cipher_lists.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/utils/generate_static_cipher_lists.sh b/utils/generate_static_cipher_lists.sh index f2b5fe2..45f2e1b 100644 --- a/utils/generate_static_cipher_lists.sh +++ b/utils/generate_static_cipher_lists.sh @@ -309,34 +309,34 @@ get_export_rsa_ciphers() { get_weak_dh_ciphers() { local -i - local hexc exportdhe_cipher_list="" exportdhe_cipher_list_hex="" + local hexc exportdh_cipher_list="" exportdh_cipher_list_hex="" for (( i=0; i < TLS_NR_CIPHERS; i++ )); do if [[ "${TLS_CIPHER_RFC_NAME[i]}" == "TLS_DHE_"* ]] && [[ "${TLS_CIPHER_EXPORT[i]}" == "export" ]]; then hexc="${TLS_CIPHER_HEXCODE[i]}" - [[ "${TLS_CIPHER_OSSL_NAME[i]}" != "-" ]] && exportdhe_cipher_list+=":${TLS_CIPHER_OSSL_NAME[i]}" - exportdhe_cipher_list_hex+=", ${hexc:2:2},${hexc:7:2}" + [[ "${TLS_CIPHER_OSSL_NAME[i]}" != "-" ]] && exportdh_cipher_list+=":${TLS_CIPHER_OSSL_NAME[i]}" + exportdh_cipher_list_hex+=", ${hexc:2:2},${hexc:7:2}" fi done - outln; pr_underline "Weak DH ciphers for run_logjam()"; outln - outln "exportdhe_cipher_list=\"${exportdhe_cipher_list:1}\"" - outln "exportdhe_cipher_list_hex=\"${exportdhe_cipher_list_hex:2}\"" + outln; pr_underline "Weak ephemeral DH ciphers for run_logjam()"; outln + outln "exportdh_cipher_list=\"${exportdh_cipher_list:1}\"" + outln "exportdh_cipher_list_hex=\"${exportdh_cipher_list_hex:2}\"" } get_dhe_ciphers() { local -i - local hexc all_dhe_ciphers="" + local hexc all_dh_ciphers="" for (( i=0; i < TLS_NR_CIPHERS; i++ )); do if [[ "${TLS_CIPHER_RFC_NAME[i]}" == "TLS_DHE_"* ]] || [[ "${TLS_CIPHER_RFC_NAME[i]}" == "TLS_DH_anon_"* ]]; then hexc="${TLS_CIPHER_HEXCODE[i]}" - all_dhe_ciphers+=", ${hexc:2:2},${hexc:7:2}" + all_dh_ciphers+=", ${hexc:2:2},${hexc:7:2}" fi done - outln; pr_underline "All DHE ciphers for run_logjam()"; outln - outln "all_dhe_ciphers=\"$(tolower "${all_dhe_ciphers:2}")\"" + outln; pr_underline "All ephemeral DH ciphers for run_logjam()"; outln + outln "all_dh_ciphers=\"$(tolower "${all_dh_ciphers:2}")\"" } get_mapping_file From d93f7031ac751b0faa40c4d05b5eacf4b6e9be62 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 1 Feb 2017 13:31:58 -0500 Subject: [PATCH 02/52] Fix neat_list() for Camellia GCM This PR increases the width of the "Encryption" column printed by `neat_list()` in order to allow room to print "CamelliaGCM." This is the alternative fix to the problem that was first addressed in #524. This PR obsoletes PR #530. --- testssl.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/testssl.sh b/testssl.sh index 0cc0573..a0a61e1 100755 --- a/testssl.sh +++ b/testssl.sh @@ -2188,8 +2188,8 @@ show_rfc_style(){ } 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" + printf -- "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits${ADD_RFC_STR:+ Cipher Suite Name (RFC)}\n" + printf -- "%s--------------------------------------------------------------------------${ADD_RFC_STR:+---------------------------------------------------}\n" } @@ -2213,14 +2213,13 @@ neat_list(){ enc="${enc//POLY1305/}" # remove POLY1305 enc="${enc//\//}" # remove "/" - enc="${enc/CamelliaGCM/Camellia}" # "CamelliaGCM" is too long echo "$export" | grep -iq export && strength="$strength,exp" [[ -n "$ADD_RFC_STR" ]] && tls_cipher="$(show_rfc_style "$hexcode")" if [[ "$5" == "false" ]]; then - line="$(printf -- " %-7s %-33s %-10s %-10s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" + line="$(printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher")" pr_litegrey "$line" return 0 fi @@ -2237,7 +2236,7 @@ neat_list(){ done fi #echo "${#kx}" # should be always 20 / 13 - printf -- " %-7s %-33s %-10s %-10s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher" + printf -- " %-7s %-33s %-10s %-12s%-8s${ADD_RFC_STR:+ %-49s}${SHOW_EACH_C:+ %-0s}" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" "$tls_cipher" } test_just_one(){ From f1eb3b85dee3278795ba1c9f583e50745efe0730 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 1 Feb 2017 15:43:15 -0500 Subject: [PATCH 03/52] Handle renaming of the Supported Elliptic Curves Extension RFC 4492 introduced the Supported Elliptic Curves Extension, but this extension was renamed Supported Groups in RFC 7919. Following RFC 7919 (and TLSv1.3), `parse_tls_serverhello()` refers to this extension as "supported groups/#10". Since, at the moment, OpenSSL's s_client refers to this extension as "elliptic curves/#10", the extension sometimes appears twice in the "TLS extensions" line, if it is detected by both OpenSSL (in `get_server_certificate()`) and `tls_sockets()` (in `determine_tls_extensions()`): ``` TLS extensions (standard) "renegotiation info/#65281" "elliptic curves/#10" "EC point formats/#11" "supported groups/#10" ``` This PR fixes the problem of the extension appearing twice in the "TLS extensions" line by replacing any instances of "elliptic curves/#10" with "supported_groups/#10" in the `$tls_extensions` line extracted from `$OPENSSL s_client`. This PR also changes "supported groups/#10" to "supported_groups/#10" in `parse_tls_serverhello()`, since the current development branch of OpenSSL uses "supported_groups" to refer to this extension (see https://github.com/openssl/openssl/pull/1825). --- testssl.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 0cc0573..4e43e56 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5427,7 +5427,10 @@ determine_tls_extensions() { success=$? fi if [[ $success -eq 0 ]]; then - tls_extensions=$(grep -a 'TLS server extension ' $TMPFILE | sed -e 's/TLS server extension //g' -e 's/\" (id=/\/#/g' -e 's/,.*$/,/g' -e 's/),$/\"/g') + tls_extensions=$(grep -a 'TLS server extension ' $TMPFILE | \ + sed -e 's/TLS server extension //g' -e 's/\" (id=/\/#/g' \ + -e 's/,.*$/,/g' -e 's/),$/\"/g' \ + -e 's/elliptic curves\/#10/supported_groups\/#10/g') tls_extensions=$(echo $tls_extensions) # into one line fi tmpfile_handle $FUNCNAME.txt @@ -5519,7 +5522,10 @@ get_server_certificate() { # this is not beautiful (grep+sed) # but maybe we should just get the ids and do a private matching, according to # https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml - tls_extensions=$(grep -a 'TLS server extension ' $TMPFILE | sed -e 's/TLS server extension //g' -e 's/\" (id=/\/#/g' -e 's/,.*$/,/g' -e 's/),$/\"/g') + tls_extensions=$(grep -a 'TLS server extension ' $TMPFILE | \ + sed -e 's/TLS server extension //g' -e 's/\" (id=/\/#/g' \ + -e 's/,.*$/,/g' -e 's/),$/\"/g' \ + -e 's/elliptic curves\/#10/supported_groups\/#10/g') tls_extensions=$(echo $tls_extensions) # into one line # check to see if any new TLS extensions were returned and add any new ones to TLS_EXTENSIONS @@ -8036,7 +8042,7 @@ parse_tls_serverhello() { 0007) tls_extensions+=" \"client authz/#7\"" ;; 0008) tls_extensions+=" \"server authz/#8\"" ;; 0009) tls_extensions+=" \"cert type/#9\"" ;; - 000A) tls_extensions+=" \"supported groups/#10\"" ;; + 000A) tls_extensions+=" \"supported_groups/#10\"" ;; 000B) tls_extensions+=" \"EC point formats/#11\"" ;; 000C) tls_extensions+=" \"SRP/#12\"" ;; 000D) tls_extensions+=" \"signature algorithms/#13\"" ;; From e9d6ac8ad1aa53b1c4c9dc44c419ba91a5255423 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 2 Feb 2017 13:04:49 -0500 Subject: [PATCH 04/52] Fix Two CRL and/or two OCSP URLs This PR fixes issue #601. The fix for OCSP URLs was easy. I don't entirely understand the first `awk` command in the line to extract the CRL URLs, but I tested it on several certificates and it seems to work correctly (ensuring that the only "URI" lines in the input to the second `awk` command are from the CRL Distribution Points extension). --- testssl.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index 2b4c5a4..c63aaba 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6188,7 +6188,8 @@ certificate_info() { fileout "${json_prefix}certcount" "INFO" "# of certificates provided : $certificates_provided" # Get both CRL and OCSP URL upfront. If there's none, this is not good. And we need to penalize this in the output - crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | awk '/CRL Distribution/,/URI/ { print $0 }' | awk -F'URI:' '/URI/ { print $2 }')" + crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 50 "X509v3 CRL Distribution Points:" | \ + tail -n +2 | awk '/^$/,/^ [a-zA-Z0-9]+|^ Signature Algorithm:/' | awk -F'URI:' '/URI/ { print $2 }')" ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE) out "$indent"; pr_bold " Certificate Revocation List " @@ -6218,7 +6219,11 @@ certificate_info() { outln "--" fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : --" else - outln "$ocsp_uri" + if [[ $(count_lines "$ocsp_uri") -eq 1 ]]; then + outln "$ocsp_uri" + else + out_row_aligned "$ocsp_uri" "$spaces" + fi fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : $ocsp_uri" fi From e7c7e7ba192b76fae9d0022a75faca0c48eb14c3 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 2 Feb 2017 15:52:32 -0500 Subject: [PATCH 05/52] Update fix to 587 In the revised code that was created to address #587, nothing is printed after "OCSP URI" if there is neither an OCSP URI nor a CRL URI. Instead, "--" should be printed. I still believe that there is an inconsistency in the reporting of the output, however. At the moment, the "Certificate Revocation List" and "OCSP URI" lines indicate it is acceptable as long as the certificate contains either a CRL URI or an OCSP URI. However, the "OCSP stapling" line reports a minor finding if an OCSP response was not included in the server's reply. Shouldn't we just assume that if the certificate doesn't include an OCSP URI, then it wouldn't be possible for the server to obtain an OCSP response to staple to its reply? If so, then it seems that no OCSP stapling should only be considered a finding if an OCSP URI is present. --- testssl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index 2b4c5a4..50e09d4 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6198,7 +6198,7 @@ certificate_info() { fileout "${json_prefix}crl" "INFO" "No CRL provided" else pr_svrty_highln "-- (NOT ok)" - fileout "${json_prefix}crl" "HIGH" "Neither CRL nor OCSP URL provided" + fileout "${json_prefix}crl" "HIGH" "Neither CRL nor OCSP URL provided" fi elif grep -q http <<< "$crl"; then if [[ $(count_lines "$crl") -eq 1 ]]; then @@ -6214,7 +6214,7 @@ certificate_info() { fi out "$indent"; pr_bold " OCSP URI " - if [[ -z "$ocsp_uri" ]] && [[ -n "$crl" ]]; then + if [[ -z "$ocsp_uri" ]]; then outln "--" fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : --" else From 3a21097cc5278ae258a3e790d110babc972c5073 Mon Sep 17 00:00:00 2001 From: Dirk Date: Sat, 4 Feb 2017 14:13:33 +0100 Subject: [PATCH 06/52] HTTP/1.1 GET handler for #254 --- testssl.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/testssl.sh b/testssl.sh index 87992be..c17b5f0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1013,6 +1013,30 @@ filter_input() { echo "$1" | sed -e 's/#.*$//' -e '/^$/d' | tr -d '\n' | tr -d '\t' } +# dl's any URL (argv1) via HTTP 1.1 GET from port 80, arg2: file to store http body +# proxy is not honored (see cmd line switches) +http_get() { + local proto z + local node="" query="" + local dl="$2" + local useragent="$UA_STD" + + "$SNEAKY" && useragent="$UA_SNEAKY" + + IFS=/ read proto z node query <<< "$1" + + exec 33<>/dev/tcp/$node/80 + printf "GET /$query HTTP/1.1\r\nHost: $node\r\nUser-Agent: $useragent\r\nConnection: Close\r\nAccept: */*\r\n\r\n" >&33 + cat <&33 | \ + tr -d '\r' | sed '1,/^$/d' >$dl + # HTTP header stripped now, closing fd: + exec 33<&- + [[ -s "$2" ]] && return 0 || return 1 +} +# example usage: +# myfile=$(mktemp $TEMPDIR/http_get.XXXXXX.txt) +# http_get "http://crl.startssl.com/sca-server1.crl" "$myfile" + wait_kill(){ local pid=$1 # pid we wait for or kill From a9cddd7afb61073b252d7d3bb5a56093d1924f0b Mon Sep 17 00:00:00 2001 From: Dirk Date: Sat, 4 Feb 2017 15:11:03 +0100 Subject: [PATCH 07/52] see #611 --- testssl.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 1344a04..015fcc8 100755 --- a/testssl.sh +++ b/testssl.sh @@ -2276,7 +2276,7 @@ test_just_one(){ "$FAST" && using_sockets=false [[ $TLS_NR_CIPHERS == 0 ]] && using_sockets=false - pr_headline " Testing single cipher with " + pr_headline " Testing ciphers with " if [[ $1 =~ $re ]]; then pr_headline "matching number pattern \"$1\" " tjolines="$tjolines matching number pattern \"$1\"\n\n" @@ -6209,8 +6209,8 @@ certificate_info() { fileout "${json_prefix}certcount" "INFO" "# of certificates provided : $certificates_provided" # Get both CRL and OCSP URL upfront. If there's none, this is not good. And we need to penalize this in the output - crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 50 "X509v3 CRL Distribution Points:" | \ - tail -n +2 | awk '/^$/,/^ [a-zA-Z0-9]+|^ Signature Algorithm:/' | awk -F'URI:' '/URI/ { print $2 }')" + crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | \ + awk '/X509v3 CRL Distribution/{i=14} i&&i--' | awk -F'URI:' '/URI/ { print $2 }')" ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE) out "$indent"; pr_bold " Certificate Revocation List " From 54e03959696e8dc08f1eca127cd7be532a82c153 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 6 Feb 2017 11:06:59 +0100 Subject: [PATCH 08/52] Reverse #600 but leave the hook in here, ANSI code for strikethru --- testssl.sh | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/testssl.sh b/testssl.sh index 4f1f3d5..a81832f 100755 --- a/testssl.sh +++ b/testssl.sh @@ -584,19 +584,18 @@ pr_litecyanln() { pr_litecyan "$1"; outln; } pr_cyan() { [[ "$COLOR" -eq 2 ]] && out "\033[1;36m$1" || out "$1"; pr_off; } # additional hint pr_cyanln() { pr_cyan "$1"; outln; } -pr_litegreyln() { pr_litegrey "$1"; outln; } -pr_litegrey() { [[ "$COLOR" -eq 2 ]] && out "\033[0;37m$1" || out "$1"; pr_off; } +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_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() { [[ "$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_svrty_low() { [[ "$COLOR" -eq 2 ]] && out "\033[1;33m$1" || out "$1"; pr_off; } # yellow brown | academic or minor problem -pr_svrty_lowln() { pr_svrty_low "$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_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_mediumln() { pr_svrty_medium "$1"; outln; } @@ -605,6 +604,8 @@ 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_criticalln(){ pr_svrty_critical "$1"; outln; } +pr_deemphasize() { out "$1"; } # hook for a weakened screen output, see #600 +pr_deemphasizeln() { outln "$1"; } # color=1 functions pr_off() { [[ "$COLOR" -ne 0 ]] && out "\033[m"; } @@ -612,6 +613,8 @@ pr_bold() { [[ "$COLOR" -ne 0 ]] && out "\033[1m$1" || out "$1"; pr_off; pr_boldln() { pr_bold "$1" ; outln; } pr_italic() { [[ "$COLOR" -ne 0 ]] && out "\033[3m$1" || out "$1"; pr_off; } pr_italicln() { pr_italic "$1" ; outln; } +pr_strikethru() { [[ "$COLOR" -ne 0 ]] && out "\033[9m$1" || out "$1"; pr_off; } # ugly! +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; } @@ -2240,7 +2243,7 @@ neat_list(){ if [[ "$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_litegrey "$line" + pr_deemphasize "$line" return 0 fi @@ -2512,7 +2515,7 @@ test_just_one(){ pr_cyan " available" fileout "cipher_${normalized_hexcode[i]}" "INFO" "$(neat_list "${normalized_hexcode[i]}" "${ciph[i]}" "${kx[i]}" "${enc[i]}") available" else - pr_litegrey " not a/v" + pr_deemphasize " not a/v" fileout "cipher_${normalized_hexcode[i]}" "INFO" "$(neat_list "${normalized_hexcode[i]}" "${ciph[i]}" "${kx[i]}" "${enc[i]}") not a/v" fi outln @@ -2766,7 +2769,7 @@ run_allciphers() { pr_cyan "$available" else available="not a/v" - pr_litegrey "$available" + pr_deemphasize "$available" fi fi outln "${sigalg[i]}" @@ -3055,7 +3058,7 @@ run_cipher_per_proto() { pr_cyan "$available" else available="not a/v" - pr_litegrey "$available" + pr_deemphasize "$available" fi fi outln "${sigalg[i]}" @@ -6657,7 +6660,7 @@ run_pfs() { if ${ciphers_found[i]}; then pr_done_best "available" else - pr_litegrey "not a/v" + pr_deemphasize "not a/v" fi fi outln "${sigalg[i]}" @@ -10288,7 +10291,7 @@ run_beast(){ pr_svrty_medium "available" fi else - pr_litegrey "not a/v" + pr_deemphasize "not a/v" fi fi outln "${sigalg[i]}" @@ -10630,7 +10633,7 @@ run_rc4() { if "${ciphers_found[i]}"; then pr_svrty_high "available" else - pr_litegrey "not a/v" + pr_deemphasize "not a/v" fi fi outln "${sigalg[i]}" From 48e264a193c0dabdbecbf7774557fbf1cb250653 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 6 Feb 2017 17:47:17 +0100 Subject: [PATCH 09/52] fixed regression #611 --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index a81832f..6d2462b 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6212,7 +6212,7 @@ certificate_info() { # Get both CRL and OCSP URL upfront. If there's none, this is not good. And we need to penalize this in the output crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | \ - awk '/X509v3 CRL Distribution/{i=14} i&&i--' | awk -F'URI:' '/URI/ { print $2 }')" + awk '/X509v3 CRL Distribution/{i=50} i&&i--' | awk '/^$/,/^ [a-zA-Z0-9]+|^ Signature Algorithm:/' | awk -F'URI:' '/URI/ { print $2 }')" ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE) out "$indent"; pr_bold " Certificate Revocation List " From 6140aa8b8cd965f66ec926b22a57d583a48cdb62 Mon Sep 17 00:00:00 2001 From: Thomas Ward Date: Tue, 7 Feb 2017 15:59:09 -0500 Subject: [PATCH 10/52] Attempt to force system binaries for WSL --- testssl.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index 6d2462b..9d500e0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -10769,10 +10769,12 @@ find_openssl_binary() { outln " Looking some place else ..." elif [[ -x "$OPENSSL" ]]; then : # 1. all ok supplied $OPENSSL was found and has excutable bit set -- testrun comes below + elif [ -e "/mnt/c/Windows/System32/bash.exe" ] && test_openssl_suffix "$(dirname "$(which openssl)")"; then + : # 2. otherwise, only if on Bash on Windows, use system binaries only. elif test_openssl_suffix $RUN_DIR; then - : # 2. otherwise try openssl in path of testssl.sh + : # 3. otherwise try openssl in path of testssl.sh elif test_openssl_suffix $RUN_DIR/bin; then - : # 3. otherwise here, this is supposed to be the standard --platform independed path in the future!!! + : # 4. otherwise here, this is supposed to be the standard --platform independed path in the future!!! elif test_openssl_suffix "$(dirname "$(which openssl)")"; then : # 5. we tried hard and failed, so now we use the system binaries fi From 0d993427a30f8963ff40f0b6cd786ac46bb4e3db Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 7 Feb 2017 23:08:29 +0100 Subject: [PATCH 11/52] - enabling TLS 1.2 via sockets - enabling sockets in run_protocols STARTTLS per default - minor output polishing --- testssl.sh | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/testssl.sh b/testssl.sh index 6d2462b..0597af2 100755 --- a/testssl.sh +++ b/testssl.sh @@ -616,6 +616,7 @@ pr_italicln() { pr_italic "$1" ; outln; } pr_strikethru() { [[ "$COLOR" -ne 0 ]] && out "\033[9m$1" || out "$1"; pr_off; } # ugly! pr_strikethruln() { pr_strikethru "$1" ; outln; } pr_underline() { [[ "$COLOR" -ne 0 ]] && out "\033[4m$1" || out "$1"; pr_off; } +pr_underlineln() { pr_underline "$1"; outln; } 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; } @@ -2626,7 +2627,7 @@ run_allciphers() { outln if "$using_sockets"; then - pr_headlineln " Testing $nr_ciphers_tested via OpenSSL and sockets against the server, ordered by encryption strength " + pr_headlineln " Testing $nr_ciphers_tested ciphers via OpenSSL plus sockets against the server, ordered by encryption strength " else pr_headlineln " Testing all $nr_ciphers_tested locally available ciphers against the server, ordered by encryption strength " [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && pr_warning " Cipher mapping not available, doing a fallback to openssl" @@ -2803,7 +2804,7 @@ run_cipher_per_proto() { outln if "$using_sockets"; then - pr_headlineln " Testing per protocol via OpenSSL and sockets against the server, ordered by encryption strength " + pr_headlineln " Testing ciphers per protocol via OpenSSL plus sockets against the server, ordered by encryption strength " else pr_headlineln " Testing all locally available ciphers per protocol against the server, ordered by encryption strength " [[ $TLS_NR_CIPHERS == 0 ]] && ! "$SSL_NATIVE" && ! "$FAST" && pr_warning " Cipher mapping not available, doing a fallback to openssl" @@ -4214,18 +4215,13 @@ run_protocols() { if "$SSL_NATIVE"; then using_sockets=false - pr_headlineln "(via native openssl)" + pr_underlineln "via native openssl" else + using_sockets=true if [[ -n "$STARTTLS" ]]; then - pr_headlineln "(via openssl, SSLv2 via sockets) " - using_sockets=false + pr_underlineln "via sockets " else - using_sockets=true - if "$EXPERIMENTAL"; then - pr_headlineln "(via sockets except SPDY+HTTP2) " - else - pr_headlineln "(via sockets except TLS 1.2, SPDY+HTTP2) " - fi + pr_underlineln "via sockets except SPDY+HTTP2 " fi fi outln @@ -4429,7 +4425,7 @@ run_protocols() { esac pr_bold " TLS 1.2 "; - if "$using_sockets" && "$EXPERIMENTAL"; then #TODO: IIS servers do have a problem here with our handshake + if "$using_sockets"; then tls_sockets "03" "$TLS12_CIPHER" else run_prototest_openssl "-tls1_2" @@ -4549,7 +4545,7 @@ run_std_cipherlists() { read_dhbits_from_file() { local bits what_dh temp curve="" local add="" - local old_fart=" (openssl cannot show DH bits)" + local old_fart=" (your $OPENSSL cannot show DH bits)" temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$1") # extract line what_dh=$(awk -F',' '{ print $1 }' <<< $temp) @@ -5252,7 +5248,7 @@ determine_trust() { if [[ $OSSL_VER_MAJOR.$OSSL_VER_MINOR != "1.0.2" ]] && \ [[ $OSSL_VER_MAJOR.$OSSL_VER_MINOR != "1.1.0" ]] && \ [[ $OSSL_VER_MAJOR.$OSSL_VER_MINOR != "1.1.1" ]]; then - addtl_warning="(Your openssl <= 1.0.2 might be too unreliable to 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 @@ -6500,7 +6496,7 @@ run_pfs() { [[ $TLS_NR_CIPHERS == 0 ]] && using_sockets=false outln - pr_headlineln " Testing robust (perfect) forward secrecy, (P)FS -- omitting Null Authentication/Encryption, 3DES, RC4 " + pr_headline " Testing robust (perfect) forward secrecy"; pr_underlineln ", (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 From 0200100750032dcc9c7eede87369d2414f07301a Mon Sep 17 00:00:00 2001 From: Dirk Date: Wed, 8 Feb 2017 08:58:28 +0100 Subject: [PATCH 12/52] see #620 --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 886ca4f..1d0b9ef 100755 --- a/testssl.sh +++ b/testssl.sh @@ -10771,7 +10771,7 @@ find_openssl_binary() { outln " Looking some place else ..." elif [[ -x "$OPENSSL" ]]; then : # 1. all ok supplied $OPENSSL was found and has excutable bit set -- testrun comes below - elif [ -e "/mnt/c/Windows/System32/bash.exe" ] && test_openssl_suffix "$(dirname "$(which openssl)")"; then + elif [[ -e "/mnt/c/Windows/System32/bash.exe" ]] && test_openssl_suffix "$(dirname "$(which openssl)")"; then : # 2. otherwise, only if on Bash on Windows, use system binaries only. elif test_openssl_suffix $RUN_DIR; then : # 3. otherwise try openssl in path of testssl.sh From 386aa924481cefcaf4e04af510eea9a9dc483f8d Mon Sep 17 00:00:00 2001 From: Dirk Date: Wed, 8 Feb 2017 09:08:05 +0100 Subject: [PATCH 13/52] keep detected status of WSL / bash on windows in a variable, see also #620 --- testssl.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 1d0b9ef..489995c 100755 --- a/testssl.sh +++ b/testssl.sh @@ -110,6 +110,7 @@ else readonly REL_DATE=$(tail -5 "$0" | awk '/dirkw Exp/ { print $5 }') fi readonly SYSTEM=$(uname -s) +SYSTEM2="" # currently only being used for WSL = bash on windows date -d @735275209 >/dev/null 2>&1 && \ readonly HAS_GNUDATE=true || \ readonly HAS_GNUDATE=false @@ -10772,7 +10773,8 @@ find_openssl_binary() { 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 - : # 2. otherwise, only if on Bash on Windows, use system binaries only. + # 2. otherwise, only if on Bash on Windows, use system binaries only. + SYSTEM2="WSL" elif test_openssl_suffix $RUN_DIR; then : # 3. otherwise try openssl in path of testssl.sh elif test_openssl_suffix $RUN_DIR/bin; then @@ -11039,6 +11041,7 @@ bash version: ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}.${BASH_VERSINFO[2]} status: ${BASH_VERSINFO[4]} machine: ${BASH_VERSINFO[5]} operating system: $SYSTEM +os constraint: $SYSTEM2 shellopts: $SHELLOPTS $($OPENSSL version -a) From d4455081f08c4cd63ae5e0226a51690c6768e330 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 9 Feb 2017 11:36:24 -0500 Subject: [PATCH 14/52] Wrap long lines This PR addresses the issue raised in #623. This PR is based on the function `out_row_aligned_max_width()` that I proposed in #623, but the `out_row_aligned_max_width()` in this PR is a little different. It takes a fourth parameter, which is the function to use to print each word in the text string to be printed. This is used in `run_pfs()` so that the "Elliptic curves offered" can be printed using this function (some servers support 25 curves), while still having the curves printed using color-coding to indicate the quality of each curve. I somewhat arbitrarily have each line wrap at 120 characters, but that could be changed (e.g., to `$TERM_WIDTH`). --- testssl.sh | 163 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 129 insertions(+), 34 deletions(-) diff --git a/testssl.sh b/testssl.sh index 489995c..338789b 100755 --- a/testssl.sh +++ b/testssl.sh @@ -975,6 +975,64 @@ out_row_aligned() { done } +# prints text over multiple lines, trying to make no line longer than $max_width. +# Each line is indented with $spaces and each word in $text is printed using +# $print_function. +out_row_aligned_max_width() { + local text="$1" + local spaces="$2" + local -i max_width="$3" + local print_function="$4" + local -i i len cut_point + local cr=$'\n' + local line entry first=true last=false + + max_width=$max_width-${#spaces} + len=${#text} + while true; do + i=$max_width + if [[ $i -ge $len ]]; then + i=$len + else + while true; do + [[ "${text:i:1}" == " " ]] && break + [[ $i -eq 0 ]] && break + i=$i-1 + done + if [[ $i -eq 0 ]]; then + i=$max_width+1 + while true; do + [[ "${text:i:1}" == " " ]] && break + [[ $i -eq $len ]] && break + i+=1 + done + fi + fi + if [[ $i -eq $len ]]; then + line="$text" + if ! "$first"; then + out "${cr}${spaces}" + fi + last=true + else + line="${text:0:i}" + if ! "$first"; then + out "${cr}${spaces}" + fi + len=$len-$i-1 + i=$i+1 + text="${text:i:len}" + first=false + [[ $len -eq 0 ]] && last=true + fi + while read entry; do + $print_function "$entry" ; out " " + done <<< "$(echo "$line" | tr ' ' '\n')" + "$last" && break + done + return 0 +} + is_number() { [[ "$1" =~ ^[1-9][0-9]*$ ]] && \ return 0 || \ @@ -4540,6 +4598,59 @@ run_std_cipherlists() { return 0 } +pr_ecdh_curve_quality() { + curve="$1" + local -i bits=0 + + case "$curve" in + "sect163k1") bits=163 ;; + "sect163r1") bits=162 ;; + "sect163r2") bits=163 ;; + "sect193r1") bits=193 ;; + "sect193r2") bits=193 ;; + "sect233k1") bits=232 ;; + "sect233r1") bits=233 ;; + "sect239k1") bits=238 ;; + "sect283k1") bits=281 ;; + "sect283r1") bits=282 ;; + "sect409k1") bits=407 ;; + "sect409r1") bits=409 ;; + "sect571k1") bits=570 ;; + "sect571r1") bits=570 ;; + "secp160k1") bits=161 ;; + "secp160r1") bits=161 ;; + "secp160r2") bits=161 ;; + "secp192k1") bits=192 ;; + "prime192v1") bits=192 ;; + "secp224k1") bits=225 ;; + "secp224r1") bits=224 ;; + "secp256k1") bits=256 ;; + "prime256v1") bits=256 ;; + "secp384r1") bits=384 ;; + "secp521r1") bits=521 ;; + "brainpoolP256r1") bits=256 ;; + "brainpoolP384r1") bits=384 ;; + "brainpoolP512r1") bits=512 ;; + "X25519") bits=253 ;; + "X448") bits=448 ;; + esac + + if [[ "$bits" -le 80 ]]; then # has that ever existed? + pr_svrty_critical "$curve" + elif [[ "$bits" -le 108 ]]; then # has that ever existed? + pr_svrty_high "$curve" + elif [[ "$bits" -le 163 ]]; then + pr_svrty_medium "$curve" + elif [[ "$bits" -le 193 ]]; then # hmm, according to https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography it should ok + pr_svrty_low "$curve" # but openssl removed it https://github.com/drwetter/testssl.sh/issues/299#issuecomment-220905416 + elif [[ "$bits" -le 224 ]]; then + out "$curve" + elif [[ "$bits" -gt 224 ]]; then + pr_done_good "$curve" + else + out "$curve" + fi +} # arg1: file with input for grepping the bit length for ECDH/DHE # arg2: whether to print warning "old fart" or not (empty: no) @@ -5149,7 +5260,7 @@ cipher_pref_check() { if [[ -n "$order" ]]; then outln printf " %-10s" "$proto: " - out "$order" + out_row_aligned_max_width "$order" " " 120 out fileout "order_$p" "INFO" "Default cipher order for protocol $p: $order" fi done @@ -5163,7 +5274,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" + printf " %-10s " "$p:" tested_cipher="-"$cipher order="$cipher" if ! "$FAST"; then @@ -5171,11 +5282,11 @@ cipher_pref_check() { $OPENSSL s_client -cipher "ALL:$tested_cipher" $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $SNI >$ERRFILE >$TMPFILE sclient_connect_successful $? $TMPFILE || break cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) - out "$cipher " tested_cipher="$tested_cipher:-$cipher" order+=" $cipher" done fi + out_row_aligned_max_width "$order" " " 120 out outln [[ -n $order ]] && fileout "order_spdy_$p" "INFO" "Default cipher order for SPDY protocol $p: $order" done @@ -5732,7 +5843,7 @@ certificate_info() { local ocsp_response_status=$6 local sni_used=$7 local cert_sig_algo cert_sig_hash_algo cert_key_algo - local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san cn + local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san all_san="" cn local issuer_DC issuerfinding cn_nosni="" local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial local policy_oid @@ -6012,10 +6123,10 @@ certificate_info() { out "$indent"; pr_bold " subjectAltName (SAN) " if [[ -n "$sans" ]]; then while read san; do - [[ -n "$san" ]] && pr_italic "$san" - out " " + [[ -n "$san" ]] && all_san+="$san " done <<< "$sans" - fileout "${json_prefix}san" "INFO" "subjectAltName (SAN) : $sans" + out_row_aligned_max_width "$all_san" " " 120 pr_italic + fileout "${json_prefix}san" "INFO" "subjectAltName (SAN) : $all_san" else out "-- " fileout "${json_prefix}san" "INFO" "subjectAltName (SAN) : --" @@ -6443,7 +6554,7 @@ run_server_defaults() { fileout "tls_extensions" "INFO" "TLS server extensions (std): (none)" else #FIXME: we rather want to have the chance to print each ext in italcs or another format. Atm is a string of quoted strings -- that needs to be fixed at the root - outln "$TLS_EXTENSIONS" + out_row_aligned_max_width "$TLS_EXTENSIONS" " " 120 out; outln fileout "tls_extensions" "INFO" "TLS server extensions (std): $TLS_EXTENSIONS" fi @@ -6493,7 +6604,7 @@ run_pfs() { local -a ffdhe_groups_output=("ffdhe2048" "ffdhe3072" "ffdhe4096" "ffdhe6144" "ffdhe8192") local -a supported_curve bits local -i nr_supported_ciphers=0 nr_curves=0 nr_ossl_curves=0 i j low high - local pfs_ciphers curves_offered="" curves_offered_text="" curves_to_test temp + local pfs_ciphers curves_offered="" curves_to_test temp local len1 len2 curve_found local has_dh_bits="$HAS_DH_BITS" local using_sockets=true @@ -6645,7 +6756,6 @@ run_pfs() { pfs_cipher="${rfc_ciph[i]}" fi pfs_ciphers+="$pfs_cipher " - ! "$WIDE" && out "$pfs_cipher " if [[ "${ciph[i]}" == "ECDHE-"* ]] || ( "$using_sockets" && [[ "${rfc_ciph[i]}" == "TLS_ECDHE_"* ]] ); then ecdhe_offered=true @@ -6669,10 +6779,9 @@ run_pfs() { outln "${sigalg[i]}" fi done - + ! "$WIDE" && out_row_aligned_max_width "$pfs_ciphers" " " 120 out debugme echo $pfs_offered "$WIDE" || outln - fileout "pfs_ciphers" "INFO" "(Perfect) Forward Secrecy Ciphers: $pfs_ciphers" fi @@ -6752,22 +6861,13 @@ 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: " + out_row_aligned_max_width "$curves_offered" " " 120 pr_ecdh_curve_quality + outln fileout "ecdhe_curves" "INFO" "Elliptic curves offered $curves_offered" fi fi @@ -10304,17 +10404,13 @@ run_beast(){ if ! "$WIDE"; then if [[ -n "$detected_cbc_ciphers" ]]; then - detected_cbc_ciphers=$(echo "$detected_cbc_ciphers" | \ - sed -e "s/ /\\${cr} ${spaces}/12" \ - -e "s/ /\\${cr} ${spaces}/9" \ - -e "s/ /\\${cr} ${spaces}/6" \ - -e "s/ /\\${cr} ${spaces}/3") fileout "cbc_$proto" "MEDIUM" "BEAST: CBC ciphers for $(toupper $proto): $detected_cbc_ciphers" "$cve" "$cwe" "$hint" ! "$first" && out "$spaces" out "$(toupper $proto):" [[ -n "$higher_proto_supported" ]] && \ - pr_svrty_lowln "$detected_cbc_ciphers" || \ - pr_svrty_mediumln "$detected_cbc_ciphers" + out_row_aligned_max_width "$detected_cbc_ciphers" " " 120 pr_svrty_low || \ + out_row_aligned_max_width "$detected_cbc_ciphers" " " 120 pr_svrty_medium + outln detected_cbc_ciphers="" # empty for next round first=false else @@ -10640,11 +10736,10 @@ run_rc4() { fi fi outln "${sigalg[i]}" - elif "${ciphers_found[i]}"; then - pr_svrty_high "${ciph[i]} " fi "${ciphers_found[i]}" && rc4_detected+="${ciph[i]} " done + ! "$WIDE" && out_row_aligned_max_width "$rc4_detected" " " 120 pr_svrty_high outln "$WIDE" && pr_svrty_high "VULNERABLE (NOT ok)" fileout "rc4" "HIGH" "RC4: VULNERABLE, Detected ciphers: $rc4_detected" "$cve" "$cwe" "$hint" From c92131c072563bb399d1fdce1e315257a0629277 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 9 Feb 2017 11:45:29 -0500 Subject: [PATCH 15/52] Don't collect number of bits in run_pfs() The `bits` array is no longer needed in `run_pfs()` since the information collected is not being used. --- testssl.sh | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/testssl.sh b/testssl.sh index 338789b..ebf1cdd 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6602,7 +6602,7 @@ run_pfs() { local -a curves_ossl_output=("K-163" "sect163r1" "B-163" "sect193r1" "sect193r2" "K-233" "B-233" "sect239k1" "K-283" "B-283" "K-409" "B-409" "K-571" "B-571" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "P-192" "secp224k1" "P-224" "secp256k1" "P-256" "P-384" "P-521" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") local -a ffdhe_groups_hex=("01,00" "01,01" "01,02" "01,03" "01,04") local -a ffdhe_groups_output=("ffdhe2048" "ffdhe3072" "ffdhe4096" "ffdhe6144" "ffdhe8192") - local -a supported_curve bits + local -a supported_curve local -i nr_supported_ciphers=0 nr_curves=0 nr_ossl_curves=0 i j low high local pfs_ciphers curves_offered="" curves_to_test temp local len1 len2 curve_found @@ -6828,9 +6828,6 @@ run_pfs() { done [[ $i -eq $high ]] && break supported_curve[i]=true - bits[i]=$(awk -F',' '{ print $3 }' <<< $temp) - grep -q bits <<< ${bits[i]} || bits[i]=$(awk -F',' '{ print $2 }' <<< $temp) - bits[i]=$(tr -d ' bits' <<< ${bits[i]}) done done fi @@ -6854,9 +6851,6 @@ run_pfs() { done [[ $i -eq $nr_curves ]] && break supported_curve[i]=true - bits[i]=$(awk -F',' '{ print $3 }' <<< $temp) - grep -q bits <<< ${bits[i]} || bits[i]=$(awk -F',' '{ print $2 }' <<< $temp) - bits[i]=$(tr -d ' bits' <<< ${bits[i]}) done fi if "$ecdhe_offered"; then From 45379ce1f9b7acbb53454d3c26f6f964ef437dcd Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 9 Feb 2017 13:29:22 -0500 Subject: [PATCH 16/52] Fix subjectAltName indendation The PR didn't account for the indentation of the subjectAltName differing depending on whether the server has one or more than one certificate. --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index ebf1cdd..e650d66 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6125,7 +6125,7 @@ certificate_info() { while read san; do [[ -n "$san" ]] && all_san+="$san " done <<< "$sans" - out_row_aligned_max_width "$all_san" " " 120 pr_italic + out_row_aligned_max_width "$all_san" "$indent " 120 pr_italic fileout "${json_prefix}san" "INFO" "subjectAltName (SAN) : $all_san" else out "-- " From 8dabc2828045e25a6b5cb69f3d0bd1e9d7d5edaa Mon Sep 17 00:00:00 2001 From: Dirk Date: Sat, 11 Feb 2017 14:01:51 +0100 Subject: [PATCH 17/52] also made sure that all old dns binaries work (SLES 11, FreeBSD 9) --- testssl.sh | 57 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/testssl.sh b/testssl.sh index 489995c..0e2cb37 100755 --- a/testssl.sh +++ b/testssl.sh @@ -11492,41 +11492,64 @@ get_aaaa_record() { # RFC6844: DNS Certification Authority Authorization (CAA) Resource Record # arg1: domain to check for get_caa_rr_record() { - local caa="" + local raw_caa="" + local caa_flag + local -i len_caa_property + local caa_property_name + local caa_property_value local saved_openssl_conf="$OPENSSL_CONF" + # if there's a type257 record there are two output formats here, mostly depending on age of distribution + # rougly that's the difference between text and binary format + # 1) 'google.com has CAA record 0 issue "symantec.com"' + # 2) 'google.com has TYPE257 record \# 19 0005697373756573796D616E7465632E636F6D' + # for dig +short the output always starts with '0 issue [..]' or '\# 19 [..]' so we normalize thereto to keep caa_flag, caa_property + # caa_property then has key/value pairs, see https://tools.ietf.org/html/rfc6844#section-3 OPENSSL_CONF="" if which dig &> /dev/null; then - caa="$(dig $1 type257 +short | awk '{ print $3 }')" + raw_caa="$(dig $1 type257 +short)" # empty if no CAA record elif which host &> /dev/null; then - caa="$(host -t type257 $1)" - if grep -wq issue <<< "$caa" && grep -wvq "has no CAA" <<< "$caa"; then - caa="$(awk '/issue/ { print $NF }' <<< "$caa")" + raw_caa="$(host -t type257 $1)" + if egrep -wvq "has no CAA|has no TYPE257" <<< "$raw_caa"; then + raw_caa="$(sed -e 's/^.*has CAA record //' -e 's/^.*has TYPE257 record //' <<< "$raw_caa")" fi elif which nslookup &> /dev/null; then - caa="$(nslookup -type=type257 $1)" - if grep -wq issue <<< "$caa" && grep -wvq "No answer" <<< "$caa"; then - caa="$(awk '/issue/ { print $NF }' <<< "$caa")" + raw_caa="$(nslookup -type=type257 $1 | grep -w rdata_257)" + if [[ -n "$raw_caa" ]]; then + raw_caa="$(sed 's/^.*rdata_257 = //' <<< "$raw_caa")" fi else return 1 # No dig, host, or nslookup --> complaint was elsewhere already and except for one which has drill only we don't get here fi OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 + debugme echo $raw_caa - # try to convert old return values - if [[ "$caa" =~ ^[A-F0-9]+$ ]]; then - caa=${caa:4:100} # ignore the first 4 bytes - caa=$(hex2ascii "$caa" | sed 's/^issue//g') + # '# 19' for google.com is the tag length probably --> we use this also to identify the binary format + if [[ "$raw_caa" =~ \#\ [0-9][0-9]\ [A-F0-9]+$ ]]; then + raw_caa=$(awk '{ print $NF }' <<< $raw_caa) # caa_length would be awk '{ print $(NF-1) }' but we don't need it + if [[ "${raw_caa:0:2}" == "00" ]]; then # probably the flag + caa_flag="0" + len_caa_property=${raw_caa:2:2} # implicit type casting, for google we have 05 here as a string + len_caa_property=$((len_caa_property*2)) # =>word! Now get name from 4th and value from 4th+len position... + caa_property_name=$(hex2ascii ${raw_caa:4:$len_caa_property}) + caa_property_value=$(hex2ascii ${raw_caa:$((4+len_caa_property)):100}) + else + outln "please report unknown CAA flag $caa_flag @ $NODE" + fi + elif grep -q '"' <<< $raw_caa; then + raw_caa=${raw_caa//\"/} # strip " first. Now we should have flag, name, value + caa_flag=$(awk '{ print $1 }' <<< $raw_caa) + caa_property_name=$(awk '{ print $2 }' <<< $raw_caa) + caa_property_value=$(awk '{ print $3 }' <<< $raw_caa) else - caa=${caa//\"/} # strip " + # no caa record + return 1 fi - echo "$caa" + echo "$caa_property_name: $caa_property_value" + # to do: -# 1: check old binaries whether they support this record at all -# done (2: check whether hexstring is returned and deal with it) -# 3: check more than domainname, see https://tools.ietf.org/html/rfc6844#section-3 # 4: check whether $1 is a CNAME and take this # 5: query with drill return 0 From d2f688e925d1baf768c285f095ad6c7e8001008c Mon Sep 17 00:00:00 2001 From: Dirk Date: Sat, 11 Feb 2017 14:16:18 +0100 Subject: [PATCH 18/52] CAA RR belongs also in JSON, see #588 --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 0e2cb37..96366d6 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6280,7 +6280,7 @@ certificate_info() { caa="$(get_caa_rr_record $NODE)" if [[ -n "$caa" ]]; then pr_done_good "OK"; out " (" ; pr_italic "$caa"; out ")" - fileout "${json_prefix}CAA_record" "OK" "DNS Certification Authority Authorization (CAA) Resource Record / RFC6844 : offered" + fileout "${json_prefix}CAA_record" "OK" "DNS Certification Authority Authorization (CAA) Resource Record / RFC6844 : \"$caa\" " else pr_svrty_low "--" fileout "${json_prefix}CAA_record" "LOW" "DNS Certification Authority Authorization (CAA) Resource Record / RFC6844 : not offered" From 7d6f1eb46f4015ef0557221375cfb66eaea56c71 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 13 Feb 2017 09:06:10 +0100 Subject: [PATCH 19/52] polishing #628, mostly make sure we automatically align to terminal width --- testssl.sh | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/testssl.sh b/testssl.sh index b568bef..e4b21bb 100755 --- a/testssl.sh +++ b/testssl.sh @@ -987,6 +987,7 @@ out_row_aligned_max_width() { local cr=$'\n' local line entry first=true last=false + max_width=$max_width-1 # at the moment we align to terminal width. This makes sure we don't wrap too late max_width=$max_width-${#spaces} len=${#text} while true; do @@ -1027,7 +1028,7 @@ out_row_aligned_max_width() { fi while read entry; do $print_function "$entry" ; out " " - done <<< "$(echo "$line" | tr ' ' '\n')" + done <<< "$(tr ' ' '\n' <<< "$line")" "$last" && break done return 0 @@ -5260,7 +5261,7 @@ cipher_pref_check() { if [[ -n "$order" ]]; then outln printf " %-10s" "$proto: " - out_row_aligned_max_width "$order" " " 120 out + out_row_aligned_max_width "$order" " " $TERM_WIDTH out fileout "order_$p" "INFO" "Default cipher order for protocol $p: $order" fi done @@ -5286,7 +5287,7 @@ cipher_pref_check() { order+=" $cipher" done fi - out_row_aligned_max_width "$order" " " 120 out + out_row_aligned_max_width "$order" " " $TERM_WIDTH out outln [[ -n $order ]] && fileout "order_spdy_$p" "INFO" "Default cipher order for SPDY protocol $p: $order" done @@ -6125,7 +6126,7 @@ certificate_info() { while read san; do [[ -n "$san" ]] && all_san+="$san " done <<< "$sans" - out_row_aligned_max_width "$all_san" "$indent " 120 pr_italic + out_row_aligned_max_width "$all_san" "$indent " $TERM_WIDTH pr_italic fileout "${json_prefix}san" "INFO" "subjectAltName (SAN) : $all_san" else out "-- " @@ -6554,7 +6555,7 @@ run_server_defaults() { fileout "tls_extensions" "INFO" "TLS server extensions (std): (none)" else #FIXME: we rather want to have the chance to print each ext in italcs or another format. Atm is a string of quoted strings -- that needs to be fixed at the root - out_row_aligned_max_width "$TLS_EXTENSIONS" " " 120 out; outln + out_row_aligned_max_width "$TLS_EXTENSIONS" " " $TERM_WIDTH out; outln fileout "tls_extensions" "INFO" "TLS server extensions (std): $TLS_EXTENSIONS" fi @@ -6779,7 +6780,7 @@ run_pfs() { outln "${sigalg[i]}" fi done - ! "$WIDE" && out_row_aligned_max_width "$pfs_ciphers" " " 120 out + ! "$WIDE" && out_row_aligned_max_width "$pfs_ciphers" " " $TERM_WIDTH out debugme echo $pfs_offered "$WIDE" || outln fileout "pfs_ciphers" "INFO" "(Perfect) Forward Secrecy Ciphers: $pfs_ciphers" @@ -6860,7 +6861,7 @@ run_pfs() { if [[ -n "$curves_offered" ]]; then "$WIDE" && outln pr_bold " Elliptic curves offered: " - out_row_aligned_max_width "$curves_offered" " " 120 pr_ecdh_curve_quality + out_row_aligned_max_width "$curves_offered" " " $TERM_WIDTH pr_ecdh_curve_quality outln fileout "ecdhe_curves" "INFO" "Elliptic curves offered $curves_offered" fi @@ -10402,8 +10403,8 @@ run_beast(){ ! "$first" && out "$spaces" out "$(toupper $proto):" [[ -n "$higher_proto_supported" ]] && \ - out_row_aligned_max_width "$detected_cbc_ciphers" " " 120 pr_svrty_low || \ - out_row_aligned_max_width "$detected_cbc_ciphers" " " 120 pr_svrty_medium + out_row_aligned_max_width "$detected_cbc_ciphers" " " $TERM_WIDTH pr_svrty_low || \ + out_row_aligned_max_width "$detected_cbc_ciphers" " " $TERM_WIDTH pr_svrty_medium outln detected_cbc_ciphers="" # empty for next round first=false @@ -10733,7 +10734,7 @@ run_rc4() { fi "${ciphers_found[i]}" && rc4_detected+="${ciph[i]} " done - ! "$WIDE" && out_row_aligned_max_width "$rc4_detected" " " 120 pr_svrty_high + ! "$WIDE" && out_row_aligned_max_width "$rc4_detected" " " $TERM_WIDTH pr_svrty_high outln "$WIDE" && pr_svrty_high "VULNERABLE (NOT ok)" fileout "rc4" "HIGH" "RC4: VULNERABLE, Detected ciphers: $rc4_detected" "$cve" "$cwe" "$hint" From c252d5ab2830179cc62b9f9bc11737b8dd9b51c9 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Mon, 13 Feb 2017 09:33:03 +0100 Subject: [PATCH 20/52] Update Readme.md --- Readme.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Readme.md b/Readme.md index d67d546..727cf52 100644 --- a/Readme.md +++ b/Readme.md @@ -36,14 +36,13 @@ and more documentation") or https://github.com/drwetter/testssl.sh/wiki/Usage-Do #### Compatibility -testssl.sh is working on every Linux/BSD distribution out of the box with -some limitations of disabled features from the openssl client -- some -workarounds are done with bash-socket-based checks. It also works on other -unixoid system out of the box, supposed they have `/bin/bash` and standard -tools like sed and awk installed. MacOS X and Windows (using MSYS2 or -cygwin) work too. OpenSSL version >= 1 is a must. OpenSSL version >= 1.0.2 -is needed for better LOGJAM checks and to display bit strengths for key -exchanges. +testssl.sh is working on every Linux/BSD distribution out of the box. In 2.9dev most +of the limitations of disabled features from the openssl client are gone due to bash-socket-based +checks. testssl.sh also works on otherunixoid system out of the box, supposed they have +`/bin/bash` and standard tools like sed and awk installed. System V needs to have GNU versions +of grep and sed installed. MacOS X and Windows (using MSYS2 or cygwin) work too. OpenSSL version +>= 1 is a must. OpenSSL version >= 1.0.2 is needed for better LOGJAM checks and to +display bit strengths for key exchanges. Update notification here or @ [twitter](https://twitter.com/drwetter). @@ -56,6 +55,11 @@ Update notification here or @ [twitter](https://twitter.com/drwetter). * testing 359 default ciphers (``testssl.sh -e``) with a mixture of sockets and openssl. Same speed as with openssl only but addtional ciphers such as post-quantum ciphers, new CHAHA20/POLY1305, CamelliaGCM etc. * finding more TLS extensions via sockets * TLS Supported Groups Registry (RFC 7919), key shares extension +* using bash sockets where ever possible +* LUCKY13 and SWEET32 checks +* LOGJAM: now checking also for known DH parameters +* Check for CAA RR +* better formatting of output #### Features planned in 2.9dev From 971c8e8b639021dc5d59c6fe43ef52f5e6cfe2c5 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Mon, 13 Feb 2017 09:33:50 +0100 Subject: [PATCH 21/52] Update Readme.md --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 727cf52..7403f12 100644 --- a/Readme.md +++ b/Readme.md @@ -40,8 +40,8 @@ testssl.sh is working on every Linux/BSD distribution out of the box. In 2.9dev of the limitations of disabled features from the openssl client are gone due to bash-socket-based checks. testssl.sh also works on otherunixoid system out of the box, supposed they have `/bin/bash` and standard tools like sed and awk installed. System V needs to have GNU versions -of grep and sed installed. MacOS X and Windows (using MSYS2 or cygwin) work too. OpenSSL version ->= 1 is a must. OpenSSL version >= 1.0.2 is needed for better LOGJAM checks and to +of grep and sed installed. MacOS X and Windows (using MSYS2 or cygwin) work too. OpenSSL +version >= 1 is a must. OpenSSL version >= 1.0.2 is needed for better LOGJAM checks and to display bit strengths for key exchanges. Update notification here or @ [twitter](https://twitter.com/drwetter). From 1dc132c6a4ce76d721fe6b2d8f80d49dc22a7403 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Mon, 13 Feb 2017 16:07:25 -0500 Subject: [PATCH 22/52] Option to show RFC cipher names When a list of cipher suites is being displayed using `neat_list()`, testssl.sh shows the cipher suite's OpenSSL name and (in most cases) the RFC name as well. However, in all other cases only the OpenSSL name is shown. This PR adds the option to have cipher suite's RFC names shown instead of the OpenSSL name, by including `--mapping rfc` in the command line. [Note: if the cipher-mapping.txt file cannot be found, then the `--mapping rfc` option is ignored and the OpenSSL names are shown.] This PR seems to be related to issue #9, but #9 may be been referring to the output created by `neat_list()`. --- testssl.sh | 123 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 25 deletions(-) diff --git a/testssl.sh b/testssl.sh index e4b21bb..180c704 100755 --- a/testssl.sh +++ b/testssl.sh @@ -229,6 +229,7 @@ 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 PORT=443 # unless otherwise auto-determined, see below NODE="" NODEIP="" @@ -4178,7 +4179,13 @@ run_client_simulation() { fi #FiXME: awk cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://') - "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && [[ $TLS_NR_CIPHERS -ne 0 ]] && cipher="$(rfc2openssl "$cipher")" + if [[ -z "$SHOW_RFC" ]] && ( [[ "$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 + cipher="$(openssl2rfc "$cipher")" + [[ -z "$cipher" ]] && cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://') + fi out "$proto $cipher" "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && has_dh_bits=$HAS_DH_BITS && HAS_DH_BITS=true "$HAS_DH_BITS" && read_dhbits_from_file $TMPFILE @@ -4736,7 +4743,7 @@ read_dhbits_from_file() { run_server_preference() { local cipher1 cipher2 - local default_cipher default_proto + local default_cipher default_cipher_ossl default_proto local remark4default_cipher supported_sslv2_ciphers local -a cipher proto local p i @@ -4862,8 +4869,14 @@ run_server_preference() { esac pr_bold " Negotiated cipher " - default_cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') - case "$default_cipher" in + default_cipher_ossl=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g') + if [[ -z "$SHOW_RFC" ]]; then + default_cipher="$default_cipher_ossl" + else + default_cipher="$(openssl2rfc "$default_cipher_ossl")" + [[ -z "$default_cipher" ]] && default_cipher="$default_cipher_ossl" + fi + case "$default_cipher_ossl" in *NULL*|*EXP*) pr_svrty_critical "$default_cipher" fileout "order_cipher" "CRITICAL" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" @@ -4921,7 +4934,11 @@ 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 - cipher[i]="${TLS_CIPHER_OSSL_NAME[j]}" + if ( [[ -z "$SHOW_RFC" ]] && [[ "${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]}" + fi break fi fi @@ -4942,8 +4959,10 @@ run_server_preference() { proto[i]="SSLv3" cipher[i]="" 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" + if [[ -z "$SHOW_RFC" ]] && [[ $TLS_NR_CIPHERS -ne 0 ]]; then + cipher[i]="$(rfc2openssl "$cipher1")" + [[ -z "${cipher[i]}" ]] && cipher[i]="$cipher1" + fi [[ $DEBUG -ge 2 ]] && outln "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" @@ -4957,6 +4976,10 @@ 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 + 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 "Default cipher for ${proto[i]}: ${cipher[i]}" else proto[i]="" @@ -4977,6 +5000,10 @@ 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 + 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 "Default cipher for ${proto[i]}: ${cipher[i]}" fi fi @@ -4988,13 +5015,21 @@ 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 + if [[ -z "$SHOW_RFC" ]]; then + printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both + else + 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 - printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both + if [[ -z "$SHOW_RFC" ]]; then + printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both + else + printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}" # print out both + fi fi fi fi @@ -5088,7 +5123,7 @@ check_tls12_pref() { cipher_pref_check() { local p proto proto_hex npn_protos sni - local tested_cipher cipher order + local tested_cipher cipher order rfc_ciph rfc_order local overflow_probe_cipherlist="ALL:-ECDHE-RSA-AES256-GCM-SHA384:-AES128-SHA:-DES-CBC3-SHA" local -i i nr_ciphers nr_nonossl_ciphers num_bundles mod_check bundle_size bundle end_of_bundle success local hexc ciphers_to_test @@ -5134,7 +5169,7 @@ cipher_pref_check() { sclient_connect_successful $? $TMPFILE || break cipher=$(awk '/Cipher *:/ { print $3 }' $TMPFILE) [[ -z "$cipher" ]] && break - order+=" $cipher" + order+="$cipher " tested_cipher+=":-"$cipher "$FAST" && break done @@ -5251,16 +5286,29 @@ cipher_pref_check() { for (( i=0; i < nr_ciphers; i++ )); do [[ "$cipher" == "${rfc_ciph[i]}" ]] && ciphers_found2[i]=true && break done - 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") - order+=" $cipher" + if [[ -z "$SHOW_RFC" ]] && [[ $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 + rfc_order="" + while read -d " " cipher; do + rfc_ciph="$(openssl2rfc "$cipher")" + if [[ -n "$rfc_ciph" ]]; then + rfc_order+="$rfc_ciph " + else + rfc_order+="$cipher " + fi + done <<< "$order" + order="$rfc_order" fi if [[ -n "$order" ]]; then outln - printf " %-10s" "$proto: " + printf " %-10s " "$proto: " out_row_aligned_max_width "$order" " " $TERM_WIDTH out fileout "order_$p" "INFO" "Default cipher order for protocol $p: $order" fi @@ -5277,16 +5325,28 @@ cipher_pref_check() { cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) printf " %-10s " "$p:" tested_cipher="-"$cipher - order="$cipher" + order="$cipher " if ! "$FAST"; then while true; do $OPENSSL s_client -cipher "ALL:$tested_cipher" $BUGS -nextprotoneg "$p" -connect $NODEIP:$PORT $SNI >$ERRFILE >$TMPFILE sclient_connect_successful $? $TMPFILE || break cipher=$(awk '/Cipher.*:/ { print $3 }' $TMPFILE) tested_cipher="$tested_cipher:-$cipher" - order+=" $cipher" + order+="$cipher " done fi + if [[ -n "$order" ]] && [[ -n "$SHOW_RFC" ]]; then + rfc_order="" + while read -d " " cipher; do + rfc_ciph="$(openssl2rfc "$cipher")" + if [[ -n "$rfc_ciph" ]]; then + rfc_order+="$rfc_ciph " + else + rfc_order+="$cipher " + fi + done <<< "$order" + order="$rfc_order" + fi out_row_aligned_max_width "$order" " " $TERM_WIDTH out outln [[ -n $order ]] && fileout "order_spdy_$p" "INFO" "Default cipher order for SPDY protocol $p: $order" @@ -6751,7 +6811,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 [[ "${ciph[i]}" != "-" ]]; then + if ( [[ -z "$SHOW_RFC" ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then pfs_cipher="${ciph[i]}" else pfs_cipher="${rfc_ciph[i]}" @@ -10329,7 +10389,11 @@ run_beast(){ [[ "$cbc_cipher" == "${ciph[i]}" ]] && break done ciphers_found[i]=true - detected_cbc_ciphers+=" ${ciph[i]}" + if [[ -z "$SHOW_RFC" ]] || [[ "${rfc_ciph[i]}" == "-" ]]; then + detected_cbc_ciphers+="${ciph[i]} " + else + detected_cbc_ciphers+="${rfc_ciph[i]} " + fi vuln_beast=true if "$WIDE" && ( [[ ${kx[i]} == "Kx=ECDH" ]] || [[ ${kx[i]} == "Kx=DH" ]] || [[ ${kx[i]} == "Kx=EDH" ]] ); then dhlen=$(read_dhbits_from_file "$TMPFILE" quiet) @@ -10356,7 +10420,7 @@ run_beast(){ [[ "$cbc_cipher" == "${rfc_ciph[i]}" ]] && break done ciphers_found[i]=true - if [[ "${ciph[i]}" != "-" ]]; then + if ( [[ -z "$SHOW_RFC" ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then detected_cbc_ciphers+=" ${ciph[i]}" else detected_cbc_ciphers+=" ${rfc_ciph[i]}" @@ -10732,7 +10796,13 @@ run_rc4() { fi outln "${sigalg[i]}" fi - "${ciphers_found[i]}" && rc4_detected+="${ciph[i]} " + if "${ciphers_found[i]}"; then + if ( [[ -z "$SHOW_RFC" ]] && [[ "${ciph[i]}" != "-" ]] ) || [[ "${rfc_ciph[i]}" == "-" ]]; then + rc4_detected+="${ciph[i]} " + else + rc4_detected+="${rfc_ciph[i]} " + fi + fi done ! "$WIDE" && out_row_aligned_max_width "$rc4_detected" " " $TERM_WIDTH pr_svrty_high outln @@ -10819,6 +10889,7 @@ get_install_dir() { if [[ ! -r "$CIPHERS_BY_STRENGTH_FILE" ]] ; then unset ADD_RFC_STR + unset SHOW_RFC debugme echo "$CIPHERS_BY_STRENGTH_FILE" pr_warningln "\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." @@ -11074,7 +11145,8 @@ 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 don't display the RFC Cipher Suite Name + --mapping (rfc: display the RFC Cipher Suite name instead of the OpenSSL name; + no-rfc: don't display the RFC Cipher Suite Name) --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" @@ -12503,8 +12575,9 @@ parse_cmd_line() { cipher_mapping=$(parse_opt_equal_sign "$1" "$2") [[ $? -eq 0 ]] && shift case "$cipher_mapping" in - no-rfc) unset ADD_RFC_STR;; - *) pr_magentaln "\nmapping can only be \"no-rfc\"" + no-rfc) unset ADD_RFC_STR; unset SHOW_RFC;; + rfc) SHOW_RFC="rfc" ;; + *) pr_magentaln "\nmapping can only be \"rfc\" or \"no-rfc\"" help 1 ;; esac ;; From 76c34dd1486e68165bd462f60705261feaf397e3 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 14 Feb 2017 09:53:38 -0500 Subject: [PATCH 23/52] Negotiated cipher per proto bugfix I have a test server that I configured to support only SSLv3 and TLSv1.2. When I set `SSLHonorCipherOrder` to `off` I get the following results: ``` ECDHE-RSA-AES256-SHA: SSLv3 ECDHE-RSA-AES256-GCM-SHA384: TLSv1.2 ``` The current code, when printing TLSv1.2 checks whether `${cipher[4]}` is empty, and since it is assume no previous protocol (SSLv2, SSLv3, TLSv1, TLSv1.1) was supported and so doesn't output a newline before outputting the cipher and protocol for TLSv1.2. This PR fixes that by changing to code to look at the previous non-empty cipher (if there is one), even if that does not come from the previous protocol. --- testssl.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index 180c704..8eaafa0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4742,7 +4742,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 @@ -5013,7 +5013,7 @@ 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 + if [[ -z "$prev_cipher" ]]; then # previous one empty #outln if [[ -z "$SHOW_RFC" ]]; then printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both @@ -5021,7 +5021,7 @@ run_server_preference() { 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 + if [[ "$prev_cipher" == "${cipher[i]}" ]]; then # and previous protocol same cipher out ", ${proto[i]}" # same cipher --> only print out protocol behind it else outln @@ -5032,6 +5032,7 @@ run_server_preference() { fi fi fi + prev_cipher="${cipher[i]}" fi fileout "order_${proto[i]}_cipher" "INFO" "Default cipher on ${proto[i]}: ${cipher[i]} $remark4default_cipher" done From e2161aef5ef85af4f57e52e26feefd22add28b85 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 14 Feb 2017 10:04:42 -0500 Subject: [PATCH 24/52] Rearrange code Just a slight rearrangement of the code in order to remove some redundancy. --- testssl.sh | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/testssl.sh b/testssl.sh index 8eaafa0..5d92727 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5013,24 +5013,15 @@ run_server_preference() { for i in 1 2 3 4 5 6; do if [[ -n "${cipher[i]}" ]]; then # cipher not empty - if [[ -z "$prev_cipher" ]]; then # previous one empty - #outln + if [[ -z "$prev_cipher" ]] || [[ "$prev_cipher" != "${cipher[i]}" ]]; then + [[ -n "$prev_cipher" ]] && outln if [[ -z "$SHOW_RFC" ]]; then printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both else printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}" # print out both fi - else # previous NOT empty - if [[ "$prev_cipher" == "${cipher[i]}" ]]; then # and previous protocol same cipher - out ", ${proto[i]}" # same cipher --> only print out protocol behind it - else - outln - if [[ -z "$SHOW_RFC" ]]; then - printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both - else - printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}" # print out both - fi - fi + else + out ", ${proto[i]}" # same cipher --> only print out protocol behind it fi prev_cipher="${cipher[i]}" fi From a22e4e5228228f9188cf6ab221b8f1f1a5b969c7 Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 14 Feb 2017 19:45:14 +0100 Subject: [PATCH 25/52] - fix heartbleed detection which sometimes case false psoitives over slow connections like sattelite links, partially addressing #352 - start revamping run)ccs_injection - fix missing space in BEAST after protocol --- testssl.sh | 134 ++++++++++++++++++++++++++--------------------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/testssl.sh b/testssl.sh index 180c704..aa37c24 100755 --- a/testssl.sh +++ b/testssl.sh @@ -9111,7 +9111,7 @@ run_heartbleed(){ local -i n ret lines_returned local -i hb_rounds=3 local append="" - local found_500_oops=false + local tls_hello_ascii="" local cve="CVE-2014-0160" local cwe="CWE-119" local hint="" @@ -9191,26 +9191,37 @@ run_heartbleed(){ # extension: heartbeat x00, x0f, x00, x01, x01" - 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)" - socksend "$client_hello" 1 + fd_socket 5 || return 6 + debugme out "\nsending client hello (TLS version $tls_hexcode)" + debugme outln " ($n of $hb_rounds)" + socksend "$client_hello" 1 - debugme outln "\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:" - fi - rm "$SOCK_REPLY_FILE" + debugme outln "\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:" + fi + rm "$SOCK_REPLY_FILE" - socksend "$heartbleed_payload" 1 - sockread_serverhello 16384 $HEARTBLEED_MAX_WAITSOCK - [[ $? -eq 3 ]] && append=", timed out" + socksend "$heartbleed_payload" 1 + sockread_serverhello 16384 $HEARTBLEED_MAX_WAITSOCK + if [[ $? -eq 3 ]]; then + append=", timed out" + pr_done_best "not vulnerable (OK)"; out "$append" + fileout "heartbleed" "OK" "Heartbleed: not vulnerable $append" "$cve" "$cwe" + ret=0 + else + + # server reply should be (>=SSLv3): 18030x in case of a heartBEAT reply -- which we take as a positive result + tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE") + debugme echo "tls_content_type: ${tls_hello_ascii:0:2}" + debugme echo "tls_protocol: ${tls_hello_ascii:2:4}" + + lines_returned=$(count_lines "$(hexdump -ve '16/1 "%02x " " \n"' "$SOCK_REPLY_FILE")") + debugme echo "lines HB reply: $lines_returned" - lines_returned=$(hexdump -ve '16/1 "%02x " " \n"' "$SOCK_REPLY_FILE" | wc -l | sed 's/ //g') if [[ $DEBUG -ge 3 ]]; then outln "\nheartbleed reply: " hexdump -C "$SOCK_REPLY_FILE" | head -20 @@ -9218,55 +9229,37 @@ run_heartbleed(){ outln fi - if [[ $lines_returned -gt 1 ]]; then + if [[ $lines_returned -gt 1 ]] && [[ "${tls_hello_ascii:0:4}" == "1803" ]]; then if [[ "$STARTTLS_PROTOCOL" == "ftp" ]] || [[ "$STARTTLS_PROTOCOL" == "ftps" ]]; then - # check possibility of weird vsftpd reply, see #426 - 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]}" - #TMPFILE="${saved_sockreply[n]}" - close_socket - #tmpfile_handle "$FUNCNAME,$n.txt" + # check possibility of weird vsftpd reply, see #426, despite "1803" seems very unlikely... + if grep -q '500 OOPS' "$SOCK_REPLY_FILE" ; then + append=", successful weeded out vsftpd false positive" + pr_done_best "not vulnerable (OK)"; out "$append" + fileout "heartbleed" "OK" "Heartbleed: not vulnerable $append" "$cve" "$cwe" + ret=0 + else + out "likely " + pr_svrty_critical "VULNERABLE (NOT ok)" + [[ $DEBUG -lt 3 ]] && out ", use debug >=3 to confirm" + fileout "heartbleed" "CRITICAL" "Heartbleed: VULNERABLE $cve" "$cwe" "$hint" + ret=1 + fi else - rm "$SOCK_REPLY_FILE" pr_svrty_critical "VULNERABLE (NOT ok)" - fileout "heartbleed" "CRITICAL" "Heartbleed: VULNERABLE $append" "$cve" "$cwe" "$hint" + fileout "heartbleed" "CRITICAL" "Heartbleed: VULNERABLE $cve" "$cwe" "$hint" ret=1 - break fi else - rm "$SOCK_REPLY_FILE" pr_done_best "not vulnerable (OK)" - fileout "heartbleed" "OK" "Heartbleed: not vulnerable $append" "$cve" "$cwe" + fileout "heartbleed" "OK" "Heartbleed: not vulnerable $cve" "$cwe" ret=0 - break fi - done - - if [[ $n -gt 1 ]]; then - # more than one round of heartbleed checks --> vsftpd probably. - # This is the robust approach. According to a few tests it could also suffice # to check for "500 OOPS" only. - # Checking for the same socket reply DOES NOT suffice -- server can be idle and return the same memory - 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" - 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" - fileout "heartbleed" "CRITICAL" "Heartbleed: likely VULNERABLE $append" "$cve" "$cwe" "$hint" - fi - else - # for the repeated tries we did that already - #TMPFILE="$SOCKREPLY" - close_socket 2>/dev/null - #tmpfile_handle $FUNCNAME.txt fi - outln "$append" + outln + TMPFILE="$SOCK_REPLY_FILE" + close_socket + tmpfile_handle $FUNCNAME.dd return $ret } @@ -9279,7 +9272,8 @@ ok_ids(){ #FIXME: At a certain point heartbleed and ccs needs to be changed and make use of code2network using a file, then tls_sockets run_ccs_injection(){ local tls_proto_offered tls_hexcode ccs_message client_hello byte6 sockreply - local -i retval ret lines + local -i retval ret lines_returned + local tls_hello_ascii="" local cve="CVE-2014-0224" local cwe="CWE-310" local hint="" @@ -9369,22 +9363,27 @@ run_ccs_injection(){ sockread_serverhello 2048 $CCS_MAX_WAITSOCK retval=$? + tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE") + debugme echo "tls_content_type: ${tls_hello_ascii:0:2}" + debugme echo "tls_protocol: ${tls_hello_ascii:2:4}" + lines_returned=$(count_lines "$(hexdump -ve '16/1 "%02x " " \n"' "$SOCK_REPLY_FILE")") + debugme echo "lines new: $lines_returned, byte6: ${tls_hello_ascii:12:2}" + if [[ $DEBUG -ge 3 ]]; then outln "\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 + hexdump -C "$SOCK_REPLY_FILE" outln fi sockreply=$(cat "$SOCK_REPLY_FILE" 2>/dev/null) - rm "$SOCK_REPLY_FILE" byte6=$(echo "$sockreply" | "${HEXDUMPPLAIN[@]}" | sed 's/^..........//') - lines=$(echo "$sockreply" | "${HEXDUMP[@]}" | count_lines ) - debugme echo "lines: $lines, byte6: $byte6" + debugme echo "lines: $lines_returned, byte6: $byte6" +# not ok: 15 | 0301 | 02 | 02 | 15 +# ALERT | TLS 1.0 | Length=2 | Decryption failed (21) +# +# ok: 0a or nothing: ==> RST - if [[ "$byte6" == "0a" ]] || [[ "$lines" -gt 1 ]]; then + if [[ "$byte6" == "0a" ]] || [[ "$lines_returned" -gt 1 ]]; then pr_done_best "not vulnerable (OK)" if [[ $retval -eq 3 ]]; then fileout "ccs" "OK" "CCS: not vulnerable (timed out)" "$cve" "$cwe" @@ -9404,8 +9403,9 @@ run_ccs_injection(){ [[ $retval -eq 3 ]] && out ", timed out" outln + TMPFILE="$SOCK_REPLY_FILE" close_socket - tmpfile_handle $FUNCNAME.txt + tmpfile_handle $FUNCNAME.dd return $ret } @@ -10465,7 +10465,7 @@ run_beast(){ if [[ -n "$detected_cbc_ciphers" ]]; then fileout "cbc_$proto" "MEDIUM" "BEAST: CBC ciphers for $(toupper $proto): $detected_cbc_ciphers" "$cve" "$cwe" "$hint" ! "$first" && out "$spaces" - out "$(toupper $proto):" + out "$(toupper $proto): " [[ -n "$higher_proto_supported" ]] && \ out_row_aligned_max_width "$detected_cbc_ciphers" " " $TERM_WIDTH pr_svrty_low || \ out_row_aligned_max_width "$detected_cbc_ciphers" " " $TERM_WIDTH pr_svrty_medium From 422171a0fa7f841eb92cdc6a7c3a611d9a104f5e Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 14 Feb 2017 20:40:38 +0100 Subject: [PATCH 26/52] - fixed bug where terminal width was not inherited in file batch mode so that terminal wdith appeared to be 80 chars - hint when URI is missing - PFS_CIPHERs rather locally --- testssl.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/testssl.sh b/testssl.sh index aa37c24..68276d0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -126,12 +126,14 @@ tty -s && \ readonly INTERACTIVE=true || \ readonly INTERACTIVE=false -if ! tput cols &>/dev/null || ! $INTERACTIVE; then # Prevent tput errors if running non interactive - TERM_WIDTH=${COLUMNS:-80} -else - TERM_WIDTH=${COLUMNS:-$(tput cols)} # for custom line wrapping and dashes +if [[ -z $TERM_WIDTH ]]; then # no batch file and no otherwise predefined TERM_WIDTH + if ! tput cols &>/dev/null || ! "$INTERACTIVE";then # Prevent tput errors if running non interactive + export TERM_WIDTH=${COLUMNS:-80} + else + export TERM_WIDTH=${COLUMNS:-$(tput cols)} # for custom line wrapping and dashes + fi fi -TERM_CURRPOS=0 # custom line wrapping needs alter the current horizontal cursor pos +TERM_CURRPOS=0 # custom line wrapping needs alter the current horizontal cursor pos # following variables make use of $ENV, e.g. OPENSSL= ./testssl.sh # 0 means (normally) true here. Some of the variables are also accessible with a command line switch, see --help @@ -158,7 +160,7 @@ LOGFILE=${LOGFILE:-""} # logfile if used JSONFILE=${JSONFILE:-""} # jsonfile if used CSVFILE=${CSVFILE:-""} # csvfile if used APPEND=${APPEND:-false} # append to csv/json file instead of overwriting it -GIVE_HINTS=false # give an addtional info to findings +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 UNBRACKTD_IPV6=${UNBRACKTD_IPV6:-false} # some versions of OpenSSL (like Gentoo) don't support [bracketed] IPv6 addresses SERVER_SIZE_LIMIT_BUG=false # Some servers have either a ClientHello total size limit or cipher limit of ~128 ciphers (e.g. old ASAs) @@ -182,9 +184,6 @@ DAYS2WARN2=${DAYS2WARN2:-30} # days to warn before cert expires, thre VULN_THRESHLD=${VULN_THRESHLD:-1} # if vulnerabilities to check >$VULN_THRESHLD we DON'T show a separate header line in the output each vuln. check NODNS=${NODNS:-false} # always do DNS lookups per default. For some pentests it might save time to set this to true readonly CLIENT_MIN_PFS=5 # number of ciphers needed to run a test for PFS - # generated from 'kEECDH:kEDH:!aNULL:!eNULL:!DES:!3DES:!RC4' with openssl 1.0.2i and openssl 1.1.0 -readonly ROBUST_PFS_CIPHERS="DHE-DSS-AES128-GCM-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-DSS-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA:DHE-DSS-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA:DHE-DSS-SEED-SHA:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA:DHE-RSA-CAMELLIA256-SHA256:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-SEED-SHA:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA256-SHA384:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305" - HAD_SLEPT=0 CAPATH="${CAPATH:-/etc/ssl/certs/}" # Does nothing yet (FC has only a CA bundle per default, ==> openssl version -d) FNAME=${FNAME:-""} # file name to read commands from @@ -6656,7 +6655,9 @@ run_pfs() { local pfs_offered=false ecdhe_offered=false ffdhe_offered=false local hexc dash pfs_cipher sslvers auth mac export curve dhlen local -a hexcode normalized_hexcode ciph rfc_ciph kx enc ciphers_found sigalg ossl_supported - local pfs_cipher_list="$ROBUST_PFS_CIPHERS" pfs_hex_cipher_list="" ciphers_to_test + # generated from 'kEECDH:kEDH:!aNULL:!eNULL:!DES:!3DES:!RC4' with openssl 1.0.2i and openssl 1.1.0 + local pfs_cipher_list="DHE-DSS-AES128-GCM-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-DSS-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA:DHE-DSS-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA:DHE-DSS-SEED-SHA:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA:DHE-RSA-CAMELLIA256-SHA256:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305:DHE-RSA-SEED-SHA:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-CAMELLIA128-SHA256:ECDHE-RSA-CAMELLIA256-SHA384:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305" + local pfs_hex_cipher_list="" ciphers_to_test local ecdhe_cipher_list="" ecdhe_cipher_list_hex="" ffdhe_cipher_list_hex="" local curves_hex=("00,01" "00,02" "00,03" "00,04" "00,05" "00,06" "00,07" "00,08" "00,09" "00,0a" "00,0b" "00,0c" "00,0d" "00,0e" "00,0f" "00,10" "00,11" "00,12" "00,13" "00,14" "00,15" "00,16" "00,17" "00,18" "00,19" "00,1a" "00,1b" "00,1c" "00,1d" "00,1e") local -a curves_ossl=("sect163k1" "sect163r1" "sect163r2" "sect193r1" "sect193r2" "sect233k1" "sect233r1" "sect239k1" "sect283k1" "sect283r1" "sect409k1" "sect409r1" "sect571k1" "sect571r1" "secp160k1" "secp160r1" "secp160r2" "secp192k1" "prime192v1" "secp224k1" "secp224r1" "secp256k1" "prime256v1" "secp384r1" "secp521r1" "brainpoolP256r1" "brainpoolP384r1" "brainpoolP512r1" "X25519" "X448") @@ -12113,8 +12114,7 @@ run_mass_testing_parallel() { fi pr_reverse "====== Running in parallel file batch mode with file=\"$FNAME\" ======"; outln outln "(output is in ....\n)" -#FIXME: once this function is being called we need a handler which does the right thing -# ==> not overwrite +#FIXME: once this function is being called we need a handler which does the right thing, i.e. ==> not to overwrite while read cmdline; do cmdline=$(filter_input "$cmdline") [[ -z "$cmdline" ]] && continue @@ -12608,7 +12608,7 @@ parse_cmd_line() { # Show usage if no options were specified if [[ -z "$1" ]] && [[ -z "$FNAME" ]] && ! $do_display_only; then - help 0 + echo && fatal "URI missing" "1" else # left off here is the URI URI="$1" From 4b193119b3c56faf0e7654de4c5a097e89e89a65 Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 14 Feb 2017 21:56:31 +0100 Subject: [PATCH 27/52] - made CCS I more robust, FIX #313 - removed cats ;-) FIX #352 --- testssl.sh | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/testssl.sh b/testssl.sh index 68276d0..4d98c64 100755 --- a/testssl.sh +++ b/testssl.sh @@ -9273,7 +9273,7 @@ ok_ids(){ #FIXME: At a certain point heartbleed and ccs needs to be changed and make use of code2network using a file, then tls_sockets run_ccs_injection(){ local tls_proto_offered tls_hexcode ccs_message client_hello byte6 sockreply - local -i retval ret lines_returned + local -i retval ret local tls_hello_ascii="" local cve="CVE-2014-0224" local cwe="CWE-310" @@ -9342,13 +9342,12 @@ run_ccs_injection(){ if [[ $DEBUG -ge 4 ]]; then hexdump -C "$SOCK_REPLY_FILE" | head -20 outln "[...]" - outln "\npayload #1 with TLS version $tls_hexcode:" + 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 2048 $CCS_MAX_WAITSOCK + sockread_serverhello 4096 $CCS_MAX_WAITSOCK if [[ $DEBUG -ge 3 ]]; then outln "\n1st reply: " hexdump -C "$SOCK_REPLY_FILE" | head -20 @@ -9356,43 +9355,40 @@ run_ccs_injection(){ # ALERT | TLS 1.0 | Length=2 | Unexpected Message (0a) # or just timed out outln - outln "payload #2 with TLS version $tls_hexcode:" + out "sending payload #2 with TLS version $tls_hexcode: " fi rm "$SOCK_REPLY_FILE" socksend "$ccs_message" 2 || ok_ids - sockread_serverhello 2048 $CCS_MAX_WAITSOCK + sockread_serverhello 4096 $CCS_MAX_WAITSOCK retval=$? tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE") - debugme echo "tls_content_type: ${tls_hello_ascii:0:2}" - debugme echo "tls_protocol: ${tls_hello_ascii:2:4}" - lines_returned=$(count_lines "$(hexdump -ve '16/1 "%02x " " \n"' "$SOCK_REPLY_FILE")") - debugme echo "lines new: $lines_returned, byte6: ${tls_hello_ascii:12:2}" + byte6="${tls_hello_ascii:12:2}" + 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 "\n2nd reply: " hexdump -C "$SOCK_REPLY_FILE" outln fi - sockreply=$(cat "$SOCK_REPLY_FILE" 2>/dev/null) - byte6=$(echo "$sockreply" | "${HEXDUMPPLAIN[@]}" | sed 's/^..........//') - debugme echo "lines: $lines_returned, byte6: $byte6" # not ok: 15 | 0301 | 02 | 02 | 15 # ALERT | TLS 1.0 | Length=2 | Decryption failed (21) # # ok: 0a or nothing: ==> RST - if [[ "$byte6" == "0a" ]] || [[ "$lines_returned" -gt 1 ]]; then + if [[ -z "${tls_hello_ascii:0:12}" ]]; then + # empty reply pr_done_best "not vulnerable (OK)" if [[ $retval -eq 3 ]]; then +### what? fileout "ccs" "OK" "CCS: not vulnerable (timed out)" "$cve" "$cwe" else fileout "ccs" "OK" "CCS: not vulnerable" "$cve" "$cwe" fi ret=0 - else + elif [[ "$byte6" == "15" ]] && [[ "${tls_hello_ascii:0:4}" == "1503" ]]; then pr_svrty_critical "VULNERABLE (NOT ok)" if [[ $retval -eq 3 ]]; then fileout "ccs" "CRITICAL" "CCS: VULNERABLE (timed out)" "$cve" "$cwe" "$hint" @@ -9400,8 +9396,17 @@ run_ccs_injection(){ fileout "ccs" "CRITICAL" "CCS: VULNERABLE" "$cve" "$cwe" "$hint" fi ret=1 + elif [[ "$byte6" == [0-9a-f][0-9a-f] ]] && [[ "${tls_hello_ascii:2:2}" != "03" ]]; then + pr_warning "test failed" + out ", probably read buffer too small (${tls_hello_ascii:0:14})" + fileout "ccs" "WARN" "CCS: test failed, probably read buffer too small (${tls_hello_ascii:0:14})" "$cve" "$cwe" "$hint" + ret=7 + else + pr_warning "test failed " + out "around line $LINENO (debug info: ${tls_hello_ascii:0:14})" + fileout "ccs" "WARN" "CCS: test failed, around line $LINENO, debug info (${tls_hello_ascii:0:14})" "$cve" "$cwe" "$hint" + ret=7 fi - [[ $retval -eq 3 ]] && out ", timed out" outln TMPFILE="$SOCK_REPLY_FILE" From 004cbad07b03480079c2bebc8d2a32d55a1a0d7b Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 14 Feb 2017 16:43:46 -0500 Subject: [PATCH 28/52] run_protocols() bug fix Since the test for TLS 1.2 in `run_protocols()` now uses `tls_sockets()` whenever `$ssl_native` is `true` (i.e., there is no longer a requirement for `$EXPERIMENTAL` to be true as well), the `$EXPERIMENTAL` flag should no longer be checked if the return value is 1. --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 4d98c64..5e437ea 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4506,7 +4506,7 @@ run_protocols() { ;; # GCM cipher in TLS 1.2: very good! 1) pr_svrty_mediumln "not offered" - if ! "$using_sockets" || ! "$EXPERIMENTAL" || [[ -z $latest_supported ]]; then + if ! "$using_sockets" || [[ -z $latest_supported ]]; then 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" From cdc5e89b64c0eb65b8ca16e6bdb0be3bbb5f1dfc Mon Sep 17 00:00:00 2001 From: Konstantin Shalygin Date: Tue, 14 Feb 2017 22:18:27 +0700 Subject: [PATCH 29/52] DNS CAA: drill query support. --- testssl.sh | 86 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/testssl.sh b/testssl.sh index 180c704..344b78c 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1081,7 +1081,7 @@ filter_input() { # dl's any URL (argv1) via HTTP 1.1 GET from port 80, arg2: file to store http body # proxy is not honored (see cmd line switches) http_get() { - local proto z + local proto z local node="" query="" local dl="$2" local useragent="$UA_STD" @@ -4609,40 +4609,40 @@ run_std_cipherlists() { pr_ecdh_curve_quality() { curve="$1" local -i bits=0 - + case "$curve" in - "sect163k1") bits=163 ;; - "sect163r1") bits=162 ;; - "sect163r2") bits=163 ;; - "sect193r1") bits=193 ;; - "sect193r2") bits=193 ;; - "sect233k1") bits=232 ;; - "sect233r1") bits=233 ;; - "sect239k1") bits=238 ;; - "sect283k1") bits=281 ;; - "sect283r1") bits=282 ;; - "sect409k1") bits=407 ;; - "sect409r1") bits=409 ;; - "sect571k1") bits=570 ;; - "sect571r1") bits=570 ;; - "secp160k1") bits=161 ;; - "secp160r1") bits=161 ;; - "secp160r2") bits=161 ;; - "secp192k1") bits=192 ;; - "prime192v1") bits=192 ;; - "secp224k1") bits=225 ;; - "secp224r1") bits=224 ;; - "secp256k1") bits=256 ;; - "prime256v1") bits=256 ;; - "secp384r1") bits=384 ;; - "secp521r1") bits=521 ;; - "brainpoolP256r1") bits=256 ;; - "brainpoolP384r1") bits=384 ;; - "brainpoolP512r1") bits=512 ;; - "X25519") bits=253 ;; - "X448") bits=448 ;; + "sect163k1") bits=163 ;; + "sect163r1") bits=162 ;; + "sect163r2") bits=163 ;; + "sect193r1") bits=193 ;; + "sect193r2") bits=193 ;; + "sect233k1") bits=232 ;; + "sect233r1") bits=233 ;; + "sect239k1") bits=238 ;; + "sect283k1") bits=281 ;; + "sect283r1") bits=282 ;; + "sect409k1") bits=407 ;; + "sect409r1") bits=409 ;; + "sect571k1") bits=570 ;; + "sect571r1") bits=570 ;; + "secp160k1") bits=161 ;; + "secp160r1") bits=161 ;; + "secp160r2") bits=161 ;; + "secp192k1") bits=192 ;; + "prime192v1") bits=192 ;; + "secp224k1") bits=225 ;; + "secp224r1") bits=224 ;; + "secp256k1") bits=256 ;; + "prime256v1") bits=256 ;; + "secp384r1") bits=384 ;; + "secp521r1") bits=521 ;; + "brainpoolP256r1") bits=256 ;; + "brainpoolP384r1") bits=384 ;; + "brainpoolP512r1") bits=512 ;; + "X25519") bits=253 ;; + "X448") bits=448 ;; esac - + if [[ "$bits" -le 80 ]]; then # has that ever existed? pr_svrty_critical "$curve" elif [[ "$bits" -le 108 ]]; then # has that ever existed? @@ -7631,7 +7631,7 @@ get_dh_ephemeralkey() { len1="82$(printf "%04x" $((dh_param_len/2)))" fi dh_param="30${len1}${dh_p}${dh_g}" - + # Make a SEQUENCE of the paramters SEQUENCE and the OID dh_param_len=22+${#dh_param} if [[ $dh_param_len -lt 256 ]]; then @@ -9982,7 +9982,7 @@ run_logjam() { local cve="CVE-2015-4000" local cwe="CWE-310" local hint="" - local server_key_exchange ephemeral_pub key_bitstring="" + local server_key_exchange ephemeral_pub key_bitstring="" local dh_p="" local spaces=" " local vuln_exportdh_ciphers=false @@ -10457,7 +10457,7 @@ run_beast(){ fi fi outln "${sigalg[i]}" - fi + fi done fi @@ -11654,7 +11654,7 @@ get_aaaa_record() { # RFC6844: DNS Certification Authority Authorization (CAA) Resource Record # arg1: domain to check for get_caa_rr_record() { - local raw_caa="" + local raw_caa="" local caa_flag local -i len_caa_property local caa_property_name @@ -11663,7 +11663,7 @@ get_caa_rr_record() { # if there's a type257 record there are two output formats here, mostly depending on age of distribution # rougly that's the difference between text and binary format - # 1) 'google.com has CAA record 0 issue "symantec.com"' + # 1) 'google.com has CAA record 0 issue "symantec.com"' # 2) 'google.com has TYPE257 record \# 19 0005697373756573796D616E7465632E636F6D' # for dig +short the output always starts with '0 issue [..]' or '\# 19 [..]' so we normalize thereto to keep caa_flag, caa_property # caa_property then has key/value pairs, see https://tools.ietf.org/html/rfc6844#section-3 @@ -11671,6 +11671,9 @@ get_caa_rr_record() { if which dig &> /dev/null; then raw_caa="$(dig $1 type257 +short)" # empty if no CAA record + elif which drill &> /dev/null; then + a="$1" + raw_caa="$(drill $a type257 | awk '/'"^${a}"'.*CAA/ { print $5,$6,$7 }')" elif which host &> /dev/null; then raw_caa="$(host -t type257 $1)" if egrep -wvq "has no CAA|has no TYPE257" <<< "$raw_caa"; then @@ -11679,14 +11682,14 @@ get_caa_rr_record() { elif which nslookup &> /dev/null; then raw_caa="$(nslookup -type=type257 $1 | grep -w rdata_257)" if [[ -n "$raw_caa" ]]; then - raw_caa="$(sed 's/^.*rdata_257 = //' <<< "$raw_caa")" + raw_caa="$(sed 's/^.*rdata_257 = //' <<< "$raw_caa")" fi else return 1 - # No dig, host, or nslookup --> complaint was elsewhere already and except for one which has drill only we don't get here + # No dig, drill, host, or nslookup --> complaint was elsewhere already fi OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 - debugme echo $raw_caa + debugme echo $raw_caa # '# 19' for google.com is the tag length probably --> we use this also to identify the binary format if [[ "$raw_caa" =~ \#\ [0-9][0-9]\ [A-F0-9]+$ ]]; then @@ -11713,7 +11716,6 @@ get_caa_rr_record() { # to do: # 4: check whether $1 is a CNAME and take this -# 5: query with drill return 0 } From 2456c808217c847699712fd10860d7659495cd31 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 15 Feb 2017 11:47:11 -0500 Subject: [PATCH 30/52] Fix early newline In the case that `tls_sockets()` is being used and the server incorrectly fails the connection rather than downgrading, testssl.sh is printing "not offered" on one line and then the error message on the next line, but all the text should appear on one line (as it does when testing TLS 1 and TLS 1.1). --- testssl.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 8f8de5f..874c139 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4505,8 +4505,9 @@ run_protocols() { add_tls_offered "tls1_2" ;; # GCM cipher in TLS 1.2: very good! 1) - pr_svrty_mediumln "not offered" + pr_svrty_medium "not offered" if ! "$using_sockets" || [[ -z $latest_supported ]]; then + 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" From c204a0b9429eca35350fd2653c7be11d7636565a Mon Sep 17 00:00:00 2001 From: Dirk Date: Wed, 15 Feb 2017 19:40:06 +0100 Subject: [PATCH 31/52] --proxy=auto takes now the value from https_proxy - made DNS lookups safe (CNAME) and awk'd them almost completely ;-) - invocation of just testssl.sh shows help again --- testssl.sh | 66 +++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/testssl.sh b/testssl.sh index eb48614..dc125cb 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6994,7 +6994,7 @@ spdy_pre(){ return 1 fi if [[ -n "$PROXY" ]]; then - [[ -n "$1" ]] && pr_warning " $1 " + [[ -n "$1" ]] && pr_warning "$1" pr_warning "not tested as proxies do not support proxying it" fileout "spdy_npn" "WARN" "SPDY/NPN : not tested as proxies do not support proxying it" return 1 @@ -7033,7 +7033,7 @@ run_spdy() { local -i ret=0 pr_bold " SPDY/NPN " - if ! spdy_pre ; then + if ! spdy_pre; then outln return 0 fi @@ -7071,7 +7071,7 @@ run_http2() { local alpn_finding="" pr_bold " HTTP2/ALPN " - if ! http2_pre ; then + if ! http2_pre; then outln return 0 fi @@ -11138,8 +11138,8 @@ tuning / connect options (most also can be preset via environment variables): --assume-http if protocol check fails it assumes HTTP protocol and enforces HTTP checks --ssl-native fallback to checks with OpenSSL where sockets are normally used --openssl use this openssl binary (default: look in \$PATH, \$RUN_DIR of $PROG_NAME) - --proxy : connect via the specified HTTP proxy - -6 use also IPv6. Works only with supporting OpenSSL version and IPv6 connectivity + --proxy connect via the specified HTTP proxy, auto: autodetermination from \$env (\$http(s)_proxy) + -6 also use IPv6. Works only with supporting OpenSSL version and IPv6 connectivity --ip a) tests the supplied v4 or v6 address instead of resolving host(s) in URI b) arg "one" means: just test the first DNS returns (useful for multiple IPs) -n, --nodns do not try any DNS lookup @@ -11584,9 +11584,9 @@ check_resolver_bins() { } # arg1: a host name. Returned will be 0-n IPv4 addresses +# watch out: $1 can also be a cname! --> all checked get_a_record() { local ip4="" - local cname_temp="" local saved_openssl_conf="$OPENSSL_CONF" "$NODNS" && return 0 # if no DNS lookup was instructed, leave here @@ -11602,25 +11602,20 @@ get_a_record() { fi if [[ -z "$ip4" ]]; then if which dig &> /dev/null ; then - cname_temp=$(dig +short -t CNAME "$1" 2>/dev/null) - if [[ -n "$cname_temp" ]]; then - ip4=$(filter_ip4_address $(dig +short -t a "$cname_temp" 2>/dev/null | sed '/^;;/d')) - else - ip4=$(filter_ip4_address $(dig +short -t a "$1" 2>/dev/null | sed '/^;;/d')) - fi + ip4=$(filter_ip4_address $(dig +short -t a "$1" 2>/dev/null | awk '/^[0-9]/')) fi fi if [[ -z "$ip4" ]]; then which host &> /dev/null && \ - ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | grep -v alias | sed 's/^.*address //')) + ip4=$(filter_ip4_address $(host -t a "$1" 2>/dev/null | awk '/address/ { print $NF }')) fi if [[ -z "$ip4" ]]; then which drill &> /dev/null && \ - ip4=$(filter_ip4_address $(drill a "$1" 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d')) + ip4=$(filter_ip4_address $(drill a "$1" | awk '/ANSWER SECTION/,/AUTHORITY SECTION/ { print $NF }' | awk '/^[0-9]/')) fi if [[ -z "$ip4" ]]; then if which nslookup &>/dev/null; then - ip4=$(filter_ip4_address $(nslookup -querytype=a "$1" 2>/dev/null | awk '/^Name/,/EOF/ { print $0 }' | grep -v Name)) + ip4=$(filter_ip4_address $(nslookup -querytype=a "$1" 2>/dev/null | awk '/^Name/ { getline; print $NF }')) fi fi OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 @@ -11628,6 +11623,7 @@ get_a_record() { } # arg1: a host name. Returned will be 0-n IPv6 addresses +# watch out: $1 can also be a cname! --> all checked get_aaaa_record() { local ip6="" local saved_openssl_conf="$OPENSSL_CONF" @@ -11637,20 +11633,20 @@ get_aaaa_record() { if [[ -z "$ip6" ]]; then if [[ "$NODE" == *.local ]]; then if which avahi-resolve &>/dev/null; then - ip6=$(filter_ip6_address $(avahi-resolve -6 -n "$NODE" 2>/dev/null | awk '{ print $2 }')) + ip6=$(filter_ip6_address $(avahi-resolve -6 -n "$1" 2>/dev/null | awk '{ print $2 }')) elif which dig &>/dev/null; then ip6=$(filter_ip6_address $(dig @ff02::fb -p 5353 -t aaaa +short +notcp "$NODE")) else fatal "Local hostname given but no 'avahi-resolve' or 'dig' avaliable." -3 fi elif which host &> /dev/null ; then - ip6=$(filter_ip6_address $(host -t aaaa "$NODE" | grep -v alias | grep -v "no AAAA record" | sed 's/^.*address //')) + ip6=$(filter_ip6_address $(host -t aaaa "$1" | awk '/address/ { print $NF }')) elif which dig &> /dev/null; then - ip6=$(filter_ip6_address $(dig +short -t aaaa "$NODE" 2>/dev/null)) + ip6=$(filter_ip6_address $(dig +short -t aaaa "$1" 2>/dev/null | awk '/^[0-9]/')) elif which drill &> /dev/null; then - ip6=$(filter_ip6_address $(drill aaaa "$NODE" 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/^\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d')) + ip6=$(filter_ip6_address $(drill aaaa "$1" | awk '/ANSWER SECTION/,/AUTHORITY SECTION/ { print $NF }' | awk '/^[0-9]/')) elif which nslookup &>/dev/null; then - ip6=$(filter_ip6_address $(nslookup -type=aaaa "$NODE" 2>/dev/null | grep -A10 Name | grep -v Name)) + ip6=$(filter_ip6_address $(nslookup -type=aaaa "$1" 2>/dev/null | awk '/'"^${a}"'.*AAAA/ { print $NF }')) fi fi OPENSSL_CONF="$saved_openssl_conf" # see https://github.com/drwetter/testssl.sh/issues/134 @@ -11678,8 +11674,7 @@ get_caa_rr_record() { raw_caa="$(dig $1 type257 +short)" # empty if no CAA record elif which drill &> /dev/null; then - a="$1" - raw_caa="$(drill $a type257 | awk '/'"^${a}"'.*CAA/ { print $5,$6,$7 }')" + raw_caa="$(drill $1 type257 | awk '/'"^${1}"'.*CAA/ { print $5,$6,$7 }')" elif which host &> /dev/null; then raw_caa="$(host -t type257 $1)" if egrep -wvq "has no CAA|has no TYPE257" <<< "$raw_caa"; then @@ -11725,18 +11720,20 @@ get_caa_rr_record() { return 0 } +# watch out: $1 can also be a cname! --> all checked get_mx_record() { local mx="" local saved_openssl_conf="$OPENSSL_CONF" OPENSSL_CONF="" # see https://github.com/drwetter/testssl.sh/issues/134 check_resolver_bins + # we need tha last two columns here! if which host &> /dev/null; then mxs=$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }') elif which dig &> /dev/null; then - mxs=$(dig +short -t MX "$1" 2>/dev/null) + mxs=$(dig +short -t MX "$1" 2>/dev/null | awk '/^[0-9]/') elif which drill &> /dev/null; then - mxs=$(drill mx "$1" 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d') + mxs=$(drill mx $1 | | awk '/IN[ \t]MX[ \t]+/ { print $(NF-1), $NF }') elif which nslookup &> /dev/null; then mxs=$(nslookup -type=MX "$1" 2>/dev/null | awk '/mail exchanger/ { print $(NF-1), $NF }') else @@ -11824,7 +11821,7 @@ determine_rdns() { elif which host &> /dev/null; then rDNS=$(host -t PTR $nodeip 2>/dev/null | awk '/pointer/ { print $NF }') elif which drill &> /dev/null; then - rDNS=$(drill -x ptr $nodeip 2>/dev/null | awk '/^\;\;\sANSWER\sSECTION\:$/,/\;\;\sAUTHORITY\sSECTION\:$/ { print $5,$6 }' | sed '/^\s$/d') + rDNS=$(drill -x ptr $nodeip 2>/dev/null | awk '/ANSWER SECTION/ { getline; print $NF }') elif which nslookup &> /dev/null; then rDNS=$(nslookup -type=PTR $nodeip 2>/dev/null | grep -v 'canonical name =' | grep 'name = ' | awk '{ print $NF }' | sed 's/\.$//') fi @@ -11841,18 +11838,23 @@ check_proxy() { if ! "$HAS_PROXY"; then fatal "Your $OPENSSL is too old to support the \"-proxy\" option" -5 fi + if [[ "$PROXY" == "auto" ]]; then + # get $ENV + PROXY=${https_proxy#*\/\/} + [[ -z "$PROXY" ]] && PROXY=${http_proxy#*\/\/} + [[ -z "$PROXY" ]] && fatal "you specified \"--proxy=auto\" but \"\$http(s)_proxy\" is empty" 2 + fi PROXYNODE=${PROXY%:*} PROXYPORT=${PROXY#*:} - is_number "$PROXYPORT" || fatal "Proxy port cannot be determined from \"$PROXY\"" "2" + is_number "$PROXYPORT" || fatal "Proxy port cannot be determined from \"$PROXY\"" 2 #if is_ipv4addr "$PROXYNODE" || is_ipv6addr "$PROXYNODE" ; then # IPv6 via openssl -proxy: that doesn't work. Sockets does -#FIXME: to finish this with LibreSSL which supports an IPv6 proxy +#FIXME: finish this with LibreSSL which supports an IPv6 proxy if is_ipv4addr "$PROXYNODE"; then PROXYIP="$PROXYNODE" else - check_resolver_bins - PROXYIP=$(get_a_record $PROXYNODE 2>/dev/null | grep -v alias | sed 's/^.*address //') + PROXYIP=$(get_a_record "$PROXYNODE" 2>/dev/null | grep -v alias | sed 's/^.*address //') [[ -z "$PROXYIP" ]] && fatal "Proxy IP cannot be determined from \"$PROXYNODE\"" "2" fi PROXY="-proxy $PROXYIP:$PROXYPORT" @@ -12274,6 +12276,8 @@ parse_opt_equal_sign() { parse_cmd_line() { + # Show usage if no options were specified + [[ -z "$1" ]] && help 0 # Set defaults if only an URI was specified, maybe ToDo: use "="-option, then: ${i#*=} i.e. substring removal [[ "$#" -eq 1 ]] && set_scanning_defaults @@ -12604,7 +12608,7 @@ parse_cmd_line() { (--) shift break ;; - (-*) pr_magentaln "0: unrecognized option \"$1\"" 1>&2; + (-*) pr_warningln "0: unrecognized option \"$1\"" 1>&2; help 1 ;; (*) break @@ -12613,7 +12617,7 @@ parse_cmd_line() { shift done - # Show usage if no options were specified + # Show usage if no further options were specified if [[ -z "$1" ]] && [[ -z "$FNAME" ]] && ! $do_display_only; then echo && fatal "URI missing" "1" else From d2cbbaf0b1bdbc8cacd72c31edb730ad575fd5d4 Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 16 Feb 2017 19:10:59 +0100 Subject: [PATCH 32/52] - FIX #636 - polish --- testssl.sh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/testssl.sh b/testssl.sh index 14ca9d8..f3da16e 100755 --- a/testssl.sh +++ b/testssl.sh @@ -6385,7 +6385,7 @@ certificate_info() { out "$indent"; pr_bold " # of certificates provided"; outln " $certificates_provided" fileout "${json_prefix}certcount" "INFO" "# of certificates provided : $certificates_provided" - # Get both CRL and OCSP URL upfront. If there's none, this is not good. And we need to penalize this in the output + # Get both CRL and OCSP URI upfront. If there's none, this is not good. And we need to penalize this in the output crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | \ awk '/X509v3 CRL Distribution/{i=50} i&&i--' | awk '/^$/,/^ [a-zA-Z0-9]+|^ Signature Algorithm:/' | awk -F'URI:' '/URI/ { print $2 }')" ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE) @@ -6396,10 +6396,11 @@ certificate_info() { outln "--" fileout "${json_prefix}crl" "INFO" "No CRL provided" else - pr_svrty_highln "-- (NOT ok)" - fileout "${json_prefix}crl" "HIGH" "Neither CRL nor OCSP URL provided" + pr_svrty_high "NOT ok --" + outln " neither CRL nor OCSP URI provided" + fileout "${json_prefix}crl" "HIGH" "Neither CRL nor OCSP URI provided" fi - elif grep -q http <<< "$crl"; then + else if [[ $(count_lines "$crl") -eq 1 ]]; then outln "$crl" fileout "${json_prefix}crl" "INFO" "Certificate Revocation List : $crl" @@ -6407,9 +6408,6 @@ certificate_info() { out_row_aligned "$crl" "$spaces" fileout "${json_prefix}crl" "INFO" "Certificate Revocation List : $crl" fi - else - pr_warningln "no parsable output \"$crl\", pls report" - fileout "${json_prefix}crl" "WARN" "Certificate Revocation List : no parsable output \"$crl\", pls report" fi out "$indent"; pr_bold " OCSP URI " @@ -11443,12 +11441,16 @@ parse_hn_port() { NODE=$(echo "$NODE" | sed -e 's/\/.*$//') # if there's a trailing ':' probably a starttls/application protocol was specified - if grep -q ':$' <<< $NODE ; then - fatal "\"$1\" is not a valid URI" 1 + if grep -q ':$' <<< $NODE; then + if grep -wq http <<< $NODE; then + fatal "\"http\" is not what you meant probably" 1 + else + fatal "\"$1\" is not a valid URI" 1 + fi fi # was the address supplied like [AA:BB:CC::]:port ? - if echo "$NODE" | grep -q ']' ; then + if grep -q ']' <<< "$NODE"; then tmp_port=$(printf "$NODE" | sed 's/\[.*\]//' | sed 's/://') # determine v6 port, supposed it was supplied additionally if [[ -n "$tmp_port" ]]; then From a26425af714ab65536045e7ac3b8404e496536da Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 17 Feb 2017 11:20:11 -0500 Subject: [PATCH 33/52] Printing Negotiated cipher `run_server_preference()` prints out the server's Negotiated cipher in a different color depending on the quality of the cipher. However, there is a "FIXME" since CBC ciphers are supposed to be flagged, but it is not easy to identity all CBC ciphers from their OpenSSL names. This PR partially addresses this. It creates a separate function for printing a cipher based on its quality. Whenever possible it determines the quality of the cipher based on the RFC name. However, if it is provided an OpenSSL name and no cipher-mapping.txt file is available, it will follow the current (imperfect) logic for determining the cipher's quality. The function also returns a value that indicates the quality of the cipher provided, with higher numbers indicating better ciphers. This return value is used by `run_server_preference()` to determine how to populate the "severity" field when calling `fileout()`. --- testssl.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 14 deletions(-) diff --git a/testssl.sh b/testssl.sh index f3da16e..35b8c1e 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4660,6 +4660,80 @@ pr_ecdh_curve_quality() { fi } +# Print $2 based on the quality of the cipher in $1. If $2 is empty, print $1. +# 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 +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 + # We have the OpenSSL name and can't convert it to the RFC name + case "$cipher" in + *NULL*|*EXP*) + pr_svrty_critical "$text" + return 1 + ;; + *RC4*) + pr_svrty_high "$text" + return 2 + ;; + *CBC*) + pr_svrty_medium "$text" + return 3 + ;; # FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list + *GCM*|*CHACHA20*) + pr_done_best "$text" + return 7 + ;; #best ones + ECDHE*AES*) + pr_svrty_low "$text" + return 4 + ;; # it's CBC. --> lucky13 + *) + out "$text" + return 5 + ;; + esac + fi + cipher="$(openssl2rfc "$cipher")" + fi + + case "$cipher" in + *NULL*|*EXP*|*RC2*|*_DES_*|*_DES40_*) + pr_svrty_critical "$text" + return 1 + ;; + *RC4*) + pr_svrty_high "$text" + return 2 + ;; + *ECDHE*AES*CBC*) + pr_svrty_low "$text" + return 4 + ;; + *CBC*) + pr_svrty_medium "$text" + return 3 + ;; + *GCM*|*CHACHA20*) + pr_done_best "$text" + return 7 + ;; + *) + out "$text" + return 5 + ;; + esac +} + # arg1: file with input for grepping the bit length for ECDH/DHE # arg2: whether to print warning "old fart" or not (empty: no) read_dhbits_from_file() { @@ -4876,28 +4950,24 @@ run_server_preference() { default_cipher="$(openssl2rfc "$default_cipher_ossl")" [[ -z "$default_cipher" ]] && default_cipher="$default_cipher_ossl" fi - case "$default_cipher_ossl" in - *NULL*|*EXP*) - pr_svrty_critical "$default_cipher" + pr_cipher_quality "$default_cipher" + case $? in + 1) fileout "order_cipher" "CRITICAL" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" ;; - *RC4*) - pr_svrty_high "$default_cipher" + 2) fileout "order_cipher" "HIGH" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" ;; - *CBC*) - pr_svrty_medium "$default_cipher" + 3) fileout "order_cipher" "MEDIUM" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" - ;; # FIXME BEAST: We miss some CBC ciphers here, need to work w/ a list - *GCM*|*CHACHA20*) - pr_done_best "$default_cipher" + ;; + 6|7) fileout "order_cipher" "OK" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" ;; # best ones - ECDHE*AES*) - pr_svrty_low "$default_cipher" + 4) fileout "order_cipher" "LOW" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") (cbc) $remark4default_cipher" ;; # it's CBC. --> lucky13 - "") + 0) pr_warning "default cipher empty" ; if [[ $OSSL_VER == 1.0.2* ]]; then out " (Hint: if IIS6 give OpenSSL 1.0.1 a try)" @@ -4907,7 +4977,6 @@ run_server_preference() { fi ;; *) - out "$default_cipher" fileout "order_cipher" "INFO" "Default cipher: $default_cipher$(read_dhbits_from_file "$TMPFILE") $remark4default_cipher" ;; esac From 8c607d425e139c5bb23dccfbce75b519f2e1fc05 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Fri, 17 Feb 2017 15:20:37 -0500 Subject: [PATCH 34/52] OCSP must staple RFC 7633 introduces the TLS Features certificate extension, which contains "Features: > The object member "Features" is a sequence of TLS extension identifiers (features, in this specification's terminology) as specified in the IANA Transport Layer Security (TLS) Extensions registry. If these features are requested by the client in its ClientHello message, then the server MUST return a ServerHello message that satisfies this request. The main purpose of this certificate extension is to implement "must staple." If the extension is present in a TLS server's certificate and it includes status_request, then the server MUST include a stapled OCSP response if the client requests one. (The same applies for the status_request_v2 extension.) This PR adds a check to `certificate_info()` of whether the server supports must staple (i.e., whether its certificate includes a TLS Features extension with "status_request"). It also changes the output for "OCSP stapling" in the case that the server did not staple an OCSP response. It indicates that: * it is a critical issue if the certificate specifies "must staple" * it is a low severity issue if the certificate does not specify "must staple," but the certificate does include an OCSP URI. * it is not an issue at all if the certificate does not specify "must staple" and certificate does not include an OCSP URI. --- testssl.sh | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/testssl.sh b/testssl.sh index f3da16e..301e830 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5894,6 +5894,50 @@ compare_server_name_to_cert() return $ret } +must_staple() { + local json_prefix="$2" + 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 + # FIXME: This will indicate that must staple is supported if the + # certificate indicates status_request or status_request_v2. This is + # probably okay, since it seems likely that any TLS Feature extension + # that includes status_request_v2 will also include status_request. + supported=true + elif $OPENSSL x509 -in "$HOSTCERT" -noout -text 2>>$ERRFILE | grep -q "1.3.6.1.5.5.7.1.24:"; then + cert="$($OPENSSL x509 -in "$HOSTCERT" -outform DER 2>>$ERRFILE | hexdump -v -e '16/1 "%02X"')" + extn="${cert##*06082B06010505070118}" + # Check for critical bit, and skip over it if present. + [[ "${extn:0:6}" == "0101FF" ]] && extn="${extn:6}" + # Next is tag and length of extnValue OCTET STRING. Assume it is less than 128 bytes. + extn="${extn:4}" + # The TLS Feature is a SEQUENCE of INTEGER. Get the length of the SEQUENCE + extn_len=2*$(hex2dec "${extn:2:2}") + # If the extension include the status_request (5), then it supports must staple. + if [[ "${extn:4:extn_len}" =~ "020105" ]]; then + supported=true + fi + fi + + if "$supported"; then + pr_done_bestln "Supported" + fileout "${json_prefix}ocsp_must_staple" "OK" "OCSP must staple : supported" + return 0 + else + outln "No" + fileout "${json_prefix}ocsp_must_staple" "INFO" "OCSP must staple : no" + return 1 + fi +} + certificate_info() { local proto local -i certificate_number=$1 @@ -5904,7 +5948,8 @@ certificate_info() { local ocsp_response_status=$6 local sni_used=$7 local cert_sig_algo cert_sig_hash_algo cert_key_algo - local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_CN issuer_C issuer_O issuer sans san all_san="" cn + local expire days2expire secs2warn ocsp_uri ocsp_must_staple crl + local startdate enddate issuer_CN issuer_C issuer_O issuer sans san all_san="" cn local issuer_DC issuerfinding cn_nosni="" local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial local policy_oid @@ -6423,10 +6468,22 @@ certificate_info() { fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : $ocsp_uri" fi + out "$indent"; pr_bold " OCSP must staple "; + must_staple "$json_prefix" + [[ $? -eq 0 ]] && ocsp_must_staple=true || ocsp_must_staple=false + out "$indent"; pr_bold " OCSP stapling " if grep -a "OCSP response" <<<"$ocsp_response" | grep -q "no response sent" ; then - pr_svrty_low "--" - fileout "${json_prefix}ocsp_stapling" "LOW" "OCSP stapling : not offered" + if "$ocsp_must_staple"; then + pr_svrty_critical "--" + fileout "${json_prefix}ocsp_stapling" "CRITICAL" "OCSP stapling : not offered" + elif [[ -n "$ocsp_uri" ]]; then + pr_svrty_low "--" + fileout "${json_prefix}ocsp_stapling" "LOW" "OCSP stapling : not offered" + else + out "--" + fileout "${json_prefix}ocsp_stapling" "INFO" "OCSP stapling : not offered" + fi else if grep -a "OCSP Response Status" <<<"$ocsp_response_status" | grep -q successful; then pr_done_good "offered" From c284185c56572cf64e3bf6c23516ba29475a22ed Mon Sep 17 00:00:00 2001 From: Dirk Date: Sat, 18 Feb 2017 13:22:17 +0100 Subject: [PATCH 35/52] - try to address #638 --- testssl.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/testssl.sh b/testssl.sh index f3da16e..a1c0f2a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -10835,11 +10835,11 @@ run_youknowwho() { # http://blog.cryptographyengineering.com/2013/03/attack-of-week-rc4-is-kind-of-broken-in.html return 0 # in a nutshell: don't use RC4, really not! - } +} # https://www.usenix.org/conference/woot13/workshop-program/presentation/smyth # https://secure-resumption.com/tlsauth.pdf - run_tls_truncation() { +run_tls_truncation() { #FIXME: difficult to test, is there any test available: pls let me know : } @@ -10857,7 +10857,11 @@ old_fart() { get_install_dir() { [[ -z "$TESTSSL_INSTALL_DIR" ]] && TESTSSL_INSTALL_DIR="$(dirname ${BASH_SOURCE[0]})" - [[ -r "$RUN_DIR/etc/cipher-mapping.txt" ]] && CIPHERS_BY_STRENGTH_FILE="$RUN_DIR/etc/cipher-mapping.txt" + if [[ -r "$RUN_DIR/etc/cipher-mapping.txt" ]]; then + 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" @@ -10865,7 +10869,7 @@ get_install_dir() { fi # we haven't found the cipher file yet... - if [[ ! -r "$mapping_file_rfc" ]] && which readlink &>/dev/null ; then + if [[ ! -r "$CIPHERS_BY_STRENGTH_FILE" ]] && which readlink &>/dev/null ; then readlink -f ls &>/dev/null && \ TESTSSL_INSTALL_DIR=$(readlink -f $(basename ${BASH_SOURCE[0]})) || \ TESTSSL_INSTALL_DIR=$(readlink $(basename ${BASH_SOURCE[0]})) @@ -10892,7 +10896,7 @@ get_install_dir() { [[ -r "$TESTSSL_INSTALL_DIR/cipher-mapping.txt" ]] && CIPHERS_BY_STRENGTH_FILE="$TESTSSL_INSTALL_DIR/cipher-mapping.txt" fi - if [[ ! -r "$CIPHERS_BY_STRENGTH_FILE" ]] ; then + if [[ ! -r "$CIPHERS_BY_STRENGTH_FILE" ]]; then unset ADD_RFC_STR unset SHOW_RFC debugme echo "$CIPHERS_BY_STRENGTH_FILE" @@ -11236,6 +11240,7 @@ PATH: $PATH PROG_NAME: $PROG_NAME TESTSSL_INSTALL_DIR: $TESTSSL_INSTALL_DIR RUN_DIR: $RUN_DIR +CIPHERS_BY_STRENGTH_FILE: $CIPHERS_BY_STRENGTH_FILE CAPATH: $CAPATH COLOR: $COLOR From bfbaba4ea79813d4353d215afbb50a705b8a5d1d Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 20 Feb 2017 09:44:52 +0100 Subject: [PATCH 36/52] - trying to address #640 . Better a bit pessimistic here... --- testssl.sh | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/testssl.sh b/testssl.sh index a1c0f2a..b67fba0 100755 --- a/testssl.sh +++ b/testssl.sh @@ -9350,9 +9350,6 @@ run_ccs_injection(){ if [[ $DEBUG -ge 3 ]]; then outln "\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 out "sending payload #2 with TLS version $tls_hexcode: " fi @@ -9372,29 +9369,38 @@ run_ccs_injection(){ outln fi -# not ok: 15 | 0301 | 02 | 02 | 15 -# ALERT | TLS 1.0 | Length=2 | Decryption failed (21) +# in general, see https://en.wikipedia.org/wiki/Transport_Layer_Security#Alert_protocol +# https://tools.ietf.org/html/rfc5246#section-7.2 # -# ok: 0a or nothing: ==> RST - +# not ok fo CCSI: 15 | 0301 | 00 02 | 02 15 +# ALERT | TLS 1.0 | Length=2 | Decryption failed (21) +# +# ok: nothing: ==> RST +# +# 0A: Unexpected message +# 28: Handshake failure if [[ -z "${tls_hello_ascii:0:12}" ]]; then # empty reply pr_done_best "not vulnerable (OK)" if [[ $retval -eq 3 ]]; then -### what? fileout "ccs" "OK" "CCS: not vulnerable (timed out)" "$cve" "$cwe" else fileout "ccs" "OK" "CCS: not vulnerable" "$cve" "$cwe" fi ret=0 elif [[ "$byte6" == "15" ]] && [[ "${tls_hello_ascii:0:4}" == "1503" ]]; then + # decyption failed received pr_svrty_critical "VULNERABLE (NOT ok)" - if [[ $retval -eq 3 ]]; then - fileout "ccs" "CRITICAL" "CCS: VULNERABLE (timed out)" "$cve" "$cwe" "$hint" - else - fileout "ccs" "CRITICAL" "CCS: VULNERABLE" "$cve" "$cwe" "$hint" - fi + fileout "ccs" "CRITICAL" "CCS: VULNERABLE" "$cve" "$cwe" "$hint" ret=1 + elif [[ "${tls_hello_ascii:0:4}" == "1503" ]]; then + if [[ "$byte6" == "0A" ]] || [[ "$byte6" == "28" ]]; then + # Unexpected message / Handshake failure received + pr_warning "likely " + out "not vulnerable (OK)" + out " - alert description type: $byte6" + fileout "ccs" "WARN" "CCS: probably not vulnerable but received 0x${byte6} instead of 0x15" "$cve" "$cwe" "$hint" + fi elif [[ "$byte6" == [0-9a-f][0-9a-f] ]] && [[ "${tls_hello_ascii:2:2}" != "03" ]]; then pr_warning "test failed" out ", probably read buffer too small (${tls_hello_ascii:0:14})" @@ -9402,8 +9408,8 @@ run_ccs_injection(){ ret=7 else pr_warning "test failed " - out "around line $LINENO (debug info: ${tls_hello_ascii:0:14})" - fileout "ccs" "WARN" "CCS: test failed, around line $LINENO, debug info (${tls_hello_ascii:0:14})" "$cve" "$cwe" "$hint" + out "around line $LINENO (debug info: ${tls_hello_ascii:0:12},$byte6)" + fileout "ccs" "WARN" "CCS: test failed, around line $LINENO, debug info (${tls_hello_ascii:0:12},$byte6)" "$cve" "$cwe" "$hint" ret=7 fi outln From 0ce7a3b7d2e2f82a69e8fbb5d36c3795132aca6c Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 21 Feb 2017 08:50:09 +0100 Subject: [PATCH 37/52] see diff ;-) --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 7403f12..51904dc 100644 --- a/Readme.md +++ b/Readme.md @@ -60,6 +60,7 @@ Update notification here or @ [twitter](https://twitter.com/drwetter). * LOGJAM: now checking also for known DH parameters * Check for CAA RR * better formatting of output +* choice showing the RFC naming scheme only #### Features planned in 2.9dev From be079acb5eb85617868880057e00250e51e90d1a Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 21 Feb 2017 11:16:14 +0100 Subject: [PATCH 38/52] - collect more TLS extensions --- testssl.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/testssl.sh b/testssl.sh index 8a984d6..bfcb5dc 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5716,7 +5716,7 @@ get_server_certificate() { local savedir local nrsaved - "$HAS_SPDY" && [[ -z $STARTTLS ]] && npn_params="-nextprotoneg \"$NPN_PROTOs\"" + "$HAS_SPDY" && [[ -z "$STARTTLS" ]] && npn_params="-nextprotoneg \"$NPN_PROTOs\"" if [[ -n "$2" ]]; then protocols_to_try="$2" @@ -5758,11 +5758,21 @@ get_server_certificate() { return $success fi + # this all needs to be moved into determine_tls_extensions() + >$TEMPDIR/tlsext.txt + # first shot w/o any protocol, then in turn we collect all extensions + $OPENSSL s_client $STARTTLS $BUGS $1 -showcerts -connect $NODEIP:$PORT $PROXY $addcmd -tlsextdebug -status $ERRFILE >$TMPFILE + sclient_connect_successful $? $TMPFILE && grep -a 'TLS server extension' $TMPFILE >$TEMPDIR/tlsext.txt for proto in $protocols_to_try; do + # we could know here which protcols are supported addcmd="" [[ ! "$proto" =~ ssl ]] && addcmd="$SNI" $OPENSSL s_client $STARTTLS $BUGS $1 -showcerts -connect $NODEIP:$PORT $PROXY $addcmd -$proto -tlsextdebug $npn_params -status $ERRFILE >$TMPFILE - sclient_connect_successful $? $TMPFILE && success=0 && break + if sclient_connect_successful $? $TMPFILE; then + success=0 + grep -a 'TLS server extension' $TMPFILE >>$TEMPDIR/tlsext.txt + break # now we have the certificate + fi done # this loop is needed for IIS6 and others which have a handshake size limitations if [[ $success -eq 7 ]]; then # "-status" above doesn't work for GOST only servers, so we do another test without it and see whether that works then: @@ -5774,6 +5784,7 @@ get_server_certificate() { tmpfile_handle $FUNCNAME.txt return 7 # this is ugly, I know else + grep -a 'TLS server extension' $TMPFILE >>$TEMPDIR/tlsext.txt GOST_STATUS_PROBLEM=true fi fi @@ -5782,7 +5793,7 @@ get_server_certificate() { # this is not beautiful (grep+sed) # but maybe we should just get the ids and do a private matching, according to # https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml - tls_extensions=$(grep -a 'TLS server extension ' $TMPFILE | \ + tls_extensions=$(grep -a 'TLS server extension ' $TEMPDIR/tlsext.txt | \ sed -e 's/TLS server extension //g' -e 's/\" (id=/\/#/g' \ -e 's/,.*$/,/g' -e 's/),$/\"/g' \ -e 's/elliptic curves\/#10/supported_groups\/#10/g') @@ -6589,8 +6600,6 @@ certificate_info() { # FIXME: Trust (only CN) - - run_server_defaults() { local ciph match_found newhostcert sni local sessticket_str="" From 62db2ae6bfd99b901ecae6e5c09defde760005b2 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 21 Feb 2017 13:36:23 -0500 Subject: [PATCH 39/52] Wrap long lines in display_rdns_etc() Some sites have a long list of IP addresses and some IP addresses have a long list of DNS names that map to them. This PR changes `display_rdns_etc()` to use `out_row_aligned_max_width()` to print the other IP addresses in `$IP46ADDRs` and to print `$rDNS`. --- testssl.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index bfcb5dc..7365621 100755 --- a/testssl.sh +++ b/testssl.sh @@ -12176,7 +12176,7 @@ determine_service() { display_rdns_etc() { - local ip + local ip further_ip_addrs="" local nodeip="$(tr -d '[]' <<< $NODEIP)" # for displaying IPv6 addresses we don't need [] @@ -12185,14 +12185,15 @@ display_rdns_etc() { outln "$PROXYIP:$PROXYPORT " fi if [[ $(count_words "$IP46ADDRs") -gt 1 ]]; then - out " further IP addresses: $CORRECT_SPACES" + out " further IP addresses: $CORRECT_SPACES" for ip in $IP46ADDRs; do if [[ "$ip" == "$NODEIP" ]] || [[ "[$ip]" == "$NODEIP" ]]; then continue else - out " $ip" + further_ip_addrs+="$ip " fi done + out_row_aligned_max_width "$further_ip_addrs" " " $TERM_WIDTH out outln fi if "$LOCAL_A"; then @@ -12201,7 +12202,8 @@ display_rdns_etc() { outln " A record via $CORRECT_SPACES supplied IP \"$CMDLINE_IP\"" fi if [[ -n "$rDNS" ]]; then - printf " %-23s %s" "rDNS ($nodeip):" "$rDNS" + printf " %-23s %s" "rDNS ($nodeip):" + out_row_aligned_max_width "$rDNS" " " $TERM_WIDTH out fi } From c3d59b655f93fbfe1671269c360b1da973e4405e Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 21 Feb 2017 13:46:59 -0500 Subject: [PATCH 40/52] Add $CORRECT_SPACES to indentation --- testssl.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testssl.sh b/testssl.sh index 7365621..2784844 100755 --- a/testssl.sh +++ b/testssl.sh @@ -12193,7 +12193,7 @@ display_rdns_etc() { further_ip_addrs+="$ip " fi done - out_row_aligned_max_width "$further_ip_addrs" " " $TERM_WIDTH out + out_row_aligned_max_width "$further_ip_addrs" " $CORRECT_SPACES" $TERM_WIDTH out outln fi if "$LOCAL_A"; then @@ -12203,7 +12203,7 @@ display_rdns_etc() { fi if [[ -n "$rDNS" ]]; then printf " %-23s %s" "rDNS ($nodeip):" - out_row_aligned_max_width "$rDNS" " " $TERM_WIDTH out + out_row_aligned_max_width "$rDNS" " $CORRECT_SPACES" $TERM_WIDTH out fi } From 5aaf78cff650bc2f2ac48bfa75bcc6d003baf650 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 21 Feb 2017 15:22:47 -0500 Subject: [PATCH 41/52] Fix issue #643 It seems that the head command on OS X does not accept a negative number as a value for the "-n" parameter. This PR provides an alternative method for removing the "generator: " line without using "head." --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index bfcb5dc..b57664d 100755 --- a/testssl.sh +++ b/testssl.sh @@ -10218,7 +10218,7 @@ run_logjam() { # now the final test for common primes if [[ -n "$key_bitstring" ]]; then - dh_p="$($OPENSSL pkey -pubin -text -noout <<< "$key_bitstring" | awk '/prime:/,/generator:/' | tail -n +2 | head -n -1)" + dh_p="$($OPENSSL pkey -pubin -text -noout <<< "$key_bitstring" | awk '/prime:/,/generator:/' | tail -n +2 | sed -e 's/generator: .*//')" 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}))" From 191d19be323b573c35d2451fd9673b42b0c1e792 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 21 Feb 2017 15:47:59 -0500 Subject: [PATCH 42/52] Use egrep -v to remove unwanted lines --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index b57664d..f7ba8df 100755 --- a/testssl.sh +++ b/testssl.sh @@ -10218,7 +10218,7 @@ run_logjam() { # now the final test for common primes if [[ -n "$key_bitstring" ]]; then - dh_p="$($OPENSSL pkey -pubin -text -noout <<< "$key_bitstring" | awk '/prime:/,/generator:/' | tail -n +2 | sed -e 's/generator: .*//')" + dh_p="$($OPENSSL pkey -pubin -text -noout <<< "$key_bitstring" | awk '/prime:/,/generator:/' | egrep -v "prime|generator")" 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}))" From 6a1c519acd306bf59061eb50b65d687207dc00a6 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 23 Feb 2017 09:31:41 -0500 Subject: [PATCH 43/52] Add option to print only the RFC cipher names This PR attempts to address #631. It allows four choices for the `--mapping` option. "openssl" (default), "rfc", "no-openssl", and "no-rfc". * "openssl" is the current default * "no-rfc" shows only the OpenSSL names (just as it currently does) * "rfc" shows the RFC name rather than the OpenSSL name for things that are not in wide now (just as it currently does). But now, in wide mode, it shows the RFC name first (further to the left) and the OpenSSL name second. * "rfc-only" shows only the RFC name. If the `--mapping` option is not provided, this is the same as "openssl". If the "cipher-mapping.txt" file cannot be found, then testssl.sh runs as if "no-rfc" had been requested. --- testssl.sh | 85 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/testssl.sh b/testssl.sh index 0faaa3b..f9e2b9a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -227,8 +227,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="" @@ -2272,8 +2271,21 @@ show_rfc_style(){ } 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" + if [[ "$DISPLAY_CIPHERNAMES" =~ "rfc" ]]; then + printf -- "Hexcode Cipher Suite Name (RFC) KeyExch. Encryption Bits" + [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && printf -- " Cipher Suite Name (OpenSSL)" + outln + printf -- "%s------------------------------------------------------------------------------------------" + [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && printf -- "---------------------------------------" + outln + else + printf -- "Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits" + [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && printf -- " Cipher Suite Name (RFC)" + outln + printf -- "%s--------------------------------------------------------------------------" + [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && printf -- "---------------------------------------------------" + outln + fi } @@ -2300,10 +2312,16 @@ neat_list(){ echo "$export" | grep -iq 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 [[ "$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")" + 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 pr_deemphasize "$line" return 0 fi @@ -2320,7 +2338,13 @@ neat_list(){ done 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" + if [[ "$DISPLAY_CIPHERNAMES" =~ "rfc" ]]; then + printf -- " %-7s %-49s %-10s %-12s%-8s" "$hexcode" "$tls_cipher" "$kx" "$enc" "$strength" + [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && printf -- " %-33s${SHOW_EACH_C:+ %-0s}" "$ossl_cipher" + else + printf -- " %-7s %-33s %-10s %-12s%-8s" "$hexcode" "$ossl_cipher" "$kx" "$enc" "$strength" + [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && printf -- " %-49s${SHOW_EACH_C:+ %-0s}" "$tls_cipher" + fi } test_just_one(){ @@ -4178,10 +4202,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 @@ -4944,7 +4968,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")" @@ -5003,7 +5027,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]}" @@ -5028,7 +5052,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 @@ -5045,7 +5069,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 @@ -5069,7 +5093,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 @@ -5084,7 +5108,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 printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both else printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}" # print out both @@ -5094,7 +5118,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 printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both else printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}" # print out both @@ -5355,14 +5379,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")" @@ -5404,7 +5428,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")" @@ -6946,7 +6970,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]}" @@ -10535,7 +10559,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]} " @@ -10566,7 +10590,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]}" @@ -10943,7 +10967,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]} " @@ -11038,8 +11062,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" pr_warningln "\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." @@ -11295,7 +11318,9 @@ 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; + --mapping rfc: use the RFC Cipher suite name as the primary name cipher suite name form; + no-openssl: don't display the OpenSSL Cipher Suite Name; no-rfc: don't display the RFC Cipher Suite Name) --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 @@ -12737,9 +12762,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" ;; - *) pr_magentaln "\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" ;; + *) pr_magentaln "\nmapping can only be \"no-openssl\", \"no-rfc\", \"openssl\", or \"rfc\"" help 1 ;; esac ;; From b4f59e91be5dcaf7fe6c3d80abcdc8752172975a Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 23 Feb 2017 17:19:52 +0100 Subject: [PATCH 44/52] FIX #621 --- testssl.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testssl.sh b/testssl.sh index 0faaa3b..e2ea254 100755 --- a/testssl.sh +++ b/testssl.sh @@ -9114,6 +9114,8 @@ socksend_tls_clienthello() { # "ephemeralkey" - extract the server's ephemeral key (if any) # arg4: (optional) additional request extensions # arg5: (optional) "true" if ClientHello should advertise compression methods other than "NULL" +# return: 0: successful connect | 1: protocol or cipher not available | 2: as (0) but downgraded +# 6: couldn't open socket | 7: couldn't open temp file tls_sockets() { local -i ret=0 local -i save=0 @@ -9850,6 +9852,7 @@ run_sweet32() { if "$using_sockets"; then tls_sockets "03" "${sweet32_ciphers_hex}" sclient_success=$? + [[ "$sclient_success" -eq 2 ]] && sclient_success=0 else nr_sweet32_ciphers=$(count_ciphers $sweet32_ciphers) nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $sweet32_ciphers)) @@ -10687,6 +10690,7 @@ run_lucky13() { if "$using_sockets"; then tls_sockets "03" "${cbc_ciphers_hex}" sclient_success=$? + [[ "$sclient_success" -eq 2 ]] && sclient_success=0 else nr_cbc_ciphers=$(count_ciphers $cbc_ciphers) nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $cbc_ciphers)) From 4361bb7cce2c43e3a8b3605a9e09730579f102db Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Fri, 24 Feb 2017 16:22:59 +0100 Subject: [PATCH 45/52] housekeeping/ cleanup --- testssl.sh | 154 +++++++++++++++++++++++++---------------------------- 1 file changed, 74 insertions(+), 80 deletions(-) diff --git a/testssl.sh b/testssl.sh index e2ea254..2d3f456 100755 --- a/testssl.sh +++ b/testssl.sh @@ -242,7 +242,6 @@ PROXY="" PROXYIP="" PROXYPORT="" VULN_COUNT=0 -IPS="" SERVICE="" # is the server running an HTTP server, SMTP, POP or IMAP? URI="" CERT_FINGERPRINT_SHA2="" @@ -267,10 +266,6 @@ END_TIME=0 TLS_LOW_BYTE="" HEX_CIPHER="" - # The various hexdump commands we need to replace xxd (BSD compatibility) -HEXDUMP=(hexdump -ve '16/1 "%02x " " \n"') # This is used to analyze the reply -HEXDUMPPLAIN=(hexdump -ve '1/1 "%.2x"') # Replaces both xxd -p and tr -cd '[:print:]' - SERVER_COUNTER=0 # Counter for multiple servers #################### SEVERITY #################### @@ -983,7 +978,7 @@ out_row_aligned_max_width() { local spaces="$2" local -i max_width="$3" local print_function="$4" - local -i i len cut_point + local -i i len local cr=$'\n' local line entry first=true last=false @@ -1779,35 +1774,35 @@ 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" +# 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" } run_server_banner() { @@ -1910,7 +1905,7 @@ run_application_banner() { run_cookie_flags() { # ARG1: Path local -i nr_cookies - local nr_httponly nr_secure + local -i nr_httponly nr_secure local negative_word local msg302="" msg302_="" @@ -1945,7 +1940,7 @@ run_cookie_flags() { # ARG1: Path [123456789]) pr_done_good "$nr_secure/$nr_cookies";; esac out " secure, " - if [[ $nr_cookies == $nr_secure ]]; then + if [[ $nr_cookies -eq $nr_secure ]]; then fileout "cookie_secure" "OK" "All $nr_cookies cookie(s) issued at \"$1\" marked as secure" else fileout "cookie_secure" "WARN" "$nr_secure/$nr_cookies cookie(s) issued at \"$1\" marked as secure" @@ -1956,7 +1951,7 @@ run_cookie_flags() { # ARG1: Path [123456789]) pr_done_good "$nr_httponly/$nr_cookies";; esac out " HttpOnly" - if [[ $nr_cookies == $nr_httponly ]]; then + if [[ $nr_cookies -eq $nr_httponly ]]; then fileout "cookie_httponly" "OK" "All $nr_cookies cookie(s) issued at \"$1\" marked as HttpOnly$msg302_" else fileout "cookie_httponly" "WARN" "$nr_secure/$nr_cookies cookie(s) issued at \"$1\" marked as HttpOnly$msg302_" @@ -1976,8 +1971,7 @@ run_cookie_flags() { # ARG1: Path run_more_flags() { local good_flags2test="X-Frame-Options X-XSS-Protection X-Content-Type-Options Content-Security-Policy X-Content-Security-Policy X-WebKit-CSP Content-Security-Policy-Report-Only" local other_flags2test="Access-Control-Allow-Origin Upgrade X-Served-By X-UA-Compatible" - local egrep_pattern="" - local f2t result_str + local f2t local first=true local spaces=" " @@ -2430,7 +2424,7 @@ test_just_one(){ supported_sslv2_ciphers="$(grep "Supported cipher: " "$TEMPDIR/$NODEIP.parse_sslv2_serverhello.txt")" "$SHOW_SIGALGO" && s="$($OPENSSL x509 -noout -text -in "$HOSTCERT" | awk -F':' '/Signature Algorithm/ { print $2 }' | head -1)" for (( i=0 ; i&5 2>/dev/null & sleep $USLEEP_SND @@ -4826,7 +4820,7 @@ run_server_preference() { # now reversed offline via tac, see https://github.com/thomassa/testssl.sh/commit/7a4106e839b8c3033259d66697893765fc468393 : local list_reverse="AES256-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES256-SHA:AES128-SHA256:AES128-SHA:RC4-SHA:DES-CBC-SHA:RC4-MD5:DES-CBC3-SHA" local has_cipher_order=true - local isok addcmd="" addcmd2="" sni="" + local addcmd="" addcmd2="" sni="" local using_sockets=true "$SSL_NATIVE" && using_sockets=false @@ -5263,8 +5257,8 @@ cipher_pref_check() { [[ "${hexc:2:2}" == "13" ]] && nr_nonossl_ciphers+=1 elif [[ "$p" == "tls1_2" ]]; then [[ "${hexc:2:2}" != "13" ]] && nr_nonossl_ciphers+=1 - elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ "SHA256" ]] && \ - [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ "SHA384" ]] && \ + elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA256 ]] && \ + [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA384 ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *"_CCM" ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *"_CCM_8" ]]; then nr_nonossl_ciphers+=1 @@ -5335,8 +5329,8 @@ cipher_pref_check() { [[ "${hexc:2:2}" == "13" ]] && nr_ciphers+=1 elif [[ "$p" == "tls1_2" ]]; then [[ "${hexc:2:2}" != "13" ]] && nr_ciphers+=1 - elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ "SHA256" ]] && \ - [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ "SHA384" ]] && \ + elif [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA256 ]] && \ + [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA384 ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *"_CCM" ]] && \ [[ "${TLS_CIPHER_RFC_NAME[i]}" != *"_CCM_8" ]]; then nr_ciphers+=1 @@ -5650,7 +5644,7 @@ determine_tls_extensions() { alpn_extn_len_hex=$(printf "%04x" $alpn_extn_len) tls_extensions+=", 00,10,${alpn_extn_len_hex:0:2},${alpn_extn_len_hex:2:2},${alpn_list_len_hex:0:2},${alpn_list_len_hex:2:2}$alpn" fi - if [[ ! "$TLS_EXTENSIONS" =~ "encrypt-then-mac" ]]; then + if [[ ! "$TLS_EXTENSIONS" =~ encrypt-then-mac ]]; then tls_sockets "03" "$cbc_cipher_list_hex, 00,ff" "all" "$tls_extensions" success=$? fi @@ -5676,7 +5670,7 @@ determine_tls_extensions() { elif [[ ! "$OPTIMAL_PROTO" =~ ssl ]]; then addcmd="$SNI" fi - if [[ ! "$TLS_EXTENSIONS" =~ "encrypt-then-mac" ]]; then + if [[ ! "$TLS_EXTENSIONS" =~ encrypt-then-mac ]]; then $OPENSSL s_client $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $addcmd $OPTIMAL_PROTO -tlsextdebug $params -cipher $cbc_cipher_list $ERRFILE >$TMPFILE sclient_connect_successful $? $TMPFILE success=$? @@ -6002,7 +5996,7 @@ must_staple() { # The TLS Feature is a SEQUENCE of INTEGER. Get the length of the SEQUENCE extn_len=2*$(hex2dec "${extn:2:2}") # If the extension include the status_request (5), then it supports must staple. - if [[ "${extn:4:extn_len}" =~ "020105" ]]; then + if [[ "${extn:4:extn_len}" =~ 020105 ]]; then supported=true fi fi @@ -6824,8 +6818,8 @@ run_pfs() { for (( i=0; i < TLS_NR_CIPHERS; i++ )); do pfs_cipher="${TLS_CIPHER_RFC_NAME[i]}" if ( [[ "$pfs_cipher" == "TLS_DHE_"* ]] || [[ "$pfs_cipher" == "TLS_ECDHE_"* ]] ) && \ - [[ ! "$pfs_cipher" =~ "NULL" ]] && [[ ! "$pfs_cipher" =~ "DES" ]] && [[ ! "$pfs_cipher" =~ "RC4" ]] && \ - [[ ! "$pfs_cipher" =~ "PSK" ]] && ( "$using_sockets" || "${TLS_CIPHER_OSSL_SUPPORTED[i]}" ); then + [[ ! "$pfs_cipher" =~ NULL ]] && [[ ! "$pfs_cipher" =~ DES ]] && [[ ! "$pfs_cipher" =~ RC4 ]] && \ + [[ ! "$pfs_cipher" =~ PSK ]] && ( "$using_sockets" || "${TLS_CIPHER_OSSL_SUPPORTED[i]}" ); then hexc="${TLS_CIPHER_HEXCODE[i]}" pfs_hex_cipher_list+=", ${hexc:2:2},${hexc:7:2}" ciph[nr_supported_ciphers]="${TLS_CIPHER_OSSL_NAME[i]}" @@ -7086,7 +7080,7 @@ run_pfs() { [[ $sclient_success -ne 0 ]] && [[ $sclient_success -ne 2 ]] && break temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") curve_found="$(awk -F', ' '{ print $2 }' <<< $temp)" - [[ ! "$curve_found" =~ "ffdhe" ]] && break + [[ ! "$curve_found" =~ ffdhe ]] && break for (( i=0; i < nr_curves; i++ )); do ! "${supported_curve[i]}" && [[ "${ffdhe_groups_output[i]}" == "$curve_found" ]] && break done @@ -7520,7 +7514,7 @@ close_socket(){ # first: helper function for protocol checks code2network() { # arg1: formatted string here in the code - NW_STR=$(echo "$1" | sed -e 's/,/\\\x/g' | sed -e 's/# .*$//g' -e 's/ //g' -e '/^$/d' | tr -d '\n' | tr -d '\t') + NW_STR=$(sed -e 's/,/\\\x/g' <<< "$1" | sed -e 's/# .*$//g' -e 's/ //g' -e '/^$/d' | tr -d '\n' | tr -d '\t') #TODO: just echo, no additional global var } @@ -8634,7 +8628,7 @@ parse_tls_serverhello() { # Now parse the server key exchange message if [[ $tls_serverkeyexchange_ascii_len -ne 0 ]]; then - if [[ $rfc_cipher_suite =~ "TLS_ECDHE_" ]] || [[ $rfc_cipher_suite =~ "TLS_ECDH_anon" ]] || \ + if [[ $rfc_cipher_suite =~ TLS_ECDHE_ ]] || [[ $rfc_cipher_suite =~ TLS_ECDH_anon ]] || \ [[ $rfc_cipher_suite == ECDHE* ]] || [[ $rfc_cipher_suite == AECDH* ]]; then if [[ $tls_serverkeyexchange_ascii_len -lt 6 ]]; then debugme echo "Malformed ServerKeyExchange Handshake message in ServerHello." @@ -8686,7 +8680,7 @@ parse_tls_serverhello() { debugme echo "dh_bits: $named_curve_str, $dh_bits bits" echo "Server Temp Key: $named_curve_str, $dh_bits bits" >> $TMPFILE fi - elif [[ $rfc_cipher_suite =~ "TLS_DHE_" ]] || [[ $rfc_cipher_suite =~ "TLS_DH_anon" ]] || \ + elif [[ $rfc_cipher_suite =~ TLS_DHE_ ]] || [[ $rfc_cipher_suite =~ TLS_DH_anon ]] || \ [[ $rfc_cipher_suite == "DHE-"* ]] || [[ $rfc_cipher_suite == "EDH-"* ]] || \ [[ $rfc_cipher_suite == "EXP1024-DHE-"* ]]; then # For DH ephemeral keys the first field is p, and the length of @@ -8736,7 +8730,7 @@ parse_tls_serverhello() { *) named_curve=0; named_curve_str="" ;; esac [[ -z "$key_bitstring" ]] && named_curve=0 && named_curve_str="" - if [[ $named_curve -ne 0 ]] && [[ "${TLS13_KEY_SHARES[named_curve]}" =~ "BEGIN" ]]; then + if [[ $named_curve -ne 0 ]] && [[ "${TLS13_KEY_SHARES[named_curve]}" =~ BEGIN ]]; then ephemeral_param="$($OPENSSL pkey -pubin -text -noout <<< "$key_bitstring" | grep -A 1000 "prime:")" rfc7919_param="$($OPENSSL pkey -text -noout <<< "${TLS13_KEY_SHARES[named_curve]}" | grep -A 1000 "prime:")" [[ "$ephemeral_param" != "$rfc7919_param" ]] && named_curve_str="" @@ -8783,7 +8777,8 @@ sslv2_sockets() { code2network "$cipher_suites" # convert CIPHER_SUITES cipher_suites="$NW_STR" # we don't have the leading \x here so string length is two byte less, see next - len_ciph_suites_byte=$(echo ${#cipher_suites}) + len_ciph_suites_byte=${#cipher_suites} + let "len_ciph_suites_byte += 2" len_ciph_suites=$(printf "%02x\n" $(($len_ciph_suites_byte / 4 ))) len_client_hello=$(printf "%02x\n" $((0x$len_ciph_suites + 0x19))) @@ -8864,8 +8859,7 @@ socksend_tls_clienthello() { code2network "$(tolower "$2")" # convert CIPHER_SUITES cipher_suites="$NW_STR" # we don't have the leading \x here so string length is two byte less, see next - - len_ciph_suites_byte=$(echo ${#cipher_suites}) + len_ciph_suites_byte=${#cipher_suites} let "len_ciph_suites_byte += 2" # we have additional 2 chars \x in each 2 byte string and 2 byte ciphers, so we need to divide by 4: @@ -9099,7 +9093,7 @@ socksend_tls_clienthello() { fd_socket 5 || return 6 code2network "$TLS_CLIENT_HELLO$all_extensions" - data=$(echo $NW_STR) + data="$NW_STR" [[ "$DEBUG" -ge 4 ]] && echo "\"$data\"" printf -- "$data" >&5 2>/dev/null & sleep $USLEEP_SND @@ -10433,7 +10427,7 @@ run_beast(){ for (( i=0; i < TLS_NR_CIPHERS; i++ )); do hexc="${TLS_CIPHER_HEXCODE[i]}" if [[ ${#hexc} -eq 9 ]] && [[ "${TLS_CIPHER_RFC_NAME[i]}" =~ CBC ]] && \ - [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ "SHA256" ]] && [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ "SHA384" ]]; then + [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA256 ]] && [[ ! "${TLS_CIPHER_RFC_NAME[i]}" =~ SHA384 ]]; then cbc_cipher_list_hex+=", ${hexc:2:2},${hexc:7:2}" ciph[nr_ciphers]="${TLS_CIPHER_OSSL_NAME[i]}" hexcode[nr_ciphers]="${hexc:2:2},${hexc:7:2}" @@ -10756,7 +10750,7 @@ run_rc4() { # get a list of all the cipher suites to test if "$using_sockets" || [[ $OSSL_VER_MAJOR -lt 1 ]]; then for (( i=0; i < TLS_NR_CIPHERS; i++ )); do - if [[ "${TLS_CIPHER_RFC_NAME[i]}" =~ "RC4" ]] && ( "$using_sockets" || "${TLS_CIPHER_OSSL_SUPPORTED[i]}" ); then + if [[ "${TLS_CIPHER_RFC_NAME[i]}" =~ RC4 ]] && ( "$using_sockets" || "${TLS_CIPHER_OSSL_SUPPORTED[i]}" ); then hexc="$(tolower "${TLS_CIPHER_HEXCODE[i]}")" ciph[nr_ciphers]="${TLS_CIPHER_OSSL_NAME[i]}" rfc_ciph[nr_ciphers]="${TLS_CIPHER_RFC_NAME[i]}" @@ -10789,7 +10783,7 @@ run_rc4() { done else while read hexc n ciph[nr_ciphers] sslvers[nr_ciphers] kx[nr_ciphers] auth enc[nr_ciphers] mac export2[nr_ciphers]; do - if [[ "${ciph[nr_ciphers]}" =~ "RC4" ]]; then + if [[ "${ciph[nr_ciphers]}" =~ RC4 ]]; then ciphers_found[nr_ciphers]=false if [[ ${#hexc} -eq 9 ]]; then if [[ "${hexc:2:2}" == "00" ]]; then @@ -11106,12 +11100,12 @@ find_openssl_binary() { # http://www.openssl.org/news/openssl-notes.html OSSL_VER=$($OPENSSL version 2>/dev/null | awk -F' ' '{ print $2 }') - OSSL_VER_MAJOR=$(echo "$OSSL_VER" | sed 's/\..*$//') - OSSL_VER_MINOR=$(echo "$OSSL_VER" | sed -e 's/^.\.//' | tr -d '[a-zA-Z]-') - OSSL_VER_APPENDIX=$(echo "$OSSL_VER" | tr -d '0-9.') + OSSL_VER_MAJOR=$(sed 's/\..*$//' <<< "$OSSL_VER") + OSSL_VER_MINOR=$(sed -e 's/^.\.//' <<< "$OSSL_VER" | tr -d '[a-zA-Z]-') + OSSL_VER_APPENDIX=$(tr -d '0-9.' "$OSSL_VER") OSSL_VER_PLATFORM=$($OPENSSL version -p 2>/dev/null | sed 's/^platform: //') OSSL_BUILD_DATE=$($OPENSSL version -a 2>/dev/null | grep '^built' | sed -e 's/built on//' -e 's/: ... //' -e 's/: //' -e 's/ UTC//' -e 's/ +0000//' -e 's/.000000000//') - echo $OSSL_BUILD_DATE | grep -q "not available" && OSSL_BUILD_DATE="" + grep -q "not available" <<< "$OSSL_BUILD_DATE" && OSSL_BUILD_DATE="" # see #190, reverting logic: unless otherwise proved openssl has no dh bits case "$OSSL_VER_MAJOR.$OSSL_VER_MINOR" in @@ -11573,7 +11567,7 @@ ignore_no_or_lame() { pr_warning "$1 --> " read a if [[ "$a" == "$(tolower "$2")" ]]; then - $ok_arg return 0 + return 0 else return 1 fi @@ -11882,13 +11876,13 @@ get_mx_record() { check_resolver_bins # we need tha last two columns here! if which host &> /dev/null; then - mxs=$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }') + mxs="$(host -t MX "$1" 2>/dev/null | awk '/is handled by/ { print $(NF-1), $NF }')" elif which dig &> /dev/null; then - mxs=$(dig +short -t MX "$1" 2>/dev/null | awk '/^[0-9]/') + mxs="$(dig +short -t MX "$1" 2>/dev/null | awk '/^[0-9]/')" elif which drill &> /dev/null; then - mxs=$(drill mx $1 | | awk '/IN[ \t]MX[ \t]+/ { print $(NF-1), $NF }') + mxs="$(drill mx $1 | awk '/IN[ \t]MX[ \t]+/ { print $(NF-1), $NF }')" elif which nslookup &> /dev/null; then - mxs=$(nslookup -type=MX "$1" 2>/dev/null | awk '/mail exchanger/ { print $(NF-1), $NF }') + mxs="$(nslookup -type=MX "$1" 2>/dev/null | awk '/mail exchanger/ { print $(NF-1), $NF }')" else fatal "No dig, host, drill or nslookup" -3 fi From e7e9a3ed6621aaf2bc4082f0ed9c31e743ff33a4 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Fri, 24 Feb 2017 16:26:22 +0100 Subject: [PATCH 46/52] addressing #645 before #554 has been addressed --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index 2d3f456..d1adc1e 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4589,7 +4589,7 @@ run_std_cipherlists() { std_cipherlists 'aNULL' " Anonymous NULL Ciphers " 1 "aNULL" "$anon_ciphers" "$sslv2_anon_ciphers" std_cipherlists 'ADH' " Anonymous DH Ciphers " 1 "ADH" "$adh_ciphers" "$sslv2_adh_ciphers" std_cipherlists 'EXPORT40' " 40 Bit encryption " 1 "EXPORT40" "$exp40_ciphers" "$sslv2_exp40_ciphers" - std_cipherlists 'EXPORT56' " 56 Bit encryption " 1 "EXPORT56" "$exp56_ciphers" "$sslv2_exp56_ciphers" + std_cipherlists 'EXPORT56' " 56 Bit export ciphers " 1 "EXPORT56" "$exp56_ciphers" "$sslv2_exp56_ciphers" std_cipherlists 'EXPORT' " Export Ciphers (general) " 1 "EXPORT" "$exp_ciphers" "$sslv2_exp_ciphers" std_cipherlists 'LOW:!ADH' " Low (<=64 Bit) " 1 "LOW" "$low_ciphers" "$sslv2_low_ciphers" std_cipherlists 'DES:!ADH:!EXPORT:!aNULL' " DES Ciphers " 1 "DES" "$des_ciphers" "$sslv2_des_ciphers" From 3f0a98b635c722741ce03f253943313eed086465 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Fri, 24 Feb 2017 17:45:23 +0100 Subject: [PATCH 47/52] Generated from utils/update_client_sim_data.pl and manually massaged ;-) Note that the internal data from testssl.sh will disappear --- etc/client_simulation.txt | 777 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 777 insertions(+) create mode 100644 etc/client_simulation.txt diff --git a/etc/client_simulation.txt b/etc/client_simulation.txt new file mode 100644 index 0000000..938fc7e --- /dev/null +++ b/etc/client_simulation.txt @@ -0,0 +1,777 @@ + + # Most clients are taken from Qualys SSL Labs --- From: https://api.dev.ssllabs.com/api/v3/getClients + + names+=("Android 2.3.7 ") + short+=("android_237") + ciphers+=("RC4-MD5:RC4-SHA:AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:EXP-RC4-MD5:EXP-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA") + sni+=("") + warning+=("") + handshakebytes+=("160301004b010000470301531f3de6b36804738bbb94a6ecd570a544789c3bb0a6ef8b9d702f997d928d4b00002000040005002f00330032000a00160013000900150012000300080014001100ff0100") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Android 4.1.1 ") + short+=("android_411") + ciphers+=("ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100d7010000d30301531f3f6dd9eb5f6b3586c628cc2cdc82cdb259b1a096237ba4df30dbbc0f26fb000044c014c00ac022c02100390038c00fc0050035c012c008c01cc01b00160013c00dc003000ac013c009c01fc01e00330032c00ec004002fc011c007c00cc0020005000400ff020100006500000014001200000f7777772e73736c6c6162732e636f6d000b000403000102000a00340032000e000d0019000b000c00180009000a00160017000800060007001400150004000500120013000100020003000f0010001100230000000f00010133740000") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Android 4.2.2 ") + short+=("android_422") + ciphers+=("ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100d1010000cd0301531f40a89e11d5681f563f3dad094375227035d4e9d2c1654d7d3954e3254558000044c014c00ac022c02100390038c00fc0050035c012c008c01cc01b00160013c00dc003000ac013c009c01fc01e00330032c00ec004002fc011c007c00cc0020005000400ff0100006000000014001200000f7777772e73736c6c6162732e636f6d000b000403000102000a00340032000e000d0019000b000c00180009000a00160017000800060007001400150004000500120013000100020003000f001000110023000033740000") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Android 4.4.2 ") + short+=("android_442") + ciphers+=("ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100d1010000cd0303531f4317998fb70d57feded18c14433a1b665f963f7e3b1b045b6cc3d61bf21300004cc030c02cc014c00a00a3009f006b006a00390038009d003d0035c012c00800160013000ac02fc02bc027c023c013c00900a2009e0067004000330032009c003c002fc011c0070005000400ff0100005800000014001200000f7777772e73736c6c6162732e636f6d000b00020100000a0008000600190018001700230000000d00220020060106020603050105020503040104020403030103020303020102020203010133740000") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Android 5.0.0 ") + short+=("android_500") + ciphers+=("ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-GCM-SHA256:AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100bd010000b9030354c21737f3d9d10696c91debf12415f9c45833a83cfbbd4c60c9b91407d2316b000038cc14cc13cc15c014c00a003900380035c012c00800160013000ac02fc02bc013c00900a2009e00330032009c002fc011c0070005000400ff0100005800000014001200000f6465762e73736c6c6162732e636f6d00230000000d00220020060106020603050105020503040104020403030103020303020102020203010133740000000b00020100000a00080006001900180017") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Android 6.0 ") + short+=("android_60") + ciphers+=("ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100e2010000de030352f98411589cd6cd9dd403e70b1685b464a1d8c7495214d2c29b557738599f3420706946c402bf34b6356bfa5979bc3c65e1979a8fc632c201e976fef1ec3d55870022cc14cc13cc15c02bc02f009ec00ac0140039c009c0130033009c0035002f000a00ff0100007300000014001200000f6465762e73736c6c6162732e636f6d0017000000230000000d001600140601060305010503040104030301030302010203000500050100000000337400000012000000100014001208687474702f312e3108737064792f332e31000b00020100000a0006000400170018") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Android 7.0 ") + short+=("android_70") + ciphers+=("ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA:AES256-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100e4010000e0030366285fd01ec41e6b9c032a373d4607a6349c509d8a1b142cecc6820364d6eab42024c69f1c56165106d550c4c72135be8c3fe21f72843d19e663602d6476babc090022cca9cca8cc14cc13c02bc02fc02cc030c009c013c00ac014009c009d002f0035000a01000075ff0100010000000014001200000f6465762e73736c6c6162732e636f6d0017000000230000000d00120010060106030501050304010403020102030005000501000000000012000000100017001502683208737064792f332e3108687474702f312e31000b00020100000a00080006001d00170018") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Baidu Jan 2015 ") + short+=("baidu_jan_2015") + ciphers+=("ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:CAMELLIA256-SHA:AES256-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDH-RSA-RC4-SHA:ECDH-RSA-AES128-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-AES128-SHA:SEED-SHA:CAMELLIA128-SHA:RC4-MD5:RC4-SHA:AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100a30100009f030154c1a814c755540538a93b25e7824623d0ee9fc294ee752869cf76819edb3aa200004800ffc00ac0140088008700390038c00fc00500840035c007c009c011c0130045004400330032c00cc00ec002c0040096004100040005002fc008c01200160013c00dc003feff000a0100002e00000014001200000f6465762e73736c6c6162732e636f6d000a00080006001700180019000b0002010000230000") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("BingPreview Jan 2015 ") + short+=("bingpreview_jan_2015") + ciphers+=("ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:IDEA-CBC-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030101510100014d030354c13b79c1ca7169ae70c45d43311f9290d8ac1e326dfc36ff0aa99ea85406d50000a0c030c02cc028c024c014c00ac022c02100a3009f006b006a0039003800880087c032c02ec02ac026c00fc005009d003d00350084c012c008c01cc01b00160013c00dc003000ac02fc02bc027c023c013c009c01fc01e00a2009e0067004000330032009a009900450044c031c02dc029c025c00ec004009c003c002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff020100008300000014001200000f6465762e73736c6c6162732e636f6d000b000403000102000a00340032000e000d0019000b000c00180009000a00160017000800060007001400150004000500120013000100020003000f00100011000d002200200601060206030501050205030401040204030301030203030201020202030101000f000101") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(false) + + names+=("Chrome 48 OS X ") + short+=("chrome_48_osx") + ciphers+=("ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100ca010000c603037ac82baca9c0d08b1a01ecfb0bf5824f195153e0c6b4b48f5bf4621846376e8a00001ec02bc02f009ecc14cc13c00ac0140039c009c0130033009c0035002f000a0100007fff0100010000000014001200000f6465762e73736c6c6162732e636f6d0017000000230000000d001600140601060305010503040104030301030302010203000500050100000000337400000012000000100017001502683208737064792f332e3108687474702f312e3175500000000b00020100000a0006000400170018") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1024) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(8192) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(false) + + names+=("Chrome 51 Win 7 ") + short+=("chrome_51_win7") + ciphers+=("ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA:AES256-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100bf010000bb030355079db3b53ce2a6d3335902717ae6a84cc4b855d0b68775ac287f38da343c55000022c02bc02fc02cc030cca9cca8cc14cc13c009c013c00ac014009c009d002f0035000a01000070ff0100010000000014001200000f6465762e73736c6c6162732e636f6d0017000000230000000d0012001006010603050105030401040302010203000500050100000000001200000010000e000c02683208687474702f312e3175500000000b00020100000a00080006001d00170018") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1024) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Edge 13 Win 10 ") + short+=("edge_13_win10") + ciphers+=("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-AES128-SHA:EDH-DSS-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300d7010000d30303576c36d45fdcc8fdee4c62a86ccb3c116eaf6ba23d0726162972e953b993a96a000038c02cc02bc030c02f009f009ec024c023c028c027c00ac009c014c01300390033009d009c003d003c0035002f000a006a00400038003200130100007200000014001200000f6465762e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100000d00140012040105010201040305030203020206010603002300000010000e000c02683208687474702f312e310017000055000006000100020002ff01000100") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1024) + maxDhBits+=(4096) + minRsaBits+=(-1) + maxRsaBits+=(16384) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Edge 13 Win Phone 10 ") + short+=("edge_13_winphone10") + ciphers+=("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-AES128-SHA:EDH-DSS-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300d3010000cf0303565ee836e62e7b9b734f4dca5f3f1ad62dc4e5f87bdf6c90f325b6a2e0012705000034c02cc02bc030c02f009f009ec024c023c028c027c00ac009c014c013009d009c003d003c0035002f000a006a00400038003200130100007200000014001200000f6465762e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100000d00140012040105010201040305030203020206010603002300000010000e000c02683208687474702f312e310017000055000006000100020002ff01000100") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1024) + maxDhBits+=(4096) + minRsaBits+=(-1) + maxRsaBits+=(16384) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Firefox 45 Win 7 ") + short+=("firefox_45_win7") + ciphers+=("ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100d8010000d40303c45b58b30c163444fbca2e8a1832e5a36999712fa83d7ff6b6c13d5a22181e7f205fd10ae0807128c0c0ede2914316ac6b777e529c1f0e89c849cdf0cbde26efa00016c02bc02fc00ac009c013c01400330039002f0035000a0100007500000014001200000f6465762e73736c6c6162732e636f6dff01000100000a00080006001700180019000b00020100002300003374000000100017001502683208737064792f332e3108687474702f312e31000500050100000000000d001600140401050106010201040305030603020304020202") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1023) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(false) + + names+=("Firefox 49 Win 7 ") + short+=("firefox_49_win7") + ciphers+=("ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100e6010000e20303129162aca1f789ad3a792eaa766ba345770bbf2eb466e80bb51c3da72a29f95420b4419268602b765f6f206b948f9e6561cdd1f43606a44dc6fb2448862e26fc50001ec02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100007b00000014001200000f6465762e73736c6c6162732e636f6d00170000ff01000100000a00080006001700180019000b00020100002300003374000000100017001502683208737064792f332e3108687474702f312e31000500050100000000000d0018001604010501060102010403050306030203050204020202") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1023) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Firefox 49 XP SP3 ") + short+=("firefox_49_xpsp3") + ciphers+=("ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100c6010000c20303655bcc0742ffca05df48e52838a668733165388e09df153a44cbdc7c39c0bb4300001ec02bc02fcca9cca8c02cc030c00ac009c013c01400330039002f0035000a0100007b00000014001200000f6465762e73736c6c6162732e636f6d00170000ff01000100000a00080006001700180019000b00020100002300003374000000100017001502683208737064792f332e3108687474702f312e31000500050100000000000d0018001604010501060102010403050306030203050204020202") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1023) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Googlebot Feb 2015 ") + short+=("googlebot_feb_2015") + ciphers+=("ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:RC4-SHA:RC4-MD5:AES128-SHA:DES-CBC3-SHA:AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100db010000d70303d9c72e000f6a7f0a156840bd4aa9fd0612df4aeb69a1a1c6452c5f1f4d0ba6b000002ac02bc02fc007c011c009c013c00ac014009c00050004002f000a003500330032001600130039003800ff0100008400000014001200000f6465762e73736c6c6162732e636f6d00230000000d0020001e06010602060305010502050304010402040303010302030302010202020333740000000b000403000102000a00340032000e000d0019000b000c00180009000a00160017000800060007001400150004000500120013000100020003000f00100011") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(false) + + names+=("IE 11 Win 10 ") + short+=("ie_11_win10") + ciphers+=("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-AES128-SHA:EDH-DSS-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300d7010000d30303576c3861086a497dbb46489b67a88ac2e541c4863147fd09634bd0c630b73e92000038c02cc02bc030c02f009f009ec024c023c028c027c00ac009c014c01300390033009d009c003d003c0035002f000a006a00400038003200130100007200000014001200000f6465762e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100000d00140012040105010201040305030203020206010603002300000010000e000c02683208687474702f312e310017000055000006000100020002ff01000100") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1024) + maxDhBits+=(4096) + minRsaBits+=(-1) + maxRsaBits+=(16384) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 11 Win 7 ") + short+=("ie_11_win7") + ciphers+=("ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300b7010000b30303576b1fad9e727d57d0e40cae894f1f8f4608151d627affc2f1e20c2df7fefe5d000038c028c027c014c013009f009e00390033009d009c003d003c0035002fc02cc02bc024c023c00ac009006a004000380032000a0013000500040100005200000014001200000f6465762e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100000d0014001206010603040105010201040305030203020200170000ff01000100") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1024) + maxDhBits+=(4096) + minRsaBits+=(-1) + maxRsaBits+=(16384) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 11 Win 8.1 ") + short+=("ie_11_win81") + ciphers+=("ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300d1010000cd0303576c36e03bf1afe8d81100c68adc72bd0c678a5162275a5569651875123a7bec000034c028c027c014c013009f009e00390033009d009c003d003c0035002fc02cc02bc024c023c00ac009006a004000380032000a00130100007000000014001200000f6465762e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100000d001400120401050106010201040305030603020302020023000000100012001006737064792f3308687474702f312e313374000000170000ff01000100") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(1024) + maxDhBits+=(4096) + minRsaBits+=(-1) + maxRsaBits+=(16384) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 11 Win Phone 8.1 ") + short+=("ie_11_winphone81") + ciphers+=("AES128-SHA256:AES128-SHA:AES256-SHA256:AES256-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA256:DHE-DSS-AES256-SHA:EDH-DSS-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300bb010000b703035363d297ad92a8fe276a4e5b9395d593e96fff9c3df0987e5dfbab544ce05832000026003c002f003d0035000ac027c013c014c02bc023c02cc024c009c00a00400032006a0038001301000068ff0100010000000014001200000f7777772e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100000d0010000e04010501020104030503020302020023000000100012001006737064792f3308687474702f312e3133740000") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 11 Win Phone 8.1 Update ") + short+=("ie_11_winphone81update") + ciphers+=("ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300c5010000c103035537a79a55362d42c3b3308fea91e85c5656021153d0a4baf03e7fef6e315c72000030c028c027c014c013009f009e009d009c003d003c0035002fc02cc02bc024c023c00ac009006a004000380032000a001301000068ff0100010000000014001200000f6465762e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100000d0010000e04010501020104030503020302020023000000100012001006737064792f3308687474702f312e3133740000") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 6 XP ") + short+=("ie_6_xp") + ciphers+=("RC4-MD5:RC4-SHA:DES-CBC3-SHA:RC4-MD5:DES-CBC3-MD5:RC2-CBC-MD5:DES-CBC-SHA:DES-CBC-MD5:EXP1024-RC4-SHA:EXP1024-DES-CBC-SHA:EXP-RC4-MD5:EXP-RC2-CBC-MD5:EXP-RC4-MD5:EXP-RC2-CBC-MD5:EDH-DSS-DES-CBC3-SHA:EDH-DSS-DES-CBC-SHA:EXP1024-DHE-DSS-DES-CBC-SHA") + sni+=("") + warning+=("") + handshakebytes+=("804f01030000360000001000000400000500000a0100800700c00300800000090600400000640000620000030000060200800400800000130000120000630000ffd9f61eed63ba552d0bca94dc016081a3") + protos+=("-ssl3 -ssl2") + lowest_protocol+=("0x0200") + highest_protocol+=("0x0300") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 7 Vista ") + short+=("ie_7_vista") + ciphers+=("AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:EDH-DSS-DES-CBC3-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("160301007d01000079030151fa62ab452795b7003c5f93ab677dbf57dd62bfa39e0ffaaeabe45b06552452000018002f00350005000ac009c00ac013c01400320038001300040100003800000014001200000f7777772e73736c6c6162732e636f6d000500050100000000000a00080006001700180019000b00020100ff01000100") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 8 Win 7 ") + short+=("ie_8_win7") + ciphers+=("AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:EDH-DSS-DES-CBC3-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("160301007b01000077030151facea9bfdefb38bc40987322ebdc092498fc6e64e491683abd95179ea8405c000018002f00350005000ac013c014c009c00a003200380013000401000036ff0100010000000014001200000f7777772e73736c6c6162732e636f6d000500050100000000000a0006000400170018000b00020100") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("IE 8 XP ") + short+=("ie_8_xp") + ciphers+=("RC4-MD5:RC4-SHA:DES-CBC3-SHA:DES-CBC-SHA:EXP1024-RC4-SHA:EXP1024-DES-CBC-SHA:EXP-RC4-MD5:EXP-RC2-CBC-MD5:EDH-DSS-DES-CBC3-SHA:EDH-DSS-DES-CBC-SHA:EXP1024-DHE-DSS-DES-CBC-SHA") + sni+=("") + warning+=("") + handshakebytes+=("1603010048010000440301550bf46d2cff1997bd24885e963ba61faa8be6c28835c1f9bf74c1675cd3cf8500001600040005000a0009006400620003000600130012006301000005ff01000100") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Java 6u45 ") + short+=("java_6u45") + ciphers+=("RC4-MD5:RC4-MD5:RC4-SHA:AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA:DES-CBC3-MD5:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC-SHA:DES-CBC-MD5:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:EXP-RC4-MD5:EXP-RC4-MD5:EXP-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA") + sni+=("") + warning+=("") + handshakebytes+=("8065010301003c0000002000000401008000000500002f00003300003200000a0700c00000160000130000090600400000150000120000030200800000080000140000110000ff52173357f48ce6722f974dbb429b9279208d1cf5b9088947c9ba16d9ecbc0fa6") + protos+=("-tls1 -ssl3 -ssl2") + lowest_protocol+=("0x0200") + highest_protocol+=("0x0301") + service+=("ANY") + minDhBits+=(-1) + maxDhBits+=(1024) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Java 7u25 ") + short+=("java_7u25") + ciphers+=("ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA:ECDH-ECDSA-AES128-SHA:ECDH-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100ad010000a9030152178334e8b855253e50e4623e475b6941c18cc312de6395a98e1cd4fd6735e700002ac009c013002fc004c00e00330032c007c0110005c002c00cc008c012000ac003c00d00160013000400ff01000056000a0034003200170001000300130015000600070009000a0018000b000c0019000d000e000f001000110002001200040005001400080016000b0002010000000014001200000f7777772e73736c6c6162732e636f6d") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("ANY") + minDhBits+=(-1) + maxDhBits+=(1024) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Java 8b132 ") + short+=("java_8b132") + ciphers+=("ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA:ECDH-ECDSA-AES128-SHA:ECDH-RSA-AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300e7010000e303035319a4a6c3909b598b7f5c0923999b7fa67cf6e79f73a016ea39a221c6989eeb000046c023c027003cc025c02900670040c009c013002fc004c00e00330032c007c0110005c002c00cc02bc02f009cc02dc031009e00a2c008c012000ac003c00d00160013000400ff01000074000a0034003200170001000300130015000600070009000a0018000b000c0019000d000e000f001000110002001200040005001400080016000b00020100000d001a001806030601050305010403040103030301020302010202010100000014001200000f7777772e73736c6c6162732e636f6d") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("ANY") + minDhBits+=(-1) + maxDhBits+=(2048) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("OpenSSL 1.0.1l ") + short+=("openssl_101l") + ciphers+=("ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:IDEA-CBC-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("160301014f0100014b030332b230e5dd8c5573c219a243f397e31f407c7a93b60a26e7c3d5cca06a566fe1000094c030c02cc028c024c014c00a00a3009f006b006a0039003800880087c032c02ec02ac026c00fc005009d003d00350084c02fc02bc027c023c013c00900a2009e0067004000330032009a009900450044c031c02dc029c025c00ec004009c003c002f009600410007c011c007c00cc00200050004c012c00800160013c00dc003000a0015001200090014001100080006000300ff0100008e00000014001200000f6465762e73736c6c6162732e636f6d000b000403000102000a00340032000e000d0019000b000c00180009000a00160017000800060007001400150004000500120013000100020003000f0010001100230000000d0020001e060106020603050105020503040104020403030103020303020102020203000500050100000000000f000101") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("ANY") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("OpenSSL 1.0.2e ") + short+=("openssl_102e") + ciphers+=("ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DH-DSS-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DH-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DH-RSA-AES256-SHA256:DH-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DH-RSA-AES256-SHA:DH-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:DH-RSA-CAMELLIA256-SHA:DH-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DH-DSS-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DH-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DH-RSA-AES128-SHA256:DH-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DH-RSA-AES128-SHA:DH-DSS-AES128-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DH-RSA-SEED-SHA:DH-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:DH-RSA-CAMELLIA128-SHA:DH-DSS-CAMELLIA128-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:IDEA-CBC-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DH-RSA-DES-CBC3-SHA:DH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DH-RSA-DES-CBC-SHA:DH-DSS-DES-CBC-SHA:DES-CBC-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030101590100015503032a9db79b37d9364a9a685dc25bfec88c21ef88c206a20b9801108c67607e79800000b6c030c02cc028c024c014c00a00a500a300a1009f006b006a0069006800390038003700360088008700860085c032c02ec02ac026c00fc005009d003d00350084c02fc02bc027c023c013c00900a400a200a0009e00670040003f003e0033003200310030009a0099009800970045004400430042c031c02dc029c025c00ec004009c003c002f009600410007c011c007c00cc00200050004c012c008001600130010000dc00dc003000a00150012000f000c000900ff0100007600000014001200000f6465762e73736c6c6162732e636f6d000b000403000102000a001c001a00170019001c001b0018001a0016000e000d000b000c0009000a00230000000d0020001e060106020603050105020503040104020403030103020303020102020203000500050100000000000f000101") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("ANY") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Opera 17 Win 7 ") + short+=("opera_17_win7") + ciphers+=("ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:AES256-SHA:AES256-SHA256:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES128-SHA256:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100d5010000d10303526793c01b8d4859d838c8658f07f895a2f35ba16fb786644db811b856197e9b000028c00ac0140039006b0035003dc007c009c023c011c013c02700330067003200050004002f003c000a0100008000000014001200000f7777772e73736c6c6162732e636f6dff01000100000a00080006001700180019000b00020100002300003374000000100022002006737064792f3206737064792f3308737064792f332e3108687474702f312e31754f0000000500050100000000000d0012001004010501020104030503020304020202") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(4096) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(false) + + names+=("Safari 5.1.9 OS X 10.6.8 ") + short+=("safari_519_osx1068") + ciphers+=("ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-RC4-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDH-ECDSA-AES128-SHA:ECDH-ECDSA-AES256-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-DES-CBC3-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDH-RSA-RC4-SHA:ECDH-RSA-DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5:AES256-SHA:DES-CBC3-SHA:DES-CBC-SHA:EXP-RC4-MD5:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:DHE-DSS-AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:EDH-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC3-SHA:EDH-DSS-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("160301009d01000099030151d15dc2887b1852fd4291e36c3f4e8a35266e15dd6354779fbf5438b59b42da000046c00ac009c007c008c013c014c011c012c004c005c002c003c00ec00fc00cc00d002f000500040035000a000900030008000600320033003800390016001500140013001200110100002a00000014001200000f7777772e73736c6c6162732e636f6d000a00080006001700180019000b00020100") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(4096) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Safari 6.0.4 OS X 10.8.4 ") + short+=("safari_604_osx1084") + ciphers+=("ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDH-ECDSA-AES128-SHA:ECDH-ECDSA-AES256-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-DES-CBC3-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDH-RSA-RC4-SHA:ECDH-RSA-DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5:AES256-SHA:DES-CBC3-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:EDH-RSA-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100a9010000a5030151fa327c6576dadde1e8a89d4d45bdc1d0c107b8cbe998337e02ca419a0bcb30204dd1c85d9fbc1607b27a35ec9dfd1dae2c589483843a73999c9de205748633b1003200ffc00ac009c007c008c014c013c011c012c004c005c002c003c00ec00fc00cc00d002f000500040035000a0033003900160100002a00000014001200000f7777772e73736c6c6162732e636f6d000a00080006001700180019000b00020100") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(4096) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Safari 7 OS X 10.9 ") + short+=("safari_7_osx109") + ciphers+=("ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDH-ECDSA-AES256-SHA384:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES256-SHA384:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES256-SHA:ECDH-ECDSA-AES128-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-DES-CBC3-SHA:ECDH-RSA-AES256-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-RC4-SHA:ECDH-RSA-DES-CBC3-SHA:AES256-SHA256:AES128-SHA256:AES128-SHA:RC4-SHA:RC4-MD5:AES256-SHA:DES-CBC3-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:EDH-RSA-DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100d1010000cd030351fa3664edce86d82606540539ccd388418b1a5cb8cfda5e15349c635d4b028b203bf83c63e3da6777e407300b5d657e429f11cd7d857977e4390fda365b8d4664004a00ffc024c023c00ac009c007c008c028c027c014c013c011c012c026c025c02ac029c005c004c002c003c00fc00ec00cc00d003d003c002f000500040035000a0067006b0033003900160100003a00000014001200000f7777772e73736c6c6162732e636f6d000a00080006001700180019000b00020100000d000c000a05010401020104030203") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(4096) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Safari 8 OS X 10.10 ") + short+=("safari_8_osx1010") + ciphers+=("ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDH-ECDSA-AES256-SHA384:ECDH-ECDSA-AES128-SHA256:ECDH-ECDSA-AES256-SHA:ECDH-ECDSA-AES128-SHA:ECDH-ECDSA-DES-CBC3-SHA:ECDH-RSA-AES256-SHA384:ECDH-RSA-AES128-SHA256:ECDH-RSA-AES256-SHA:ECDH-RSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100b5010000b1030354c20a44e0d7681f3d55d7e9a764b67e6ffa6722c17b21e15bc2c9c98892460a00004a00ffc024c023c00ac009c008c028c027c014c013c012c026c025c005c004c003c02ac029c00fc00ec00d006b0067003900330016003d003c0035002f000ac007c011c002c00c000500040100003e00000014001200000f6465762e73736c6c6162732e636f6d000a00080006001700180019000b00020100000d000c000a0501040102010403020333740000") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(768) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(8192) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Safari 9 iOS 9 ") + short+=("safari_9_ios9") + ciphers+=("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100e2010000de030355fb38fdc94c6c1ff6ee066f0e69579f40a83ce5454787e8834b60fd8c31e5ac00003400ffc02cc02bc024c023c00ac009c008c030c02fc028c027c014c013c012009d009c003d003c0035002f000ac007c011000500040100008100000014001200000f6465762e73736c6c6162732e636f6d000a00080006001700180019000b00020100000d000e000c0501040102010503040302033374000000100030002e0268320568322d31360568322d31350568322d313408737064792f332e3106737064792f3308687474702f312e3100050005010000000000120000") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(768) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(8192) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Safari 9 OS X 10.11 ") + short+=("safari_9_osx1011") + ciphers+=("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:RC4-SHA:RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100e2010000de030355def1c4d1f6a12227389012da236581104b0bfa8b8a5bc849372531349dccc600003400ffc02cc02bc024c023c00ac009c008c030c02fc028c027c014c013c012009d009c003d003c0035002f000ac007c011000500040100008100000014001200000f6465762e73736c6c6162732e636f6d000a00080006001700180019000b00020100000d000e000c0501040102010503040302033374000000100030002e0268320568322d31360568322d31350568322d313408737064792f332e3106737064792f3308687474702f312e3100050005010000000000120000") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(768) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(8192) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Safari 10 OS X 10.12 ") + short+=("safari_10_osx1012") + ciphers+=("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100e2010000de030357fde32ec4b7eb1c967e535ba93d9129ffd6a35fc5d6b14f785205e2a0c7e35600002c00ffc02cc02bc024c023c00ac009c008c030c02fc028c027c014c013c012009d009c003d003c0035002f000a0100008900000014001200000f6465762e73736c6c6162732e636f6d000a00080006001700180019000b00020100000d00120010040102010501060104030203050306033374000000100030002e0268320568322d31360568322d31350568322d313408737064792f332e3106737064792f3308687474702f312e310005000501000000000012000000170000") + protos+=("-tls1_2 -tls1_1 -tls1") + lowest_protocol+=("0x0301") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(768) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(8192) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Apple ATS 9 iOS 9 ") + short+=("apple_ats_9_ios9") + ciphers+=("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030300c6010000c2030355def146b7ed606006d8d54a3ece6c9c1b5070b51ce0e81d354178f0311d2e0100001800ffc02cc02bc024c00ac023c009c030c02fc028c027c0130100008100000014001200000f6465762e73736c6c6162732e636f6d000a00080006001700180019000b00020100000d000e000c0501040102010503040302033374000000100030002e0268320568322d31360568322d31350568322d313408737064792f332e3106737064792f3308687474702f312e3100050005010000000000120000") + protos+=("-tls1_2") + lowest_protocol+=("0x0303") + highest_protocol+=("0x0303") + service+=("HTTP") + minDhBits+=(768) + maxDhBits+=(-1) + minRsaBits+=(2048) + maxRsaBits+=(8192) + minEcdsaBits+=(256) + requiresSha2+=(true) + current+=(true) + + names+=("Tor 17.0.9 Win 7 ") + short+=("tor_1709_win7") + ciphers+=("ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:CAMELLIA256-SHA:AES256-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDH-RSA-RC4-SHA:ECDH-RSA-AES128-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-AES128-SHA:SEED-SHA:CAMELLIA128-SHA:RC4-SHA:RC4-MD5:AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030100a30100009f0301526795b7dd72263ca4170729d52799a927b2e8ec0e2d844bca2cd7061de7a57d00004800ffc00ac0140088008700390038c00fc00500840035c007c009c011c0130045004400330032c00cc00ec002c0040096004100050004002fc008c01200160013c00dc003feff000a0100002e00000014001200000f7777772e73736c6c6162732e636f6d000a00080006001700180019000b0002010033740000") + protos+=("-tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0301") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(true) + + names+=("Yahoo Slurp Jan 2015 ") + short+=("yahoo_slurp_jan_2015") + ciphers+=("ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:IDEA-CBC-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("160301011a01000116030354c1f2e62a9427a5c66f85499abd08114e2f02822304c68a85ebf2b54182bca5000094c030c02cc028c024c014c00a00a3009f006b006a0039003800880087c032c02ec02ac026c00fc005009d003d00350084c012c00800160013c00dc003000ac02fc02bc027c023c013c00900a2009e0067004000330032009a009900450044c031c02dc029c025c00ec004009c003c002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff0100005900000014001200000f6465762e73736c6c6162732e636f6d000b000403000102000a000600040018001700230000000d002200200601060206030501050205030401040204030301030203030201020202030101000f000101") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(false) + + names+=("YandexBot Jan 2015 ") + short+=("yandexbot_jan_2015") + ciphers+=("ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:IDEA-CBC-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC4-MD5") + sni+=("$SNI") + warning+=("") + handshakebytes+=("16030101400100013c03030732cb0b19a74de19e2e6047368eea606cabff2fa27be340c8dee38625eedccd00008ec030c02cc028c024c014c00ac022c02100a3009f006b006a00390038c032c02ec02ac026c00fc005009d003d0035c012c008c01cc01b00160013c00dc003000ac02fc02bc027c023c013c009c01fc01e00a2009e0067004000330032c031c02dc029c025c00ec004009c003c002f0007c011c007c00cc002000500040015001200090014001100080006000300ff0100008500000014001200000f6465762e73736c6c6162732e636f6d000b000403000102000a00340032000e000d0019000b000c00180009000a00160017000800060007001400150004000500120013000100020003000f0010001100230000000d0020001e060106020603050105020503040104020403030103020303020102020203000f000101") + protos+=("-tls1_2 -tls1_1 -tls1 -ssl3") + lowest_protocol+=("0x0300") + highest_protocol+=("0x0303") + service+=("HTTP,FTP") + minDhBits+=(-1) + maxDhBits+=(-1) + minRsaBits+=(-1) + maxRsaBits+=(-1) + minEcdsaBits+=(-1) + requiresSha2+=(false) + current+=(false) + From ca1843395967e9f527de577b240ea2c4772de6a8 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Fri, 24 Feb 2017 17:55:20 +0100 Subject: [PATCH 48/52] Update README.md --- etc/README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/etc/README.md b/etc/README.md index d15f7d1..7522541 100644 --- a/etc/README.md +++ b/etc/README.md @@ -28,7 +28,11 @@ get a warning for the other certificate stores while scanning internal net- works. Second catch: If you scan other hosts in the internet the check against your Root CA will fail, too. This will be fixed in the future, see #230. -#### Mapping files -The file ``mapping-rfc.txt`` uses the hexcode to map OpenSSL names -against the RFC/IANA names. ``curves.txt`` is not being used yet, it -is supposed to map EC curve names properly. +#### Further needed files +* ``mapping-rfc.txt`` uses the hexcode to map OpenSSL against the RFC/IANA names. + +* ``ca_hashes.txt`` is used for HPKP test in order to have a fast comparison with known CAs + +* ``common-primes.txt`` is used for LOGJAM + +* ``client_simulation.txt`` as the name indicates it's the data for the client simulation From 783b90980466fa2447967c1e4fbb0e471b16d925 Mon Sep 17 00:00:00 2001 From: Todd Swatling Date: Fri, 24 Feb 2017 15:56:26 -0500 Subject: [PATCH 49/52] removed trailing spaces --- testssl.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/testssl.sh b/testssl.sh index d1adc1e..f99a9ce 100755 --- a/testssl.sh +++ b/testssl.sh @@ -4658,14 +4658,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 @@ -5973,11 +5973,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 @@ -11000,7 +11000,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" @@ -11986,7 +11986,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 From 12c3de70394f70d6ed32e0ed8992facc9b4c5c19 Mon Sep 17 00:00:00 2001 From: Todd Swatling Date: Fri, 24 Feb 2017 15:59:34 -0500 Subject: [PATCH 50/52] added missing herestring redirect (<<<) in find_openssl_binary function --- testssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testssl.sh b/testssl.sh index f99a9ce..a56838a 100755 --- a/testssl.sh +++ b/testssl.sh @@ -11102,7 +11102,7 @@ find_openssl_binary() { OSSL_VER=$($OPENSSL version 2>/dev/null | awk -F' ' '{ print $2 }') OSSL_VER_MAJOR=$(sed 's/\..*$//' <<< "$OSSL_VER") OSSL_VER_MINOR=$(sed -e 's/^.\.//' <<< "$OSSL_VER" | tr -d '[a-zA-Z]-') - OSSL_VER_APPENDIX=$(tr -d '0-9.' "$OSSL_VER") + OSSL_VER_APPENDIX=$(tr -d '0-9.' <<< "$OSSL_VER") OSSL_VER_PLATFORM=$($OPENSSL version -p 2>/dev/null | sed 's/^platform: //') OSSL_BUILD_DATE=$($OPENSSL version -a 2>/dev/null | grep '^built' | sed -e 's/built on//' -e 's/: ... //' -e 's/: //' -e 's/ UTC//' -e 's/ +0000//' -e 's/.000000000//') grep -q "not available" <<< "$OSSL_BUILD_DATE" && OSSL_BUILD_DATE="" From 2232929bc5e752fb49517637d93026d0d33600d9 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 27 Feb 2017 13:43:23 +0100 Subject: [PATCH 51/52] Polish #646 "=~" doesn't need quotes if there's a text string one wants to match against (and shellcheck complains about this) pr_magenta shouldn't be used anymore as the logic what color we use should be done some place else. --- testssl.sh | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/testssl.sh b/testssl.sh index 8beee49..96e4314 100755 --- a/testssl.sh +++ b/testssl.sh @@ -2265,7 +2265,7 @@ show_rfc_style(){ } neat_header(){ - if [[ "$DISPLAY_CIPHERNAMES" =~ "rfc" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then printf -- "Hexcode Cipher Suite Name (RFC) KeyExch. Encryption Bits" [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && printf -- " Cipher Suite Name (OpenSSL)" outln @@ -2304,12 +2304,12 @@ 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" [[ "$DISPLAY_CIPHERNAMES" != "openssl-only" ]] && tls_cipher="$(show_rfc_style "$hexcode")" if [[ "$5" == "false" ]]; then - if [[ "$DISPLAY_CIPHERNAMES" =~ "rfc" ]]; 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 @@ -2332,7 +2332,7 @@ neat_list(){ done fi #echo "${#kx}" # should be always 20 / 13 - if [[ "$DISPLAY_CIPHERNAMES" =~ "rfc" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then printf -- " %-7s %-49s %-10s %-12s%-8s" "$hexcode" "$tls_cipher" "$kx" "$enc" "$strength" [[ "$DISPLAY_CIPHERNAMES" != "rfc-only" ]] && printf -- " %-33s${SHOW_EACH_C:+ %-0s}" "$ossl_cipher" else @@ -4196,10 +4196,10 @@ run_client_simulation() { fi #FiXME: awk cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://') - if [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] && ( [[ "$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 [[ "$DISPLAY_CIPHERNAMES" =~ "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 @@ -4962,7 +4962,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 [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then default_cipher="$default_cipher_ossl" else default_cipher="$(openssl2rfc "$default_cipher_ossl")" @@ -5021,7 +5021,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 ( [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] && [[ "${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]}" @@ -5046,7 +5046,7 @@ run_server_preference() { proto[i]="SSLv3" cipher[i]="" cipher1=$(awk '/Cipher *:/ { print $3 }' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") - if [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] && [[ $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 @@ -5063,7 +5063,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 [[ "$DISPLAY_CIPHERNAMES" =~ "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 @@ -5087,7 +5087,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 [[ "$DISPLAY_CIPHERNAMES" =~ "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 @@ -5102,7 +5102,7 @@ run_server_preference() { if [[ -n "${cipher[i]}" ]]; then # cipher not empty if [[ -z "${cipher[i-1]}" ]]; then # previous one empty #outln - if [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both else printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}" # print out both @@ -5112,7 +5112,7 @@ run_server_preference() { out ", ${proto[i]}" # same cipher --> only print out protocol behind it else outln - if [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then printf -- " %-30s %s" "${cipher[i]}:" "${proto[i]}" # print out both else printf -- " %-51s %s" "${cipher[i]}:" "${proto[i]}" # print out both @@ -5373,14 +5373,14 @@ cipher_pref_check() { for (( i=0; i < nr_ciphers; i++ )); do [[ "$cipher" == "${rfc_ciph[i]}" ]] && ciphers_found2[i]=true && break done - if [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] && [[ $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" ]] && [[ "$DISPLAY_CIPHERNAMES" =~ "rfc" ]]; then + elif [[ -n "$order" ]] && [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then rfc_order="" while read -d " " cipher; do rfc_ciph="$(openssl2rfc "$cipher")" @@ -5422,7 +5422,7 @@ cipher_pref_check() { order+="$cipher " done fi - if [[ -n "$order" ]] && [[ "$DISPLAY_CIPHERNAMES" =~ "rfc" ]]; then + if [[ -n "$order" ]] && [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]]; then rfc_order="" while read -d " " cipher; do rfc_ciph="$(openssl2rfc "$cipher")" @@ -6964,7 +6964,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 ( [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] && [[ "${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]}" @@ -10556,7 +10556,7 @@ run_beast(){ [[ "$cbc_cipher" == "${ciph[i]}" ]] && break done ciphers_found[i]=true - if [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] || [[ "${rfc_ciph[i]}" == "-" ]]; then + if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] || [[ "${rfc_ciph[i]}" == "-" ]]; then detected_cbc_ciphers+="${ciph[i]} " else detected_cbc_ciphers+="${rfc_ciph[i]} " @@ -10587,7 +10587,7 @@ run_beast(){ [[ "$cbc_cipher" == "${rfc_ciph[i]}" ]] && break done ciphers_found[i]=true - if ( [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] && [[ "${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]}" @@ -10965,7 +10965,7 @@ run_rc4() { outln "${sigalg[i]}" fi if "${ciphers_found[i]}"; then - if ( [[ "$DISPLAY_CIPHERNAMES" =~ "openssl" ]] && [[ "${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]} " @@ -11316,10 +11316,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: use the RFC Cipher suite name as the primary name cipher suite name form; - no-openssl: don't display the OpenSSL Cipher Suite 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" @@ -12764,7 +12764,7 @@ parse_cmd_line() { no-rfc) DISPLAY_CIPHERNAMES="openssl-only" ;; openssl) DISPLAY_CIPHERNAMES="openssl" ;; rfc) DISPLAY_CIPHERNAMES="rfc" ;; - *) pr_magentaln "\nmapping can only be \"no-openssl\", \"no-rfc\", \"openssl\", or \"rfc\"" + *) pr_warningln "\nmapping can only be \"no-openssl\", \"no-rfc\", \"openssl\" or \"rfc\"" help 1 ;; esac ;; From ac193a8ef043c370910680f0069a0cb9b4bd0dae Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 27 Feb 2017 19:12:59 +0100 Subject: [PATCH 52/52] adding spring boot header detection --- testssl.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/testssl.sh b/testssl.sh index 96e4314..08a81a2 100755 --- a/testssl.sh +++ b/testssl.sh @@ -1798,6 +1798,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" \