Use determine_optimal_sockets_params() in run_protocols()

This PR modifies run_protocols() to use the information collected by determine_optimal_sockets_params(). If it has already been determined that a protocol is supported, then no test is run. run_protocols() will still run a test for a protocol even if it has been determined that the server does not support that protocol. The reason for running the test is to verify that the server handles version negotiation correctly. This could be a TLSv1 server that rejects a TLSv1.2 or TLSv1.3 ClientHello, or it could happen in the opposite direction. At one point there was a server that would respond to an SSLv3 ClientHello with a TLSv1.2 ServerHello.

This PR required a couple of changes to determine_optimal_sockets_params() so that additional information could be passed to run_protocols(). If the server supports TLS 1.3, then run_protocols() needs to know which version (RFC 8446, draft 28, draft 27, etc.) rather than just that TLS 1.3 is supported. If the server supports TLS 1.2, but not TLS 1.3, then run_protocols() needs to know about at least one TLS 1.2 cipher that the server supports so that it can form a TLS 1.3 ClientHello that has no more than 128 ciphers and that should result in the server returning a TLS 1.2 ServerHello.
This commit is contained in:
David Cooper 2019-10-04 16:55:09 -04:00 committed by GitHub
parent 35c69bee27
commit 30b93d4c72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -285,6 +285,7 @@ NR_SOCKET_FAIL=0 # Counter for socket failures
NR_OSSL_FAIL=0 # .. for OpenSSL connects
NR_HEADER_FAIL=0 # .. for HTTP_GET
PROTOS_OFFERED="" # This keeps which protocol is being offered. See has_server_protocol().
TLS12_CIPHER_OFFERED="" # This contains the hexcode of a cipher known to be supported by the server with TLS 1.2
CURVES_OFFERED="" # This keeps which curves have been detected. Just for error handling
KNOWN_OSSL_PROB=false # We need OpenSSL a few times. This variable is an indicator if we can't connect. Eases handling
DETECTED_TLS_VERSION="" # .. as hex string, e.g. 0300 or 0303
@ -4868,7 +4869,7 @@ run_protocols() {
local tls13_ciphers_to_test=""
local i drafts_offered="" drafts_offered_str="" supported_versions debug_recomm=""
local tls12_detected_version
local -i ret=0 ret_val_tls12=0 ret_val_tls13=0
local -i ret=0 ret_val_ssl3 ret_val_tls1 ret_val_tls11 ret_val_tls12=0 ret_val_tls13=0
local offers_tls13=false
local jsonID="SSLv2"
@ -4962,12 +4963,16 @@ run_protocols() {
pr_bold " SSLv3 ";
jsonID="SSLv3"
if "$using_sockets"; then
if [[ $(has_server_protocol ssl3) -eq 0 ]]; then
ret_val_ssl3=0
elif "$using_sockets"; then
tls_sockets "00" "$TLS_CIPHER"
ret_val_ssl3=$?
else
run_prototest_openssl "-ssl3"
ret_val_ssl3=$?
fi
case $? in
case $ret_val_ssl3 in
0) prln_svrty_high "offered (NOT ok)"
fileout "$jsonID" "HIGH" "offered"
latest_supported="0300"
@ -5024,12 +5029,16 @@ run_protocols() {
pr_bold " TLS 1 ";
jsonID="TLS1"
if "$using_sockets"; then
if [[ $(has_server_protocol tls1) -eq 0 ]]; then
ret_val_tls1=0
elif "$using_sockets"; then
tls_sockets "01" "$TLS_CIPHER"
ret_val_tls1=$?
else
run_prototest_openssl "-tls1"
ret_val_tls1=$?
fi
case $? in
case $ret_val_tls1 in
0) pr_svrty_low "offered" ; outln " (deprecated)"
fileout "$jsonID" "LOW" "offered (deprecated)"
latest_supported="0301"
@ -5098,12 +5107,16 @@ run_protocols() {
pr_bold " TLS 1.1 ";
jsonID="TLS1_1"
if "$using_sockets"; then
if [[ $(has_server_protocol tls1_1) -eq 0 ]]; then
ret_val_tls11=0
elif "$using_sockets"; then
tls_sockets "02" "$TLS_CIPHER"
ret_val_tls11=$?
else
run_prototest_openssl "-tls1_1"
ret_val_tls11=$?
fi
case $? in
case $ret_val_tls11 in
0) pr_svrty_low "offered" ; outln " (deprecated)"
fileout "$jsonID" "LOW" "offered (deprecated)"
latest_supported="0302"
@ -5176,35 +5189,36 @@ run_protocols() {
# Now, we are doing a basic/pre test for TLS 1.2 and 1.3 in order not to penalize servers (medium)
# running TLS 1.3 only when TLS 1.2 is not offered. 0 and 5 are the return codes for
# TLS 1.3 support (kind of, including deprecated pre-versions of TLS 1.3)
if "$using_sockets"; then
if [[ $(has_server_protocol tls1_2) -eq 0 ]]; then
ret_val_tls12=0
elif "$using_sockets"; then
tls_sockets "03" "$TLS12_CIPHER"
ret_val_tls12=$?
tls12_detected_version="$DETECTED_TLS_VERSION"
else
run_prototest_openssl "-tls1_2"
ret_val_tls12=$?
fi
if [[ $(has_server_protocol tls1_3) -eq 0 ]]; then
ret_val_tls13=0
elif "$using_sockets"; then
# Need to ensure that at most 128 ciphers are included in ClientHello.
# If the TLSv1.2 test was successful, then use the 5 TLSv1.3 ciphers
# plus the cipher selected in the TLSv1.2 test. If the TLSv1.2 test was
# not successful, then just use the 5 TLSv1.3 ciphers plus the list of
# ciphers used in all of the previous tests ($TLS_CIPHER).
if [[ $ret_val_tls12 -eq 0 ]] || [[ $ret_val_tls12 -eq 2 ]]; then
tls13_ciphers_to_test="$(get_cipher "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")"
if [[ "$tls13_ciphers_to_test" == TLS_* ]] || [[ "$tls13_ciphers_to_test" == SSL_* ]]; then
tls13_ciphers_to_test="$(rfc2hexcode "$tls13_ciphers_to_test")"
else
tls13_ciphers_to_test="$(openssl2hexcode "$tls13_ciphers_to_test")"
fi
fi
if [[ ${#tls13_ciphers_to_test} -eq 9 ]]; then
tls13_ciphers_to_test="$TLS13_CIPHER, ${tls13_ciphers_to_test:2:2},${tls13_ciphers_to_test:7:2}, 00,ff"
# If the TLSv1.2 test in determine_optimal_sockets_params() was successful,
# then use the 5 TLSv1.3 ciphers plus the cipher selected in the TLSv1.2 test.
# If the TLSv1.2 test was not successful, then just use the 5 TLSv1.3 ciphers
# plus the list of ciphers used in all of the previous tests ($TLS_CIPHER).
if [[ -n "$TLS12_CIPHER_OFFERED" ]]; then
tls13_ciphers_to_test="$TLS13_CIPHER, $TLS12_CIPHER_OFFERED, 00,ff"
else
tls13_ciphers_to_test="$TLS13_CIPHER,$TLS_CIPHER"
fi
tls_sockets "04" "$tls13_ciphers_to_test"
ret_val_tls13=$?
else
run_prototest_openssl "-tls1_2"
ret_val_tls12=$?
run_prototest_openssl "-tls1_3"
ret_val_tls13=$?
fi
ret_val_tls13=$?
if [[ $ret_val_tls13 -eq 0 ]] || [[ $ret_val_tls13 -eq 5 ]]; then
offers_tls13=true # This variable comes in handy for further if statements below
fi
@ -5300,17 +5314,13 @@ run_protocols() {
prln_svrty_best "offered (OK)"
fileout "$jsonID" "OK" "offered"
else
# Determine which version of TLS 1.3 was offered. For drafts 18-21 the
# version appears in the ProtocolVersion field of the ServerHello. For
# drafts 22-28 and the final TLS 1.3 the ProtocolVersion field contains
# 0303 and the actual version appears in the supported_versions extension.
if [[ "${TLS_SERVER_HELLO:8:3}" == 7F1 ]]; then
drafts_offered+=" ${TLS_SERVER_HELLO:8:4} "
elif [[ "$TLS_SERVER_HELLO" =~ 002B00020304 ]]; then
# If TLS 1.3 is offered, then its support was detected
# by determine_optimal_sockets_params().
if [[ $(has_server_protocol tls1_3_rfc8446) -eq 0 ]]; then
drafts_offered+=" 0304 "
else
for i in 1C 1B 1A 19 18 17 16 15 14 13 12; do
if [[ "$TLS_SERVER_HELLO" =~ 002B00027F$i ]]; then
if [[ $(has_server_protocol tls1_3_draft$(hex2dec "$i")) -eq 0 ]]; then
drafts_offered+=" 7F$i "
break
fi
@ -5457,8 +5467,9 @@ run_protocols() {
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
fi
if [[ "$PROTOS_OFFERED" =~ tls1_3:yes ]]; then
if [[ ! "${PROTOS_OFFERED//tls1_3:yes /}" =~ yes ]]; then
if [[ "$(has_server_protocol "tls1_3")" -eq 0 ]]; then
if [[ "$(has_server_protocol "tls1_2")" -ne 0 ]] && [[ "$(has_server_protocol "tls1_1")" -ne 0 ]] &&
[[ "$(has_server_protocol "tls1")" -ne 0 ]] && [[ "$(has_server_protocol "ssl3")" -ne 0 ]]; then
TLS13_ONLY=true
if ! "$HAS_TLS13"; then
pr_magenta " $NODE:$PORT appears to support TLS 1.3 ONLY. You better use --openssl=<path_to_openssl_supporting_TLS_1.3>"
@ -17804,8 +17815,8 @@ sclient_auth() {
# This information can be used by determine_optimal_proto() to help distinguish between a server
# that is not TLS/SSL enabled and one that is not compatible with the version of OpenSSL being used.
determine_optimal_sockets_params() {
local -i ret1 ret2
local proto
local -i ret1=1 ret2=1
local i proto cipher_offered
local all_failed=true
# If a STARTTLS protocol is specified and $SSL_NATIVE is true, then skip this test, since
@ -17832,6 +17843,24 @@ determine_optimal_sockets_params() {
KEY_SHARE_EXTN_NR="33"
fi
fi
if ! "$all_failed"; then
# Determine which version of TLS 1.3 was offered. For drafts 18-21 the
# version appears in the ProtocolVersion field of the ServerHello. For
# drafts 22-28 and the final TLS 1.3 the ProtocolVersion field contains
# 0303 and the actual version appears in the supported_versions extension.
if [[ "${TLS_SERVER_HELLO:8:3}" == 7F1 ]]; then
add_tls_offered tls1_3_draft$(hex2dec "${TLS_SERVER_HELLO:10:2}") yes
elif [[ "$TLS_SERVER_HELLO" =~ 002B00020304 ]]; then
add_tls_offered tls1_3_rfc8446 yes
else
for i in 1C 1B 1A 19 18 17 16 15 14 13 12; do
if [[ "$TLS_SERVER_HELLO" =~ 002B00027F$i ]]; then
add_tls_offered tls1_3_draft$(hex2dec "$i") yes
break
fi
done
fi
fi
# Need to determine which set of ciphers is best to use with
# a TLSv1.2 ClientHello since there are far more than 128 ciphers
@ -17873,6 +17902,15 @@ determine_optimal_sockets_params() {
all_failed=false
fi
fi
if [[ $ret1 -eq 0 ]] || [[ $ret2 -eq 0 ]]; then
cipher_offered="$(get_cipher "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt")"
if [[ "$cipher_offered" == TLS_* ]] || [[ "$cipher_offered" == SSL_* ]]; then
cipher_offered="$(rfc2hexcode "$cipher_offered")"
else
cipher_offered="$(openssl2hexcode "$cipher_offered")"
fi
[[ ${#cipher_offered} -eq 9 ]] && TLS12_CIPHER_OFFERED="${cipher_offered:2:2},${cipher_offered:7:2}"
fi
if "$all_failed"; then
# One of the following must be true: