Merged master fixed conflict.

This commit is contained in:
David Cooper 2016-05-24 14:19:19 -04:00
commit 2a4d987f31

View File

@ -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
# now scrape two bytes out of the reply per byte if [[ $tls_hello_ascii_len-$i -lt 10 ]]; then
tls_content_type="${tls_hello_ascii:0:2}" # normally this is x16 (Handshake) here # This could just be a result of the server's response being
tls_protocol="${tls_hello_ascii:2:4}" # split across two or more packets.
DETECTED_TLS_VERSION=$tls_protocol continue
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
echo "tls_protocol (reclyr): 0x$tls_protocol"
echo "tls_content_type: 0x$tls_content_type"
echo "tls_len_all: $tls_len_all"
echo "tls_err_descr: 0x${tls_err_descr} / = $(hex2dec ${tls_err_descr})"
echo "tls_err_level: ${tls_err_level} (warning:1, fatal:2)"
fi fi
# now, here comes a strange thing... -- on the first glance tls_content_type="${tls_hello_ascii:i:2}"
# IF an apache 2.2/2.4 server e.g. has a default servername configured but we send SNI <myhostname> i=$i+2
# we get a TLS ALERT saying "unrecognized_name" (0x70) and a warning (0x1), see RFC https://tools.ietf.org/html/rfc6066#page-17 tls_protocol="${tls_hello_ascii:i:4}"
# note that RFC recommended to fail instead: https://tools.ietf.org/html/rfc6066#section-3 i=$i+4
# we need to handle this properly -- otherwise we always return that the protocol or cipher is not available! msg_len=2*$(hex2dec "${tls_hello_ascii:i:4}")
if [[ "$tls_err_descr" == 70 ]] && [[ "${tls_err_level}" == "01" ]]; then i=$i+4
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) if [[ $DEBUG -ge 2 ]]; then
tls_protocol2="${tls_hello_ascii:32:4}" # here, too echo " tls_protocol (reclyr): 0x$tls_protocol"
tls_hello_time="${tls_hello_ascii:36:8}" # and here, too out " tls_content_type: 0x$tls_content_type"
else case $tls_content_type in
15) outln " (alert)" ;;
16) outln " (handshake)" ;;
*) outln ;;
esac
echo " msg_len: $((msg_len/2))"
outln
fi
if [[ $tls_content_type != "15" ]] && [[ $tls_content_type != "16" ]]; then
debugme pr_warningln "Content type other than alert or handshake detected."
return 1
elif [[ "${tls_protocol:0:2}" != "03" ]]; then
debugme pr_warningln "Protocol record_version.major is not 03."
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
if [[ $tls_content_type == "16" ]]; then
tls_handshake_ascii="$tls_handshake_ascii${tls_hello_ascii:i:msg_len}"
elif [[ $tls_content_type == "15" ]]; then # TLS ALERT
tls_alert_ascii="$tls_alert_ascii${tls_hello_ascii:i:msg_len}"
fi
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
outln " ($tls_alert_descrip)"
out " tls_err_level: ${tls_err_level}"
case $tls_err_level in
01) outln " (warning)" ;;
02) outln " (fatal)" ;;
*) outln ;;
esac
outln
fi
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 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_TIME=$(hex2dec "$tls_hello_time")
tls_sid_len=$(hex2dec "${tls_hello_ascii:$sid_len_offset:2}")
let sid_offset=$sid_len_offset+2+$tls_sid_len*2 tls_sid_len_hex="${tls_serverhello_ascii:68:2}"
tls_cipher_suite="${tls_hello_ascii:$sid_offset:4}" tls_sid_len=2*$(hex2dec "$tls_sid_len_hex")
let sid_offset=$sid_len_offset+6++$tls_sid_len*2 let offset=70+$tls_sid_len
tls_compression_method="${tls_hello_ascii:$sid_offset:2}"
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 if [[ $DEBUG -ge 2 ]]; then
echo "tls_protocol (reclyr): 0x$tls_protocol" echo "TLS server hello message:"
echo "tls_hello: 0x$tls_hello"
if [[ $DEBUG -ge 4 ]]; then if [[ $DEBUG -ge 4 ]]; then
echo "tls_protocol: 0x$tls_protocol2" echo " tls_protocol: 0x$tls_protocol2"
echo "tls_sid_len: 0x$(dec2hex $tls_sid_len) / = $tls_sid_len" echo " tls_sid_len: 0x$tls_sid_len_hex / = $((tls_sid_len/2))"
fi fi
echo -n "tls_hello_time: 0x$tls_hello_time " 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 $