mirror of
				https://github.com/drwetter/testssl.sh.git
				synced 2025-10-31 05:45:26 +01:00 
			
		
		
		
	Merged master fixed conflict.
This commit is contained in:
		
							
								
								
									
										412
									
								
								testssl.sh
									
									
									
									
									
								
							
							
						
						
									
										412
									
								
								testssl.sh
									
									
									
									
									
								
							| @@ -488,11 +488,6 @@ hex2dec() { | |||||||
|      echo $((16#$1)) |      echo $((16#$1)) | ||||||
| } | } | ||||||
|  |  | ||||||
| dec2hex() { |  | ||||||
|      #/usr/bin/printf -- "%x" "$1" |  | ||||||
|      echo $((0x$1)) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # trim spaces for BSD and old sed | # trim spaces for BSD and old sed | ||||||
| count_lines() { | count_lines() { | ||||||
|      wc -l <<<"$1" | sed 's/ //g' |      wc -l <<<"$1" | sed 's/ //g' | ||||||
| @@ -1078,7 +1073,7 @@ run_server_banner() { | |||||||
|                if [[ "$serverbanner" = *Microsoft-IIS/6.* ]] && [[ $OSSL_VER == 1.0.2* ]]; then |                if [[ "$serverbanner" = *Microsoft-IIS/6.* ]] && [[ $OSSL_VER == 1.0.2* ]]; then | ||||||
|                     pr_warningln "                              It's recommended to run another test w/ OpenSSL 1.0.1 !" |                     pr_warningln "                              It's recommended to run another test w/ OpenSSL 1.0.1 !" | ||||||
|                     # see https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892 |                     # see https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892 | ||||||
|                     fileout "IIS6_openssl_mismatch" "WARN" "It is recommended to rerun this test w/ OpenSSL 1.0.1\nSee https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892" |                     fileout "IIS6_openssl_mismatch" "WARN" "It is recommended to rerun this test w/ OpenSSL 1.0.1. See https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892" | ||||||
|                fi |                fi | ||||||
|           fi |           fi | ||||||
|           # mozilla.github.io/server-side-tls/ssl-config-generator/ |           # mozilla.github.io/server-side-tls/ssl-config-generator/ | ||||||
| @@ -1392,8 +1387,8 @@ std_cipherlists() { | |||||||
|                     ;; |                     ;; | ||||||
|                3) # not totally bad |                3) # not totally bad | ||||||
|                     if [[ $sclient_success -eq 0 ]]; then |                     if [[ $sclient_success -eq 0 ]]; then | ||||||
|                          pr_svrty_mediumln "offered (NOT ok)" |                          pr_svrty_mediumln "offered" | ||||||
|                          fileout "std_$4" "NOT ok" "$2 offered (NOT ok) - not too bad" |                          fileout "std_$4" "NOT ok" "$2 offered - not too bad" | ||||||
|                     else |                     else | ||||||
|                          outln "not offered (OK)" |                          outln "not offered (OK)" | ||||||
|                          fileout "std_$4" "OK" "$2 not offered (OK)" |                          fileout "std_$4" "OK" "$2 not offered (OK)" | ||||||
| @@ -2433,7 +2428,7 @@ run_protocols() { | |||||||
|                fi |                fi | ||||||
|                ;; |                ;; | ||||||
|           2) |           2) | ||||||
|                pr_svrty_medium "not offered (NOT ok)" |                pr_svrty_medium "not offered" | ||||||
|                if [[ "$DETECTED_TLS_VERSION" == "0300" ]]; then |                if [[ "$DETECTED_TLS_VERSION" == "0300" ]]; then | ||||||
|                     detected_version_string="SSLv3" |                     detected_version_string="SSLv3" | ||||||
|                elif [[ "$DETECTED_TLS_VERSION" == 03* ]]; then |                elif [[ "$DETECTED_TLS_VERSION" == 03* ]]; then | ||||||
| @@ -2442,7 +2437,7 @@ run_protocols() { | |||||||
|                if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then |                if [[ "$DETECTED_TLS_VERSION" == "$latest_supported" ]]; then | ||||||
|                     [[ $DEBUG -eq 1 ]] && out " -- downgraded" |                     [[ $DEBUG -eq 1 ]] && out " -- downgraded" | ||||||
|                     outln |                     outln | ||||||
|                     fileout "tls1_2" "NOT ok" "TLSv1.2 is not offered and downgraded to a weaker protocol (NOT ok)" |                     fileout "tls1_2" "INFO" "TLSv1.2 is not offered and downgraded to a weaker protocol (medium)" | ||||||
|                elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -lt 0x$latest_supported ]]; then |                elif [[ "$DETECTED_TLS_VERSION" == 03* ]] && [[ 0x$DETECTED_TLS_VERSION -lt 0x$latest_supported ]]; then | ||||||
|                     pr_svrty_criticalln " -- server supports $latest_supported_string, but downgraded to $detected_version_string" |                     pr_svrty_criticalln " -- server supports $latest_supported_string, but downgraded to $detected_version_string" | ||||||
|                     fileout "tls1_2" "NOT ok" "TLSv1.2 is not offered, and downgraded to $detected_version_string rather than $latest_supported_string (NOT ok)" |                     fileout "tls1_2" "NOT ok" "TLSv1.2 is not offered, and downgraded to $detected_version_string rather than $latest_supported_string (NOT ok)" | ||||||
| @@ -3144,7 +3139,7 @@ certificate_info() { | |||||||
|      local cert_keysize=$4 |      local cert_keysize=$4 | ||||||
|      local ocsp_response=$5 |      local ocsp_response=$5 | ||||||
|      local ocsp_response_status=$6 |      local ocsp_response_status=$6 | ||||||
|      local cert_sig_algo cert_key_algo |      local cert_sig_algo cert_sig_hash_algo cert_key_algo | ||||||
|      local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_C issuer_O issuer sans san cn cn_nosni |      local expire days2expire secs2warn ocsp_uri crl startdate enddate issuer_C issuer_O issuer sans san cn cn_nosni | ||||||
|      local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial |      local cert_fingerprint_sha1 cert_fingerprint_sha2 cert_fingerprint_serial | ||||||
|      local policy_oid |      local policy_oid | ||||||
| @@ -3177,6 +3172,10 @@ certificate_info() { | |||||||
|                pr_svrty_mediumln "SHA1 with RSA" |                pr_svrty_mediumln "SHA1 with RSA" | ||||||
|                fileout "${json_prefix}algorithm" "WARN" "Signature Algorithm: SHA1 with RSA (warning)" |                fileout "${json_prefix}algorithm" "WARN" "Signature Algorithm: SHA1 with RSA (warning)" | ||||||
|                ;; |                ;; | ||||||
|  |           sha224WithRSAEncryption) | ||||||
|  |                outln "SHA224 with RSA" | ||||||
|  |                fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: SHA224 with RSA" | ||||||
|  |                ;; | ||||||
|           sha256WithRSAEncryption) |           sha256WithRSAEncryption) | ||||||
|                pr_done_goodln "SHA256 with RSA" |                pr_done_goodln "SHA256 with RSA" | ||||||
|                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA256 with RSA (OK)" |                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA256 with RSA (OK)" | ||||||
| @@ -3189,10 +3188,75 @@ certificate_info() { | |||||||
|                pr_done_goodln "SHA512 with RSA" |                pr_done_goodln "SHA512 with RSA" | ||||||
|                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA512 with RSA (OK)" |                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA512 with RSA (OK)" | ||||||
|                ;; |                ;; | ||||||
|  |           ecdsa-with-SHA1) | ||||||
|  |                pr_svrty_mediumln "ECDSA with SHA1" | ||||||
|  |                fileout "${json_prefix}algorithm" "WARN" "Signature Algorithm: ECDSA with SHA1 (warning)" | ||||||
|  |                ;; | ||||||
|  |           ecdsa-with-SHA224) | ||||||
|  |                outln "ECDSA with SHA224" | ||||||
|  |                fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: ECDSA with SHA224" | ||||||
|  |                ;; | ||||||
|           ecdsa-with-SHA256) |           ecdsa-with-SHA256) | ||||||
|                pr_done_goodln "ECDSA with SHA256" |                pr_done_goodln "ECDSA with SHA256" | ||||||
|                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA256 (OK)" |                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA256 (OK)" | ||||||
|                ;; |                ;; | ||||||
|  |           ecdsa-with-SHA384) | ||||||
|  |                pr_done_goodln "ECDSA with SHA384" | ||||||
|  |                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA384 (OK)" | ||||||
|  |                ;; | ||||||
|  |           ecdsa-with-SHA512) | ||||||
|  |                pr_done_goodln "ECDSA with SHA512" | ||||||
|  |                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA512 (OK)" | ||||||
|  |                ;; | ||||||
|  |           dsaWithSHA1) | ||||||
|  |                pr_svrty_mediumln "DSA with SHA1" | ||||||
|  |                fileout "${json_prefix}algorithm" "WARN" "Signature Algorithm: DSA with SHA1 (warning)" | ||||||
|  |                ;; | ||||||
|  |           dsa_with_SHA224) | ||||||
|  |                outln "DSA with SHA224" | ||||||
|  |                fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: DSA with SHA224" | ||||||
|  |                ;; | ||||||
|  |           dsa_with_SHA256) | ||||||
|  |                pr_done_goodln "DSA with SHA256" | ||||||
|  |                fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: DSA with SHA256 (OK)" | ||||||
|  |                ;; | ||||||
|  |           rsassaPss) | ||||||
|  |                cert_sig_hash_algo="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 1 "Signature Algorithm" | head -2 | tail -1 | sed 's/^.*Hash Algorithm: //')" | ||||||
|  |                case $cert_sig_hash_algo in | ||||||
|  |                     sha1) | ||||||
|  |                          pr_svrty_mediumln "RSASSA-PSS with SHA1" | ||||||
|  |                          fileout "${json_prefix}algorithm" "WARN" "Signature Algorithm: RSASSA-PSS with SHA1 (warning)" | ||||||
|  |                          ;; | ||||||
|  |                     sha224) | ||||||
|  |                          outln "RSASSA-PSS with SHA224" | ||||||
|  |                          fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: RSASSA-PSS with SHA224" | ||||||
|  |                          ;; | ||||||
|  |                     sha256) | ||||||
|  |                          pr_done_goodln "RSASSA-PSS with SHA256" | ||||||
|  |                          fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: RSASSA-PSS with SHA256 (OK)" | ||||||
|  |                          ;; | ||||||
|  |                     sha384) | ||||||
|  |                          pr_done_goodln "RSASSA-PSS with SHA384" | ||||||
|  |                          fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: RSASSA-PSS with SHA384 (OK)" | ||||||
|  |                          ;; | ||||||
|  |                     sha512) | ||||||
|  |                          pr_done_goodln "RSASSA-PSS with SHA512" | ||||||
|  |                          fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: RSASSA-PSS with SHA512 (OK)" | ||||||
|  |                          ;; | ||||||
|  |                     *) | ||||||
|  |                          out "RSASSA-PSS with $cert_sig_hash_algo" | ||||||
|  |                          pr_warningln " (Unknown hash algorithm)" | ||||||
|  |                          fileout "${json_prefix}algorithm" "WARN" "Signature Algorithm: RSASSA-PSS with $cert_sig_hash_algo" | ||||||
|  |                     esac | ||||||
|  |                     ;; | ||||||
|  |           md2*) | ||||||
|  |                pr_svrty_criticalln "MD2" | ||||||
|  |                fileout "${json_prefix}algorithm" "NOT ok" "Signature Algorithm: MD2 (NOT ok)" | ||||||
|  |                ;; | ||||||
|  |           md4*) | ||||||
|  |                pr_svrty_criticalln "MD4" | ||||||
|  |                fileout "${json_prefix}algorithm" "NOT ok" "Signature Algorithm: MD4 (NOT ok)" | ||||||
|  |                ;; | ||||||
|           md5*) |           md5*) | ||||||
|                pr_svrty_criticalln "MD5" |                pr_svrty_criticalln "MD5" | ||||||
|                fileout "${json_prefix}algorithm" "NOT ok" "Signature Algorithm: MD5 (NOT ok)" |                fileout "${json_prefix}algorithm" "NOT ok" "Signature Algorithm: MD5 (NOT ok)" | ||||||
| @@ -3215,7 +3279,7 @@ certificate_info() { | |||||||
|           # http://infoscience.epfl.ch/record/164526/files/NPDF-22.pdf |           # http://infoscience.epfl.ch/record/164526/files/NPDF-22.pdf | ||||||
|           # see http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf |           # see http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf | ||||||
|           # Table 2 @ chapter 5.6.1 (~ p64) |           # Table 2 @ chapter 5.6.1 (~ p64) | ||||||
|           if [[ $cert_sig_algo =~ ecdsa ]] || [[ $cert_key_algo =~ ecPublicKey  ]]; then |           if [[ $cert_key_algo =~ ecdsa ]] || [[ $cert_key_algo =~ ecPublicKey  ]]; then | ||||||
|                if [[ "$cert_keysize" -le 110 ]]; then       # a guess  |                if [[ "$cert_keysize" -le 110 ]]; then       # a guess  | ||||||
|                     pr_svrty_critical "$cert_keysize" |                     pr_svrty_critical "$cert_keysize" | ||||||
|                     fileout "${json_prefix}key_size" "NOT ok" "Server keys $cert_keysize EC bits (NOT ok)" |                     fileout "${json_prefix}key_size" "NOT ok" "Server keys $cert_keysize EC bits (NOT ok)" | ||||||
| @@ -3236,7 +3300,7 @@ certificate_info() { | |||||||
|                     fileout "${json_prefix}key_size" "WARN" "Server keys $cert_keysize bits (not expected)" |                     fileout "${json_prefix}key_size" "WARN" "Server keys $cert_keysize bits (not expected)" | ||||||
|                fi |                fi | ||||||
|                outln " bits" |                outln " bits" | ||||||
|           elif [[ $cert_sig_algo = *RSA* ]]; then |           elif [[ $cert_key_algo = *RSA* ]] || [[ $cert_key_algo = *rsa* ]] || [[ $cert_key_algo = *dsa* ]]; then | ||||||
|                if [[ "$cert_keysize" -le 512 ]]; then |                if [[ "$cert_keysize" -le 512 ]]; then | ||||||
|                     pr_svrty_critical "$cert_keysize" |                     pr_svrty_critical "$cert_keysize" | ||||||
|                     outln " bits" |                     outln " bits" | ||||||
| @@ -3672,7 +3736,7 @@ run_pfs() { | |||||||
|      local pfs_ciphers |      local pfs_ciphers | ||||||
|  |  | ||||||
|      outln |      outln | ||||||
|      pr_headlineln " Testing (perfect) forward secrecy, (P)FS -- omitting 3DES, RC4 and Null Encryption here " |      pr_headlineln " Testing robust (perfect) forward secrecy, (P)FS -- omitting Null Authentication/Encryption as well as 3DES and RC4 here " | ||||||
|      if ! "$HAS_DH_BITS" && "$WIDE"; then |      if ! "$HAS_DH_BITS" && "$WIDE"; then | ||||||
|           pr_warningln "    (Your $OPENSSL cannot show DH/ECDH bits)" |           pr_warningln "    (Your $OPENSSL cannot show DH/ECDH bits)" | ||||||
|      fi |      fi | ||||||
| @@ -4138,92 +4202,268 @@ parse_sslv2_serverhello() { | |||||||
| # arg1: name of file with socket reply | # arg1: name of file with socket reply | ||||||
| parse_tls_serverhello() { | parse_tls_serverhello() { | ||||||
|      local tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$1") |      local tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$1") | ||||||
|      local tls_content_type tls_protocol tls_len_all |      local tls_handshake_ascii="" tls_alert_ascii="" | ||||||
| #TODO: all vars here |      local -i tls_hello_ascii_len tls_handshake_ascii_len tls_alert_ascii_len msg_len | ||||||
|  |      local tls_serverhello_ascii="" | ||||||
|  |      local -i tls_serverhello_ascii_len=0 | ||||||
|  |      local tls_alert_descrip tls_sid_len_hex | ||||||
|  |      local -i tls_sid_len offset | ||||||
|  |      local tls_msg_type tls_content_type tls_protocol tls_protocol2 tls_hello_time | ||||||
|  |      local tls_err_level tls_err_descr tls_cipher_suite tls_compression_method | ||||||
|  |      local -i i | ||||||
|  |  | ||||||
|      TLS_TIME="" |      TLS_TIME="" | ||||||
|      DETECTED_TLS_VERSION="" |      DETECTED_TLS_VERSION="" | ||||||
|  |  | ||||||
|      # server hello, handshake details see http://en.wikipedia.org/wiki/Transport_Layer_Security-SSL#TLS_record |      # $tls_hello_ascii may contain trailing whitespace. Remove it: | ||||||
|  |      tls_hello_ascii="${tls_hello_ascii%%[!0-9A-F]*}" | ||||||
|  |      [[ "$DEBUG" -eq 5 ]] && echo $tls_hello_ascii      # one line without any blanks | ||||||
|  |  | ||||||
|  |      # Client messages, including handshake messages, are carried by the record layer. | ||||||
|  |      # First, extract the handshake and alert messages. | ||||||
|  |      # see http://en.wikipedia.org/wiki/Transport_Layer_Security-SSL#TLS_record | ||||||
|      # byte 0:      content type:                 0x14=CCS,    0x15=TLS alert  x16=Handshake,  0x17 Aplication, 0x18=HB |      # byte 0:      content type:                 0x14=CCS,    0x15=TLS alert  x16=Handshake,  0x17 Aplication, 0x18=HB | ||||||
|      # byte 1+2:    TLS version word, major is 03, minor 00=SSL3, 01=TLS1 02=TLS1.1 03=TLS 1.2 |      # byte 1+2:    TLS version word, major is 03, minor 00=SSL3, 01=TLS1 02=TLS1.1 03=TLS 1.2 | ||||||
|      # byte 3+4:    length all |      # byte 3+4:    fragment length | ||||||
|      # byte 5:      handshake type (2=hello)      TLS alert: level (2=fatal), descr (0x28=handshake failure) |      # bytes 5...:  message fragment | ||||||
|      # byte 6+7+8:  length server hello |      tls_hello_ascii_len=${#tls_hello_ascii} | ||||||
|      # byte 9+10:   03, TLS version word          see byte 1+2 |      if [[ $DEBUG -ge 2 ]] && [[ $tls_hello_ascii_len -gt 0 ]]; then | ||||||
|      # byte 11-14:  TLS timestamp                 for OpenSSL <1.0.1f |          echo "TLS message fragments:" | ||||||
|      # byte 15-42:  random, 28 bytes |  | ||||||
|      # byte 43:     session id length |  | ||||||
|      # byte 44+45+sid-len:  cipher suite! |  | ||||||
|      # byte 46+sid-len:     compression method:  00: none, 01: deflate |  | ||||||
|      # byte 47+48+sid-len:  extension length |  | ||||||
|  |  | ||||||
|      [[ "$DEBUG" -eq 5 ]] && echo $tls_hello_ascii      # one line without any blanks |  | ||||||
|      if [[ -z "$tls_hello_ascii" ]]; then |  | ||||||
|           debugme echo "server hello empty, TCP connection closed" |  | ||||||
|           return 1              # no server hello received |  | ||||||
|      fi |      fi | ||||||
|  |      for (( i=0; i<tls_hello_ascii_len; i=i+msg_len )); do | ||||||
|  |           if [[ $tls_hello_ascii_len-$i -lt 10 ]]; then | ||||||
|  |                # This could just be a result of the server's response being | ||||||
|  |                # split across two or more packets. | ||||||
|  |                continue | ||||||
|  |           fi | ||||||
|  |           tls_content_type="${tls_hello_ascii:i:2}" | ||||||
|  |           i=$i+2 | ||||||
|  |           tls_protocol="${tls_hello_ascii:i:4}" | ||||||
|  |           i=$i+4 | ||||||
|  |           msg_len=2*$(hex2dec "${tls_hello_ascii:i:4}") | ||||||
|  |           i=$i+4 | ||||||
|  |  | ||||||
|      # now scrape two bytes out of the reply per byte |  | ||||||
|      tls_content_type="${tls_hello_ascii:0:2}"         # normally this is x16 (Handshake) here |  | ||||||
|      tls_protocol="${tls_hello_ascii:2:4}" |  | ||||||
|      DETECTED_TLS_VERSION=$tls_protocol |  | ||||||
|  |  | ||||||
|      tls_len_all=${tls_hello_ascii:6:4} |  | ||||||
|  |  | ||||||
|      sid_len_offset=86 |  | ||||||
|      tls_hello="${tls_hello_ascii:10:2}"               # normally this is x02 |  | ||||||
|      tls_protocol2="${tls_hello_ascii:18:4}" |  | ||||||
|      tls_hello_time="${tls_hello_ascii:22:8}" |  | ||||||
|  |  | ||||||
|      if [[ $tls_content_type == "15" ]]; then          # TLS ALERT |  | ||||||
|           tls_err_level=${tls_hello_ascii:10:2}        # 1: warning, 2: fatal |  | ||||||
|           tls_err_descr=${tls_hello_ascii:12:2}        # 112/0x70: Unrecognized name, 111/0x6F: certificate_unobtainable, |  | ||||||
|                                                        # 113/0x71: bad_certificate_status_response, #114/0x72: bad_certificate_hash_value |  | ||||||
|           if [[ $DEBUG -ge 2 ]]; then |           if [[ $DEBUG -ge 2 ]]; then | ||||||
|                echo "tls_protocol (reclyr):  0x$tls_protocol" |                echo "     tls_protocol (reclyr):  0x$tls_protocol" | ||||||
|                echo "tls_content_type:       0x$tls_content_type" |                out  "     tls_content_type:       0x$tls_content_type" | ||||||
|                echo "tls_len_all:            $tls_len_all" |                case $tls_content_type in | ||||||
|                echo "tls_err_descr:          0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})" |                     15) outln " (alert)" ;; | ||||||
|                echo "tls_err_level:          ${tls_err_level} (warning:1, fatal:2)" |                     16) outln " (handshake)" ;; | ||||||
|  |                      *) outln ;; | ||||||
|  |                esac | ||||||
|  |                echo "     msg_len:                $((msg_len/2))" | ||||||
|  |                outln | ||||||
|           fi |           fi | ||||||
|           # now, here comes a strange thing... -- on the first glance |           if [[ $tls_content_type != "15" ]] && [[ $tls_content_type != "16" ]]; then | ||||||
|           # IF an apache 2.2/2.4 server e.g. has a default servername configured but we send SNI <myhostname> |                debugme pr_warningln "Content type other than alert or handshake detected." | ||||||
|           # we get a TLS ALERT saying "unrecognized_name" (0x70) and a warning (0x1), see RFC https://tools.ietf.org/html/rfc6066#page-17 |                return 1 | ||||||
|           # note that RFC recommended to fail instead: https://tools.ietf.org/html/rfc6066#section-3 |           elif [[ "${tls_protocol:0:2}" != "03" ]]; then | ||||||
|           # we need to handle this properly -- otherwise we always return that the protocol or cipher is not available! |                debugme pr_warningln "Protocol record_version.major is not 03." | ||||||
|           if [[ "$tls_err_descr" == 70 ]] && [[ "${tls_err_level}" == "01" ]]; then |  | ||||||
|                sid_len_offset=100                      # we are 2x7 bytes off (formerly: 86 instead of 100) |  | ||||||
|                tls_hello="${tls_hello_ascii:24:2}"     # here, too       (normally this is (02) |  | ||||||
|                tls_protocol2="${tls_hello_ascii:32:4}" # here, too |  | ||||||
|                tls_hello_time="${tls_hello_ascii:36:8}"     # and here, too |  | ||||||
|           else |  | ||||||
|                return 1 |                return 1 | ||||||
|           fi |           fi | ||||||
|  |           DETECTED_TLS_VERSION=$tls_protocol | ||||||
|  |  | ||||||
|  |           if [[ $msg_len -gt $tls_hello_ascii_len-$i ]]; then | ||||||
|  |                # This could just be a result of the server's response being | ||||||
|  |                # split across two or more packets. Just grab the part that | ||||||
|  |                # is available. | ||||||
|  |                msg_len=$tls_hello_ascii_len-$i | ||||||
|           fi |           fi | ||||||
|  |  | ||||||
|      TLS_TIME=$(hex2dec "$tls_hello_time") |           if [[ $tls_content_type == "16" ]]; then | ||||||
|      tls_sid_len=$(hex2dec "${tls_hello_ascii:$sid_len_offset:2}") |                tls_handshake_ascii="$tls_handshake_ascii${tls_hello_ascii:i:msg_len}" | ||||||
|      let sid_offset=$sid_len_offset+2+$tls_sid_len*2 |           elif [[ $tls_content_type == "15" ]]; then   # TLS ALERT | ||||||
|      tls_cipher_suite="${tls_hello_ascii:$sid_offset:4}" |                tls_alert_ascii="$tls_alert_ascii${tls_hello_ascii:i:msg_len}" | ||||||
|      let sid_offset=$sid_len_offset+6++$tls_sid_len*2 |           fi | ||||||
|      tls_compression_method="${tls_hello_ascii:$sid_offset:2}" |      done | ||||||
|  |  | ||||||
|  |      # Now check the alert messages. | ||||||
|  |      tls_alert_ascii_len=${#tls_alert_ascii} | ||||||
|  |      if [[ $tls_alert_ascii_len -gt 0 ]]; then | ||||||
|  |           debugme echo "TLS alert messages:" | ||||||
|  |           for (( i=0; i+3 < tls_alert_ascii_len; i=i+4 )); do | ||||||
|  |                tls_err_level=${tls_alert_ascii:i:2}    # 1: warning, 2: fatal | ||||||
|  |                j=$i+2 | ||||||
|  |                tls_err_descr=${tls_alert_ascii:j:2}    # 112/0x70: Unrecognized name, 111/0x6F: certificate_unobtainable, | ||||||
|  |                                                        # 113/0x71: bad_certificate_status_response, #114/0x72: bad_certificate_hash_value | ||||||
|  |  | ||||||
|  |                debugme out  "     tls_err_descr:          0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})" | ||||||
|  |                case $tls_err_descr in | ||||||
|  |                     00) tls_alert_descrip="close notify" ;; | ||||||
|  |                     0A) tls_alert_descrip="unexpected message" ;; | ||||||
|  |                     14) tls_alert_descrip="bad record mac" ;; | ||||||
|  |                     15) tls_alert_descrip="decryption failed" ;; | ||||||
|  |                     16) tls_alert_descrip="record overflow" ;; | ||||||
|  |                     1E) tls_alert_descrip="decompression failure" ;; | ||||||
|  |                     28) tls_alert_descrip="handshake failure" ;; | ||||||
|  |                     29) tls_alert_descrip="no certificate RESERVED" ;; | ||||||
|  |                     2A) tls_alert_descrip="bad certificate" ;; | ||||||
|  |                     2B) tls_alert_descrip="unsupported certificate" ;; | ||||||
|  |                     2C) tls_alert_descrip="certificate revoked" ;; | ||||||
|  |                     2D) tls_alert_descrip="certificate expired" ;; | ||||||
|  |                     2E) tls_alert_descrip="certificate unknown" ;; | ||||||
|  |                     2F) tls_alert_descrip="illegal parameter" ;; | ||||||
|  |                     30) tls_alert_descrip="unknown ca" ;; | ||||||
|  |                     31) tls_alert_descrip="access denied" ;; | ||||||
|  |                     32) tls_alert_descrip="decode error" ;; | ||||||
|  |                     33) tls_alert_descrip="decrypt error" ;; | ||||||
|  |                     3C) tls_alert_descrip="export restriction RESERVED" ;; | ||||||
|  |                     46) tls_alert_descrip="protocol version" ;; | ||||||
|  |                     47) tls_alert_descrip="insufficient security" ;; | ||||||
|  |                     50) tls_alert_descrip="internal error" ;; | ||||||
|  |                     56) tls_alert_descrip="inappropriate fallback" ;; | ||||||
|  |                     5A) tls_alert_descrip="user canceled" ;; | ||||||
|  |                     64) tls_alert_descrip="no renegotiation" ;; | ||||||
|  |                     6E) tls_alert_descrip="unsupported extension" ;; | ||||||
|  |                     6F) tls_alert_descrip="certificate unobtainable" ;; | ||||||
|  |                     70) tls_alert_descrip="unrecognized name" ;; | ||||||
|  |                     71) tls_alert_descrip="bad certificate status response" ;; | ||||||
|  |                     72) tls_alert_descrip="bad certificate hash value" ;; | ||||||
|  |                     73) tls_alert_descrip="unknown psk identity" ;; | ||||||
|  |                     78) tls_alert_descrip="no application protocol" ;; | ||||||
|  |                      *) tls_alert_descrip="$(hex2dec "$tls_err_descr")";; | ||||||
|  |                esac | ||||||
|  |  | ||||||
|                if [[ $DEBUG -ge 2 ]]; then |                if [[ $DEBUG -ge 2 ]]; then | ||||||
|           echo "tls_protocol (reclyr):  0x$tls_protocol" |                     outln " ($tls_alert_descrip)" | ||||||
|           echo "tls_hello:              0x$tls_hello" |                     out  "     tls_err_level:          ${tls_err_level}" | ||||||
|           if [[ $DEBUG -ge 4 ]]; then |                     case $tls_err_level in | ||||||
|                echo "tls_protocol:           0x$tls_protocol2" |                          01) outln " (warning)" ;; | ||||||
|                echo "tls_sid_len:            0x$(dec2hex $tls_sid_len) / = $tls_sid_len" |                          02) outln " (fatal)" ;; | ||||||
|  |                           *) outln ;; | ||||||
|  |                     esac | ||||||
|  |                     outln | ||||||
|                fi |                fi | ||||||
|           echo -n "tls_hello_time:         0x$tls_hello_time " |                if [[ "$tls_err_level" != "01" ]] && [[ "$tls_err_level" != "02" ]]; then | ||||||
|  |                     debugme pr_warningln "Unexpected AlertLevel (0x$tls_err_level)." | ||||||
|  |                     return 1 | ||||||
|  |                elif [[ "$tls_err_level" == "02" ]]; then | ||||||
|  |                     # Fatal alert | ||||||
|  |                     return 1 | ||||||
|  |                fi | ||||||
|  |           done | ||||||
|  |      fi | ||||||
|  |  | ||||||
|  |      # Now extract just the server hello handshake message. | ||||||
|  |      tls_handshake_ascii_len=${#tls_handshake_ascii} | ||||||
|  |      if [[ $DEBUG -ge 2 ]] && [[ $tls_handshake_ascii_len -gt 0 ]]; then | ||||||
|  |          echo "TLS handshake messages:" | ||||||
|  |      fi | ||||||
|  |      for (( i=0; i<tls_handshake_ascii_len; i=i+msg_len )); do | ||||||
|  |           if [[ $tls_handshake_ascii_len-$i -lt 8 ]]; then | ||||||
|  |                # This could just be a result of the server's response being | ||||||
|  |                # split across two or more packets. | ||||||
|  |                continue | ||||||
|  |           fi | ||||||
|  |           tls_msg_type="${tls_handshake_ascii:i:2}" | ||||||
|  |           i=$i+2 | ||||||
|  |           msg_len=2*$(hex2dec "${tls_handshake_ascii:i:6}") | ||||||
|  |           i=$i+6 | ||||||
|  |  | ||||||
|  |           if [[ $DEBUG -ge 2 ]]; then | ||||||
|  |                out  "     handshake type:         0x${tls_msg_type}" | ||||||
|  |                case $tls_msg_type in | ||||||
|  |                     00) outln " (hello_request)" ;; | ||||||
|  |                     01) outln " (client_hello)" ;; | ||||||
|  |                     02) outln " (server_hello)" ;; | ||||||
|  |                     03) outln " (hello_verify_request)" ;; | ||||||
|  |                     04) outln " (NewSessionTicket)" ;; | ||||||
|  |                     0B) outln " (certificate)" ;; | ||||||
|  |                     0C) outln " (server_key_exchange)" ;; | ||||||
|  |                     0D) outln " (certificate_request)" ;; | ||||||
|  |                     0E) outln " (server_hello_done)" ;; | ||||||
|  |                     0F) outln " (certificate_verify)" ;; | ||||||
|  |                     10) outln " (client_key_exchange)" ;; | ||||||
|  |                     14) outln " (finished)" ;; | ||||||
|  |                     15) outln " (certificate_url)" ;; | ||||||
|  |                     16) outln " (certificate_status)" ;; | ||||||
|  |                     17) outln " (supplemental_data)" ;; | ||||||
|  |                     *) outln ;; | ||||||
|  |                esac | ||||||
|  |                echo "     msg_len:                $((msg_len/2))" | ||||||
|  |                outln | ||||||
|  |           fi | ||||||
|  |           if [[ $msg_len -gt $tls_handshake_ascii_len-$i ]]; then | ||||||
|  |                # This could just be a result of the server's response being | ||||||
|  |                # split across two or more packets. Just grab the part that | ||||||
|  |                # is available. | ||||||
|  |                msg_len=$tls_handshake_ascii_len-$i | ||||||
|  |           fi | ||||||
|  |  | ||||||
|  |           if [[ "$tls_msg_type" == "02" ]]; then | ||||||
|  |                if [[ -n "$tls_serverhello_ascii" ]]; then | ||||||
|  |                     debugme pr_warningln "Response contained more than one ServerHello handshake message." | ||||||
|  |                     return 1 | ||||||
|  |                fi | ||||||
|  |                tls_serverhello_ascii="${tls_handshake_ascii:i:msg_len}" | ||||||
|  |                tls_serverhello_ascii_len=$msg_len | ||||||
|  |           fi | ||||||
|  |      done | ||||||
|  |  | ||||||
|  |      if [[ $tls_serverhello_ascii_len -eq 0 ]]; then | ||||||
|  |           debugme echo "server hello empty, TCP connection closed" | ||||||
|  |           return 1              # no server hello received | ||||||
|  |      elif [[ $tls_serverhello_ascii_len -lt 76 ]]; then | ||||||
|  |           debugme echo "Malformed response" | ||||||
|  |           return 1 | ||||||
|  |      elif [[ "${tls_handshake_ascii:0:2}" != "02" ]]; then | ||||||
|  |           # the ServerHello MUST be the first handshake message | ||||||
|  |           debugme pr_warningln "The first handshake protocol message is not a ServerHello." | ||||||
|  |           return 1 | ||||||
|  |      fi | ||||||
|  |  | ||||||
|  |      # Parse the server hello handshake message | ||||||
|  |      # byte 0+1:    03, TLS version word          see byte 1+2 | ||||||
|  |      # byte 2-5:    TLS timestamp                 for OpenSSL <1.01f | ||||||
|  |      # byte 6-33:  random, 28 bytes | ||||||
|  |      # byte 34:     session id length | ||||||
|  |      # byte 35+36+sid-len:  cipher suite! | ||||||
|  |      # byte 37+sid-len:     compression method:  00: none, 01: deflate, 64: LZS | ||||||
|  |      # byte 38+39+sid-len:  extension length | ||||||
|  |      tls_protocol2="${tls_serverhello_ascii:0:4}" | ||||||
|  |      if [[ "${tls_protocol2:0:2}" != "03" ]]; then | ||||||
|  |           debugme pr_warningln "server_version.major in ServerHello is not 03." | ||||||
|  |           return 1 | ||||||
|  |      fi | ||||||
|  |      DETECTED_TLS_VERSION="$tls_protocol2" | ||||||
|  |  | ||||||
|  |      tls_hello_time="${tls_serverhello_ascii:4:8}" | ||||||
|  |      TLS_TIME=$(hex2dec "$tls_hello_time") | ||||||
|  |  | ||||||
|  |      tls_sid_len_hex="${tls_serverhello_ascii:68:2}" | ||||||
|  |      tls_sid_len=2*$(hex2dec "$tls_sid_len_hex") | ||||||
|  |      let offset=70+$tls_sid_len | ||||||
|  |  | ||||||
|  |      if [[ $tls_serverhello_ascii_len -lt 76+$tls_sid_len ]]; then | ||||||
|  |           debugme echo "Malformed response" | ||||||
|  |           return 1 | ||||||
|  |      fi | ||||||
|  |  | ||||||
|  |      tls_cipher_suite="${tls_serverhello_ascii:$offset:4}" | ||||||
|  |  | ||||||
|  |      let offset=74+$tls_sid_len | ||||||
|  |      tls_compression_method="${tls_serverhello_ascii:$offset:2}" | ||||||
|  |  | ||||||
|  |      if [[ $DEBUG -ge 2 ]]; then | ||||||
|  |           echo "TLS server hello message:" | ||||||
|  |           if [[ $DEBUG -ge 4 ]]; then | ||||||
|  |                echo "     tls_protocol:           0x$tls_protocol2" | ||||||
|  |                echo "     tls_sid_len:            0x$tls_sid_len_hex / = $((tls_sid_len/2))" | ||||||
|  |           fi | ||||||
|  |           echo -n "     tls_hello_time:         0x$tls_hello_time " | ||||||
|           if "$HAS_GNUDATE"; then |           if "$HAS_GNUDATE"; then | ||||||
|                date --date="@$TLS_TIME" "+%Y-%m-%d %r" |                date --date="@$TLS_TIME" "+%Y-%m-%d %r" | ||||||
|           else |           else | ||||||
|                LC_ALL=C date -j -f %s "$TLS_TIME" "+%Y-%m-%d %r" |                LC_ALL=C date -j -f %s "$TLS_TIME" "+%Y-%m-%d %r" | ||||||
|           fi |           fi | ||||||
|           echo "tls_cipher_suite:       0x$tls_cipher_suite" |           echo "     tls_cipher_suite:       0x$tls_cipher_suite" | ||||||
|           echo "tls_compression_method: 0x$tls_compression_method" |           echo -n "     tls_compression_method: 0x$tls_compression_method " | ||||||
|  |           case $tls_compression_method in | ||||||
|  |                00) echo "(NONE)" ;; | ||||||
|  |                01) echo "(zlib compression)" ;; | ||||||
|  |                40) echo "(LZS compression)" ;; | ||||||
|  |                 *) echo "(unrecognized compression method)" ;; | ||||||
|  |           esac | ||||||
|           outln |           outln | ||||||
|      fi |      fi | ||||||
|      return 0 |      return 0 | ||||||
| @@ -5711,7 +5951,8 @@ special invocations: | |||||||
| partly mandatory parameters: | partly mandatory parameters: | ||||||
|      URI                           host|host:port|URL|URL:port   (port 443 is assumed unless otherwise specified) |      URI                           host|host:port|URL|URL:port   (port 443 is assumed unless otherwise specified) | ||||||
|      pattern                       an ignore case word pattern of cipher hexcode or any other string in the name, kx or bits |      pattern                       an ignore case word pattern of cipher hexcode or any other string in the name, kx or bits | ||||||
|      protocol                      is one of ftp,smtp,pop3,imap,xmpp,telnet,ldap (for the latter two you need e.g. the supplied openssl) |      protocol                      is one of the STARTTLS protocols ftp,smtp,pop3,imap,xmpp,telnet,ldap  | ||||||
|  |                                    (for the latter two you need e.g. the supplied openssl) | ||||||
|  |  | ||||||
| tuning options (can also be preset via environment variables): | tuning options (can also be preset via environment variables): | ||||||
|      --bugs                        enables the "-bugs" option of s_client, needed e.g. for some buggy F5s |      --bugs                        enables the "-bugs" option of s_client, needed e.g. for some buggy F5s | ||||||
| @@ -5969,6 +6210,11 @@ parse_hn_port() { | |||||||
|      # strip trailing urlpath |      # strip trailing urlpath | ||||||
|      NODE=$(echo "$NODE" | sed -e 's/\/.*$//') |      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 | ||||||
|  |      fi | ||||||
|  |  | ||||||
|      # was the address supplied like [AA:BB:CC::]:port ? |      # was the address supplied like [AA:BB:CC::]:port ? | ||||||
|      if echo "$NODE" | grep -q ']' ; then |      if echo "$NODE" | grep -q ']' ; then | ||||||
|           tmp_port=$(printf "$NODE" | sed 's/\[.*\]//' | sed 's/://') |           tmp_port=$(printf "$NODE" | sed 's/\[.*\]//' | sed 's/://') | ||||||
| @@ -6899,7 +7145,7 @@ parse_cmd_line() { | |||||||
|                     do_logging=true |                     do_logging=true | ||||||
|                     ;;   # DEFINITION of LOGFILE if no arg specified: automagically in parse_hn_port() |                     ;;   # DEFINITION of LOGFILE if no arg specified: automagically in parse_hn_port() | ||||||
|                     # following does the same but we can specify a log location additionally |                     # following does the same but we can specify a log location additionally | ||||||
|                --logfile=*) |                --logfile|--logfile=*) | ||||||
|                     LOGFILE=$(parse_opt_equal_sign "$1" "$2") |                     LOGFILE=$(parse_opt_equal_sign "$1" "$2") | ||||||
|                     [[ $? -eq 0 ]] && shift |                     [[ $? -eq 0 ]] && shift | ||||||
|                     do_logging=true |                     do_logging=true | ||||||
| @@ -6908,7 +7154,7 @@ parse_cmd_line() { | |||||||
|                     do_json=true |                     do_json=true | ||||||
|                     ;;   # DEFINITION of JSONFILE is not arg specified: automagically in parse_hn_port() |                     ;;   # DEFINITION of JSONFILE is not arg specified: automagically in parse_hn_port() | ||||||
|                     # following does the same but we can specify a log location additionally |                     # following does the same but we can specify a log location additionally | ||||||
|                --jsonfile=*) |                --jsonfile|--jsonfile=*) | ||||||
|                     JSONFILE=$(parse_opt_equal_sign "$1" "$2") |                     JSONFILE=$(parse_opt_equal_sign "$1" "$2") | ||||||
|                     [[ $? -eq 0 ]] && shift |                     [[ $? -eq 0 ]] && shift | ||||||
|                     do_json=true |                     do_json=true | ||||||
| @@ -6917,7 +7163,7 @@ parse_cmd_line() { | |||||||
|                     do_csv=true |                     do_csv=true | ||||||
|                     ;;   # DEFINITION of CSVFILE is not arg specified: automagically in parse_hn_port() |                     ;;   # DEFINITION of CSVFILE is not arg specified: automagically in parse_hn_port() | ||||||
|                     # following does the same but we can specify a log location additionally |                     # following does the same but we can specify a log location additionally | ||||||
|                --csvfile=*) |                --csvfile|--csvfile=*) | ||||||
|                     CSVFILE=$(parse_opt_equal_sign "$1" "$2") |                     CSVFILE=$(parse_opt_equal_sign "$1" "$2") | ||||||
|                     [[ $? -eq 0 ]] && shift |                     [[ $? -eq 0 ]] && shift | ||||||
|                     do_csv=true |                     do_csv=true | ||||||
| @@ -7133,4 +7379,4 @@ fi | |||||||
| exit $? | exit $? | ||||||
|  |  | ||||||
|  |  | ||||||
| #  $Id: testssl.sh,v 1.481 2016/04/21 16:44:56 dirkw Exp $ | #  $Id: testssl.sh,v 1.487 2016/05/23 20:42:39 dirkw Exp $ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 David Cooper
					David Cooper