From 76c34dd1486e68165bd462f60705261feaf397e3 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 14 Feb 2017 09:53:38 -0500 Subject: [PATCH 1/7] 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 2/7] 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 6a1c519acd306bf59061eb50b65d687207dc00a6 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Thu, 23 Feb 2017 09:31:41 -0500 Subject: [PATCH 3/7] 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 2232929bc5e752fb49517637d93026d0d33600d9 Mon Sep 17 00:00:00 2001 From: Dirk Date: Mon, 27 Feb 2017 13:43:23 +0100 Subject: [PATCH 4/7] 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 5/7] 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" \ From f02948e24a8c50ba7dfcf7655c8e846289a92dec Mon Sep 17 00:00:00 2001 From: David Cooper Date: Mon, 6 Mar 2017 14:37:52 -0500 Subject: [PATCH 6/7] Add spaces in show_finding() When I view testssl.sh in KDE's text editor (kate), the code after "INFO" line in `show_finding()` isn't highlighted correctly, and the highlighting doesn't correct again until `pr_liteblueln()`. This PR fixes the highlighting issue by adding spaces between "]]" and ")". To be "safe," I also added spaces between "(" and "[[", and similarly added spaces in `is_json_format()`. --- testssl.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/testssl.sh b/testssl.sh index 4e86ae7..18ce7cd 100755 --- a/testssl.sh +++ b/testssl.sh @@ -297,14 +297,14 @@ set_severity_level() { show_finding() { local severity=$1 - ([[ "$severity" == "DEBUG" ]]) || - ([[ "$severity" == "WARN" ]]) || - ([[ "$severity" == "INFO" ]] && [[ $SEVERITY_LEVEL -le $INFO ]]) || - ([[ "$severity" == "OK" ]] && [[ $SEVERITY_LEVEL -le $OK ]]) || - ([[ "$severity" == "LOW" ]] && [[ $SEVERITY_LEVEL -le $LOW ]]) || - ([[ "$severity" == "MEDIUM" ]] && [[ $SEVERITY_LEVEL -le $MEDIUM ]]) || - ([[ "$severity" == "HIGH" ]] && [[ $SEVERITY_LEVEL -le $HIGH ]]) || - ([[ "$severity" == "CRITICAL" ]] && [[ $SEVERITY_LEVEL -le $CRITICAL ]]) + ( [[ "$severity" == "DEBUG" ]] ) || + ( [[ "$severity" == "WARN" ]] ) || + ( [[ "$severity" == "INFO" ]] && [[ $SEVERITY_LEVEL -le $INFO ]] ) || + ( [[ "$severity" == "OK" ]] && [[ $SEVERITY_LEVEL -le $OK ]] ) || + ( [[ "$severity" == "LOW" ]] && [[ $SEVERITY_LEVEL -le $LOW ]] ) || + ( [[ "$severity" == "MEDIUM" ]] && [[ $SEVERITY_LEVEL -le $MEDIUM ]] ) || + ( [[ "$severity" == "HIGH" ]] && [[ $SEVERITY_LEVEL -le $HIGH ]] ) || + ( [[ "$severity" == "CRITICAL" ]] && [[ $SEVERITY_LEVEL -le $CRITICAL ]] ) } @@ -838,7 +838,7 @@ fileout_json_finding() { } is_json_format() { - ([[ -f "$JSONFILE" ]] && ("$do_json" || "$do_pretty_json")) + ( [[ -f "$JSONFILE" ]] && ("$do_json" || "$do_pretty_json") ) } ################# JSON FILE FORMATING END #################### From 875cd430873a71dd2ae8d1fc79a179aee49c72c5 Mon Sep 17 00:00:00 2001 From: David Cooper Date: Wed, 15 Mar 2017 10:22:04 -0400 Subject: [PATCH 7/7] Speedup normalize_ciphercode() While doing some performance testing I discovered that `normalize_ciphercode()` is very slow. This PR simplifies the function and speeds it up significantly. This PR also addresses the TODO item in `normalize_ciphercode()` by eliminating the global variable HEXC. --- testssl.sh | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/testssl.sh b/testssl.sh index 4e86ae7..630f43f 100755 --- a/testssl.sh +++ b/testssl.sh @@ -209,7 +209,6 @@ GOST_STATUS_PROBLEM=false DETECTED_TLS_VERSION="" PATTERN2SHOW="" SOCK_REPLY_FILE="" -HEXC="" NW_STR="" LEN_STR="" SNI="" @@ -2022,30 +2021,19 @@ run_more_flags() { } -# #1: string with 2 opensssl codes, HEXC= same in NSS/ssllabs terminology +# #1: string with 2 opensssl codes, output is same in NSS/ssllabs terminology normalize_ciphercode() { - part1=$(echo "$1" | awk -F',' '{ print $1 }') - part2=$(echo "$1" | awk -F',' '{ print $2 }') - part3=$(echo "$1" | awk -F',' '{ print $3 }') - if [[ "$part1" == "0x00" ]]; then # leading 0x00 - HEXC=$part2 + if [[ "${1:2:2}" == "00" ]]; then + out "$(tolower "x${1:7:2}")" else - #part2=$(echo $part2 | sed 's/0x//g') - part2=${part2//0x/} - if [[ -n "$part3" ]]; then # a SSLv2 cipher has three parts - #part3=$(echo $part3 | sed 's/0x//g') - part3=${part3//0x/} - fi - HEXC="$part1$part2$part3" + out "$(tolower "x${1:2:2}${1:7:2}${1:12:2}")" fi -#TODO: we should just echo this and avoid the global var HEXC - HEXC=$(tolower "$HEXC"| sed 's/0x/x/') # strip leading 0 return 0 } prettyprint_local() { local arg - local hexcode dash ciph sslvers kx auth enc mac export + local hexc hexcode dash ciph sslvers kx auth enc mac export local re='^[0-9A-Fa-f]+$' if [[ "$1" == 0x* ]] || [[ "$1" == 0X* ]]; then @@ -2066,19 +2054,19 @@ prettyprint_local() { if [[ -z "$1" ]]; then $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do # -V doesn't work with openssl < 1.0 - normalize_ciphercode $hexcode - neat_list "$HEXC" "$ciph" "$kx" "$enc" + hexc="$(normalize_ciphercode $hexcode)" + neat_list "$hexc" "$ciph" "$kx" "$enc" outln done else #for arg in $(echo $@ | sed 's/,/ /g'); do for arg in ${*//,/ /}; do $OPENSSL ciphers -V 'ALL:COMPLEMENTOFALL:@STRENGTH' 2>$ERRFILE | while read hexcode dash ciph sslvers kx auth enc mac export ; do # -V doesn't work with openssl < 1.0 - normalize_ciphercode $hexcode + hexc="$(normalize_ciphercode $hexcode)" # for numbers we don't do word matching: [[ $arg =~ $re ]] && \ - neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -ai "$arg" || \ - neat_list "$HEXC" "$ciph" "$kx" "$enc" | grep -wai "$arg" + neat_list "$hexc" "$ciph" "$kx" "$enc" | grep -ai "$arg" || \ + neat_list "$hexc" "$ciph" "$kx" "$enc" | grep -wai "$arg" done done fi @@ -2418,16 +2406,16 @@ test_just_one(){ done else while read hexc n ciph[nr_ciphers] sslvers[nr_ciphers] kx[nr_ciphers] auth enc[nr_ciphers] mac export2[nr_ciphers]; do - normalize_ciphercode $hexc + hexc="$(normalize_ciphercode $hexc)" # is argument a number? if [[ $arg =~ $re ]]; then - neat_list "$HEXC" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qai "$arg" + neat_list "$hexc" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qai "$arg" else - neat_list "$HEXC" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qwai "$arg" + neat_list "$hexc" "${ciph[nr_ciphers]}" "${kx[nr_ciphers]}" "${enc[nr_ciphers]}" | grep -qwai "$arg" fi if [[ $? -eq 0 ]]; then # string matches, so we can ssl to it: ciphers_found[nr_ciphers]=false - normalized_hexcode[nr_ciphers]="$HEXC" + normalized_hexcode[nr_ciphers]="$hexc" sigalg[nr_ciphers]="" ossl_supported[nr_ciphers]=true nr_ciphers+=1